فهرست منبع

Added Assimp 3.2 source

markcwm 8 سال پیش
والد
کامیت
a082afc102
100فایلهای تغییر یافته به همراه30865 افزوده شده و 25804 حذف شده
  1. 157 116
      assimplib.mod/assimp/CHANGES
  2. 342 0
      assimplib.mod/assimp/CMakeLists.txt
  3. 160 150
      assimplib.mod/assimp/CREDITS
  4. 84 84
      assimplib.mod/assimp/LICENSE
  5. 134 120
      assimplib.mod/assimp/Readme.md
  6. 8 0
      assimplib.mod/assimp/code/.editorconfig
  7. 761 756
      assimplib.mod/assimp/code/3DSConverter.cpp
  8. 565 0
      assimplib.mod/assimp/code/3DSExporter.cpp
  9. 98 0
      assimplib.mod/assimp/code/3DSExporter.h
  10. 458 451
      assimplib.mod/assimp/code/3DSHelper.h
  11. 456 439
      assimplib.mod/assimp/code/3DSLoader.cpp
  12. 205 203
      assimplib.mod/assimp/code/3DSLoader.h
  13. 790 749
      assimplib.mod/assimp/code/ACLoader.cpp
  14. 179 172
      assimplib.mod/assimp/code/ACLoader.h
  15. 1165 1156
      assimplib.mod/assimp/code/ASELoader.cpp
  16. 108 108
      assimplib.mod/assimp/code/ASELoader.h
  17. 1895 1894
      assimplib.mod/assimp/code/ASEParser.cpp
  18. 467 467
      assimplib.mod/assimp/code/ASEParser.h
  19. 769 0
      assimplib.mod/assimp/code/AssbinExporter.cpp
  20. 49 0
      assimplib.mod/assimp/code/AssbinExporter.h
  21. 687 0
      assimplib.mod/assimp/code/AssbinLoader.cpp
  22. 105 0
      assimplib.mod/assimp/code/AssbinLoader.h
  23. 363 318
      assimplib.mod/assimp/code/Assimp.cpp
  24. 40 38
      assimplib.mod/assimp/code/AssimpCExport.cpp
  25. 0 135
      assimplib.mod/assimp/code/AssimpPCH.cpp
  26. 0 162
      assimplib.mod/assimp/code/AssimpPCH.h
  27. 641 0
      assimplib.mod/assimp/code/AssxmlExporter.cpp
  28. 49 0
      assimplib.mod/assimp/code/AssxmlExporter.h
  29. 483 475
      assimplib.mod/assimp/code/B3DImporter.cpp
  30. 72 68
      assimplib.mod/assimp/code/B3DImporter.h
  31. 393 385
      assimplib.mod/assimp/code/BVHLoader.cpp
  32. 83 81
      assimplib.mod/assimp/code/BVHLoader.h
  33. 434 419
      assimplib.mod/assimp/code/BaseImporter.cpp
  34. 284 277
      assimplib.mod/assimp/code/BaseImporter.h
  35. 31 31
      assimplib.mod/assimp/code/BaseProcess.cpp
  36. 189 189
      assimplib.mod/assimp/code/BaseProcess.h
  37. 94 92
      assimplib.mod/assimp/code/Bitmap.cpp
  38. 56 51
      assimplib.mod/assimp/code/Bitmap.h
  39. 95 69
      assimplib.mod/assimp/code/BlenderBMesh.cpp
  40. 49 48
      assimplib.mod/assimp/code/BlenderBMesh.h
  41. 258 257
      assimplib.mod/assimp/code/BlenderDNA.cpp
  42. 469 464
      assimplib.mod/assimp/code/BlenderDNA.h
  43. 488 486
      assimplib.mod/assimp/code/BlenderDNA.inl
  44. 143 122
      assimplib.mod/assimp/code/BlenderIntermediate.h
  45. 965 954
      assimplib.mod/assimp/code/BlenderLoader.cpp
  46. 152 145
      assimplib.mod/assimp/code/BlenderLoader.h
  47. 222 218
      assimplib.mod/assimp/code/BlenderModifier.cpp
  48. 61 61
      assimplib.mod/assimp/code/BlenderModifier.h
  49. 100 100
      assimplib.mod/assimp/code/BlenderScene.cpp
  50. 432 430
      assimplib.mod/assimp/code/BlenderScene.h
  51. 15 12
      assimplib.mod/assimp/code/BlenderSceneGen.h
  52. 262 263
      assimplib.mod/assimp/code/BlenderTessellator.cpp
  53. 135 135
      assimplib.mod/assimp/code/BlenderTessellator.h
  54. 223 212
      assimplib.mod/assimp/code/BlobIOSystem.h
  55. 1 0
      assimplib.mod/assimp/code/BoostWorkaround/boost/format.hpp
  56. 3 0
      assimplib.mod/assimp/code/BoostWorkaround/boost/shared_ptr.hpp
  57. 2 1
      assimplib.mod/assimp/code/BoostWorkaround/boost/timer.hpp
  58. 3 3
      assimplib.mod/assimp/code/BoostWorkaround/boost/tuple/tuple.hpp
  59. 0 285
      assimplib.mod/assimp/code/ByteSwap.h
  60. 286 0
      assimplib.mod/assimp/code/ByteSwapper.h
  61. 644 0
      assimplib.mod/assimp/code/C4DImporter.cpp
  62. 123 0
      assimplib.mod/assimp/code/C4DImporter.h
  63. 97 95
      assimplib.mod/assimp/code/CInterfaceIOWrapper.h
  64. 630 586
      assimplib.mod/assimp/code/CMakeLists.txt
  65. 716 706
      assimplib.mod/assimp/code/COBLoader.cpp
  66. 91 87
      assimplib.mod/assimp/code/COBLoader.h
  67. 128 125
      assimplib.mod/assimp/code/COBScene.h
  68. 225 218
      assimplib.mod/assimp/code/CSMLoader.cpp
  69. 27 24
      assimplib.mod/assimp/code/CSMLoader.h
  70. 196 197
      assimplib.mod/assimp/code/CalcTangentsProcess.cpp
  71. 50 50
      assimplib.mod/assimp/code/CalcTangentsProcess.h
  72. 750 480
      assimplib.mod/assimp/code/ColladaExporter.cpp
  73. 90 64
      assimplib.mod/assimp/code/ColladaExporter.h
  74. 395 371
      assimplib.mod/assimp/code/ColladaHelper.h
  75. 1259 1188
      assimplib.mod/assimp/code/ColladaLoader.cpp
  76. 181 171
      assimplib.mod/assimp/code/ColladaLoader.h
  77. 1316 1253
      assimplib.mod/assimp/code/ColladaParser.cpp
  78. 337 325
      assimplib.mod/assimp/code/ColladaParser.h
  79. 399 399
      assimplib.mod/assimp/code/ComputeUVMappingProcess.cpp
  80. 85 82
      assimplib.mod/assimp/code/ComputeUVMappingProcess.h
  81. 180 167
      assimplib.mod/assimp/code/ConvertToLHProcess.cpp
  82. 70 68
      assimplib.mod/assimp/code/ConvertToLHProcess.h
  83. 129 126
      assimplib.mod/assimp/code/DXFHelper.h
  84. 570 566
      assimplib.mod/assimp/code/DXFLoader.cpp
  85. 76 76
      assimplib.mod/assimp/code/DXFLoader.h
  86. 372 371
      assimplib.mod/assimp/code/DeboneProcess.cpp
  87. 63 63
      assimplib.mod/assimp/code/DeboneProcess.h
  88. 61 60
      assimplib.mod/assimp/code/DefaultIOStream.cpp
  89. 66 57
      assimplib.mod/assimp/code/DefaultIOStream.h
  90. 93 60
      assimplib.mod/assimp/code/DefaultIOSystem.cpp
  91. 44 29
      assimplib.mod/assimp/code/DefaultIOSystem.h
  92. 243 243
      assimplib.mod/assimp/code/DefaultLogger.cpp
  93. 18 18
      assimplib.mod/assimp/code/DefaultProgressHandler.h
  94. 49 0
      assimplib.mod/assimp/code/Defines.h
  95. 47 46
      assimplib.mod/assimp/code/Exceptional.h
  96. 413 266
      assimplib.mod/assimp/code/Exporter.cpp
  97. 196 196
      assimplib.mod/assimp/code/FBXAnimation.cpp
  98. 266 261
      assimplib.mod/assimp/code/FBXBinaryTokenizer.cpp
  99. 22 22
      assimplib.mod/assimp/code/FBXCompileConfig.h
  100. 2930 2837
      assimplib.mod/assimp/code/FBXConverter.cpp

+ 157 - 116
assimplib.mod/assimp/CHANGES

@@ -1,116 +1,157 @@
-----------------------------------------------------------------------
-CHANGELOG
-----------------------------------------------------------------------
-
-
-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
+----------------------------------------------------------------------
+
+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.

+ 342 - 0
assimplib.mod/assimp/CMakeLists.txt

@@ -0,0 +1,342 @@
+set(CMAKE_LEGACY_CYGWIN_WIN32 0) # Remove when CMake >= 2.8.4 is required
+cmake_minimum_required( VERSION 2.8 )
+PROJECT( Assimp )
+
+option(BUILD_SHARED_LIBS "Build package with shared libraries." ON)
+if(NOT BUILD_SHARED_LIBS)
+  #set(CMAKE_EXE_LINKER_FLAGS "-static")
+  set(LINK_SEARCH_START_STATIC TRUE)
+endif(NOT BUILD_SHARED_LIBS)
+
+# Define here the needed parameters
+set (ASSIMP_VERSION_MAJOR 3)
+set (ASSIMP_VERSION_MINOR 2)
+set (ASSIMP_VERSION_PATCH 0) # subversion revision?
+set (ASSIMP_VERSION ${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH})
+set (ASSIMP_SOVERSION 3)
+set (PROJECT_VERSION "${ASSIMP_VERSION}")
+
+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 )
+
+# Get the current working branch
+execute_process(
+  COMMAND git rev-parse --abbrev-ref HEAD
+  WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+  OUTPUT_VARIABLE GIT_BRANCH
+  OUTPUT_STRIP_TRAILING_WHITESPACE
+  ERROR_QUIET
+)
+
+# Get the latest abbreviated commit hash of the working branch
+execute_process(
+  COMMAND git log -1 --format=%h
+  WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
+  OUTPUT_VARIABLE GIT_COMMIT_HASH
+  OUTPUT_STRIP_TRAILING_WHITESPACE
+  ERROR_QUIET
+)
+
+if(NOT GIT_COMMIT_HASH)
+  set(GIT_COMMIT_HASH 0)
+endif(NOT GIT_COMMIT_HASH)
+
+configure_file(
+  ${CMAKE_CURRENT_SOURCE_DIR}/revision.h.in
+  ${CMAKE_CURRENT_BINARY_DIR}/revision.h
+)
+
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
+
+option(ASSIMP_OPT_BUILD_PACKAGES "Set to ON to generate CPack configuration files and packaging targets" OFF)
+set(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")
+
+option(ASSIMP_ANDROID_JNIIOSYSTEM "Android JNI IOSystem support is active" OFF)
+
+# Workaround to be able to deal with compiler bug "Too many sections" with mingw.
+if( CMAKE_COMPILER_IS_MINGW )
+  ADD_DEFINITIONS(-DASSIMP_BUILD_NO_IFC_IMPORTER )
+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")
+  endif()
+  # hide all not-exported symbols
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -Wall" )
+elseif(MSVC)
+  # enable multi-core compilation with MSVC
+  add_definitions(/MP)
+endif()
+
+INCLUDE (FindPkgConfig)
+INCLUDE_DIRECTORIES( include )
+
+INCLUDE (PrecompiledHeader)
+
+# If this is an in-source build (CMAKE_SOURCE_DIR == CMAKE_BINARY_DIR),
+# write the library/executable files to the respective directories in the
+# source tree. During an out-of-source build, however, do not litter this
+# directory, since that is probably what the user wanted to avoid.
+IF ( CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR )
+  SET( CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/lib" )
+  SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/lib" )
+  SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/bin" )
+ENDIF ( CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR )
+
+# Cache these to allow the user to override them manually.
+SET( ASSIMP_LIB_INSTALL_DIR "lib" CACHE PATH
+  "Path the built library files are installed to." )
+SET( ASSIMP_INCLUDE_INSTALL_DIR "include" CACHE PATH
+  "Path the header files are installed to." )
+SET( ASSIMP_BIN_INSTALL_DIR "bin" CACHE PATH
+  "Path the tool executables are installed to." )
+
+IF (CMAKE_BUILD_TYPE STREQUAL "Release")
+  SET(CMAKE_DEBUG_POSTFIX "" CACHE STRING "Debug Postfix for lib, samples and tools")
+ELSE()
+  SET(CMAKE_DEBUG_POSTFIX "d" CACHE STRING "Debug Postfix for lib, samples and tools")
+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)
+  add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
+ENDIF()
+
+# Globally enable Boost resp. the Boost workaround – it is also needed by the
+# tools which include the Assimp headers.
+option ( ASSIMP_ENABLE_BOOST_WORKAROUND
+  "If a simple implementation of the used Boost functions is used. Slightly reduces functionality, but enables builds without Boost available."
+  ON
+)
+IF ( ASSIMP_ENABLE_BOOST_WORKAROUND )
+  INCLUDE_DIRECTORIES( code/BoostWorkaround )
+  ADD_DEFINITIONS( -DASSIMP_BUILD_BOOST_WORKAROUND )
+  MESSAGE( STATUS "Building a non-boost version of Assimp." )
+ELSE ( ASSIMP_ENABLE_BOOST_WORKAROUND )
+  SET( Boost_DETAILED_FAILURE_MSG ON )
+  IF ( NOT Boost_ADDITIONAL_VERSIONS )
+    SET( Boost_ADDITIONAL_VERSIONS "1.47" "1.47.0" "1.48.0" "1.48" "1.49" "1.49.0" "1.50" "1.50.0" "1.51" "1.51.0" "1.52.0" "1.53.0" "1.54.0" "1.55" "1.55.0" "1.56" "1.56.0" "1.57" "1.57.0" "1.58" "1.58.0" "1.59" "1.59.0")
+  ENDIF ( NOT Boost_ADDITIONAL_VERSIONS )
+  FIND_PACKAGE( Boost )
+  IF ( NOT Boost_FOUND )
+    MESSAGE( FATAL_ERROR
+      "Boost libraries (http://www.boost.org/) not found. "
+      "You can build a non-boost version of Assimp with slightly reduced "
+      "functionality by specifying -DASSIMP_ENABLE_BOOST_WORKAROUND=ON."
+    )
+  ENDIF ( NOT Boost_FOUND )
+
+  INCLUDE_DIRECTORIES( ${Boost_INCLUDE_DIRS} )
+ENDIF ( ASSIMP_ENABLE_BOOST_WORKAROUND )
+
+# 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)
+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 )
+
+option ( ASSIMP_NO_EXPORT
+  "Disable Assimp's export functionality."
+  OFF
+)
+
+if( CMAKE_COMPILER_IS_GNUCXX )
+  set(LIBSTDC++_LIBRARIES -lstdc++)
+endif( CMAKE_COMPILER_IS_GNUCXX )
+
+# Search for external dependencies, and build them from source if not found
+# Search for zlib
+find_package(ZLIB)
+if( NOT ZLIB_FOUND )
+  message(STATUS "compiling zlib from souces")
+  include(CheckIncludeFile)
+  include(CheckTypeSize)
+  include(CheckFunctionExists)
+  # compile from sources
+  add_subdirectory(contrib/zlib)
+  set(ZLIB_FOUND 1)
+  set(ZLIB_LIBRARIES zlibstatic)
+  set(ZLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/contrib/zlib ${CMAKE_CURRENT_BINARY_DIR}/contrib/zlib)
+else(NOT ZLIB_FOUND)
+  ADD_DEFINITIONS(-DASSIMP_BUILD_NO_OWN_ZLIB)
+  set(ZLIB_LIBRARIES_LINKED -lz)
+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)
+
+IF ( ASSIMP_NO_EXPORT )
+  ADD_DEFINITIONS( -DASSIMP_BUILD_NO_EXPORT)
+  MESSAGE( STATUS "Build an import-only version of Assimp." )
+ENDIF( ASSIMP_NO_EXPORT )
+
+SET ( ASSIMP_BUILD_ARCHITECTURE "" CACHE STRING
+  "describe the current architecture."
+)
+IF    ( ASSIMP_BUILD_ARCHITECTURE STREQUAL "")
+ELSE  ( ASSIMP_BUILD_ARCHITECTURE STREQUAL "")
+  ADD_DEFINITIONS ( -D'ASSIMP_BUILD_ARCHITECTURE="${ASSIMP_BUILD_ARCHITECTURE}"' )
+ENDIF ( ASSIMP_BUILD_ARCHITECTURE STREQUAL "")
+
+# ${CMAKE_GENERATOR}
+SET ( ASSIMP_BUILD_COMPILER "" CACHE STRING
+  "describe the current compiler."
+)
+IF    ( ASSIMP_BUILD_COMPILER STREQUAL "")
+ELSE  ( ASSIMP_BUILD_COMPILER STREQUAL "")
+  ADD_DEFINITIONS ( -D'ASSIMP_BUILD_COMPILER="${ASSIMP_BUILD_COMPILER}"' )
+ENDIF ( ASSIMP_BUILD_COMPILER STREQUAL "")
+
+MARK_AS_ADVANCED ( ASSIMP_BUILD_ARCHITECTURE ASSIMP_BUILD_COMPILER )
+
+
+SET ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER OFF CACHE BOOL
+  "Build the C4D importer, which relies on the non-free Melange SDK." 
+)
+
+IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
+  IF ( MSVC )
+    SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Melange/_melange/includes")
+
+    # pick the correct prebuilt library
+    IF(MSVC11)
+      SET(C4D_LIB_POSTFIX "_2012md")
+    ELSEIF(MSVC10)
+      SET(C4D_LIB_POSTFIX "_2010md")
+    ELSEIF(MSVC90)
+      SET(C4D_LIB_POSTFIX "_2008md")
+    ELSE()
+      MESSAGE( FATAL_ERROR 
+        "C4D is currently only supported with MSVC 9, 10, 11"
+      )
+    ENDIF()
+      
+    IF(CMAKE_CL_64)
+      SET(C4D_LIB_ARCH_POSTFIX "_x64")
+    ELSE()
+      SET(C4D_LIB_ARCH_POSTFIX "")
+    ENDIF()
+    
+    SET(C4D_LIB_BASE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Melange/_melange/lib/WIN")
+    
+    SET(C4D_DEBUG_LIBRARY "${C4D_LIB_BASE_PATH}/debug/_melange_lib${C4D_LIB_ARCH_POSTFIX}${C4D_LIB_POSTFIX}.lib")
+    SET(C4D_RELEASE_LIBRARY "${C4D_LIB_BASE_PATH}/release/_melange_lib${C4D_LIB_ARCH_POSTFIX}${C4D_LIB_POSTFIX}.lib")
+    
+    # winsock and winmm are necessary dependencies of melange (this is undocumented, but true.)
+    SET(C4D_EXTRA_LIBRARIES WSock32.lib Winmm.lib)
+  ELSE ()
+    MESSAGE( FATAL_ERROR 
+      "C4D is currently only available on Windows with melange SDK installed in contrib/Melange"
+    )
+  ENDIF ( MSVC )
+else (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
+  ADD_DEFINITIONS( -DASSIMP_BUILD_NO_C4D_IMPORTER )
+ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
+
+
+
+ADD_SUBDIRECTORY( code/ )
+option ( ASSIMP_BUILD_ASSIMP_TOOLS
+  "If the supplementary tools for Assimp are built in addition to the library."
+  ON
+)
+IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
+  IF ( WIN32 AND DirectX_FOUND )
+    ADD_SUBDIRECTORY( tools/assimp_view/ )
+  ENDIF ( WIN32 AND DirectX_FOUND )
+  ADD_SUBDIRECTORY( tools/assimp_cmd/ )
+ENDIF ( ASSIMP_BUILD_ASSIMP_TOOLS )
+
+option ( ASSIMP_BUILD_SAMPLES
+  "If the official samples are built as well (needs Glut)."
+  OFF
+)
+
+IF ( ASSIMP_BUILD_SAMPLES)
+  IF ( WIN32 )
+    ADD_SUBDIRECTORY( samples/SimpleTexturedOpenGL/ )
+  ENDIF ( WIN32 )
+  ADD_SUBDIRECTORY( samples/SimpleOpenGL/ )
+ENDIF ( ASSIMP_BUILD_SAMPLES )
+
+option ( ASSIMP_BUILD_TESTS
+  "If the test suite for Assimp is built in addition to the library."
+  ON
+)
+
+IF ( ASSIMP_BUILD_TESTS )
+  ADD_SUBDIRECTORY( test/ )
+ENDIF ( ASSIMP_BUILD_TESTS )
+
+IF(MSVC)
+  option ( ASSIMP_INSTALL_PDB
+    "Install MSVC debug files."
+    ON
+  )
+ENDIF(MSVC)
+
+# Generate a pkg-config .pc for the Assimp library.
+CONFIGURE_FILE( "${PROJECT_SOURCE_DIR}/assimp.pc.in" "${PROJECT_BINARY_DIR}/assimp.pc" @ONLY )
+INSTALL( FILES "${PROJECT_BINARY_DIR}/assimp.pc" DESTINATION ${ASSIMP_LIB_INSTALL_DIR}/pkgconfig/ COMPONENT ${LIBASSIMP-DEV_COMPONENT})
+
+if(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES)
+  # Packing information
+  set(CPACK_PACKAGE_NAME                    "assimp{ASSIMP_VERSION_MAJOR}")
+  set(CPACK_PACKAGE_CONTACT "" CACHE STRING "Package maintainer and PGP signer.")
+  set(CPACK_PACKAGE_VENDOR                  "http://assimp.sourceforge.net/")
+  set(CPACK_PACKAGE_DISPLAY_NAME            "Assimp ${ASSIMP_VERSION}")
+  set(CPACK_PACKAGE_DESCRIPTION_SUMMARY     " - Open Asset Import Library ${ASSIMP_VERSION}")
+  set(CPACK_PACKAGE_VERSION                 "${ASSIMP_VERSION}.${ASSIMP_PACKAGE_VERSION}" )
+  set(CPACK_PACKAGE_VERSION_MAJOR           "${ASSIMP_VERSION_MAJOR}")
+  set(CPACK_PACKAGE_VERSION_MINOR           "${ASSIMP_VERSION_MINOR}")
+  set(CPACK_PACKAGE_VERSION_PATCH           "${ASSIMP_VERSION_PATCH}")
+  set(CPACK_PACKAGE_INSTALL_DIRECTORY       "assimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}")
+  set(CPACK_RESOURCE_FILE_LICENSE           "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
+
+  string(TOUPPER ${LIBASSIMP_COMPONENT}     "LIBASSIMP_COMPONENT_UPPER")
+  string(TOUPPER ${LIBASSIMP-DEV_COMPONENT} "LIBASSIMP-DEV_COMPONENT_UPPER")
+
+  set(CPACK_COMPONENT_ASSIMP-BIN_DISPLAY_NAME                       "tools")
+  set(CPACK_COMPONENT_ASSIMP-BIN_DEPENDS                            "${LIBASSIMP_COMPONENT}" )
+  set(CPACK_COMPONENT_${LIBASSIMP_COMPONENT_UPPER}_DISPLAY_NAME     "libraries")
+  set(CPACK_COMPONENT_${LIBASSIMP-DEV_COMPONENT_UPPER}_DISPLAY_NAME "common headers and installs")
+  set(CPACK_COMPONENT_${LIBASSIMP-DEV_COMPONENT_UPPER}_DEPENDS $    "{LIBASSIMP_COMPONENT}" )
+  set(CPACK_COMPONENT_ASSIMP-DEV_DISPLAY_NAME                       "${CPACK_COMPONENT_${LIBASSIMP-DEV_COMPONENT}_DISPLAY_NAME}" )
+  set(CPACK_COMPONENT_ASSIMP-DEV_DEPENDS                            "${LIBASSIMP-DEV_COMPONENT}" )
+  set(CPACK_DEBIAN_BUILD_DEPENDS debhelper cmake libboost-dev libboost-thread-dev libboost-math-dev zlib1g-dev pkg-config)
+
+  # debian
+  set(CPACK_DEBIAN_PACKAGE_PRIORITY "optional")
+  set(CPACK_DEBIAN_CMAKE_OPTIONS    "-DBUILD_ASSIMP_SAMPLES:BOOL=${ASSIMP_BUILD_SAMPLES}")
+  set(CPACK_DEBIAN_PACKAGE_SECTION  "libs" )
+  set(CPACK_DEBIAN_PACKAGE_DEPENDS  "${CPACK_COMPONENTS_ALL}")
+  set(CPACK_DEBIAN_PACKAGE_SUGGESTS)
+  set(CPACK_DEBIAN_PACKAGE_NAME     "assimp")
+  set(CPACK_DEBIAN_PACKAGE_REMOVE_SOURCE_FILES contrib/cppunit-1.12.1 contrib/cppunit_note.txt contrib/zlib workspaces test doc obj samples packaging)
+  set(CPACK_DEBIAN_PACKAGE_SOURCE_COPY svn export --force)
+  set(CPACK_DEBIAN_CHANGELOG)
+  execute_process(COMMAND lsb_release -is
+    OUTPUT_VARIABLE _lsb_distribution OUTPUT_STRIP_TRAILING_WHITESPACE
+    RESULT_VARIABLE _lsb_release_failed)
+  set(CPACK_DEBIAN_DISTRIBUTION_NAME ${_lsb_distribution} CACHE STRING "Name of the distrubiton")
+  string(TOLOWER ${CPACK_DEBIAN_DISTRIBUTION_NAME} CPACK_DEBIAN_DISTRIBUTION_NAME)
+  if( ${CPACK_DEBIAN_DISTRIBUTION_NAME} STREQUAL "ubuntu" )
+    set(CPACK_DEBIAN_DISTRIBUTION_RELEASES lucid maverick natty oneiric precise CACHE STRING "Release code-names of the distrubiton release")
+  endif()
+  set(DPUT_HOST "" CACHE STRING "PPA repository to upload the debian sources")
+  include(CPack)
+  include(DebSourcePPA)
+endif()

+ 160 - 150
assimplib.mod/assimp/CREDITS

@@ -1,150 +1,160 @@
-===============================================================
-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 (Admin and Design).
-
-- Thomas Schulze,
-X-, Collada-, BVH-Loader, Postprocessing framework. Data structure & Interface design, documentation.
-
-- Kim Kulling,
-Obj-Loader, Logging system, Scons-build environment, CMake build environment, Linux build.
-
-- 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 enviroment 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 improvments 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
+===============================================================
+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 (Admin and Design).
+
+- Thomas Schulze,
+X-, Collada-, BVH-Loader, Postprocessing framework. Data structure & Interface design, documentation.
+
+- Kim Kulling,
+Obj-Loader, Logging system, Scons-build environment, CMake build environment, Linux build.
+
+- 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 enviroment 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 improvments 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
+
+

+ 84 - 84
assimplib.mod/assimp/LICENSE

@@ -1,84 +1,84 @@
-Open Asset Import Library (assimp)
-
-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.
-
-
-
-******************************************************************************
-
-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-2015, 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.
+
+
+
+
+
+

+ 134 - 120
assimplib.mod/assimp/Readme.md

@@ -1,120 +1,134 @@
-Open Asset Import Library (assimp) 
-========
-
-Open Asset Import Library is a Open Source library designed to load various __3d file formats and convert them into a shared, in-memory format__. It supports more than __30 file formats__ for import and a growing selection of file formats for export. Additionally, assimp features various __post processing tools__ to refine the imported data: _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 of assimp 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. According to [Travis-CI] (https://travis-ci.org/), the current build status of the trunk is [![Build Status](https://travis-ci.org/assimp/assimp.png)](https://travis-ci.org/assimp/assimp)
-
-#### Supported file formats ####
-
-The library provides importers for a lot of file formats, including:
-
-- 3DS
-- BLEND (Blender 3D)
-- DAE/Collada
-- FBX
-- IFC-STEP 
-- ASE
-- DXF
-- HMP
-- MD2
-- MD3 
-- MD5
-- MDC
-- MDL
-- NFF
-- PLY
-- STL
-- X 
-- OBJ 
-- SMD
-- LWO 
-- LXO 
-- LWS  
-- TER 
-- AC3D 
-- MS3D 
-- COB
-- Q3BSP
-- XGL
-- CSM
-- BVH
-- B3D
-- NDO
-- Ogre Binary
-- Ogre XML
-- Q3D
- 
-Additionally, the following formats are also supported, but not part of the core library as they depend on proprietary libraries.
-
-- C4D (https://github.com/acgessler/assimp-cinema4d)
-
-Exporters include:
-
-- DAE (Collada)
-- STL
-- OBJ
-- PLY
-- JSON (for WebGl, via https://github.com/acgessler/assimp2json)
-	
-See [the full list here](http://assimp.sourceforge.net/main_features_formats.html).
-
-
-
-#### Repository structure ####
-
-
-Open Asset Import Library is implemented in C++ (but provides both a C and a 
-C++ish interface). The directory structure is:
-
-	/bin		Folder for binaries, only used on Windows
-	/code		Source code
-	/contrib	Third-party libraries
-	/doc		Documentation (doxysource and pre-compiled docs)
-	/include	Public header C and C++ header files
-	/lib		Static library location for Windows
-	/obj		Object file location for Windows
-	/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 (viewer, command line `assimp`)
-	/samples	A small number of samples to illustrate possible 
-                        use cases for Assimp
-	/workspaces	Build enviroments for vc,xcode,... (deprecated,
-			CMake has superseeded all legacy build options!)
-
-
-
-### Building ###
-
-
-Take a look into the `INSTALL` file. Our build system is CMake, if you already used CMake before there is a good chance you know what to do.
-
-
-### 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 documentation doesn't solve your problems, 
-[try our forums at SF.net](http://sourceforge.net/p/assimp/discussion/817654) or ask on
-[StackOverflow](http://stackoverflow.com/questions/tagged/assimp?sort=newest).
-
-For development discussions, there is also a mailing list, _assimp-discussions_
-  [(subscribe here)]( https://lists.sourceforge.net/lists/listinfo/assimp-discussions) 
-
-### 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, which is very liberal. 
-
-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. 
-
+Open Asset Import Library (assimp) 
+========
+
+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.
+
+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:
+
+Linux [![Linux Build Status](https://travis-ci.org/assimp/assimp.png)](https://travis-ci.org/assimp/assimp)
+Windows [![Windows Build Status](https://ci.appveyor.com/api/projects/status/tmo433wax6u6cjp4?svg=true)](https://ci.appveyor.com/project/kimkulling/assimp)
+Coverity<a href="https://scan.coverity.com/projects/5607">
+  <img alt="Coverity Scan Build Status"
+       src="https://scan.coverity.com/projects/5607/badge.svg"/>
+</a>
+
+__[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)
+ 
+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
+	
+### 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.
+
+
+#### 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 enviroments 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) 
+
+And we also have an IRC-channel at freenode: #assetimporterlib . You can easily join us via: [KiwiIRC/freenote](https://kiwiirc.com/client/irc.freenode.net), choose your nickname and type
+> /join #assetimporterlib
+
+### 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 ...

+ 8 - 0
assimplib.mod/assimp/code/.editorconfig

@@ -0,0 +1,8 @@
+# See <http://EditorConfig.org> for details
+
+[*.{h,hpp,c,cpp}]
+end_of_line = lf
+insert_final_newline = true
+trim_trailing_whitespace = true
+indent_size = 4
+indent_style = space

+ 761 - 756
assimplib.mod/assimp/code/3DSConverter.cpp

@@ -3,12 +3,12 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -25,28 +25,33 @@ conditions are met:
   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 
+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 
+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 
+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 
+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 Implementation of the 3ds importer class */
 
-#include "AssimpPCH.h"
+
 #ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
 
 // internal headers
 #include "3DSLoader.h"
 #include "TargetAnimation.h"
+#include "../include/assimp/scene.h"
+#include "../include/assimp/DefaultLogger.hpp"
+#include "StringComparison.h"
+#include <boost/scoped_array.hpp>
+#include <cctype>
 
 using namespace Assimp;
 
@@ -54,808 +59,808 @@ using namespace Assimp;
 // 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;
-	for (unsigned int i = 0; i < mScene->mMaterials.size();++i)
-	{
-		std::string s = mScene->mMaterials[i].mName;
-		for (std::string::iterator it = s.begin(); it != s.end(); ++it)
-			*it = ::tolower(*it);
-
-		if (std::string::npos == s.find("default"))continue;
-
-		if (mScene->mMaterials[i].mDiffuse.r !=
-			mScene->mMaterials[i].mDiffuse.g ||
-			mScene->mMaterials[i].mDiffuse.r !=
-			mScene->mMaterials[i].mDiffuse.b)continue;
-
-		if (mScene->mMaterials[i].sTexDiffuse.mMapName.length()   != 0	||
-			mScene->mMaterials[i].sTexBump.mMapName.length()      != 0	|| 
-			mScene->mMaterials[i].sTexOpacity.mMapName.length()   != 0	||
-			mScene->mMaterials[i].sTexEmissive.mMapName.length()  != 0	||
-			mScene->mMaterials[i].sTexSpecular.mMapName.length()  != 0	||
-			mScene->mMaterials[i].sTexShininess.mMapName.length() != 0 )
-		{
-			continue;
-		}
-		idx = i;
-	}
-	if (0xcdcdcdcd == 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
-	unsigned int cnt = 0;
-	for (std::vector<D3DS::Mesh>::iterator
-		i =  mScene->mMeshes.begin();
-		i != mScene->mMeshes.end();++i)
-	{
-		for (std::vector<unsigned int>::iterator
-			a =  (*i).mFaceMaterials.begin();
-			a != (*i).mFaceMaterials.end();++a)
-		{
-			// NOTE: The additional check seems to be necessary,
-			// some exporters seem to generate invalid data here
-			if (0xcdcdcdcd == (*a))
-			{
-				(*a) = idx;
-				++cnt;
-			}
-			else if ( (*a) >= mScene->mMaterials.size())
-			{
-				(*a) = idx;
-				DefaultLogger::get()->warn("Material index overflow in 3DS file. Using default material");
-				++cnt;
-			}
-		}
-	}
-	if (cnt && idx == mScene->mMaterials.size())
-	{
-		// We need to create our own default material
-		D3DS::Material sMat;
-		sMat.mDiffuse = aiColor3D(0.3f,0.3f,0.3f);
-		sMat.mName = "%%%DEFAULT";
-		mScene->mMaterials.push_back(sMat);
-
-		DefaultLogger::get()->info("3DS: Generating default material");
-	}
+
+    // 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;
+    for (unsigned int i = 0; i < mScene->mMaterials.size();++i)
+    {
+        std::string s = mScene->mMaterials[i].mName;
+        for (std::string::iterator it = s.begin(); it != s.end(); ++it)
+            *it = ::tolower(*it);
+
+        if (std::string::npos == s.find("default"))continue;
+
+        if (mScene->mMaterials[i].mDiffuse.r !=
+            mScene->mMaterials[i].mDiffuse.g ||
+            mScene->mMaterials[i].mDiffuse.r !=
+            mScene->mMaterials[i].mDiffuse.b)continue;
+
+        if (mScene->mMaterials[i].sTexDiffuse.mMapName.length()   != 0  ||
+            mScene->mMaterials[i].sTexBump.mMapName.length()      != 0  ||
+            mScene->mMaterials[i].sTexOpacity.mMapName.length()   != 0  ||
+            mScene->mMaterials[i].sTexEmissive.mMapName.length()  != 0  ||
+            mScene->mMaterials[i].sTexSpecular.mMapName.length()  != 0  ||
+            mScene->mMaterials[i].sTexShininess.mMapName.length() != 0 )
+        {
+            continue;
+        }
+        idx = i;
+    }
+    if (0xcdcdcdcd == 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
+    unsigned int cnt = 0;
+    for (std::vector<D3DS::Mesh>::iterator
+        i =  mScene->mMeshes.begin();
+        i != mScene->mMeshes.end();++i)
+    {
+        for (std::vector<unsigned int>::iterator
+            a =  (*i).mFaceMaterials.begin();
+            a != (*i).mFaceMaterials.end();++a)
+        {
+            // NOTE: The additional check seems to be necessary,
+            // some exporters seem to generate invalid data here
+            if (0xcdcdcdcd == (*a))
+            {
+                (*a) = idx;
+                ++cnt;
+            }
+            else if ( (*a) >= mScene->mMaterials.size())
+            {
+                (*a) = idx;
+                DefaultLogger::get()->warn("Material index overflow in 3DS file. Using default material");
+                ++cnt;
+            }
+        }
+    }
+    if (cnt && idx == mScene->mMaterials.size())
+    {
+        // We need to create our own default material
+        D3DS::Material sMat;
+        sMat.mDiffuse = aiColor3D(0.3f,0.3f,0.3f);
+        sMat.mName = "%%%DEFAULT";
+        mScene->mMaterials.push_back(sMat);
+
+        DefaultLogger::get()->info("3DS: Generating default material");
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 // Check whether all indices are valid. Otherwise we'd crash before the validation step is reached
 void Discreet3DSImporter::CheckIndices(D3DS::Mesh& sMesh)
 {
-	for (std::vector< D3DS::Face >::iterator i =  sMesh.mFaces.begin(); i != sMesh.mFaces.end();++i)
-	{
-		// check whether all indices are in range
-		for (unsigned int a = 0; a < 3;++a)
-		{
-			if ((*i).mIndices[a] >= sMesh.mPositions.size())
-			{
-				DefaultLogger::get()->warn("3DS: Vertex index overflow)");
-				(*i).mIndices[a] = (uint32_t)sMesh.mPositions.size()-1;
-			}
-			if ( !sMesh.mTexCoords.empty() && (*i).mIndices[a] >= sMesh.mTexCoords.size())
-			{
-				DefaultLogger::get()->warn("3DS: Texture coordinate index overflow)");
-				(*i).mIndices[a] = (uint32_t)sMesh.mTexCoords.size()-1;
-			}
-		}
-	}
+    for (std::vector< D3DS::Face >::iterator i =  sMesh.mFaces.begin(); i != sMesh.mFaces.end();++i)
+    {
+        // check whether all indices are in range
+        for (unsigned int a = 0; a < 3;++a)
+        {
+            if ((*i).mIndices[a] >= sMesh.mPositions.size())
+            {
+                DefaultLogger::get()->warn("3DS: Vertex index overflow)");
+                (*i).mIndices[a] = (uint32_t)sMesh.mPositions.size()-1;
+            }
+            if ( !sMesh.mTexCoords.empty() && (*i).mIndices[a] >= sMesh.mTexCoords.size())
+            {
+                DefaultLogger::get()->warn("3DS: Texture coordinate index overflow)");
+                (*i).mIndices[a] = (uint32_t)sMesh.mTexCoords.size()-1;
+            }
+        }
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 // Generate out unique verbose format representation
 void Discreet3DSImporter::MakeUnique(D3DS::Mesh& sMesh)
 {
-	// TODO: really necessary? I don't think. Just a waste of memory and time
-	// to do it now in a separate buffer. 
-
-	// Allocate output storage
-	std::vector<aiVector3D> vNew  (sMesh.mFaces.size() * 3);
-	std::vector<aiVector3D> vNew2;
-	if (sMesh.mTexCoords.size())
-		vNew2.resize(sMesh.mFaces.size() * 3);
-
-	for (unsigned int i = 0, base = 0; i < sMesh.mFaces.size();++i)
-	{
-		D3DS::Face& face = sMesh.mFaces[i];
-
-		// Positions
-		for (unsigned int a = 0; a < 3;++a,++base)
-		{
-			vNew[base] = sMesh.mPositions[face.mIndices[a]];
-			if (sMesh.mTexCoords.size())
-				vNew2[base] = sMesh.mTexCoords[face.mIndices[a]];
-
-			face.mIndices[a] = base;
-		}
-	}
-	sMesh.mPositions = vNew;
-	sMesh.mTexCoords = vNew2;
+    // TODO: really necessary? I don't think. Just a waste of memory and time
+    // to do it now in a separate buffer.
+
+    // Allocate output storage
+    std::vector<aiVector3D> vNew  (sMesh.mFaces.size() * 3);
+    std::vector<aiVector3D> vNew2;
+    if (sMesh.mTexCoords.size())
+        vNew2.resize(sMesh.mFaces.size() * 3);
+
+    for (unsigned int i = 0, base = 0; i < sMesh.mFaces.size();++i)
+    {
+        D3DS::Face& face = sMesh.mFaces[i];
+
+        // Positions
+        for (unsigned int a = 0; a < 3;++a,++base)
+        {
+            vNew[base] = sMesh.mPositions[face.mIndices[a]];
+            if (sMesh.mTexCoords.size())
+                vNew2[base] = sMesh.mTexCoords[face.mIndices[a]];
+
+            face.mIndices[a] = base;
+        }
+    }
+    sMesh.mPositions = vNew;
+    sMesh.mTexCoords = vNew2;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Convert a 3DS texture to texture keys in an aiMaterial
 void CopyTexture(aiMaterial& mat, D3DS::Texture& texture, aiTextureType type)
 {
-	// Setup the texture name
-	aiString tex;
-	tex.Set( texture.mMapName);
-	mat.AddProperty( &tex, AI_MATKEY_TEXTURE(type,0));
-
-	// Setup the texture blend factor
-	if (is_not_qnan(texture.mTextureBlend))
-		mat.AddProperty<float>( &texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type,0));
-
-	// Setup the texture mapping mode
-	mat.AddProperty<int>((int*)&texture.mMapMode,1,AI_MATKEY_MAPPINGMODE_U(type,0));
-	mat.AddProperty<int>((int*)&texture.mMapMode,1,AI_MATKEY_MAPPINGMODE_V(type,0));
-
-	// Mirroring - double the scaling values 
-	// FIXME: this is not really correct ...
-	if (texture.mMapMode == aiTextureMapMode_Mirror)
-	{
-		texture.mScaleU *= 2.f;
-		texture.mScaleV *= 2.f;
-		texture.mOffsetU /= 2.f;
-		texture.mOffsetV /= 2.f;
-	}
-	
-	// Setup texture UV transformations
-	mat.AddProperty<float>(&texture.mOffsetU,5,AI_MATKEY_UVTRANSFORM(type,0));
+    // Setup the texture name
+    aiString tex;
+    tex.Set( texture.mMapName);
+    mat.AddProperty( &tex, AI_MATKEY_TEXTURE(type,0));
+
+    // Setup the texture blend factor
+    if (is_not_qnan(texture.mTextureBlend))
+        mat.AddProperty<float>( &texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type,0));
+
+    // Setup the texture mapping mode
+    mat.AddProperty<int>((int*)&texture.mMapMode,1,AI_MATKEY_MAPPINGMODE_U(type,0));
+    mat.AddProperty<int>((int*)&texture.mMapMode,1,AI_MATKEY_MAPPINGMODE_V(type,0));
+
+    // Mirroring - double the scaling values
+    // FIXME: this is not really correct ...
+    if (texture.mMapMode == aiTextureMapMode_Mirror)
+    {
+        texture.mScaleU *= 2.f;
+        texture.mScaleV *= 2.f;
+        texture.mOffsetU /= 2.f;
+        texture.mOffsetV /= 2.f;
+    }
+
+    // Setup texture UV transformations
+    mat.AddProperty<float>(&texture.mOffsetU,5,AI_MATKEY_UVTRANSFORM(type,0));
 }
 
 // ------------------------------------------------------------------------------------------------
 // Convert a 3DS material to an aiMaterial
 void Discreet3DSImporter::ConvertMaterial(D3DS::Material& oldMat,
-	aiMaterial& mat)
+    aiMaterial& mat)
 {
-	// NOTE: Pass the background image to the viewer by bypassing the
-	// material system. This is an evil hack, never do it again!
-	if (0 != mBackgroundImage.length() && bHasBG)
-	{
-		aiString tex;
-		tex.Set( mBackgroundImage);
-		mat.AddProperty( &tex, AI_MATKEY_GLOBAL_BACKGROUND_IMAGE);
-
-		// Be sure this is only done for the first material
-		mBackgroundImage = std::string("");
-	}
-
-	// At first add the base ambient color of the scene to the material
-	oldMat.mAmbient.r += mClrAmbient.r;
-	oldMat.mAmbient.g += mClrAmbient.g;
-	oldMat.mAmbient.b += mClrAmbient.b;
-
-	aiString name;
-	name.Set( oldMat.mName);
-	mat.AddProperty( &name, AI_MATKEY_NAME);
-
-	// Material colors
-	mat.AddProperty( &oldMat.mAmbient, 1, AI_MATKEY_COLOR_AMBIENT);
-	mat.AddProperty( &oldMat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
-	mat.AddProperty( &oldMat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR);
-	mat.AddProperty( &oldMat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE);
-
-	// Phong shininess and shininess strength
-	if (D3DS::Discreet3DS::Phong == oldMat.mShading || 
-		D3DS::Discreet3DS::Metal == oldMat.mShading)
-	{
-		if (!oldMat.mSpecularExponent || !oldMat.mShininessStrength)
-		{
-			oldMat.mShading = D3DS::Discreet3DS::Gouraud;
-		}
-		else
-		{
-			mat.AddProperty( &oldMat.mSpecularExponent, 1, AI_MATKEY_SHININESS);
-			mat.AddProperty( &oldMat.mShininessStrength, 1, AI_MATKEY_SHININESS_STRENGTH);
-		}
-	}
-
-	// Opacity
-	mat.AddProperty<float>( &oldMat.mTransparency,1,AI_MATKEY_OPACITY);
-
-	// Bump height scaling
-	mat.AddProperty<float>( &oldMat.mBumpHeight,1,AI_MATKEY_BUMPSCALING);
-
-	// Two sided rendering?
-	if (oldMat.mTwoSided)
-	{
-		int i = 1;
-		mat.AddProperty<int>(&i,1,AI_MATKEY_TWOSIDED);
-	}
-
-	// Shading mode
-	aiShadingMode eShading = aiShadingMode_NoShading;
-	switch (oldMat.mShading)
-	{
-		case D3DS::Discreet3DS::Flat:
-			eShading = aiShadingMode_Flat; break;
-
-		// I don't know what "Wire" shading should be,
-		// assume it is simple lambertian diffuse shading
-		case D3DS::Discreet3DS::Wire:
-			{
-				// Set the wireframe flag
-				unsigned int iWire = 1;
-				mat.AddProperty<int>( (int*)&iWire,1,AI_MATKEY_ENABLE_WIREFRAME);
-			}
-
-		case D3DS::Discreet3DS::Gouraud:
-			eShading = aiShadingMode_Gouraud; break;
-
-		// assume cook-torrance shading for metals.
-		case D3DS::Discreet3DS::Phong :
-			eShading = aiShadingMode_Phong; break;
-
-		case D3DS::Discreet3DS::Metal :
-			eShading = aiShadingMode_CookTorrance; break;
-
-			// FIX to workaround a warning with GCC 4 who complained
-			// about a missing case Blinn: here - Blinn isn't a valid
-			// value in the 3DS Loader, it is just needed for ASE
-		case D3DS::Discreet3DS::Blinn :
-			eShading = aiShadingMode_Blinn; break;
-	}
-	mat.AddProperty<int>( (int*)&eShading,1,AI_MATKEY_SHADING_MODEL);
-
-	// DIFFUSE texture
-	if( oldMat.sTexDiffuse.mMapName.length() > 0)
-		CopyTexture(mat,oldMat.sTexDiffuse, aiTextureType_DIFFUSE);
-
-	// SPECULAR texture
-	if( oldMat.sTexSpecular.mMapName.length() > 0)
-		CopyTexture(mat,oldMat.sTexSpecular, aiTextureType_SPECULAR);
-
-	// OPACITY texture
-	if( oldMat.sTexOpacity.mMapName.length() > 0)
-		CopyTexture(mat,oldMat.sTexOpacity, aiTextureType_OPACITY);
-
-	// EMISSIVE texture
-	if( oldMat.sTexEmissive.mMapName.length() > 0)
-		CopyTexture(mat,oldMat.sTexEmissive, aiTextureType_EMISSIVE);
-
-	// BUMP texture
-	if( oldMat.sTexBump.mMapName.length() > 0)
-		CopyTexture(mat,oldMat.sTexBump, aiTextureType_HEIGHT);
-
-	// SHININESS texture
-	if( oldMat.sTexShininess.mMapName.length() > 0)
-		CopyTexture(mat,oldMat.sTexShininess, aiTextureType_SHININESS);
-
-	// REFLECTION texture
-	if( oldMat.sTexReflective.mMapName.length() > 0)
-		CopyTexture(mat,oldMat.sTexReflective, aiTextureType_REFLECTION);
-
-	// Store the name of the material itself, too
-	if( oldMat.mName.length())	{
-		aiString tex;
-		tex.Set( oldMat.mName);
-		mat.AddProperty( &tex, AI_MATKEY_NAME);
-	}
+    // NOTE: Pass the background image to the viewer by bypassing the
+    // material system. This is an evil hack, never do it again!
+    if (0 != mBackgroundImage.length() && bHasBG)
+    {
+        aiString tex;
+        tex.Set( mBackgroundImage);
+        mat.AddProperty( &tex, AI_MATKEY_GLOBAL_BACKGROUND_IMAGE);
+
+        // Be sure this is only done for the first material
+        mBackgroundImage = std::string("");
+    }
+
+    // At first add the base ambient color of the scene to the material
+    oldMat.mAmbient.r += mClrAmbient.r;
+    oldMat.mAmbient.g += mClrAmbient.g;
+    oldMat.mAmbient.b += mClrAmbient.b;
+
+    aiString name;
+    name.Set( oldMat.mName);
+    mat.AddProperty( &name, AI_MATKEY_NAME);
+
+    // Material colors
+    mat.AddProperty( &oldMat.mAmbient, 1, AI_MATKEY_COLOR_AMBIENT);
+    mat.AddProperty( &oldMat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
+    mat.AddProperty( &oldMat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR);
+    mat.AddProperty( &oldMat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE);
+
+    // Phong shininess and shininess strength
+    if (D3DS::Discreet3DS::Phong == oldMat.mShading ||
+        D3DS::Discreet3DS::Metal == oldMat.mShading)
+    {
+        if (!oldMat.mSpecularExponent || !oldMat.mShininessStrength)
+        {
+            oldMat.mShading = D3DS::Discreet3DS::Gouraud;
+        }
+        else
+        {
+            mat.AddProperty( &oldMat.mSpecularExponent, 1, AI_MATKEY_SHININESS);
+            mat.AddProperty( &oldMat.mShininessStrength, 1, AI_MATKEY_SHININESS_STRENGTH);
+        }
+    }
+
+    // Opacity
+    mat.AddProperty<float>( &oldMat.mTransparency,1,AI_MATKEY_OPACITY);
+
+    // Bump height scaling
+    mat.AddProperty<float>( &oldMat.mBumpHeight,1,AI_MATKEY_BUMPSCALING);
+
+    // Two sided rendering?
+    if (oldMat.mTwoSided)
+    {
+        int i = 1;
+        mat.AddProperty<int>(&i,1,AI_MATKEY_TWOSIDED);
+    }
+
+    // Shading mode
+    aiShadingMode eShading = aiShadingMode_NoShading;
+    switch (oldMat.mShading)
+    {
+        case D3DS::Discreet3DS::Flat:
+            eShading = aiShadingMode_Flat; break;
+
+        // I don't know what "Wire" shading should be,
+        // assume it is simple lambertian diffuse shading
+        case D3DS::Discreet3DS::Wire:
+            {
+                // Set the wireframe flag
+                unsigned int iWire = 1;
+                mat.AddProperty<int>( (int*)&iWire,1,AI_MATKEY_ENABLE_WIREFRAME);
+            }
+
+        case D3DS::Discreet3DS::Gouraud:
+            eShading = aiShadingMode_Gouraud; break;
+
+        // assume cook-torrance shading for metals.
+        case D3DS::Discreet3DS::Phong :
+            eShading = aiShadingMode_Phong; break;
+
+        case D3DS::Discreet3DS::Metal :
+            eShading = aiShadingMode_CookTorrance; break;
+
+            // FIX to workaround a warning with GCC 4 who complained
+            // about a missing case Blinn: here - Blinn isn't a valid
+            // value in the 3DS Loader, it is just needed for ASE
+        case D3DS::Discreet3DS::Blinn :
+            eShading = aiShadingMode_Blinn; break;
+    }
+    mat.AddProperty<int>( (int*)&eShading,1,AI_MATKEY_SHADING_MODEL);
+
+    // DIFFUSE texture
+    if( oldMat.sTexDiffuse.mMapName.length() > 0)
+        CopyTexture(mat,oldMat.sTexDiffuse, aiTextureType_DIFFUSE);
+
+    // SPECULAR texture
+    if( oldMat.sTexSpecular.mMapName.length() > 0)
+        CopyTexture(mat,oldMat.sTexSpecular, aiTextureType_SPECULAR);
+
+    // OPACITY texture
+    if( oldMat.sTexOpacity.mMapName.length() > 0)
+        CopyTexture(mat,oldMat.sTexOpacity, aiTextureType_OPACITY);
+
+    // EMISSIVE texture
+    if( oldMat.sTexEmissive.mMapName.length() > 0)
+        CopyTexture(mat,oldMat.sTexEmissive, aiTextureType_EMISSIVE);
+
+    // BUMP texture
+    if( oldMat.sTexBump.mMapName.length() > 0)
+        CopyTexture(mat,oldMat.sTexBump, aiTextureType_HEIGHT);
+
+    // SHININESS texture
+    if( oldMat.sTexShininess.mMapName.length() > 0)
+        CopyTexture(mat,oldMat.sTexShininess, aiTextureType_SHININESS);
+
+    // REFLECTION texture
+    if( oldMat.sTexReflective.mMapName.length() > 0)
+        CopyTexture(mat,oldMat.sTexReflective, aiTextureType_REFLECTION);
+
+    // Store the name of the material itself, too
+    if( oldMat.mName.length())  {
+        aiString tex;
+        tex.Set( oldMat.mName);
+        mat.AddProperty( &tex, AI_MATKEY_NAME);
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 // Split meshes by their materials and generate output aiMesh'es
 void Discreet3DSImporter::ConvertMeshes(aiScene* pcOut)
 {
-	std::vector<aiMesh*> avOutMeshes;
-	avOutMeshes.reserve(mScene->mMeshes.size() * 2);
-
-	unsigned int iFaceCnt = 0,num = 0;
-	aiString name;
-
-	// we need to split all meshes by their materials
-	for (std::vector<D3DS::Mesh>::iterator i =  mScene->mMeshes.begin(); i != mScene->mMeshes.end();++i)	{
-		boost::scoped_array< std::vector<unsigned int> > aiSplit(new std::vector<unsigned int>[mScene->mMaterials.size()]);
-
-		name.length = ASSIMP_itoa10(name.data,num++);
-
-		unsigned int iNum = 0;
-		for (std::vector<unsigned int>::const_iterator a =  (*i).mFaceMaterials.begin();
-			a != (*i).mFaceMaterials.end();++a,++iNum)
-		{
-			aiSplit[*a].push_back(iNum);
-		}
-		// now generate submeshes
-		for (unsigned int p = 0; p < mScene->mMaterials.size();++p)
-		{
-			if (aiSplit[p].empty())	{
-				continue;
-			}
-			aiMesh* meshOut = new aiMesh();
-			meshOut->mName = name;
-			meshOut->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
-
-			// be sure to setup the correct material index
-			meshOut->mMaterialIndex = p;
-
-			// use the color data as temporary storage
-			meshOut->mColors[0] = (aiColor4D*)(&*i);
-			avOutMeshes.push_back(meshOut);
-
-			// convert vertices
-			meshOut->mNumFaces = (unsigned int)aiSplit[p].size();
-			meshOut->mNumVertices = meshOut->mNumFaces*3;
-
-			// allocate enough storage for faces
-			meshOut->mFaces = new aiFace[meshOut->mNumFaces];
-			iFaceCnt += meshOut->mNumFaces;
-
-			meshOut->mVertices = new aiVector3D[meshOut->mNumVertices];
-			meshOut->mNormals  = new aiVector3D[meshOut->mNumVertices];
-			if ((*i).mTexCoords.size())
-			{
-				meshOut->mTextureCoords[0] = new aiVector3D[meshOut->mNumVertices];
-			}
-			for (unsigned int q = 0, base = 0; q < aiSplit[p].size();++q)
-			{
-				register unsigned int index = aiSplit[p][q];
-				aiFace& face = meshOut->mFaces[q];
-
-				face.mIndices = new unsigned int[3];
-				face.mNumIndices = 3;
-
-				for (unsigned int a = 0; a < 3;++a,++base)
-				{
-					unsigned int idx = (*i).mFaces[index].mIndices[a];
-					meshOut->mVertices[base]  = (*i).mPositions[idx];
-					meshOut->mNormals [base]  = (*i).mNormals[idx];
-
-					if ((*i).mTexCoords.size())
-						meshOut->mTextureCoords[0][base] = (*i).mTexCoords[idx];
-
-					face.mIndices[a] = base;
-				}
-			}
-		}
-	}
-
-	// Copy them to the output array
-	pcOut->mNumMeshes = (unsigned int)avOutMeshes.size();
-	pcOut->mMeshes = new aiMesh*[pcOut->mNumMeshes]();
-	for (unsigned int a = 0; a < pcOut->mNumMeshes;++a) {
-		pcOut->mMeshes[a] = avOutMeshes[a];
-	}
-
-	// We should have at least one face here
-	if (!iFaceCnt) {
-		throw DeadlyImportError("No faces loaded. The mesh is empty");
-	}
+    std::vector<aiMesh*> avOutMeshes;
+    avOutMeshes.reserve(mScene->mMeshes.size() * 2);
+
+    unsigned int iFaceCnt = 0,num = 0;
+    aiString name;
+
+    // we need to split all meshes by their materials
+    for (std::vector<D3DS::Mesh>::iterator i =  mScene->mMeshes.begin(); i != mScene->mMeshes.end();++i)    {
+        boost::scoped_array< std::vector<unsigned int> > aiSplit(new std::vector<unsigned int>[mScene->mMaterials.size()]);
+
+        name.length = ASSIMP_itoa10(name.data,num++);
+
+        unsigned int iNum = 0;
+        for (std::vector<unsigned int>::const_iterator a =  (*i).mFaceMaterials.begin();
+            a != (*i).mFaceMaterials.end();++a,++iNum)
+        {
+            aiSplit[*a].push_back(iNum);
+        }
+        // now generate submeshes
+        for (unsigned int p = 0; p < mScene->mMaterials.size();++p)
+        {
+            if (aiSplit[p].empty()) {
+                continue;
+            }
+            aiMesh* meshOut = new aiMesh();
+            meshOut->mName = name;
+            meshOut->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
+
+            // be sure to setup the correct material index
+            meshOut->mMaterialIndex = p;
+
+            // use the color data as temporary storage
+            meshOut->mColors[0] = (aiColor4D*)(&*i);
+            avOutMeshes.push_back(meshOut);
+
+            // convert vertices
+            meshOut->mNumFaces = (unsigned int)aiSplit[p].size();
+            meshOut->mNumVertices = meshOut->mNumFaces*3;
+
+            // allocate enough storage for faces
+            meshOut->mFaces = new aiFace[meshOut->mNumFaces];
+            iFaceCnt += meshOut->mNumFaces;
+
+            meshOut->mVertices = new aiVector3D[meshOut->mNumVertices];
+            meshOut->mNormals  = new aiVector3D[meshOut->mNumVertices];
+            if ((*i).mTexCoords.size())
+            {
+                meshOut->mTextureCoords[0] = new aiVector3D[meshOut->mNumVertices];
+            }
+            for (unsigned int q = 0, base = 0; q < aiSplit[p].size();++q)
+            {
+                unsigned int index = aiSplit[p][q];
+                aiFace& face = meshOut->mFaces[q];
+
+                face.mIndices = new unsigned int[3];
+                face.mNumIndices = 3;
+
+                for (unsigned int a = 0; a < 3;++a,++base)
+                {
+                    unsigned int idx = (*i).mFaces[index].mIndices[a];
+                    meshOut->mVertices[base]  = (*i).mPositions[idx];
+                    meshOut->mNormals [base]  = (*i).mNormals[idx];
+
+                    if ((*i).mTexCoords.size())
+                        meshOut->mTextureCoords[0][base] = (*i).mTexCoords[idx];
+
+                    face.mIndices[a] = base;
+                }
+            }
+        }
+    }
+
+    // Copy them to the output array
+    pcOut->mNumMeshes = (unsigned int)avOutMeshes.size();
+    pcOut->mMeshes = new aiMesh*[pcOut->mNumMeshes]();
+    for (unsigned int a = 0; a < pcOut->mNumMeshes;++a) {
+        pcOut->mMeshes[a] = avOutMeshes[a];
+    }
+
+    // We should have at least one face here
+    if (!iFaceCnt) {
+        throw DeadlyImportError("No faces loaded. The mesh is empty");
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 // Add a node to the scenegraph and setup its final transformation
 void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,
-	D3DS::Node* pcIn, aiMatrix4x4& /*absTrafo*/)
+    D3DS::Node* pcIn, aiMatrix4x4& /*absTrafo*/)
 {
-	std::vector<unsigned int> iArray;
-	iArray.reserve(3);
-
-	aiMatrix4x4 abs;
-
-	// Find all meshes with the same name as the node
-	for (unsigned int a = 0; a < pcSOut->mNumMeshes;++a)
-	{
-		const D3DS::Mesh* pcMesh = (const D3DS::Mesh*)pcSOut->mMeshes[a]->mColors[0];
-		ai_assert(NULL != pcMesh);
-
-		if (pcIn->mName == pcMesh->mName)
-			iArray.push_back(a);
-	}
-	if (!iArray.empty())
-	{
-		// The matrix should be identical for all meshes with the 
-		// same name. It HAS to be identical for all meshes .....
-		D3DS::Mesh* imesh = ((D3DS::Mesh*)pcSOut->mMeshes[iArray[0]]->mColors[0]);
-
-		// Compute the inverse of the transformation matrix to move the
-		// vertices back to their relative and local space
-		aiMatrix4x4 mInv = imesh->mMat, mInvTransposed = imesh->mMat;
-		mInv.Inverse();mInvTransposed.Transpose();
-		aiVector3D pivot = pcIn->vPivot;
-
-		pcOut->mNumMeshes = (unsigned int)iArray.size();
-		pcOut->mMeshes = new unsigned int[iArray.size()];
-		for (unsigned int i = 0;i < iArray.size();++i)	{
-			const unsigned int iIndex = iArray[i];
-			aiMesh* const mesh = pcSOut->mMeshes[iIndex];
-
-			if (mesh->mColors[1] == NULL)
-			{
-				// Transform the vertices back into their local space
-				// fixme: consider computing normals after this, so we don't need to transform them
-				const aiVector3D* const pvEnd = mesh->mVertices + mesh->mNumVertices;
-				aiVector3D* pvCurrent = mesh->mVertices, *t2 = mesh->mNormals;
-
-				for (; pvCurrent != pvEnd; ++pvCurrent, ++t2) {
-					*pvCurrent = mInv * (*pvCurrent);
-					*t2 = mInvTransposed * (*t2);
-				}
-
-				// Handle negative transformation matrix determinant -> invert vertex x
-				if (imesh->mMat.Determinant() < 0.0f)
-				{
-					/* we *must* have normals */
-					for (pvCurrent = mesh->mVertices, t2 = mesh->mNormals; pvCurrent != pvEnd; ++pvCurrent, ++t2) {
-						pvCurrent->x *= -1.f;
-						t2->x *= -1.f;
-					}
-					DefaultLogger::get()->info("3DS: Flipping mesh X-Axis");
-				}
-
-				// Handle pivot point
-				if (pivot.x || pivot.y || pivot.z)
-				{
-					for (pvCurrent = mesh->mVertices; pvCurrent != pvEnd; ++pvCurrent)	{
-						*pvCurrent -= pivot;
-					}
-				}
-
-				mesh->mColors[1] = (aiColor4D*)1;
-			}
-			else
-				mesh->mColors[1] = (aiColor4D*)1;
-
-			// Setup the mesh index
-			pcOut->mMeshes[i] = iIndex;
-		}
-	}
-
-	// Setup the name of the node
-	// First instance keeps its name otherwise something might break, all others will be postfixed with their instance number
-	if (pcIn->mInstanceNumber > 1)
-	{
-		char tmp[12];
-		ASSIMP_itoa10(tmp, pcIn->mInstanceNumber);
-		std::string tempStr = pcIn->mName + "_inst_";
-		tempStr += tmp;
-		pcOut->mName.Set(tempStr);
-	}
-	else
-		pcOut->mName.Set(pcIn->mName);
-
-	// Now build the transformation matrix of the node
-	// ROTATION
-	if (pcIn->aRotationKeys.size()){
-
-		// FIX to get to Assimp's quaternion conventions
-		for (std::vector<aiQuatKey>::iterator it = pcIn->aRotationKeys.begin(); it != pcIn->aRotationKeys.end(); ++it) {
-			(*it).mValue.w *= -1.f;
-		}
-
-		pcOut->mTransformation = aiMatrix4x4( pcIn->aRotationKeys[0].mValue.GetMatrix() );
-	}
-	else if (pcIn->aCameraRollKeys.size()) 
-	{
-		aiMatrix4x4::RotationZ(AI_DEG_TO_RAD(- pcIn->aCameraRollKeys[0].mValue),
-			pcOut->mTransformation);
-	}
-
-	// SCALING
-	aiMatrix4x4& m = pcOut->mTransformation;
-	if (pcIn->aScalingKeys.size())
-	{
-		const aiVector3D& v = pcIn->aScalingKeys[0].mValue;
-		m.a1 *= v.x; m.b1 *= v.x; m.c1 *= v.x;
-		m.a2 *= v.y; m.b2 *= v.y; m.c2 *= v.y;
-		m.a3 *= v.z; m.b3 *= v.z; m.c3 *= v.z;
-	}
-
-	// TRANSLATION
-	if (pcIn->aPositionKeys.size())
-	{
-		const aiVector3D& v = pcIn->aPositionKeys[0].mValue;
-		m.a4 += v.x;
-		m.b4 += v.y;
-		m.c4 += v.z;
-	}
-
-	// Generate animation channels for the node
-	if (pcIn->aPositionKeys.size()  > 1  || pcIn->aRotationKeys.size()   > 1 ||
-		pcIn->aScalingKeys.size()   > 1  || pcIn->aCameraRollKeys.size() > 1 ||
-		pcIn->aTargetPositionKeys.size() > 1)
-	{
-		aiAnimation* anim = pcSOut->mAnimations[0];
-		ai_assert(NULL != anim);
-
-		if (pcIn->aCameraRollKeys.size() > 1)
-		{
-			DefaultLogger::get()->debug("3DS: Converting camera roll track ...");
-
-			// Camera roll keys - in fact they're just rotations
-			// around the camera's z axis. The angles are given
-			// in degrees (and they're clockwise).
-			pcIn->aRotationKeys.resize(pcIn->aCameraRollKeys.size());
-			for (unsigned int i = 0; i < pcIn->aCameraRollKeys.size();++i)
-			{
-				aiQuatKey&  q = pcIn->aRotationKeys[i];
-				aiFloatKey& f = pcIn->aCameraRollKeys[i];
-
-				q.mTime  = f.mTime;
-
-				// FIX to get to Assimp quaternion conventions
-				q.mValue = aiQuaternion(0.f,0.f,AI_DEG_TO_RAD( /*-*/ f.mValue));
-			}
-		}
+    std::vector<unsigned int> iArray;
+    iArray.reserve(3);
+
+    aiMatrix4x4 abs;
+
+    // Find all meshes with the same name as the node
+    for (unsigned int a = 0; a < pcSOut->mNumMeshes;++a)
+    {
+        const D3DS::Mesh* pcMesh = (const D3DS::Mesh*)pcSOut->mMeshes[a]->mColors[0];
+        ai_assert(NULL != pcMesh);
+
+        if (pcIn->mName == pcMesh->mName)
+            iArray.push_back(a);
+    }
+    if (!iArray.empty())
+    {
+        // The matrix should be identical for all meshes with the
+        // same name. It HAS to be identical for all meshes .....
+        D3DS::Mesh* imesh = ((D3DS::Mesh*)pcSOut->mMeshes[iArray[0]]->mColors[0]);
+
+        // Compute the inverse of the transformation matrix to move the
+        // vertices back to their relative and local space
+        aiMatrix4x4 mInv = imesh->mMat, mInvTransposed = imesh->mMat;
+        mInv.Inverse();mInvTransposed.Transpose();
+        aiVector3D pivot = pcIn->vPivot;
+
+        pcOut->mNumMeshes = (unsigned int)iArray.size();
+        pcOut->mMeshes = new unsigned int[iArray.size()];
+        for (unsigned int i = 0;i < iArray.size();++i)  {
+            const unsigned int iIndex = iArray[i];
+            aiMesh* const mesh = pcSOut->mMeshes[iIndex];
+
+            if (mesh->mColors[1] == NULL)
+            {
+                // Transform the vertices back into their local space
+                // fixme: consider computing normals after this, so we don't need to transform them
+                const aiVector3D* const pvEnd = mesh->mVertices + mesh->mNumVertices;
+                aiVector3D* pvCurrent = mesh->mVertices, *t2 = mesh->mNormals;
+
+                for (; pvCurrent != pvEnd; ++pvCurrent, ++t2) {
+                    *pvCurrent = mInv * (*pvCurrent);
+                    *t2 = mInvTransposed * (*t2);
+                }
+
+                // Handle negative transformation matrix determinant -> invert vertex x
+                if (imesh->mMat.Determinant() < 0.0f)
+                {
+                    /* we *must* have normals */
+                    for (pvCurrent = mesh->mVertices, t2 = mesh->mNormals; pvCurrent != pvEnd; ++pvCurrent, ++t2) {
+                        pvCurrent->x *= -1.f;
+                        t2->x *= -1.f;
+                    }
+                    DefaultLogger::get()->info("3DS: Flipping mesh X-Axis");
+                }
+
+                // Handle pivot point
+                if (pivot.x || pivot.y || pivot.z)
+                {
+                    for (pvCurrent = mesh->mVertices; pvCurrent != pvEnd; ++pvCurrent)  {
+                        *pvCurrent -= pivot;
+                    }
+                }
+
+                mesh->mColors[1] = (aiColor4D*)1;
+            }
+            else
+                mesh->mColors[1] = (aiColor4D*)1;
+
+            // Setup the mesh index
+            pcOut->mMeshes[i] = iIndex;
+        }
+    }
+
+    // Setup the name of the node
+    // First instance keeps its name otherwise something might break, all others will be postfixed with their instance number
+    if (pcIn->mInstanceNumber > 1)
+    {
+        char tmp[12];
+        ASSIMP_itoa10(tmp, pcIn->mInstanceNumber);
+        std::string tempStr = pcIn->mName + "_inst_";
+        tempStr += tmp;
+        pcOut->mName.Set(tempStr);
+    }
+    else
+        pcOut->mName.Set(pcIn->mName);
+
+    // Now build the transformation matrix of the node
+    // ROTATION
+    if (pcIn->aRotationKeys.size()){
+
+        // FIX to get to Assimp's quaternion conventions
+        for (std::vector<aiQuatKey>::iterator it = pcIn->aRotationKeys.begin(); it != pcIn->aRotationKeys.end(); ++it) {
+            (*it).mValue.w *= -1.f;
+        }
+
+        pcOut->mTransformation = aiMatrix4x4( pcIn->aRotationKeys[0].mValue.GetMatrix() );
+    }
+    else if (pcIn->aCameraRollKeys.size())
+    {
+        aiMatrix4x4::RotationZ(AI_DEG_TO_RAD(- pcIn->aCameraRollKeys[0].mValue),
+            pcOut->mTransformation);
+    }
+
+    // SCALING
+    aiMatrix4x4& m = pcOut->mTransformation;
+    if (pcIn->aScalingKeys.size())
+    {
+        const aiVector3D& v = pcIn->aScalingKeys[0].mValue;
+        m.a1 *= v.x; m.b1 *= v.x; m.c1 *= v.x;
+        m.a2 *= v.y; m.b2 *= v.y; m.c2 *= v.y;
+        m.a3 *= v.z; m.b3 *= v.z; m.c3 *= v.z;
+    }
+
+    // TRANSLATION
+    if (pcIn->aPositionKeys.size())
+    {
+        const aiVector3D& v = pcIn->aPositionKeys[0].mValue;
+        m.a4 += v.x;
+        m.b4 += v.y;
+        m.c4 += v.z;
+    }
+
+    // Generate animation channels for the node
+    if (pcIn->aPositionKeys.size()  > 1  || pcIn->aRotationKeys.size()   > 1 ||
+        pcIn->aScalingKeys.size()   > 1  || pcIn->aCameraRollKeys.size() > 1 ||
+        pcIn->aTargetPositionKeys.size() > 1)
+    {
+        aiAnimation* anim = pcSOut->mAnimations[0];
+        ai_assert(NULL != anim);
+
+        if (pcIn->aCameraRollKeys.size() > 1)
+        {
+            DefaultLogger::get()->debug("3DS: Converting camera roll track ...");
+
+            // Camera roll keys - in fact they're just rotations
+            // around the camera's z axis. The angles are given
+            // in degrees (and they're clockwise).
+            pcIn->aRotationKeys.resize(pcIn->aCameraRollKeys.size());
+            for (unsigned int i = 0; i < pcIn->aCameraRollKeys.size();++i)
+            {
+                aiQuatKey&  q = pcIn->aRotationKeys[i];
+                aiFloatKey& f = pcIn->aCameraRollKeys[i];
+
+                q.mTime  = f.mTime;
+
+                // FIX to get to Assimp quaternion conventions
+                q.mValue = aiQuaternion(0.f,0.f,AI_DEG_TO_RAD( /*-*/ f.mValue));
+            }
+        }
 #if 0
-		if (pcIn->aTargetPositionKeys.size() > 1)
-		{
-			DefaultLogger::get()->debug("3DS: Converting target track ...");
-
-			// Camera or spot light - need to convert the separate
-			// target position channel to our representation
-			TargetAnimationHelper helper;
-
-			if (pcIn->aPositionKeys.empty())
-			{
-				// We can just pass zero here ...
-				helper.SetFixedMainAnimationChannel(aiVector3D());
-			}
-			else  helper.SetMainAnimationChannel(&pcIn->aPositionKeys);
-			helper.SetTargetAnimationChannel(&pcIn->aTargetPositionKeys);
-
-			// Do the conversion
-			std::vector<aiVectorKey> distanceTrack;
-			helper.Process(&distanceTrack);
-
-			// Now add a new node as child, name it <ourName>.Target
-			// and assign the distance track to it. This is that the
-			// information where the target is and how it moves is
-			// not lost
-			D3DS::Node* nd = new D3DS::Node();
-			pcIn->push_back(nd);
-
-			nd->mName = pcIn->mName + ".Target";
-
-			aiNodeAnim* nda = anim->mChannels[anim->mNumChannels++] = new aiNodeAnim();
-			nda->mNodeName.Set(nd->mName);
-
-			nda->mNumPositionKeys = (unsigned int)distanceTrack.size();
-			nda->mPositionKeys = new aiVectorKey[nda->mNumPositionKeys];
-			::memcpy(nda->mPositionKeys,&distanceTrack[0],
-				sizeof(aiVectorKey)*nda->mNumPositionKeys);
-		}
+        if (pcIn->aTargetPositionKeys.size() > 1)
+        {
+            DefaultLogger::get()->debug("3DS: Converting target track ...");
+
+            // Camera or spot light - need to convert the separate
+            // target position channel to our representation
+            TargetAnimationHelper helper;
+
+            if (pcIn->aPositionKeys.empty())
+            {
+                // We can just pass zero here ...
+                helper.SetFixedMainAnimationChannel(aiVector3D());
+            }
+            else  helper.SetMainAnimationChannel(&pcIn->aPositionKeys);
+            helper.SetTargetAnimationChannel(&pcIn->aTargetPositionKeys);
+
+            // Do the conversion
+            std::vector<aiVectorKey> distanceTrack;
+            helper.Process(&distanceTrack);
+
+            // Now add a new node as child, name it <ourName>.Target
+            // and assign the distance track to it. This is that the
+            // information where the target is and how it moves is
+            // not lost
+            D3DS::Node* nd = new D3DS::Node();
+            pcIn->push_back(nd);
+
+            nd->mName = pcIn->mName + ".Target";
+
+            aiNodeAnim* nda = anim->mChannels[anim->mNumChannels++] = new aiNodeAnim();
+            nda->mNodeName.Set(nd->mName);
+
+            nda->mNumPositionKeys = (unsigned int)distanceTrack.size();
+            nda->mPositionKeys = new aiVectorKey[nda->mNumPositionKeys];
+            ::memcpy(nda->mPositionKeys,&distanceTrack[0],
+                sizeof(aiVectorKey)*nda->mNumPositionKeys);
+        }
 #endif
 
-		// Cameras or lights define their transformation in their parent node and in the
-		// corresponding light or camera chunks. However, we read and process the latter
-		// to to be able to return valid cameras/lights even if no scenegraph is given.
-		for (unsigned int n = 0; n < pcSOut->mNumCameras;++n)	{
-			if (pcSOut->mCameras[n]->mName == pcOut->mName) {
-				pcSOut->mCameras[n]->mLookAt = aiVector3D(0.f,0.f,1.f);
-			}
-		}
-		for (unsigned int n = 0; n < pcSOut->mNumLights;++n)	{
-			if (pcSOut->mLights[n]->mName == pcOut->mName) {
-				pcSOut->mLights[n]->mDirection = aiVector3D(0.f,0.f,1.f);
-			}
-		}
-
-		// Allocate a new node anim and setup its name
-		aiNodeAnim* nda = anim->mChannels[anim->mNumChannels++] = new aiNodeAnim();
-		nda->mNodeName.Set(pcIn->mName);
-
-		// POSITION keys
-		if (pcIn->aPositionKeys.size()  > 0)
-		{
-			nda->mNumPositionKeys = (unsigned int)pcIn->aPositionKeys.size();
-			nda->mPositionKeys = new aiVectorKey[nda->mNumPositionKeys];
-			::memcpy(nda->mPositionKeys,&pcIn->aPositionKeys[0],
-				sizeof(aiVectorKey)*nda->mNumPositionKeys);
-		}
-
-		// ROTATION keys
-		if (pcIn->aRotationKeys.size()  > 0)
-		{
-			nda->mNumRotationKeys = (unsigned int)pcIn->aRotationKeys.size();
-			nda->mRotationKeys = new aiQuatKey[nda->mNumRotationKeys];
-
-			// Rotations are quaternion offsets
-			aiQuaternion abs;
-			for (unsigned int n = 0; n < nda->mNumRotationKeys;++n)
-			{
-				const aiQuatKey& q = pcIn->aRotationKeys[n];
-
-				abs = (n ? abs * q.mValue : q.mValue);
-				nda->mRotationKeys[n].mTime  = q.mTime;
-				nda->mRotationKeys[n].mValue = abs.Normalize();
-			}
-		}
-
-		// SCALING keys
-		if (pcIn->aScalingKeys.size()  > 0)
-		{
-			nda->mNumScalingKeys = (unsigned int)pcIn->aScalingKeys.size();
-			nda->mScalingKeys = new aiVectorKey[nda->mNumScalingKeys];
-			::memcpy(nda->mScalingKeys,&pcIn->aScalingKeys[0],
-				sizeof(aiVectorKey)*nda->mNumScalingKeys);
-		}
-	}
-
-	// Allocate storage for children 
-	pcOut->mNumChildren = (unsigned int)pcIn->mChildren.size();
-	pcOut->mChildren = new aiNode*[pcIn->mChildren.size()];
-
-	// Recursively process all children
-	const unsigned int size = pcIn->mChildren.size();
-	for (unsigned int i = 0; i < size;++i)
-	{
-		pcOut->mChildren[i] = new aiNode();
-		pcOut->mChildren[i]->mParent = pcOut;
-		AddNodeToGraph(pcSOut,pcOut->mChildren[i],pcIn->mChildren[i],abs);
-	}
+        // Cameras or lights define their transformation in their parent node and in the
+        // corresponding light or camera chunks. However, we read and process the latter
+        // to to be able to return valid cameras/lights even if no scenegraph is given.
+        for (unsigned int n = 0; n < pcSOut->mNumCameras;++n)   {
+            if (pcSOut->mCameras[n]->mName == pcOut->mName) {
+                pcSOut->mCameras[n]->mLookAt = aiVector3D(0.f,0.f,1.f);
+            }
+        }
+        for (unsigned int n = 0; n < pcSOut->mNumLights;++n)    {
+            if (pcSOut->mLights[n]->mName == pcOut->mName) {
+                pcSOut->mLights[n]->mDirection = aiVector3D(0.f,0.f,1.f);
+            }
+        }
+
+        // Allocate a new node anim and setup its name
+        aiNodeAnim* nda = anim->mChannels[anim->mNumChannels++] = new aiNodeAnim();
+        nda->mNodeName.Set(pcIn->mName);
+
+        // POSITION keys
+        if (pcIn->aPositionKeys.size()  > 0)
+        {
+            nda->mNumPositionKeys = (unsigned int)pcIn->aPositionKeys.size();
+            nda->mPositionKeys = new aiVectorKey[nda->mNumPositionKeys];
+            ::memcpy(nda->mPositionKeys,&pcIn->aPositionKeys[0],
+                sizeof(aiVectorKey)*nda->mNumPositionKeys);
+        }
+
+        // ROTATION keys
+        if (pcIn->aRotationKeys.size()  > 0)
+        {
+            nda->mNumRotationKeys = (unsigned int)pcIn->aRotationKeys.size();
+            nda->mRotationKeys = new aiQuatKey[nda->mNumRotationKeys];
+
+            // Rotations are quaternion offsets
+            aiQuaternion abs;
+            for (unsigned int n = 0; n < nda->mNumRotationKeys;++n)
+            {
+                const aiQuatKey& q = pcIn->aRotationKeys[n];
+
+                abs = (n ? abs * q.mValue : q.mValue);
+                nda->mRotationKeys[n].mTime  = q.mTime;
+                nda->mRotationKeys[n].mValue = abs.Normalize();
+            }
+        }
+
+        // SCALING keys
+        if (pcIn->aScalingKeys.size()  > 0)
+        {
+            nda->mNumScalingKeys = (unsigned int)pcIn->aScalingKeys.size();
+            nda->mScalingKeys = new aiVectorKey[nda->mNumScalingKeys];
+            ::memcpy(nda->mScalingKeys,&pcIn->aScalingKeys[0],
+                sizeof(aiVectorKey)*nda->mNumScalingKeys);
+        }
+    }
+
+    // Allocate storage for children
+    pcOut->mNumChildren = (unsigned int)pcIn->mChildren.size();
+    pcOut->mChildren = new aiNode*[pcIn->mChildren.size()];
+
+    // Recursively process all children
+    const unsigned int size = pcIn->mChildren.size();
+    for (unsigned int i = 0; i < size;++i)
+    {
+        pcOut->mChildren[i] = new aiNode();
+        pcOut->mChildren[i]->mParent = pcOut;
+        AddNodeToGraph(pcSOut,pcOut->mChildren[i],pcIn->mChildren[i],abs);
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 // Find out how many node animation channels we'll have finally
 void CountTracks(D3DS::Node* node, unsigned int& cnt)
 {
-	//////////////////////////////////////////////////////////////////////////////
-	// We will never generate more than one channel for a node, so
-	// this is rather easy here.
-
-	if (node->aPositionKeys.size()  > 1  || node->aRotationKeys.size()   > 1   ||
-		node->aScalingKeys.size()   > 1  || node->aCameraRollKeys.size() > 1 ||
-		node->aTargetPositionKeys.size()  > 1)
-	{
-		++cnt;
-
-		// account for the additional channel for the camera/spotlight target position
-		if (node->aTargetPositionKeys.size()  > 1)++cnt;
-	}
-
-	// Recursively process all children
-	for (unsigned int i = 0; i < node->mChildren.size();++i)
-		CountTracks(node->mChildren[i],cnt);
+    //////////////////////////////////////////////////////////////////////////////
+    // We will never generate more than one channel for a node, so
+    // this is rather easy here.
+
+    if (node->aPositionKeys.size()  > 1  || node->aRotationKeys.size()   > 1   ||
+        node->aScalingKeys.size()   > 1  || node->aCameraRollKeys.size() > 1 ||
+        node->aTargetPositionKeys.size()  > 1)
+    {
+        ++cnt;
+
+        // account for the additional channel for the camera/spotlight target position
+        if (node->aTargetPositionKeys.size()  > 1)++cnt;
+    }
+
+    // Recursively process all children
+    for (unsigned int i = 0; i < node->mChildren.size();++i)
+        CountTracks(node->mChildren[i],cnt);
 }
 
 // ------------------------------------------------------------------------------------------------
 // Generate the output node graph
 void Discreet3DSImporter::GenerateNodeGraph(aiScene* pcOut)
 {
-	pcOut->mRootNode = new aiNode();
-	if (0 == mRootNode->mChildren.size())
-	{
-		//////////////////////////////////////////////////////////////////////////////
-		// It seems the file is so messed up that it has not even a hierarchy.
-		// generate a flat hiearachy which looks like this:
-		//
-		//                ROOT_NODE
-		//                   |
-		//   ----------------------------------------
-		//   |       |       |            |         |  
-		// MESH_0  MESH_1  MESH_2  ...  MESH_N    CAMERA_0 ....
-		//
-		DefaultLogger::get()->warn("No hierarchy information has been found in the file. ");
-
-		pcOut->mRootNode->mNumChildren = pcOut->mNumMeshes + 
-			mScene->mCameras.size() + mScene->mLights.size();
-
-		pcOut->mRootNode->mChildren = new aiNode* [ pcOut->mRootNode->mNumChildren ];
-		pcOut->mRootNode->mName.Set("<3DSDummyRoot>");
-
-		// Build dummy nodes for all meshes
-		unsigned int a = 0;
-		for (unsigned int i = 0; i < pcOut->mNumMeshes;++i,++a)
-		{
-			aiNode* pcNode = pcOut->mRootNode->mChildren[a] = new aiNode();
-			pcNode->mParent = pcOut->mRootNode;
-			pcNode->mMeshes = new unsigned int[1];
-			pcNode->mMeshes[0] = i;
-			pcNode->mNumMeshes = 1;
-
-			// Build a name for the node
-			pcNode->mName.length = sprintf(pcNode->mName.data,"3DSMesh_%i",i);	
-		}
-
-		// Build dummy nodes for all cameras
-		for (unsigned int i = 0; i < (unsigned int )mScene->mCameras.size();++i,++a)
-		{
-			aiNode* pcNode = pcOut->mRootNode->mChildren[a] = new aiNode();
-			pcNode->mParent = pcOut->mRootNode;
-
-			// Build a name for the node
-			pcNode->mName = mScene->mCameras[i]->mName;
-		}
-
-		// Build dummy nodes for all lights
-		for (unsigned int i = 0; i < (unsigned int )mScene->mLights.size();++i,++a)
-		{
-			aiNode* pcNode = pcOut->mRootNode->mChildren[a] = new aiNode();
-			pcNode->mParent = pcOut->mRootNode;
-
-			// Build a name for the node
-			pcNode->mName = mScene->mLights[i]->mName;
-		}
-	}
-	else
-	{
-		// First of all: find out how many scaling, rotation and translation
-		// animation tracks we'll have afterwards
-		unsigned int numChannel = 0;
-		CountTracks(mRootNode,numChannel);
-
-		if (numChannel)
-		{
-			// Allocate a primary animation channel
-			pcOut->mNumAnimations = 1;
-			pcOut->mAnimations    = new aiAnimation*[1];
-			aiAnimation* anim     = pcOut->mAnimations[0] = new aiAnimation();
-
-			anim->mName.Set("3DSMasterAnim");
-
-			// Allocate enough storage for all node animation channels, 
-			// but don't set the mNumChannels member - we'll use it to
-			// index into the array
-			anim->mChannels = new aiNodeAnim*[numChannel];
-		}
-
-		aiMatrix4x4 m;
-		AddNodeToGraph(pcOut,  pcOut->mRootNode, mRootNode,m);
-	}
-
-	// We used the first and second vertex color set to store some temporary values so we need to cleanup here
-	for (unsigned int a = 0; a < pcOut->mNumMeshes; ++a)
-	{
-		pcOut->mMeshes[a]->mColors[0] = NULL;
-		pcOut->mMeshes[a]->mColors[1] = NULL;
-	}
-
-	pcOut->mRootNode->mTransformation = aiMatrix4x4(
-		1.f,0.f,0.f,0.f,
-		0.f,0.f,1.f,0.f,
-		0.f,-1.f,0.f,0.f,
-		0.f,0.f,0.f,1.f) * pcOut->mRootNode->mTransformation;
-
-	// If the root node is unnamed name it "<3DSRoot>"
-	if (::strstr( pcOut->mRootNode->mName.data, "UNNAMED" ) ||
-		(pcOut->mRootNode->mName.data[0] == '$' && pcOut->mRootNode->mName.data[1] == '$') )
-	{
-		pcOut->mRootNode->mName.Set("<3DSRoot>");
-	}
+    pcOut->mRootNode = new aiNode();
+    if (0 == mRootNode->mChildren.size())
+    {
+        //////////////////////////////////////////////////////////////////////////////
+        // It seems the file is so messed up that it has not even a hierarchy.
+        // generate a flat hiearachy which looks like this:
+        //
+        //                ROOT_NODE
+        //                   |
+        //   ----------------------------------------
+        //   |       |       |            |         |
+        // MESH_0  MESH_1  MESH_2  ...  MESH_N    CAMERA_0 ....
+        //
+        DefaultLogger::get()->warn("No hierarchy information has been found in the file. ");
+
+        pcOut->mRootNode->mNumChildren = pcOut->mNumMeshes +
+            mScene->mCameras.size() + mScene->mLights.size();
+
+        pcOut->mRootNode->mChildren = new aiNode* [ pcOut->mRootNode->mNumChildren ];
+        pcOut->mRootNode->mName.Set("<3DSDummyRoot>");
+
+        // Build dummy nodes for all meshes
+        unsigned int a = 0;
+        for (unsigned int i = 0; i < pcOut->mNumMeshes;++i,++a)
+        {
+            aiNode* pcNode = pcOut->mRootNode->mChildren[a] = new aiNode();
+            pcNode->mParent = pcOut->mRootNode;
+            pcNode->mMeshes = new unsigned int[1];
+            pcNode->mMeshes[0] = i;
+            pcNode->mNumMeshes = 1;
+
+            // Build a name for the node
+            pcNode->mName.length = sprintf(pcNode->mName.data,"3DSMesh_%u",i);
+        }
+
+        // Build dummy nodes for all cameras
+        for (unsigned int i = 0; i < (unsigned int )mScene->mCameras.size();++i,++a)
+        {
+            aiNode* pcNode = pcOut->mRootNode->mChildren[a] = new aiNode();
+            pcNode->mParent = pcOut->mRootNode;
+
+            // Build a name for the node
+            pcNode->mName = mScene->mCameras[i]->mName;
+        }
+
+        // Build dummy nodes for all lights
+        for (unsigned int i = 0; i < (unsigned int )mScene->mLights.size();++i,++a)
+        {
+            aiNode* pcNode = pcOut->mRootNode->mChildren[a] = new aiNode();
+            pcNode->mParent = pcOut->mRootNode;
+
+            // Build a name for the node
+            pcNode->mName = mScene->mLights[i]->mName;
+        }
+    }
+    else
+    {
+        // First of all: find out how many scaling, rotation and translation
+        // animation tracks we'll have afterwards
+        unsigned int numChannel = 0;
+        CountTracks(mRootNode,numChannel);
+
+        if (numChannel)
+        {
+            // Allocate a primary animation channel
+            pcOut->mNumAnimations = 1;
+            pcOut->mAnimations    = new aiAnimation*[1];
+            aiAnimation* anim     = pcOut->mAnimations[0] = new aiAnimation();
+
+            anim->mName.Set("3DSMasterAnim");
+
+            // Allocate enough storage for all node animation channels,
+            // but don't set the mNumChannels member - we'll use it to
+            // index into the array
+            anim->mChannels = new aiNodeAnim*[numChannel];
+        }
+
+        aiMatrix4x4 m;
+        AddNodeToGraph(pcOut,  pcOut->mRootNode, mRootNode,m);
+    }
+
+    // We used the first and second vertex color set to store some temporary values so we need to cleanup here
+    for (unsigned int a = 0; a < pcOut->mNumMeshes; ++a)
+    {
+        pcOut->mMeshes[a]->mColors[0] = NULL;
+        pcOut->mMeshes[a]->mColors[1] = NULL;
+    }
+
+    pcOut->mRootNode->mTransformation = aiMatrix4x4(
+        1.f,0.f,0.f,0.f,
+        0.f,0.f,1.f,0.f,
+        0.f,-1.f,0.f,0.f,
+        0.f,0.f,0.f,1.f) * pcOut->mRootNode->mTransformation;
+
+    // If the root node is unnamed name it "<3DSRoot>"
+    if (::strstr( pcOut->mRootNode->mName.data, "UNNAMED" ) ||
+        (pcOut->mRootNode->mName.data[0] == '$' && pcOut->mRootNode->mName.data[1] == '$') )
+    {
+        pcOut->mRootNode->mName.Set("<3DSRoot>");
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 // Convert all meshes in the scene and generate the final output scene.
 void Discreet3DSImporter::ConvertScene(aiScene* pcOut)
 {
-	// Allocate enough storage for all output materials
-	pcOut->mNumMaterials = (unsigned int)mScene->mMaterials.size();
-	pcOut->mMaterials    = new aiMaterial*[pcOut->mNumMaterials];
-
-	//  ... and convert the 3DS materials to aiMaterial's
-	for (unsigned int i = 0; i < pcOut->mNumMaterials;++i)
-	{
-		aiMaterial* pcNew = new aiMaterial();
-		ConvertMaterial(mScene->mMaterials[i],*pcNew);
-		pcOut->mMaterials[i] = pcNew;
-	}
-
-	// Generate the output mesh list
-	ConvertMeshes(pcOut);
-
-	// Now copy all light sources to the output scene
-	pcOut->mNumLights = (unsigned int)mScene->mLights.size();
-	if (pcOut->mNumLights)
-	{
-		pcOut->mLights = new aiLight*[pcOut->mNumLights];
-		::memcpy(pcOut->mLights,&mScene->mLights[0],sizeof(void*)*pcOut->mNumLights);
-	}
-
-	// Now copy all cameras to the output scene
-	pcOut->mNumCameras = (unsigned int)mScene->mCameras.size();
-	if (pcOut->mNumCameras)
-	{
-		pcOut->mCameras = new aiCamera*[pcOut->mNumCameras];
-		::memcpy(pcOut->mCameras,&mScene->mCameras[0],sizeof(void*)*pcOut->mNumCameras);
-	}
+    // Allocate enough storage for all output materials
+    pcOut->mNumMaterials = (unsigned int)mScene->mMaterials.size();
+    pcOut->mMaterials    = new aiMaterial*[pcOut->mNumMaterials];
+
+    //  ... and convert the 3DS materials to aiMaterial's
+    for (unsigned int i = 0; i < pcOut->mNumMaterials;++i)
+    {
+        aiMaterial* pcNew = new aiMaterial();
+        ConvertMaterial(mScene->mMaterials[i],*pcNew);
+        pcOut->mMaterials[i] = pcNew;
+    }
+
+    // Generate the output mesh list
+    ConvertMeshes(pcOut);
+
+    // Now copy all light sources to the output scene
+    pcOut->mNumLights = (unsigned int)mScene->mLights.size();
+    if (pcOut->mNumLights)
+    {
+        pcOut->mLights = new aiLight*[pcOut->mNumLights];
+        ::memcpy(pcOut->mLights,&mScene->mLights[0],sizeof(void*)*pcOut->mNumLights);
+    }
+
+    // Now copy all cameras to the output scene
+    pcOut->mNumCameras = (unsigned int)mScene->mCameras.size();
+    if (pcOut->mNumCameras)
+    {
+        pcOut->mCameras = new aiCamera*[pcOut->mNumCameras];
+        ::memcpy(pcOut->mCameras,&mScene->mCameras[0],sizeof(void*)*pcOut->mNumCameras);
+    }
 }
 
 #endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER

+ 565 - 0
assimplib.mod/assimp/code/3DSExporter.cpp

@@ -0,0 +1,565 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2015, 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_3DS_EXPORTER
+
+#include "3DSExporter.h"
+#include "3DSLoader.h"
+#include "SceneCombiner.h"
+#include "SplitLargeMeshes.h"
+#include "StringComparison.h"
+#include "../include/assimp/IOSystem.hpp"
+#include "../include/assimp/DefaultLogger.hpp"
+#include "../include/assimp/Exporter.hpp"
+#include <memory>
+
+using namespace Assimp;
+namespace Assimp    {
+
+namespace {
+
+    //////////////////////////////////////////////////////////////////////////////////////
+    // Scope utility to write a 3DS file chunk.
+    //
+    // Upon construction, the chunk header is written with the chunk type (flags)
+    // filled out, but the chunk size left empty. Upon destruction, the correct chunk
+    // size based on the then-position of the output stream cursor is filled in.
+    class ChunkWriter {
+        enum {
+              CHUNK_SIZE_NOT_SET = 0xdeadbeef
+            , SIZE_OFFSET        = 2
+        };
+    public:
+
+        ChunkWriter(StreamWriterLE& writer, uint16_t chunk_type)
+            : writer(writer)
+        {
+            chunk_start_pos = writer.GetCurrentPos();
+            writer.PutU2(chunk_type);
+            writer.PutU4(CHUNK_SIZE_NOT_SET);
+        }
+
+        ~ChunkWriter() {
+            std::size_t head_pos = writer.GetCurrentPos();
+
+            ai_assert(head_pos > chunk_start_pos);
+            const std::size_t chunk_size = head_pos - chunk_start_pos;
+
+            writer.SetCurrentPos(chunk_start_pos + SIZE_OFFSET);
+            writer.PutU4(chunk_size);
+            writer.SetCurrentPos(head_pos);
+        }
+
+    private:
+        StreamWriterLE& writer;
+        std::size_t chunk_start_pos;
+    };
+
+
+    // Return an unique name for a given |mesh| attached to |node| that
+    // preserves the mesh's given name if it has one. |index| is the index
+    // of the mesh in |aiScene::mMeshes|.
+    std::string GetMeshName(const aiMesh& mesh, unsigned int index, const aiNode& node) {
+        static const std::string underscore = "_";
+        char postfix[10] = {0};
+        ASSIMP_itoa10(postfix, index);
+
+        std::string result = node.mName.C_Str();
+        if (mesh.mName.length > 0) {
+            result += underscore + mesh.mName.C_Str();
+        }
+        return result + underscore + postfix;
+    }
+
+    // Return an unique name for a given |mat| with original position |index|
+    // in |aiScene::mMaterials|. The name preserves the original material
+    // name if possible.
+    std::string GetMaterialName(const aiMaterial& mat, unsigned int index) {
+        static const std::string underscore = "_";
+        char postfix[10] = {0};
+        ASSIMP_itoa10(postfix, index);
+
+        aiString mat_name;
+        if (AI_SUCCESS == mat.Get(AI_MATKEY_NAME, mat_name)) {
+            return mat_name.C_Str() + underscore + postfix;
+        }
+
+        return "Material" + underscore + postfix;
+    }
+
+    // Collect world transformations for each node
+    void CollectTrafos(const aiNode* node, std::map<const aiNode*, aiMatrix4x4>& trafos) {
+        const aiMatrix4x4& parent = node->mParent ? trafos[node->mParent] : aiMatrix4x4();
+        trafos[node] = parent * node->mTransformation;
+        for (unsigned int i = 0; i < node->mNumChildren; ++i) {
+            CollectTrafos(node->mChildren[i], trafos);
+        }
+    }
+
+    // Generate a flat list of the meshes (by index) assigned to each node
+    void CollectMeshes(const aiNode* node, std::multimap<const aiNode*, unsigned int>& meshes) {
+        for (unsigned int i = 0; i < node->mNumMeshes; ++i) {
+            meshes.insert(std::make_pair(node, node->mMeshes[i]));
+        }
+        for (unsigned int i = 0; i < node->mNumChildren; ++i) {
+            CollectMeshes(node->mChildren[i], meshes);
+        }
+    }
+}
+
+// ------------------------------------------------------------------------------------------------
+// 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)
+{
+    boost::shared_ptr<IOStream> outfile (pIOSystem->Open(pFile, "wb"));
+    if(!outfile) {
+        throw DeadlyExportError("Could not open output .3ds file: " + std::string(pFile));
+    }
+
+    // TODO: This extra copy should be avoided and all of this made a preprocess
+    // requirement of the 3DS exporter.
+    //
+    // 3DS meshes can be max 0xffff (16 Bit) vertices and faces, respectively.
+    // SplitLargeMeshes can do this, but it requires the correct limit to be set
+    // which is not possible with the current way of specifying preprocess steps
+    // in |Exporter::ExportFormatEntry|.
+    aiScene* scenecopy_tmp;
+    SceneCombiner::CopyScene(&scenecopy_tmp,pScene);
+    std::auto_ptr<aiScene> scenecopy(scenecopy_tmp);
+
+    SplitLargeMeshesProcess_Triangle tri_splitter;
+    tri_splitter.SetLimit(0xffff);
+    tri_splitter.Execute(scenecopy.get());
+
+    SplitLargeMeshesProcess_Vertex vert_splitter;
+    vert_splitter.SetLimit(0xffff);
+    vert_splitter.Execute(scenecopy.get());
+
+    // Invoke the actual exporter
+    Discreet3DSExporter exporter(outfile, scenecopy.get());
+}
+
+} // end of namespace Assimp
+
+// ------------------------------------------------------------------------------------------------
+Discreet3DSExporter:: Discreet3DSExporter(boost::shared_ptr<IOStream> outfile, const aiScene* scene)
+: scene(scene)
+, writer(outfile)
+{
+    CollectTrafos(scene->mRootNode, trafos);
+    CollectMeshes(scene->mRootNode, meshes);
+
+    ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAIN);
+
+    {
+        ChunkWriter chunk(writer, Discreet3DS::CHUNK_OBJMESH);
+        WriteMaterials();
+        WriteMeshes();
+
+        {
+            ChunkWriter chunk(writer, Discreet3DS::CHUNK_MASTER_SCALE);
+            writer.PutF4(1.0f);
+        }
+    }
+
+    {
+        ChunkWriter chunk(writer, Discreet3DS::CHUNK_KEYFRAMER);
+        WriteHierarchy(*scene->mRootNode, -1, -1);
+    }
+}
+
+// ------------------------------------------------------------------------------------------------
+int Discreet3DSExporter::WriteHierarchy(const aiNode& node, int seq, int sibling_level)
+{
+    // 3DS scene hierarchy is serialized as in http://www.martinreddy.net/gfx/3d/3DS.spec
+    {
+        ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKINFO);
+        {
+            ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKOBJNAME);
+
+            // Assimp node names are unique and distinct from all mesh-node
+            // names we generate; thus we can use them as-is
+            WriteString(node.mName);
+
+            // Two unknown int16 values - it is even unclear if 0 is a safe value
+            // but luckily importers do not know better either.
+            writer.PutI4(0);
+
+            int16_t hierarchy_pos = static_cast<int16_t>(seq);
+            if (sibling_level != -1) {
+                hierarchy_pos = sibling_level;
+            }
+
+            // Write the hierarchy position
+            writer.PutI2(hierarchy_pos);
+        }
+    }
+
+    // TODO: write transformation chunks
+
+    ++seq;
+    sibling_level = seq;
+
+    // Write all children
+    for (unsigned int i = 0; i < node.mNumChildren; ++i) {
+        seq = WriteHierarchy(*node.mChildren[i], seq, i == 0 ? -1 : sibling_level);
+    }
+
+    // Write all meshes as separate nodes to be able to reference the meshes by name
+    for (unsigned int i = 0; i < node.mNumMeshes; ++i) {
+        const bool first_child = node.mNumChildren == 0 && i == 0;
+
+        const unsigned int mesh_idx = node.mMeshes[i];
+        const aiMesh& mesh = *scene->mMeshes[mesh_idx];
+
+        ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKINFO);
+        {
+            ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRACKOBJNAME);
+            WriteString(GetMeshName(mesh, mesh_idx, node));
+
+            writer.PutI4(0);
+            writer.PutI2(static_cast<int16_t>(first_child ? seq : sibling_level));
+            ++seq;
+        }
+    }
+    return seq;
+}
+
+// ------------------------------------------------------------------------------------------------
+void Discreet3DSExporter::WriteMaterials()
+{
+    for (unsigned int i = 0; i < scene->mNumMaterials; ++i) {
+        ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_MATERIAL);
+        const aiMaterial& mat = *scene->mMaterials[i];
+
+        {
+            ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_MATNAME);
+            const std::string& name = GetMaterialName(mat, i);
+            WriteString(name);
+        }
+
+        aiColor3D color;
+        if (mat.Get(AI_MATKEY_COLOR_DIFFUSE, color) == AI_SUCCESS) {
+            ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_DIFFUSE);
+            WriteColor(color);
+        }
+
+        if (mat.Get(AI_MATKEY_COLOR_SPECULAR, color) == AI_SUCCESS) {
+            ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SPECULAR);
+            WriteColor(color);
+        }
+
+        if (mat.Get(AI_MATKEY_COLOR_AMBIENT, color) == AI_SUCCESS) {
+            ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_AMBIENT);
+            WriteColor(color);
+        }
+
+        if (mat.Get(AI_MATKEY_COLOR_EMISSIVE, color) == AI_SUCCESS) {
+            ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SELF_ILLUM);
+            WriteColor(color);
+        }
+
+        aiShadingMode shading_mode = aiShadingMode_Flat;
+        if (mat.Get(AI_MATKEY_SHADING_MODEL, shading_mode) == AI_SUCCESS) {
+            ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHADING);
+
+            Discreet3DS::shadetype3ds shading_mode_out;
+            switch(shading_mode) {
+            case aiShadingMode_Flat:
+            case aiShadingMode_NoShading:
+                shading_mode_out = Discreet3DS::Flat;
+                break;
+
+            case aiShadingMode_Gouraud:
+            case aiShadingMode_Toon:
+            case aiShadingMode_OrenNayar:
+            case aiShadingMode_Minnaert:
+                shading_mode_out = Discreet3DS::Gouraud;
+                break;
+
+            case aiShadingMode_Phong:
+            case aiShadingMode_Blinn:
+            case aiShadingMode_CookTorrance:
+            case aiShadingMode_Fresnel:
+                shading_mode_out = Discreet3DS::Phong;
+                break;
+
+            default:
+                shading_mode_out = Discreet3DS::Flat;
+                ai_assert(false);
+            };
+            writer.PutU2(static_cast<uint16_t>(shading_mode_out));
+        }
+
+
+        float f;
+        if (mat.Get(AI_MATKEY_SHININESS, f) == AI_SUCCESS) {
+            ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHININESS);
+            WritePercentChunk(f);
+        }
+
+        if (mat.Get(AI_MATKEY_SHININESS_STRENGTH, f) == AI_SUCCESS) {
+            ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_SHININESS_PERCENT);
+            WritePercentChunk(f);
+        }
+
+        int twosided;
+        if (mat.Get(AI_MATKEY_TWOSIDED, twosided) == AI_SUCCESS && twosided != 0) {
+            ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_TWO_SIDE);
+            writer.PutI2(1);
+        }
+
+        WriteTexture(mat, aiTextureType_DIFFUSE, Discreet3DS::CHUNK_MAT_TEXTURE);
+        WriteTexture(mat, aiTextureType_HEIGHT, Discreet3DS::CHUNK_MAT_BUMPMAP);
+        WriteTexture(mat, aiTextureType_OPACITY, Discreet3DS::CHUNK_MAT_OPACMAP);
+        WriteTexture(mat, aiTextureType_SHININESS, Discreet3DS::CHUNK_MAT_MAT_SHINMAP);
+        WriteTexture(mat, aiTextureType_SPECULAR, Discreet3DS::CHUNK_MAT_SPECMAP);
+        WriteTexture(mat, aiTextureType_EMISSIVE, Discreet3DS::CHUNK_MAT_SELFIMAP);
+        WriteTexture(mat, aiTextureType_REFLECTION, Discreet3DS::CHUNK_MAT_REFLMAP);
+    }
+}
+
+// ------------------------------------------------------------------------------------------------
+void Discreet3DSExporter::WriteTexture(const aiMaterial& mat, aiTextureType type, uint16_t chunk_flags)
+{
+    aiString path;
+    aiTextureMapMode map_mode[2] = {
+        aiTextureMapMode_Wrap, aiTextureMapMode_Wrap
+    };
+    float blend = 1.0f;
+    if (mat.GetTexture(type, 0, &path, NULL, NULL, &blend, NULL, map_mode) != AI_SUCCESS || !path.length) {
+        return;
+    }
+
+    // TODO: handle embedded textures properly
+    if (path.data[0] == '*') {
+        DefaultLogger::get()->error("Ignoring embedded texture for export: " + std::string(path.C_Str()));
+        return;
+    }
+
+    ChunkWriter chunk(writer, chunk_flags);
+    {
+        ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAPFILE);
+        WriteString(path);
+    }
+
+    WritePercentChunk(blend);
+
+    {
+        ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAT_MAP_TILING);
+        uint16_t val = 0; // WRAP
+        if (map_mode[0] == aiTextureMapMode_Mirror) {
+            val = 0x2;
+        }
+        else if (map_mode[0] == aiTextureMapMode_Decal) {
+            val = 0x10;
+        }
+        writer.PutU2(val);
+    }
+    // TODO: export texture transformation (i.e. UV offset, scale, rotation)
+}
+
+// ------------------------------------------------------------------------------------------------
+void Discreet3DSExporter::WriteMeshes()
+{
+    // NOTE: 3DS allows for instances. However:
+    //   i)  not all importers support reading them
+    //   ii) instances are not as flexible as they are in assimp, in particular,
+    //        nodes can carry (and instance) only one mesh.
+    //
+    // This exporter currently deep clones all instanced meshes, i.e. for each mesh
+    // attached to a node a full TRIMESH chunk is written to the file.
+    //
+    // Furthermore, the TRIMESH is transformed into world space so that it will
+    // appear correctly if importers don't read the scene hierarchy at all.
+    for (MeshesByNodeMap::const_iterator it = meshes.begin(); it != meshes.end(); ++it) {
+        const aiNode& node = *(*it).first;
+        const unsigned int mesh_idx = (*it).second;
+
+        const aiMesh& mesh = *scene->mMeshes[mesh_idx];
+
+        // This should not happen if the SLM step is correctly executed
+        // before the scene is handed to the exporter
+        ai_assert(mesh.mNumVertices <= 0xffff);
+        ai_assert(mesh.mNumFaces <= 0xffff);
+
+        const aiMatrix4x4& trafo = trafos[&node];
+
+        ChunkWriter chunk(writer, Discreet3DS::CHUNK_OBJBLOCK);
+
+        // Mesh name is tied to the node it is attached to so it can later be referenced
+        const std::string& name = GetMeshName(mesh, mesh_idx, node);
+        WriteString(name);
+
+
+        // TRIMESH chunk
+        ChunkWriter chunk2(writer, Discreet3DS::CHUNK_TRIMESH);
+
+        // Vertices in world space
+        {
+            ChunkWriter chunk(writer, Discreet3DS::CHUNK_VERTLIST);
+
+            const uint16_t count = static_cast<uint16_t>(mesh.mNumVertices);
+            writer.PutU2(count);
+            for (unsigned int i = 0; i < mesh.mNumVertices; ++i) {
+                const aiVector3D& v = trafo * mesh.mVertices[i];
+                writer.PutF4(v.x);
+                writer.PutF4(v.y);
+                writer.PutF4(v.z);
+            }
+        }
+
+        // UV coordinates
+        if (mesh.HasTextureCoords(0)) {
+            ChunkWriter chunk(writer, Discreet3DS::CHUNK_MAPLIST);
+            const uint16_t count = static_cast<uint16_t>(mesh.mNumVertices);
+            writer.PutU2(count);
+
+            for (unsigned int i = 0; i < mesh.mNumVertices; ++i) {
+                const aiVector3D& v = mesh.mTextureCoords[0][i];
+                writer.PutF4(v.x);
+                writer.PutF4(v.y);
+            }
+        }
+
+        // Faces (indices)
+        {
+            ChunkWriter chunk(writer, Discreet3DS::CHUNK_FACELIST);
+
+            ai_assert(mesh.mNumFaces <= 0xffff);
+
+            // Count triangles, discard lines and points
+            uint16_t count = 0;
+            for (unsigned int i = 0; i < mesh.mNumFaces; ++i) {
+                const aiFace& f = mesh.mFaces[i];
+                if (f.mNumIndices < 3) {
+                    continue;
+                }
+                // TRIANGULATE step is a pre-requisite so we should not see polys here
+                ai_assert(f.mNumIndices == 3);
+                ++count;
+            }
+
+            writer.PutU2(count);
+            for (unsigned int i = 0; i < mesh.mNumFaces; ++i) {
+                const aiFace& f = mesh.mFaces[i];
+                if (f.mNumIndices < 3) {
+                    continue;
+                }
+
+                for (unsigned int j = 0; j < 3; ++j) {
+                    ai_assert(f.mIndices[j] <= 0xffff);
+                    writer.PutI2(static_cast<uint16_t>(f.mIndices[j]));
+                }
+
+                // Edge visibility flag
+                writer.PutI2(0x0);
+            }
+
+            // TODO: write smoothing groups (CHUNK_SMOOLIST)
+
+            WriteFaceMaterialChunk(mesh);
+        }
+
+        // Transformation matrix by which the mesh vertices have been pre-transformed with.
+        {
+            ChunkWriter chunk(writer, Discreet3DS::CHUNK_TRMATRIX);
+            for (unsigned int r = 0; r < 4; ++r) {
+                for (unsigned int c = 0; c < 3; ++c) {
+                    writer.PutF4(trafo[r][c]);
+                }
+            }
+        }
+    }
+}
+
+// ------------------------------------------------------------------------------------------------
+void Discreet3DSExporter::WriteFaceMaterialChunk(const aiMesh& mesh)
+{
+    ChunkWriter chunk(writer, Discreet3DS::CHUNK_FACEMAT);
+    const std::string& name = GetMaterialName(*scene->mMaterials[mesh.mMaterialIndex], mesh.mMaterialIndex);
+    WriteString(name);
+
+    // Because assimp splits meshes by material, only a single
+    // FACEMAT chunk needs to be written
+    ai_assert(mesh.mNumFaces <= 0xffff);
+    const uint16_t count = static_cast<uint16_t>(mesh.mNumFaces);
+    writer.PutU2(count);
+
+    for (unsigned int i = 0; i < mesh.mNumFaces; ++i) {
+        writer.PutU2(static_cast<uint16_t>(i));
+    }
+}
+
+// ------------------------------------------------------------------------------------------------
+void Discreet3DSExporter::WriteString(const std::string& s) {
+    for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) {
+        writer.PutI1(*it);
+    }
+    writer.PutI1('\0');
+}
+
+// ------------------------------------------------------------------------------------------------
+void Discreet3DSExporter::WriteString(const aiString& s) {
+    for (std::size_t i = 0; i < s.length; ++i) {
+        writer.PutI1(s.data[i]);
+    }
+    writer.PutI1('\0');
+}
+
+// ------------------------------------------------------------------------------------------------
+void Discreet3DSExporter::WriteColor(const aiColor3D& color) {
+    ChunkWriter chunk(writer, Discreet3DS::CHUNK_RGBF);
+    writer.PutF4(color.r);
+    writer.PutF4(color.g);
+    writer.PutF4(color.b);
+}
+
+// ------------------------------------------------------------------------------------------------
+void Discreet3DSExporter::WritePercentChunk(float f) {
+    ChunkWriter chunk(writer, Discreet3DS::CHUNK_PERCENTF);
+    writer.PutF4(f);
+}
+
+
+#endif // ASSIMP_BUILD_NO_3DS_EXPORTER
+#endif // ASSIMP_BUILD_NO_EXPORT

+ 98 - 0
assimplib.mod/assimp/code/3DSExporter.h

@@ -0,0 +1,98 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2015, 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 3DSExporter.h
+ * 3DS Exporter Main Header
+ */
+#ifndef AI_3DSEXPORTER_H_INC
+#define AI_3DSEXPORTER_H_INC
+
+#include <map>
+#include <boost/shared_ptr.hpp>
+
+#include "StreamWriter.h"
+#include "./../include/assimp/material.h"
+
+struct aiScene;
+struct aiNode;
+struct aiMaterial;
+struct aiMesh;
+
+namespace Assimp
+{
+
+// ------------------------------------------------------------------------------------------------
+/** Helper class to export a given scene to a 3DS file. */
+// ------------------------------------------------------------------------------------------------
+class Discreet3DSExporter
+{
+public:
+    Discreet3DSExporter(boost::shared_ptr<IOStream> outfile, const aiScene* pScene);
+
+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);
+    void WritePercentChunk(float f);
+
+private:
+
+    const aiScene* const scene;
+    StreamWriterLE writer;
+
+    std::map<const aiNode*, aiMatrix4x4> trafos;
+
+    typedef std::multimap<const aiNode*, unsigned int> MeshesByNodeMap;
+    MeshesByNodeMap meshes;
+
+};
+
+}
+
+#endif

+ 458 - 451
assimplib.mod/assimp/code/3DSHelper.h

@@ -2,11 +2,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -23,16 +23,16 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -46,9 +46,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include "SpatialSort.h"
 #include "SmoothingGroups.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 <stdio.h> //sprintf
 
-namespace Assimp	{
-namespace D3DS	{
+namespace Assimp    {
+namespace D3DS  {
 
 #include "./../include/assimp/Compiler/pushpack1.h"
 
@@ -59,253 +65,253 @@ namespace D3DS	{
 class Discreet3DS
 {
 private:
-	inline Discreet3DS() {}
+    inline Discreet3DS() {}
 
 public:
 
-	//! data structure for a single chunk in a .3ds file
-	struct Chunk
-	{
-		uint16_t	Flag;
-		uint32_t	Size;
-	} PACK_STRUCT;
-
-
-	//! Used for shading field in material3ds structure
-	//! From AutoDesk 3ds SDK
-	typedef enum
-	{
-		// translated to gouraud shading with wireframe active
-		Wire = 0x0,
-
-		// if this material is set, no vertex normals will
-		// be calculated for the model. Face normals + gouraud
-		Flat = 0x1,
-
-		// standard gouraud shading
-		Gouraud = 0x2,
-
-		// phong shading
-		Phong = 0x3,
-
-		// cooktorrance or anistropic phong shading ...
-		// the exact meaning is unknown, if you know it
-		// feel free to tell me ;-)
-		Metal = 0x4,
-
-		// required by the ASE loader
-		Blinn = 0x5
-	} shadetype3ds;
-
-	// Flags for animated keys
-	enum
-	{
-		KEY_USE_TENS         = 0x1,
-		KEY_USE_CONT         = 0x2,
-		KEY_USE_BIAS         = 0x4,
-		KEY_USE_EASE_TO      = 0x8,
-		KEY_USE_EASE_FROM    = 0x10
-	} ;
-
-	enum 
-	{
-
-		// ********************************************************************
-		// Basic chunks which can be found everywhere in the file
-		CHUNK_VERSION	= 0x0002,
-		CHUNK_RGBF      = 0x0010,		// float4 R; float4 G; float4 B
-		CHUNK_RGBB      = 0x0011,		// int1 R; int1 G; int B
-
-		// Linear color values (gamma = 2.2?)
-		CHUNK_LINRGBF      = 0x0013,	// float4 R; float4 G; float4 B
-		CHUNK_LINRGBB      = 0x0012,	// int1 R; int1 G; int B
-
-		CHUNK_PERCENTW	= 0x0030,		// int2   percentage
-		CHUNK_PERCENTF	= 0x0031,		// float4  percentage
-		// ********************************************************************
-
-		// Prj master chunk
-		CHUNK_PRJ       = 0xC23D,
-
-		// MDLI master chunk
-		CHUNK_MLI       = 0x3DAA,
-
-		// Primary main chunk of the .3ds file
-		CHUNK_MAIN      = 0x4D4D,
-
-		// Mesh main chunk
-		CHUNK_OBJMESH   = 0x3D3D,
-
-		// Specifies the background color of the .3ds file
-		// This is passed through the material system for
-		// viewing purposes.
-		CHUNK_BKGCOLOR  = 0x1200,
-
-		// Specifies the ambient base color of the scene.
-		// This is added to all materials in the file
-		CHUNK_AMBCOLOR  = 0x2100,
-
-		// Specifies the background image for the whole scene
-		// This value is passed through the material system
-		// to the viewer 
-		CHUNK_BIT_MAP   = 0x1100,
-		CHUNK_BIT_MAP_EXISTS  = 0x1101,
-
-		// ********************************************************************
-		// Viewport related stuff. Ignored
-		CHUNK_DEFAULT_VIEW = 0x3000,
-		CHUNK_VIEW_TOP = 0x3010,
-		CHUNK_VIEW_BOTTOM = 0x3020,
-		CHUNK_VIEW_LEFT = 0x3030,
-		CHUNK_VIEW_RIGHT = 0x3040,
-		CHUNK_VIEW_FRONT = 0x3050,
-		CHUNK_VIEW_BACK = 0x3060,
-		CHUNK_VIEW_USER = 0x3070,
-		CHUNK_VIEW_CAMERA = 0x3080,
-		// ********************************************************************
-
-		// Mesh chunks
-		CHUNK_OBJBLOCK  = 0x4000,
-		CHUNK_TRIMESH   = 0x4100,
-		CHUNK_VERTLIST  = 0x4110,
-		CHUNK_VERTFLAGS = 0x4111,
-		CHUNK_FACELIST  = 0x4120,
-		CHUNK_FACEMAT   = 0x4130,
-		CHUNK_MAPLIST   = 0x4140,
-		CHUNK_SMOOLIST  = 0x4150,
-		CHUNK_TRMATRIX  = 0x4160,
-		CHUNK_MESHCOLOR = 0x4165,
-		CHUNK_TXTINFO   = 0x4170,
-		CHUNK_LIGHT     = 0x4600,
-		CHUNK_CAMERA    = 0x4700,
-		CHUNK_HIERARCHY = 0x4F00,
-
-		// Specifies the global scaling factor. This is applied
-		// to the root node's transformation matrix
-		CHUNK_MASTER_SCALE    = 0x0100,
-
-		// ********************************************************************
-		// Material chunks
-		CHUNK_MAT_MATERIAL  = 0xAFFF,
-
-			// asciiz containing the name of the material
-			CHUNK_MAT_MATNAME   = 0xA000, 
-			CHUNK_MAT_AMBIENT   = 0xA010, // followed by color chunk
-			CHUNK_MAT_DIFFUSE   = 0xA020, // followed by color chunk
-			CHUNK_MAT_SPECULAR  = 0xA030, // followed by color chunk
-
-			// Specifies the shininess of the material
-			// followed by percentage chunk
-			CHUNK_MAT_SHININESS  = 0xA040, 
-			CHUNK_MAT_SHININESS_PERCENT  = 0xA041 ,
-
-			// Specifies the shading mode to be used
-			// followed by a short
-			CHUNK_MAT_SHADING  = 0xA100, 
-
-			// NOTE: Emissive color (self illumination) seems not
-			// to be a color but a single value, type is unknown.
-			// Make the parser accept both of them.
-			// followed by percentage chunk (?)
-			CHUNK_MAT_SELF_ILLUM = 0xA080,  
-
-			// Always followed by percentage chunk	(?)
-			CHUNK_MAT_SELF_ILPCT = 0xA084,  
-
-			// Always followed by percentage chunk
-			CHUNK_MAT_TRANSPARENCY = 0xA050, 
-
-			// Diffuse texture channel 0 
-			CHUNK_MAT_TEXTURE   = 0xA200,
-
-			// Contains opacity information for each texel
-			CHUNK_MAT_OPACMAP = 0xA210,
-
-			// Contains a reflection map to be used to reflect
-			// the environment. This is partially supported.
-			CHUNK_MAT_REFLMAP = 0xA220,
-
-			// Self Illumination map (emissive colors)
-			CHUNK_MAT_SELFIMAP = 0xA33d,	
-
-			// Bumpmap. Not specified whether it is a heightmap
-			// or a normal map. Assme it is a heightmap since
-			// artist normally prefer this format.
-			CHUNK_MAT_BUMPMAP = 0xA230,
-
-			// Specular map. Seems to influence the specular color
-			CHUNK_MAT_SPECMAP = 0xA204,
-
-			// Holds shininess data. 
-			CHUNK_MAT_MAT_SHINMAP = 0xA33C,
-
-			// Scaling in U/V direction.
-			// (need to gen separate UV coordinate set 
-			// and do this by hand)
-			CHUNK_MAT_MAP_USCALE 	  = 0xA354,
-			CHUNK_MAT_MAP_VSCALE 	  = 0xA356,
-
-			// Translation in U/V direction.
-			// (need to gen separate UV coordinate set 
-			// and do this by hand)
-			CHUNK_MAT_MAP_UOFFSET 	  = 0xA358,
-			CHUNK_MAT_MAP_VOFFSET 	  = 0xA35a,
-
-			// UV-coordinates rotation around the z-axis
-			// Assumed to be in radians.
-			CHUNK_MAT_MAP_ANG = 0xA35C,
-
-			// Tiling flags for 3DS files
-			CHUNK_MAT_MAP_TILING = 0xa351,
-
-			// Specifies the file name of a texture
-			CHUNK_MAPFILE   = 0xA300,
-
-			// Specifies whether a materail requires two-sided rendering
-			CHUNK_MAT_TWO_SIDE = 0xA081,  
-		// ********************************************************************
-
-		// Main keyframer chunk. Contains translation/rotation/scaling data
-		CHUNK_KEYFRAMER		= 0xB000,
-
-		// Supported sub chunks
-		CHUNK_TRACKINFO		= 0xB002,
-		CHUNK_TRACKOBJNAME  = 0xB010,
-		CHUNK_TRACKDUMMYOBJNAME  = 0xB011,
-		CHUNK_TRACKPIVOT    = 0xB013,
-		CHUNK_TRACKPOS      = 0xB020,
-		CHUNK_TRACKROTATE   = 0xB021,
-		CHUNK_TRACKSCALE    = 0xB022,
-
-		// ********************************************************************
-		// Keyframes for various other stuff in the file
-		// Partially ignored
-		CHUNK_AMBIENTKEY    = 0xB001,
-		CHUNK_TRACKMORPH    = 0xB026,
-		CHUNK_TRACKHIDE     = 0xB029,
-		CHUNK_OBJNUMBER     = 0xB030,
-		CHUNK_TRACKCAMERA	= 0xB003,
-		CHUNK_TRACKFOV		= 0xB023,
-		CHUNK_TRACKROLL		= 0xB024,
-		CHUNK_TRACKCAMTGT	= 0xB004,
-		CHUNK_TRACKLIGHT	= 0xB005,
-		CHUNK_TRACKLIGTGT	= 0xB006,
-		CHUNK_TRACKSPOTL	= 0xB007,
-		CHUNK_FRAMES		= 0xB008,
-		// ********************************************************************
-
-		// light sub-chunks
-		CHUNK_DL_OFF                 = 0x4620,
-		CHUNK_DL_OUTER_RANGE         = 0x465A,
-		CHUNK_DL_INNER_RANGE         = 0x4659,
-		CHUNK_DL_MULTIPLIER          = 0x465B,
-		CHUNK_DL_EXCLUDE             = 0x4654,
-		CHUNK_DL_ATTENUATE           = 0x4625,
-		CHUNK_DL_SPOTLIGHT           = 0x4610,
-
-		// camera sub-chunks
-		CHUNK_CAM_RANGES             = 0x4720
-	};
+    //! data structure for a single chunk in a .3ds file
+    struct Chunk
+    {
+        uint16_t    Flag;
+        uint32_t    Size;
+    } PACK_STRUCT;
+
+
+    //! Used for shading field in material3ds structure
+    //! From AutoDesk 3ds SDK
+    typedef enum
+    {
+        // translated to gouraud shading with wireframe active
+        Wire = 0x0,
+
+        // if this material is set, no vertex normals will
+        // be calculated for the model. Face normals + gouraud
+        Flat = 0x1,
+
+        // standard gouraud shading
+        Gouraud = 0x2,
+
+        // phong shading
+        Phong = 0x3,
+
+        // cooktorrance or anistropic phong shading ...
+        // the exact meaning is unknown, if you know it
+        // feel free to tell me ;-)
+        Metal = 0x4,
+
+        // required by the ASE loader
+        Blinn = 0x5
+    } shadetype3ds;
+
+    // Flags for animated keys
+    enum
+    {
+        KEY_USE_TENS         = 0x1,
+        KEY_USE_CONT         = 0x2,
+        KEY_USE_BIAS         = 0x4,
+        KEY_USE_EASE_TO      = 0x8,
+        KEY_USE_EASE_FROM    = 0x10
+    } ;
+
+    enum
+    {
+
+        // ********************************************************************
+        // Basic chunks which can be found everywhere in the file
+        CHUNK_VERSION   = 0x0002,
+        CHUNK_RGBF      = 0x0010,       // float4 R; float4 G; float4 B
+        CHUNK_RGBB      = 0x0011,       // int1 R; int1 G; int B
+
+        // Linear color values (gamma = 2.2?)
+        CHUNK_LINRGBF      = 0x0013,    // float4 R; float4 G; float4 B
+        CHUNK_LINRGBB      = 0x0012,    // int1 R; int1 G; int B
+
+        CHUNK_PERCENTW  = 0x0030,       // int2   percentage
+        CHUNK_PERCENTF  = 0x0031,       // float4  percentage
+        // ********************************************************************
+
+        // Prj master chunk
+        CHUNK_PRJ       = 0xC23D,
+
+        // MDLI master chunk
+        CHUNK_MLI       = 0x3DAA,
+
+        // Primary main chunk of the .3ds file
+        CHUNK_MAIN      = 0x4D4D,
+
+        // Mesh main chunk
+        CHUNK_OBJMESH   = 0x3D3D,
+
+        // Specifies the background color of the .3ds file
+        // This is passed through the material system for
+        // viewing purposes.
+        CHUNK_BKGCOLOR  = 0x1200,
+
+        // Specifies the ambient base color of the scene.
+        // This is added to all materials in the file
+        CHUNK_AMBCOLOR  = 0x2100,
+
+        // Specifies the background image for the whole scene
+        // This value is passed through the material system
+        // to the viewer
+        CHUNK_BIT_MAP   = 0x1100,
+        CHUNK_BIT_MAP_EXISTS  = 0x1101,
+
+        // ********************************************************************
+        // Viewport related stuff. Ignored
+        CHUNK_DEFAULT_VIEW = 0x3000,
+        CHUNK_VIEW_TOP = 0x3010,
+        CHUNK_VIEW_BOTTOM = 0x3020,
+        CHUNK_VIEW_LEFT = 0x3030,
+        CHUNK_VIEW_RIGHT = 0x3040,
+        CHUNK_VIEW_FRONT = 0x3050,
+        CHUNK_VIEW_BACK = 0x3060,
+        CHUNK_VIEW_USER = 0x3070,
+        CHUNK_VIEW_CAMERA = 0x3080,
+        // ********************************************************************
+
+        // Mesh chunks
+        CHUNK_OBJBLOCK  = 0x4000,
+        CHUNK_TRIMESH   = 0x4100,
+        CHUNK_VERTLIST  = 0x4110,
+        CHUNK_VERTFLAGS = 0x4111,
+        CHUNK_FACELIST  = 0x4120,
+        CHUNK_FACEMAT   = 0x4130,
+        CHUNK_MAPLIST   = 0x4140,
+        CHUNK_SMOOLIST  = 0x4150,
+        CHUNK_TRMATRIX  = 0x4160,
+        CHUNK_MESHCOLOR = 0x4165,
+        CHUNK_TXTINFO   = 0x4170,
+        CHUNK_LIGHT     = 0x4600,
+        CHUNK_CAMERA    = 0x4700,
+        CHUNK_HIERARCHY = 0x4F00,
+
+        // Specifies the global scaling factor. This is applied
+        // to the root node's transformation matrix
+        CHUNK_MASTER_SCALE    = 0x0100,
+
+        // ********************************************************************
+        // Material chunks
+        CHUNK_MAT_MATERIAL  = 0xAFFF,
+
+            // asciiz containing the name of the material
+            CHUNK_MAT_MATNAME   = 0xA000,
+            CHUNK_MAT_AMBIENT   = 0xA010, // followed by color chunk
+            CHUNK_MAT_DIFFUSE   = 0xA020, // followed by color chunk
+            CHUNK_MAT_SPECULAR  = 0xA030, // followed by color chunk
+
+            // Specifies the shininess of the material
+            // followed by percentage chunk
+            CHUNK_MAT_SHININESS  = 0xA040,
+            CHUNK_MAT_SHININESS_PERCENT  = 0xA041 ,
+
+            // Specifies the shading mode to be used
+            // followed by a short
+            CHUNK_MAT_SHADING  = 0xA100,
+
+            // NOTE: Emissive color (self illumination) seems not
+            // to be a color but a single value, type is unknown.
+            // Make the parser accept both of them.
+            // followed by percentage chunk (?)
+            CHUNK_MAT_SELF_ILLUM = 0xA080,
+
+            // Always followed by percentage chunk  (?)
+            CHUNK_MAT_SELF_ILPCT = 0xA084,
+
+            // Always followed by percentage chunk
+            CHUNK_MAT_TRANSPARENCY = 0xA050,
+
+            // Diffuse texture channel 0
+            CHUNK_MAT_TEXTURE   = 0xA200,
+
+            // Contains opacity information for each texel
+            CHUNK_MAT_OPACMAP = 0xA210,
+
+            // Contains a reflection map to be used to reflect
+            // the environment. This is partially supported.
+            CHUNK_MAT_REFLMAP = 0xA220,
+
+            // Self Illumination map (emissive colors)
+            CHUNK_MAT_SELFIMAP = 0xA33d,
+
+            // Bumpmap. Not specified whether it is a heightmap
+            // or a normal map. Assme it is a heightmap since
+            // artist normally prefer this format.
+            CHUNK_MAT_BUMPMAP = 0xA230,
+
+            // Specular map. Seems to influence the specular color
+            CHUNK_MAT_SPECMAP = 0xA204,
+
+            // Holds shininess data.
+            CHUNK_MAT_MAT_SHINMAP = 0xA33C,
+
+            // Scaling in U/V direction.
+            // (need to gen separate UV coordinate set
+            // and do this by hand)
+            CHUNK_MAT_MAP_USCALE      = 0xA354,
+            CHUNK_MAT_MAP_VSCALE      = 0xA356,
+
+            // Translation in U/V direction.
+            // (need to gen separate UV coordinate set
+            // and do this by hand)
+            CHUNK_MAT_MAP_UOFFSET     = 0xA358,
+            CHUNK_MAT_MAP_VOFFSET     = 0xA35a,
+
+            // UV-coordinates rotation around the z-axis
+            // Assumed to be in radians.
+            CHUNK_MAT_MAP_ANG = 0xA35C,
+
+            // Tiling flags for 3DS files
+            CHUNK_MAT_MAP_TILING = 0xa351,
+
+            // Specifies the file name of a texture
+            CHUNK_MAPFILE   = 0xA300,
+
+            // Specifies whether a materail requires two-sided rendering
+            CHUNK_MAT_TWO_SIDE = 0xA081,
+        // ********************************************************************
+
+        // Main keyframer chunk. Contains translation/rotation/scaling data
+        CHUNK_KEYFRAMER     = 0xB000,
+
+        // Supported sub chunks
+        CHUNK_TRACKINFO     = 0xB002,
+        CHUNK_TRACKOBJNAME  = 0xB010,
+        CHUNK_TRACKDUMMYOBJNAME  = 0xB011,
+        CHUNK_TRACKPIVOT    = 0xB013,
+        CHUNK_TRACKPOS      = 0xB020,
+        CHUNK_TRACKROTATE   = 0xB021,
+        CHUNK_TRACKSCALE    = 0xB022,
+
+        // ********************************************************************
+        // Keyframes for various other stuff in the file
+        // Partially ignored
+        CHUNK_AMBIENTKEY    = 0xB001,
+        CHUNK_TRACKMORPH    = 0xB026,
+        CHUNK_TRACKHIDE     = 0xB029,
+        CHUNK_OBJNUMBER     = 0xB030,
+        CHUNK_TRACKCAMERA   = 0xB003,
+        CHUNK_TRACKFOV      = 0xB023,
+        CHUNK_TRACKROLL     = 0xB024,
+        CHUNK_TRACKCAMTGT   = 0xB004,
+        CHUNK_TRACKLIGHT    = 0xB005,
+        CHUNK_TRACKLIGTGT   = 0xB006,
+        CHUNK_TRACKSPOTL    = 0xB007,
+        CHUNK_FRAMES        = 0xB008,
+        // ********************************************************************
+
+        // light sub-chunks
+        CHUNK_DL_OFF                 = 0x4620,
+        CHUNK_DL_OUTER_RANGE         = 0x465A,
+        CHUNK_DL_INNER_RANGE         = 0x4659,
+        CHUNK_DL_MULTIPLIER          = 0x465B,
+        CHUNK_DL_EXCLUDE             = 0x4654,
+        CHUNK_DL_ATTENUATE           = 0x4625,
+        CHUNK_DL_SPOTLIGHT           = 0x4610,
+
+        // camera sub-chunks
+        CHUNK_CAM_RANGES             = 0x4720
+    };
 };
 
 // ---------------------------------------------------------------------------
@@ -318,38 +324,39 @@ struct Face : public FaceWithSmoothingGroup
 /** Helper structure representing a texture */
 struct Texture
 {
-	//! Default constructor
-	Texture()
-		: mOffsetU	(0.0f)
-		, mOffsetV	(0.0f)
-		, mScaleU	(1.0f)
-		, mScaleV	(1.0f)
-		, mRotation	(0.0f)
-		, mMapMode	(aiTextureMapMode_Wrap)
-		, iUVSrc	(0)
-	{
-		mTextureBlend = get_qnan();
-	}
-
-	//! Specifies the blend factor for the texture
-	float mTextureBlend;
-
-	//! Specifies the filename of the texture
-	std::string mMapName;
-
-	//! Specifies texture coordinate offsets/scaling/rotations
-	float mOffsetU;
-	float mOffsetV;
-	float mScaleU;
-	float mScaleV;
-	float mRotation;
-
-	//! Specifies the mapping mode to be used for the texture
-	aiTextureMapMode mMapMode;
-
-	//! Used internally
-	bool bPrivate;
-	int iUVSrc;
+    //! Default constructor
+    Texture()
+        : mOffsetU  (0.0f)
+        , mOffsetV  (0.0f)
+        , mScaleU   (1.0f)
+        , mScaleV   (1.0f)
+        , mRotation (0.0f)
+        , mMapMode  (aiTextureMapMode_Wrap)
+        , bPrivate()
+        , iUVSrc    (0)
+    {
+        mTextureBlend = get_qnan();
+    }
+
+    //! Specifies the blend factor for the texture
+    float mTextureBlend;
+
+    //! Specifies the filename of the texture
+    std::string mMapName;
+
+    //! Specifies texture coordinate offsets/scaling/rotations
+    float mOffsetU;
+    float mOffsetV;
+    float mScaleU;
+    float mScaleV;
+    float mRotation;
+
+    //! Specifies the mapping mode to be used for the texture
+    aiTextureMapMode mMapMode;
+
+    //! Used internally
+    bool bPrivate;
+    int iUVSrc;
 };
 
 #include "./../include/assimp/Compiler/poppack1.h"
@@ -358,117 +365,117 @@ struct Texture
 /** Helper structure representing a 3ds material */
 struct Material
 {
-	//! Default constructor. Builds a default name for the material
-	Material()
-		: 
-	mDiffuse			(0.6f,0.6f,0.6f), // FIX ... we won't want object to be black
-	mSpecularExponent	(0.0f),
-	mShininessStrength	(1.0f),
-	mShading(Discreet3DS::Gouraud),
-	mTransparency		(1.0f),
-	mBumpHeight			(1.0f),
-	mTwoSided			(false)
-	{
-		static int iCnt = 0;
-		
-		char szTemp[128];
-		sprintf(szTemp,"UNNAMED_%i",iCnt++);
-		mName = szTemp;
-	}
-
-	//! Name of the material
-	std::string mName;
-	//! Diffuse color of the material
-	aiColor3D mDiffuse;
-	//! Specular exponent
-	float mSpecularExponent;
-	//! Shininess strength, in percent
-	float mShininessStrength;
-	//! Specular color of the material
-	aiColor3D mSpecular;
-	//! Ambient color of the material
-	aiColor3D mAmbient;
-	//! Shading type to be used
-	Discreet3DS::shadetype3ds mShading;
-	//! Opacity of the material
-	float mTransparency;
-	//! Diffuse texture channel
-	Texture sTexDiffuse;
-	//! Opacity texture channel
-	Texture sTexOpacity;
-	//! Specular texture channel
-	Texture sTexSpecular;
-	//! Reflective texture channel
-	Texture sTexReflective;
-	//! Bump texture channel
-	Texture sTexBump;
-	//! Emissive texture channel
-	Texture sTexEmissive;
-	//! Shininess texture channel
-	Texture sTexShininess;
-	//! Scaling factor for the bump values
-	float mBumpHeight;
-	//! Emissive color
-	aiColor3D mEmissive;
-	//! Ambient texture channel
-	//! (used by the ASE format)
-	Texture sTexAmbient;
-	//! True if the material must be rendered from two sides
-	bool mTwoSided;
+    //! Default constructor. Builds a default name for the material
+    Material()
+        :
+    mDiffuse            (0.6f,0.6f,0.6f), // FIX ... we won't want object to be black
+    mSpecularExponent   (0.0f),
+    mShininessStrength  (1.0f),
+    mShading(Discreet3DS::Gouraud),
+    mTransparency       (1.0f),
+    mBumpHeight         (1.0f),
+    mTwoSided           (false)
+    {
+        static int iCnt = 0;
+
+        char szTemp[128];
+        sprintf(szTemp,"UNNAMED_%i",iCnt++);
+        mName = szTemp;
+    }
+
+    //! Name of the material
+    std::string mName;
+    //! Diffuse color of the material
+    aiColor3D mDiffuse;
+    //! Specular exponent
+    float mSpecularExponent;
+    //! Shininess strength, in percent
+    float mShininessStrength;
+    //! Specular color of the material
+    aiColor3D mSpecular;
+    //! Ambient color of the material
+    aiColor3D mAmbient;
+    //! Shading type to be used
+    Discreet3DS::shadetype3ds mShading;
+    //! Opacity of the material
+    float mTransparency;
+    //! Diffuse texture channel
+    Texture sTexDiffuse;
+    //! Opacity texture channel
+    Texture sTexOpacity;
+    //! Specular texture channel
+    Texture sTexSpecular;
+    //! Reflective texture channel
+    Texture sTexReflective;
+    //! Bump texture channel
+    Texture sTexBump;
+    //! Emissive texture channel
+    Texture sTexEmissive;
+    //! Shininess texture channel
+    Texture sTexShininess;
+    //! Scaling factor for the bump values
+    float mBumpHeight;
+    //! Emissive color
+    aiColor3D mEmissive;
+    //! Ambient texture channel
+    //! (used by the ASE format)
+    Texture sTexAmbient;
+    //! True if the material must be rendered from two sides
+    bool mTwoSided;
 };
 
 // ---------------------------------------------------------------------------
 /** Helper structure to represent a 3ds file mesh */
 struct Mesh : public MeshWithSmoothingGroups<D3DS::Face>
 {
-	//! Default constructor
-	Mesh()
-	{
-		static int iCnt = 0;
-		
-		// Generate a default name for the mesh
-		char szTemp[128];
-		::sprintf(szTemp,"UNNAMED_%i",iCnt++);
-		mName = szTemp;
-	}
-
-	//! Name of the mesh
-	std::string mName;
-
-	//! Texture coordinates
-	std::vector<aiVector3D> mTexCoords;
-
-	//! Face materials
-	std::vector<unsigned int> mFaceMaterials;
-
-	//! Local transformation matrix
-	aiMatrix4x4 mMat;
+    //! Default constructor
+    Mesh()
+    {
+        static int iCnt = 0;
+
+        // Generate a default name for the mesh
+        char szTemp[128];
+        ::sprintf(szTemp,"UNNAMED_%i",iCnt++);
+        mName = szTemp;
+    }
+
+    //! Name of the mesh
+    std::string mName;
+
+    //! Texture coordinates
+    std::vector<aiVector3D> mTexCoords;
+
+    //! Face materials
+    std::vector<unsigned int> mFaceMaterials;
+
+    //! Local transformation matrix
+    aiMatrix4x4 mMat;
 };
 
 // ---------------------------------------------------------------------------
 /** Float key - quite similar to aiVectorKey and aiQuatKey. Both are in the
     C-API, so it would be difficult to make them a template. */
-struct aiFloatKey 
+struct aiFloatKey
 {
-	double mTime;      ///< The time of this key
-	float mValue;	///< The value of this key
+    double mTime;      ///< The time of this key
+    float mValue;   ///< The value of this key
 
 #ifdef __cplusplus
 
-	// time is not compared
-	bool operator == (const aiFloatKey& o) const
-		{return o.mValue == this->mValue;}
+    // time is not compared
+    bool operator == (const aiFloatKey& o) const
+        {return o.mValue == this->mValue;}
 
-	bool operator != (const aiFloatKey& o) const
-		{return o.mValue != this->mValue;}
+    bool operator != (const aiFloatKey& o) const
+        {return o.mValue != this->mValue;}
 
-	// Only time is compared. This operator is defined
-	// for use with std::sort
-	bool operator < (const aiFloatKey& o) const
-		{return mTime < o.mTime;}
+    // Only time is compared. This operator is defined
+    // for use with std::sort
+    bool operator < (const aiFloatKey& o) const
+        {return mTime < o.mTime;}
 
-	bool operator > (const aiFloatKey& o) const
-		{return mTime < o.mTime;}
+    bool operator > (const aiFloatKey& o) const
+        {return mTime > o.mTime;}
 
 #endif
 };
@@ -477,104 +484,104 @@ struct aiFloatKey
 /** Helper structure to represent a 3ds file node */
 struct Node
 {
-	Node()
-
-		:	mHierarchyPos		(0)
-		,	mHierarchyIndex		(0)
-		,	mInstanceCount		(1)
+    Node()
+        : mParent()
+        , mInstanceNumber()
+        ,   mHierarchyPos       (0)
+        ,   mHierarchyIndex     (0)
+        ,   mInstanceCount      (1)
+    {
+        static int iCnt = 0;
 
-	{
-		static int iCnt = 0;
-		
-		// Generate a default name for the node
-		char szTemp[128];
-		::sprintf(szTemp,"UNNAMED_%i",iCnt++);
-		mName = szTemp;
+        // Generate a default name for the node
+        char szTemp[128];
+        ::sprintf(szTemp,"UNNAMED_%i",iCnt++);
+        mName = szTemp;
 
-		aRotationKeys.reserve (20);
-		aPositionKeys.reserve (20);
-		aScalingKeys.reserve  (20);
-	}
+        aRotationKeys.reserve (20);
+        aPositionKeys.reserve (20);
+        aScalingKeys.reserve  (20);
+    }
 
-	~Node()
-	{
-		for (unsigned int i = 0; i < mChildren.size();++i)
-			delete mChildren[i];
-	}
+    ~Node()
+    {
+        for (unsigned int i = 0; i < mChildren.size();++i)
+            delete mChildren[i];
+    }
 
-	//! Pointer to the parent node
-	Node* mParent;
+    //! Pointer to the parent node
+    Node* mParent;
 
-	//! Holds all child nodes
-	std::vector<Node*> mChildren;
+    //! Holds all child nodes
+    std::vector<Node*> mChildren;
 
-	//! Name of the node
-	std::string mName;
+    //! Name of the node
+    std::string mName;
 
-	//! InstanceNumber of the node
-	int32_t mInstanceNumber;
+    //! InstanceNumber of the node
+    int32_t mInstanceNumber;
 
-	//! Dummy nodes: real name to be combined with the $$$DUMMY 
-	std::string mDummyName;
+    //! Dummy nodes: real name to be combined with the $$$DUMMY
+    std::string mDummyName;
 
-	//! Position of the node in the hierarchy (tree depth)
-	int16_t mHierarchyPos;
+    //! Position of the node in the hierarchy (tree depth)
+    int16_t mHierarchyPos;
 
-	//! Index of the node
-	int16_t mHierarchyIndex;
+    //! Index of the node
+    int16_t mHierarchyIndex;
 
-	//! Rotation keys loaded from the file
-	std::vector<aiQuatKey> aRotationKeys;
+    //! Rotation keys loaded from the file
+    std::vector<aiQuatKey> aRotationKeys;
 
-	//! Position keys loaded from the file
-	std::vector<aiVectorKey> aPositionKeys;
+    //! Position keys loaded from the file
+    std::vector<aiVectorKey> aPositionKeys;
 
-	//! Scaling keys loaded from the file
-	std::vector<aiVectorKey> aScalingKeys;
+    //! Scaling keys loaded from the file
+    std::vector<aiVectorKey> aScalingKeys;
 
 
-	// For target lights (spot lights and directional lights):
-	// The position of the target
-	std::vector< aiVectorKey > aTargetPositionKeys;
+    // For target lights (spot lights and directional lights):
+    // The position of the target
+    std::vector< aiVectorKey > aTargetPositionKeys;
 
-	// For cameras: the camera roll angle
-	std::vector< aiFloatKey > aCameraRollKeys;
+    // For cameras: the camera roll angle
+    std::vector< aiFloatKey > aCameraRollKeys;
 
-	//! Pivot position loaded from the file
-	aiVector3D vPivot;
+    //! Pivot position loaded from the file
+    aiVector3D vPivot;
 
-	//instance count, will be kept only for the first node
-	int32_t mInstanceCount;
+    //instance count, will be kept only for the first node
+    int32_t mInstanceCount;
 
-	//! Add a child node, setup the right parent node for it
-	//! \param pc Node to be 'adopted'
-	inline Node& push_back(Node* pc)
-	{
-		mChildren.push_back(pc);
-		pc->mParent = this;
-		return *this;
-	}
+    //! Add a child node, setup the right parent node for it
+    //! \param pc Node to be 'adopted'
+    inline Node& push_back(Node* pc)
+    {
+        mChildren.push_back(pc);
+        pc->mParent = this;
+        return *this;
+    }
 };
 // ---------------------------------------------------------------------------
 /** Helper structure analogue to aiScene */
 struct Scene
 {
-	//! List of all materials loaded
-	//! NOTE: 3ds references materials globally
-	std::vector<Material> mMaterials;
+    //! List of all materials loaded
+    //! NOTE: 3ds references materials globally
+    std::vector<Material> mMaterials;
 
-	//! List of all meshes loaded
-	std::vector<Mesh> mMeshes;
+    //! List of all meshes loaded
+    std::vector<Mesh> mMeshes;
 
-	//! List of all cameras loaded
-	std::vector<aiCamera*> mCameras;
+    //! List of all cameras loaded
+    std::vector<aiCamera*> mCameras;
 
-	//! List of all lights loaded
-	std::vector<aiLight*> mLights;
+    //! List of all lights loaded
+    std::vector<aiLight*> mLights;
 
-	//! Pointer to the root node of the scene
-	// --- moved to main class
-	// Node* pcRootNode;
+    //! Pointer to the root node of the scene
+    // --- moved to main class
+    // Node* pcRootNode;
 };
 
 

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 456 - 439
assimplib.mod/assimp/code/3DSLoader.cpp


+ 205 - 203
assimplib.mod/assimp/code/3DSLoader.h

@@ -3,11 +3,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -24,16 +24,16 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -50,10 +50,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
 
-struct aiNode;
 #include "3DSHelper.h"
+#include "StreamReader.h"
+
+struct aiNode;
 
-namespace Assimp	{
+namespace Assimp    {
 
 
 using namespace D3DS;
@@ -65,216 +67,216 @@ class Discreet3DSImporter : public BaseImporter
 {
 public:
 
-	Discreet3DSImporter();
-	~Discreet3DSImporter();
+    Discreet3DSImporter();
+    ~Discreet3DSImporter();
 
 public:
 
-	// -------------------------------------------------------------------
-	/** Returns whether the class can handle the format of the given file. 
-	 * See BaseImporter::CanRead() for details.	
-	 */
-	bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
-		bool checkSig) const;
+    // -------------------------------------------------------------------
+    /** Returns whether the class can handle the format of the given file.
+     * See BaseImporter::CanRead() for details.
+     */
+    bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+        bool checkSig) const;
 
-	// -------------------------------------------------------------------
-	/** Called prior to ReadFile().
-	 * The function is a request to the importer to update its configuration
-	 * basing on the Importer's configuration property list.
-	 */
-	void SetupProperties(const Importer* pImp);
+    // -------------------------------------------------------------------
+    /** Called prior to ReadFile().
+     * The function is a request to the importer to update its configuration
+     * basing on the Importer's configuration property list.
+     */
+    void SetupProperties(const Importer* pImp);
 
 protected:
 
-	// -------------------------------------------------------------------
-	/** Return importer meta information.
-	 * See #BaseImporter::GetInfo for the details
-	 */
-	const aiImporterDesc* GetInfo () const;
-
-	// -------------------------------------------------------------------
-	/** Imports the given file into the given scene structure. 
-	 * See BaseImporter::InternReadFile() for details
-	 */
-	void InternReadFile( const std::string& pFile, aiScene* pScene, 
-		IOSystem* pIOHandler);
-
-	// -------------------------------------------------------------------
-	/** Converts a temporary material to the outer representation 
-	 */
-	void ConvertMaterial(D3DS::Material& p_cMat,
-		aiMaterial& p_pcOut);
-
-	// -------------------------------------------------------------------
-	/** Read a chunk
-	 *
-	 *  @param pcOut Receives the current chunk
-	 */
-	void ReadChunk(Discreet3DS::Chunk* pcOut);
-
-	// -------------------------------------------------------------------
-	/** Parse a percentage chunk. mCurrent will point to the next
-	* chunk behind afterwards. If no percentage chunk is found
-	* QNAN is returned.
-	*/
-	float ParsePercentageChunk();
-
-	// -------------------------------------------------------------------
-	/** Parse a color chunk. mCurrent will point to the next
-	* chunk behind afterwards. If no color chunk is found
-	* QNAN is returned in all members.
-	*/
-	void ParseColorChunk(aiColor3D* p_pcOut,
-		bool p_bAcceptPercent = true);
-
-
-	// -------------------------------------------------------------------
-	/** Skip a chunk in the file
-	*/
-	void SkipChunk();
-
-	// -------------------------------------------------------------------
-	/** Generate the nodegraph
-	*/
-	void GenerateNodeGraph(aiScene* pcOut);
-
-	// -------------------------------------------------------------------
-	/** Parse a main top-level chunk in the file
-	*/
-	void ParseMainChunk();
-
-	// -------------------------------------------------------------------
-	/** Parse a top-level chunk in the file
-	*/
-	void ParseChunk(const char* name, unsigned int num);
-
-	// -------------------------------------------------------------------
-	/** Parse a top-level editor chunk in the file
-	*/
-	void ParseEditorChunk();
-
-	// -------------------------------------------------------------------
-	/** Parse a top-level object chunk in the file
-	*/
-	void ParseObjectChunk();
-
-	// -------------------------------------------------------------------
-	/** Parse a material chunk in the file
-	*/
-	void ParseMaterialChunk();
-
-	// -------------------------------------------------------------------
-	/** Parse a mesh chunk in the file
-	*/
-	void ParseMeshChunk();
-
-	// -------------------------------------------------------------------
-	/** Parse a light chunk in the file
-	*/
-	void ParseLightChunk();
-
-	// -------------------------------------------------------------------
-	/** Parse a camera chunk in the file
-	*/
-	void ParseCameraChunk();
-
-	// -------------------------------------------------------------------
-	/** Parse a face list chunk in the file
-	*/
-	void ParseFaceChunk();
-
-	// -------------------------------------------------------------------
-	/** Parse a keyframe chunk in the file
-	*/
-	void ParseKeyframeChunk();
-
-	// -------------------------------------------------------------------
-	/** Parse a hierarchy chunk in the file
-	*/
-	void ParseHierarchyChunk(uint16_t parent);
-
-	// -------------------------------------------------------------------
-	/** Parse a texture chunk in the file
-	*/
-	void ParseTextureChunk(D3DS::Texture* pcOut);
-
-	// -------------------------------------------------------------------
-	/** Convert the meshes in the file
-	*/
-	void ConvertMeshes(aiScene* pcOut);
-
-	// -------------------------------------------------------------------
-	/** Replace the default material in the scene
-	*/
-	void ReplaceDefaultMaterial();
-
-	// -------------------------------------------------------------------
-	/** Convert the whole scene
-	*/
-	void ConvertScene(aiScene* pcOut);
-
-	// -------------------------------------------------------------------
-	/** generate unique vertices for a mesh
-	*/
-	void MakeUnique(D3DS::Mesh& sMesh);
-
-	// -------------------------------------------------------------------
-	/** Add a node to the node graph
-	*/
-	void AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Node* pcIn,
-		aiMatrix4x4& absTrafo);
-
-	// -------------------------------------------------------------------
-	/** Search for a node in the graph.
-	* Called recursively
-	*/
-	void InverseNodeSearch(D3DS::Node* pcNode,D3DS::Node* pcCurrent);
-
-	// -------------------------------------------------------------------
-	/** Apply the master scaling factor to the mesh
-	*/
-	void ApplyMasterScale(aiScene* pScene);
-
-	// -------------------------------------------------------------------
-	/** Clamp all indices in the file to a valid range
-	*/
-	void CheckIndices(D3DS::Mesh& sMesh);
-
-	// -------------------------------------------------------------------
-	/** Skip the TCB info in a track key
-	*/
-	void SkipTCBInfo();
+    // -------------------------------------------------------------------
+    /** Return importer meta information.
+     * See #BaseImporter::GetInfo for the details
+     */
+    const aiImporterDesc* GetInfo () const;
+
+    // -------------------------------------------------------------------
+    /** Imports the given file into the given scene structure.
+     * See BaseImporter::InternReadFile() for details
+     */
+    void InternReadFile( const std::string& pFile, aiScene* pScene,
+        IOSystem* pIOHandler);
+
+    // -------------------------------------------------------------------
+    /** Converts a temporary material to the outer representation
+     */
+    void ConvertMaterial(D3DS::Material& p_cMat,
+        aiMaterial& p_pcOut);
+
+    // -------------------------------------------------------------------
+    /** Read a chunk
+     *
+     *  @param pcOut Receives the current chunk
+     */
+    void ReadChunk(Discreet3DS::Chunk* pcOut);
+
+    // -------------------------------------------------------------------
+    /** Parse a percentage chunk. mCurrent will point to the next
+    * chunk behind afterwards. If no percentage chunk is found
+    * QNAN is returned.
+    */
+    float ParsePercentageChunk();
+
+    // -------------------------------------------------------------------
+    /** Parse a color chunk. mCurrent will point to the next
+    * chunk behind afterwards. If no color chunk is found
+    * QNAN is returned in all members.
+    */
+    void ParseColorChunk(aiColor3D* p_pcOut,
+        bool p_bAcceptPercent = true);
+
+
+    // -------------------------------------------------------------------
+    /** Skip a chunk in the file
+    */
+    void SkipChunk();
+
+    // -------------------------------------------------------------------
+    /** Generate the nodegraph
+    */
+    void GenerateNodeGraph(aiScene* pcOut);
+
+    // -------------------------------------------------------------------
+    /** Parse a main top-level chunk in the file
+    */
+    void ParseMainChunk();
+
+    // -------------------------------------------------------------------
+    /** Parse a top-level chunk in the file
+    */
+    void ParseChunk(const char* name, unsigned int num);
+
+    // -------------------------------------------------------------------
+    /** Parse a top-level editor chunk in the file
+    */
+    void ParseEditorChunk();
+
+    // -------------------------------------------------------------------
+    /** Parse a top-level object chunk in the file
+    */
+    void ParseObjectChunk();
+
+    // -------------------------------------------------------------------
+    /** Parse a material chunk in the file
+    */
+    void ParseMaterialChunk();
+
+    // -------------------------------------------------------------------
+    /** Parse a mesh chunk in the file
+    */
+    void ParseMeshChunk();
+
+    // -------------------------------------------------------------------
+    /** Parse a light chunk in the file
+    */
+    void ParseLightChunk();
+
+    // -------------------------------------------------------------------
+    /** Parse a camera chunk in the file
+    */
+    void ParseCameraChunk();
+
+    // -------------------------------------------------------------------
+    /** Parse a face list chunk in the file
+    */
+    void ParseFaceChunk();
+
+    // -------------------------------------------------------------------
+    /** Parse a keyframe chunk in the file
+    */
+    void ParseKeyframeChunk();
+
+    // -------------------------------------------------------------------
+    /** Parse a hierarchy chunk in the file
+    */
+    void ParseHierarchyChunk(uint16_t parent);
+
+    // -------------------------------------------------------------------
+    /** Parse a texture chunk in the file
+    */
+    void ParseTextureChunk(D3DS::Texture* pcOut);
+
+    // -------------------------------------------------------------------
+    /** Convert the meshes in the file
+    */
+    void ConvertMeshes(aiScene* pcOut);
+
+    // -------------------------------------------------------------------
+    /** Replace the default material in the scene
+    */
+    void ReplaceDefaultMaterial();
+
+    // -------------------------------------------------------------------
+    /** Convert the whole scene
+    */
+    void ConvertScene(aiScene* pcOut);
+
+    // -------------------------------------------------------------------
+    /** generate unique vertices for a mesh
+    */
+    void MakeUnique(D3DS::Mesh& sMesh);
+
+    // -------------------------------------------------------------------
+    /** Add a node to the node graph
+    */
+    void AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,D3DS::Node* pcIn,
+        aiMatrix4x4& absTrafo);
+
+    // -------------------------------------------------------------------
+    /** Search for a node in the graph.
+    * Called recursively
+    */
+    void InverseNodeSearch(D3DS::Node* pcNode,D3DS::Node* pcCurrent);
+
+    // -------------------------------------------------------------------
+    /** Apply the master scaling factor to the mesh
+    */
+    void ApplyMasterScale(aiScene* pScene);
+
+    // -------------------------------------------------------------------
+    /** Clamp all indices in the file to a valid range
+    */
+    void CheckIndices(D3DS::Mesh& sMesh);
+
+    // -------------------------------------------------------------------
+    /** Skip the TCB info in a track key
+    */
+    void SkipTCBInfo();
 
 protected:
 
-	/** Stream to read from */
-	StreamReaderLE* stream;
+    /** Stream to read from */
+    StreamReaderLE* stream;
 
-	/** Last touched node index */
-	short mLastNodeIndex;
+    /** Last touched node index */
+    short mLastNodeIndex;
 
-	/** Current node, root node */
-	D3DS::Node* mCurrentNode, *mRootNode;
+    /** Current node, root node */
+    D3DS::Node* mCurrentNode, *mRootNode;
 
-	/** Scene under construction */
-	D3DS::Scene* mScene;
+    /** Scene under construction */
+    D3DS::Scene* mScene;
 
-	/** Ambient base color of the scene */
-	aiColor3D mClrAmbient;
+    /** Ambient base color of the scene */
+    aiColor3D mClrAmbient;
 
-	/** Master scaling factor of the scene */
-	float mMasterScale;
+    /** Master scaling factor of the scene */
+    float mMasterScale;
 
-	/** Path to the background image of the scene */
-	std::string mBackgroundImage;
-	bool bHasBG;
+    /** Path to the background image of the scene */
+    std::string mBackgroundImage;
+    bool bHasBG;
 
-	/** true if PRJ file */
-	bool bIsPrj;
+    /** true if PRJ file */
+    bool bIsPrj;
 };
 
-#endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER
-
 } // end of namespace Assimp
 
+#endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER
+
 #endif // AI_3DSIMPORTER_H_INC

+ 790 - 749
assimplib.mod/assimp/code/ACLoader.cpp

@@ -4,12 +4,12 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -26,23 +26,23 @@ conditions are met:
   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 
+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 
+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 
+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 
+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 Implementation of the AC3D importer class */
 
-#include "AssimpPCH.h"
+
 
 #ifndef ASSIMP_BUILD_NO_AC_IMPORTER
 
@@ -51,816 +51,857 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "ParsingUtils.h"
 #include "fast_atof.h"
 #include "Subdivision.h"
+#include "Importer.h"
+#include "BaseImporter.h"
+#include "../include/assimp/Importer.hpp"
+#include "../include/assimp/light.h"
+#include "../include/assimp/DefaultLogger.hpp"
+#include "../include/assimp/material.h"
+#include "../include/assimp/scene.h"
+#include "../include/assimp/config.h"
+#include "../include/assimp/IOSystem.hpp"
+#include <boost/scoped_ptr.hpp>
 
 using namespace Assimp;
 
 static const aiImporterDesc desc = {
-	"AC3D Importer",
-	"",
-	"",
-	"",
-	aiImporterFlags_SupportTextFlavour,
-	0,
-	0,
-	0,
-	0,
-	"ac acc ac3d"
+    "AC3D Importer",
+    "",
+    "",
+    "",
+    aiImporterFlags_SupportTextFlavour,
+    0,
+    0,
+    0,
+    0,
+    "ac acc ac3d"
 };
 
 // ------------------------------------------------------------------------------------------------
 // skip to the next token
 #define AI_AC_SKIP_TO_NEXT_TOKEN() \
-	if (!SkipSpaces(&buffer)) \
-	{ \
-		DefaultLogger::get()->error("AC3D: Unexpected EOF/EOL"); \
-		continue; \
-	} 
+    if (!SkipSpaces(&buffer)) \
+    { \
+        DefaultLogger::get()->error("AC3D: Unexpected EOF/EOL"); \
+        continue; \
+    }
 
 // ------------------------------------------------------------------------------------------------
 // read a string (may be enclosed in double quotation marks). buffer must point to "
 #define AI_AC_GET_STRING(out) \
-	++buffer; \
-	const char* sz = buffer; \
-	while ('\"' != *buffer) \
-	{ \
-		if (IsLineEnd( *buffer )) \
-		{ \
-			DefaultLogger::get()->error("AC3D: Unexpected EOF/EOL in string"); \
-			out = "ERROR"; \
-			break; \
-		} \
-		++buffer; \
-	} \
-	if (IsLineEnd( *buffer ))continue; \
-	out = std::string(sz,(unsigned int)(buffer-sz)); \
-	++buffer;
+    if (*buffer == '\0') { \
+        throw DeadlyImportError("AC3D: Unexpected EOF in string"); \
+    } \
+    ++buffer; \
+    const char* sz = buffer; \
+    while ('\"' != *buffer) \
+    { \
+        if (IsLineEnd( *buffer )) \
+        { \
+            DefaultLogger::get()->error("AC3D: Unexpected EOF/EOL in string"); \
+            out = "ERROR"; \
+            break; \
+        } \
+        ++buffer; \
+    } \
+    if (IsLineEnd( *buffer ))continue; \
+    out = std::string(sz,(unsigned int)(buffer-sz)); \
+    ++buffer;
 
 
 // ------------------------------------------------------------------------------------------------
-// read 1 to n floats prefixed with an optional predefined identifier 
+// read 1 to n floats prefixed with an optional predefined identifier
 #define AI_AC_CHECKED_LOAD_FLOAT_ARRAY(name,name_length,num,out) \
-	AI_AC_SKIP_TO_NEXT_TOKEN(); \
-	if (name_length) \
-	{ \
-		if (strncmp(buffer,name,name_length) || !IsSpace(buffer[name_length])) \
-		{ \
-			DefaultLogger::get()->error("AC3D: Unexpexted token. " name " was expected."); \
-			continue; \
-		} \
-		buffer += name_length+1; \
-	} \
-	for (unsigned int i = 0; i < num;++i) \
-	{ \
-		AI_AC_SKIP_TO_NEXT_TOKEN(); \
-		buffer = fast_atoreal_move<float>(buffer,((float*)out)[i]); \
-	}
+    AI_AC_SKIP_TO_NEXT_TOKEN(); \
+    if (name_length) \
+    { \
+        if (strncmp(buffer,name,name_length) || !IsSpace(buffer[name_length])) \
+        { \
+            DefaultLogger::get()->error("AC3D: Unexpexted token. " name " was expected."); \
+            continue; \
+        } \
+        buffer += name_length+1; \
+    } \
+    for (unsigned int i = 0; i < num;++i) \
+    { \
+        AI_AC_SKIP_TO_NEXT_TOKEN(); \
+        buffer = fast_atoreal_move<float>(buffer,((float*)out)[i]); \
+    }
 
 
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 AC3DImporter::AC3DImporter()
+    : buffer(),
+    configSplitBFCull(),
+    configEvalSubdivision(),
+    mNumMeshes(),
+    mLights(),
+    lights(),
+    groups(),
+    polys(),
+    worlds()
 {
-	// nothing to be done here
+    // nothing to be done here
 }
 
 // ------------------------------------------------------------------------------------------------
-// Destructor, private as well 
+// Destructor, private as well
 AC3DImporter::~AC3DImporter()
 {
-	// nothing to be done here
+    // nothing to be done here
 }
 
 // ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file. 
+// Returns whether the class can handle the format of the given file.
 bool AC3DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
 {
-	std::string extension = GetExtension(pFile);
-
-	// fixme: are acc and ac3d *really* used? Some sources say they are
-	if(extension == "ac" || extension == "ac3d" || extension == "acc") {
-		return true;
-	}
-	if (!extension.length() || checkSig) {
-		uint32_t token = AI_MAKE_MAGIC("AC3D");
-		return CheckMagicToken(pIOHandler,pFile,&token,1,0);
-	}
-	return false;
+    std::string extension = GetExtension(pFile);
+
+    // fixme: are acc and ac3d *really* used? Some sources say they are
+    if(extension == "ac" || extension == "ac3d" || extension == "acc") {
+        return true;
+    }
+    if (!extension.length() || checkSig) {
+        uint32_t token = AI_MAKE_MAGIC("AC3D");
+        return CheckMagicToken(pIOHandler,pFile,&token,1,0);
+    }
+    return false;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Loader meta information
 const aiImporterDesc* AC3DImporter::GetInfo () const
 {
-	return &desc;
+    return &desc;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Get a pointer to the next line from the file
 bool AC3DImporter::GetNextLine( )
 {
-	SkipLine(&buffer); 
-	return SkipSpaces(&buffer);
+    SkipLine(&buffer);
+    return SkipSpaces(&buffer);
 }
 
 // ------------------------------------------------------------------------------------------------
 // Parse an object section in an AC file
 void AC3DImporter::LoadObjectSection(std::vector<Object>& objects)
 {
-	if (!TokenMatch(buffer,"OBJECT",6))
-		return;
-
-	SkipSpaces(&buffer);
-
-	++mNumMeshes;
-
-	objects.push_back(Object());
-	Object& obj = objects.back();
-
-	aiLight* light = NULL;
-	if (!ASSIMP_strincmp(buffer,"light",5))
-	{
-		// This is a light source. Add it to the list
-		mLights->push_back(light = new aiLight());
-
-		// Return a point light with no attenuation
-		light->mType = aiLightSource_POINT;
-		light->mColorDiffuse = light->mColorSpecular = aiColor3D(1.f,1.f,1.f);
-		light->mAttenuationConstant = 1.f;
-
-		// Generate a default name for both the light source and the node
-		// FIXME - what's the right way to print a size_t? Is 'zu' universally available? stick with the safe version.
-		light->mName.length = ::sprintf(light->mName.data,"ACLight_%i",static_cast<unsigned int>(mLights->size())-1);
-		obj.name = std::string( light->mName.data );
-
-		DefaultLogger::get()->debug("AC3D: Light source encountered");
-		obj.type = Object::Light;
-	}
-	else if (!ASSIMP_strincmp(buffer,"group",5))
-	{
-		obj.type = Object::Group;
-	}
-	else if (!ASSIMP_strincmp(buffer,"world",5))
-	{
-		obj.type = Object::World;
-	}
-	else obj.type = Object::Poly;
-	while (GetNextLine())
-	{
-		if (TokenMatch(buffer,"kids",4))
-		{
-			SkipSpaces(&buffer);
-			unsigned int num = strtoul10(buffer,&buffer);
-			GetNextLine();
-			if (num)
-			{
-				// load the children of this object recursively
-				obj.children.reserve(num);
-				for (unsigned int i = 0; i < num; ++i)
-					LoadObjectSection(obj.children);
-			}
-			return;
-		}
-		else if (TokenMatch(buffer,"name",4))
-		{
-			SkipSpaces(&buffer);
-			AI_AC_GET_STRING(obj.name);
-
-			// If this is a light source, we'll also need to store
-			// the name of the node in it.
-			if (light)
-			{
-				light->mName.Set(obj.name);
-			}
-		}
-		else if (TokenMatch(buffer,"texture",7))
-		{
-			SkipSpaces(&buffer);
-			AI_AC_GET_STRING(obj.texture);
-		}
-		else if (TokenMatch(buffer,"texrep",6))
-		{
-			SkipSpaces(&buffer);
-			AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,2,&obj.texRepeat);
-			if (!obj.texRepeat.x || !obj.texRepeat.y)
-				obj.texRepeat = aiVector2D (1.f,1.f);
-		}
-		else if (TokenMatch(buffer,"texoff",6))
-		{
-			SkipSpaces(&buffer);
-			AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,2,&obj.texOffset);
-		}
-		else if (TokenMatch(buffer,"rot",3))
-		{
-			SkipSpaces(&buffer);
-			AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,9,&obj.rotation);
-		}
-		else if (TokenMatch(buffer,"loc",3))
-		{
-			SkipSpaces(&buffer);
-			AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,3,&obj.translation);
-		}
-		else if (TokenMatch(buffer,"subdiv",6))
-		{
-			SkipSpaces(&buffer);
-			obj.subDiv = strtoul10(buffer,&buffer);
-		}
-		else if (TokenMatch(buffer,"crease",6))
-		{
-			SkipSpaces(&buffer);
-			obj.crease = fast_atof(buffer);
-		}
-		else if (TokenMatch(buffer,"numvert",7))
-		{
-			SkipSpaces(&buffer);
-
-			unsigned int t = strtoul10(buffer,&buffer);
-			obj.vertices.reserve(t);
-			for (unsigned int i = 0; i < t;++i)
-			{
-				if (!GetNextLine())
-				{
-					DefaultLogger::get()->error("AC3D: Unexpected EOF: not all vertices have been parsed yet");
-					break;
-				}
-				else if (!IsNumeric(*buffer))
-				{
-					DefaultLogger::get()->error("AC3D: Unexpected token: not all vertices have been parsed yet");
-					--buffer; // make sure the line is processed a second time
-					break;
-				}
-				obj.vertices.push_back(aiVector3D());
-				aiVector3D& v = obj.vertices.back();
-				AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,3,&v.x);
-			}
-		}
-		else if (TokenMatch(buffer,"numsurf",7))
-		{
-			SkipSpaces(&buffer);
-			
-			bool Q3DWorkAround = false;
-
-			const unsigned int t = strtoul10(buffer,&buffer);
-			obj.surfaces.reserve(t);
-			for (unsigned int i = 0; i < t;++i)
-			{
-				GetNextLine();
-				if (!TokenMatch(buffer,"SURF",4))
-				{
-					// FIX: this can occur for some files - Quick 3D for 
-					// example writes no surf chunks
-					if (!Q3DWorkAround)
-					{
-						DefaultLogger::get()->warn("AC3D: SURF token was expected");
-						DefaultLogger::get()->debug("Continuing with Quick3D Workaround enabled");
-					}
-					--buffer; // make sure the line is processed a second time
-					// break; --- see fix notes above
-
-					Q3DWorkAround = true;
-				}
-				SkipSpaces(&buffer);
-				obj.surfaces.push_back(Surface());
-				Surface& surf = obj.surfaces.back();
-				surf.flags = strtoul_cppstyle(buffer);
-			
-				while (1)
-				{
-					if(!GetNextLine())
-					{
-						DefaultLogger::get()->error("AC3D: Unexpected EOF: surface is incomplete");
-						break;
-					}
-					if (TokenMatch(buffer,"mat",3))
-					{
-						SkipSpaces(&buffer);
-						surf.mat = strtoul10(buffer);
-					}
-					else if (TokenMatch(buffer,"refs",4))
-					{
-						// --- see fix notes above
-						if (Q3DWorkAround)
-						{
-							if (!surf.entries.empty())
-							{
-								buffer -= 6;
-								break;
-							}
-						}
-
-						SkipSpaces(&buffer);
-						const unsigned int m = strtoul10(buffer);
-						surf.entries.reserve(m);
-
-						obj.numRefs += m;
-
-						for (unsigned int k = 0; k < m; ++k)
-						{
-							if(!GetNextLine())
-							{
-								DefaultLogger::get()->error("AC3D: Unexpected EOF: surface references are incomplete");
-								break;
-							}
-							surf.entries.push_back(Surface::SurfaceEntry());
-							Surface::SurfaceEntry& entry = surf.entries.back();
-
-							entry.first = strtoul10(buffer,&buffer);
-							SkipSpaces(&buffer);
-							AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,2,&entry.second);
-						}
-					}
-					else 
-					{
-
-						--buffer; // make sure the line is processed a second time
-						break;
-					}
-				}
-			}
-		}
-	}
-	DefaultLogger::get()->error("AC3D: Unexpected EOF: \'kids\' line was expected");
+    if (!TokenMatch(buffer,"OBJECT",6))
+        return;
+
+    SkipSpaces(&buffer);
+
+    ++mNumMeshes;
+
+    objects.push_back(Object());
+    Object& obj = objects.back();
+
+    aiLight* light = NULL;
+    if (!ASSIMP_strincmp(buffer,"light",5))
+    {
+        // This is a light source. Add it to the list
+        mLights->push_back(light = new aiLight());
+
+        // Return a point light with no attenuation
+        light->mType = aiLightSource_POINT;
+        light->mColorDiffuse = light->mColorSpecular = aiColor3D(1.f,1.f,1.f);
+        light->mAttenuationConstant = 1.f;
+
+        // Generate a default name for both the light source and the node
+        // FIXME - what's the right way to print a size_t? Is 'zu' universally available? stick with the safe version.
+        light->mName.length = ::sprintf(light->mName.data,"ACLight_%i",static_cast<unsigned int>(mLights->size())-1);
+        obj.name = std::string( light->mName.data );
+
+        DefaultLogger::get()->debug("AC3D: Light source encountered");
+        obj.type = Object::Light;
+    }
+    else if (!ASSIMP_strincmp(buffer,"group",5))
+    {
+        obj.type = Object::Group;
+    }
+    else if (!ASSIMP_strincmp(buffer,"world",5))
+    {
+        obj.type = Object::World;
+    }
+    else obj.type = Object::Poly;
+    while (GetNextLine())
+    {
+        if (TokenMatch(buffer,"kids",4))
+        {
+            SkipSpaces(&buffer);
+            unsigned int num = strtoul10(buffer,&buffer);
+            GetNextLine();
+            if (num)
+            {
+                // load the children of this object recursively
+                obj.children.reserve(num);
+                for (unsigned int i = 0; i < num; ++i)
+                    LoadObjectSection(obj.children);
+            }
+            return;
+        }
+        else if (TokenMatch(buffer,"name",4))
+        {
+            SkipSpaces(&buffer);
+            AI_AC_GET_STRING(obj.name);
+
+            // If this is a light source, we'll also need to store
+            // the name of the node in it.
+            if (light)
+            {
+                light->mName.Set(obj.name);
+            }
+        }
+        else if (TokenMatch(buffer,"texture",7))
+        {
+            SkipSpaces(&buffer);
+            AI_AC_GET_STRING(obj.texture);
+        }
+        else if (TokenMatch(buffer,"texrep",6))
+        {
+            SkipSpaces(&buffer);
+            AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,2,&obj.texRepeat);
+            if (!obj.texRepeat.x || !obj.texRepeat.y)
+                obj.texRepeat = aiVector2D (1.f,1.f);
+        }
+        else if (TokenMatch(buffer,"texoff",6))
+        {
+            SkipSpaces(&buffer);
+            AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,2,&obj.texOffset);
+        }
+        else if (TokenMatch(buffer,"rot",3))
+        {
+            SkipSpaces(&buffer);
+            AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,9,&obj.rotation);
+        }
+        else if (TokenMatch(buffer,"loc",3))
+        {
+            SkipSpaces(&buffer);
+            AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,3,&obj.translation);
+        }
+        else if (TokenMatch(buffer,"subdiv",6))
+        {
+            SkipSpaces(&buffer);
+            obj.subDiv = strtoul10(buffer,&buffer);
+        }
+        else if (TokenMatch(buffer,"crease",6))
+        {
+            SkipSpaces(&buffer);
+            obj.crease = fast_atof(buffer);
+        }
+        else if (TokenMatch(buffer,"numvert",7))
+        {
+            SkipSpaces(&buffer);
+
+            unsigned int t = strtoul10(buffer,&buffer);
+            if (t >= AI_MAX_ALLOC(aiVector3D)) {
+                throw DeadlyImportError("AC3D: Too many vertices, would run out of memory");
+            }
+            obj.vertices.reserve(t);
+            for (unsigned int i = 0; i < t;++i)
+            {
+                if (!GetNextLine())
+                {
+                    DefaultLogger::get()->error("AC3D: Unexpected EOF: not all vertices have been parsed yet");
+                    break;
+                }
+                else if (!IsNumeric(*buffer))
+                {
+                    DefaultLogger::get()->error("AC3D: Unexpected token: not all vertices have been parsed yet");
+                    --buffer; // make sure the line is processed a second time
+                    break;
+                }
+                obj.vertices.push_back(aiVector3D());
+                aiVector3D& v = obj.vertices.back();
+                AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,3,&v.x);
+            }
+        }
+        else if (TokenMatch(buffer,"numsurf",7))
+        {
+            SkipSpaces(&buffer);
+
+            bool Q3DWorkAround = false;
+
+            const unsigned int t = strtoul10(buffer,&buffer);
+            obj.surfaces.reserve(t);
+            for (unsigned int i = 0; i < t;++i)
+            {
+                GetNextLine();
+                if (!TokenMatch(buffer,"SURF",4))
+                {
+                    // FIX: this can occur for some files - Quick 3D for
+                    // example writes no surf chunks
+                    if (!Q3DWorkAround)
+                    {
+                        DefaultLogger::get()->warn("AC3D: SURF token was expected");
+                        DefaultLogger::get()->debug("Continuing with Quick3D Workaround enabled");
+                    }
+                    --buffer; // make sure the line is processed a second time
+                    // break; --- see fix notes above
+
+                    Q3DWorkAround = true;
+                }
+                SkipSpaces(&buffer);
+                obj.surfaces.push_back(Surface());
+                Surface& surf = obj.surfaces.back();
+                surf.flags = strtoul_cppstyle(buffer);
+
+                while (1)
+                {
+                    if(!GetNextLine())
+                    {
+                        throw DeadlyImportError("AC3D: Unexpected EOF: surface is incomplete");
+                    }
+                    if (TokenMatch(buffer,"mat",3))
+                    {
+                        SkipSpaces(&buffer);
+                        surf.mat = strtoul10(buffer);
+                    }
+                    else if (TokenMatch(buffer,"refs",4))
+                    {
+                        // --- see fix notes above
+                        if (Q3DWorkAround)
+                        {
+                            if (!surf.entries.empty())
+                            {
+                                buffer -= 6;
+                                break;
+                            }
+                        }
+
+                        SkipSpaces(&buffer);
+                        const unsigned int m = strtoul10(buffer);
+                        surf.entries.reserve(m);
+
+                        obj.numRefs += m;
+
+                        for (unsigned int k = 0; k < m; ++k)
+                        {
+                            if(!GetNextLine())
+                            {
+                                DefaultLogger::get()->error("AC3D: Unexpected EOF: surface references are incomplete");
+                                break;
+                            }
+                            surf.entries.push_back(Surface::SurfaceEntry());
+                            Surface::SurfaceEntry& entry = surf.entries.back();
+
+                            entry.first = strtoul10(buffer,&buffer);
+                            SkipSpaces(&buffer);
+                            AI_AC_CHECKED_LOAD_FLOAT_ARRAY("",0,2,&entry.second);
+                        }
+                    }
+                    else
+                    {
+
+                        --buffer; // make sure the line is processed a second time
+                        break;
+                    }
+                }
+            }
+        }
+    }
+    DefaultLogger::get()->error("AC3D: Unexpected EOF: \'kids\' line was expected");
 }
 
 // ------------------------------------------------------------------------------------------------
 // Convert a material from AC3DImporter::Material to aiMaterial
 void AC3DImporter::ConvertMaterial(const Object& object,
-	const Material& matSrc,
-	aiMaterial& matDest)
+    const Material& matSrc,
+    aiMaterial& matDest)
 {
-	aiString s;
-
-	if (matSrc.name.length())
-	{
-		s.Set(matSrc.name);
-		matDest.AddProperty(&s,AI_MATKEY_NAME);
-	}
-	if (object.texture.length())
-	{
-		s.Set(object.texture);
-		matDest.AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0));
-
-		// UV transformation
-		if (1.f != object.texRepeat.x || 1.f != object.texRepeat.y ||
-			object.texOffset.x        || object.texOffset.y)
-		{
-			aiUVTransform transform;
-			transform.mScaling = object.texRepeat;
-			transform.mTranslation = object.texOffset;
-			matDest.AddProperty(&transform,1,AI_MATKEY_UVTRANSFORM_DIFFUSE(0));
-		}
-	}
-
-	matDest.AddProperty<aiColor3D>(&matSrc.rgb,1, AI_MATKEY_COLOR_DIFFUSE);
-	matDest.AddProperty<aiColor3D>(&matSrc.amb,1, AI_MATKEY_COLOR_AMBIENT);
-	matDest.AddProperty<aiColor3D>(&matSrc.emis,1,AI_MATKEY_COLOR_EMISSIVE);
-	matDest.AddProperty<aiColor3D>(&matSrc.spec,1,AI_MATKEY_COLOR_SPECULAR);
-
-	int n;
-	if (matSrc.shin)
-	{
-		n = aiShadingMode_Phong;
-		matDest.AddProperty<float>(&matSrc.shin,1,AI_MATKEY_SHININESS);
-	}
-	else n = aiShadingMode_Gouraud;
-	matDest.AddProperty<int>(&n,1,AI_MATKEY_SHADING_MODEL);
-
-	float f = 1.f - matSrc.trans;
-	matDest.AddProperty<float>(&f,1,AI_MATKEY_OPACITY);
+    aiString s;
+
+    if (matSrc.name.length())
+    {
+        s.Set(matSrc.name);
+        matDest.AddProperty(&s,AI_MATKEY_NAME);
+    }
+    if (object.texture.length())
+    {
+        s.Set(object.texture);
+        matDest.AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0));
+
+        // UV transformation
+        if (1.f != object.texRepeat.x || 1.f != object.texRepeat.y ||
+            object.texOffset.x        || object.texOffset.y)
+        {
+            aiUVTransform transform;
+            transform.mScaling = object.texRepeat;
+            transform.mTranslation = object.texOffset;
+            matDest.AddProperty(&transform,1,AI_MATKEY_UVTRANSFORM_DIFFUSE(0));
+        }
+    }
+
+    matDest.AddProperty<aiColor3D>(&matSrc.rgb,1, AI_MATKEY_COLOR_DIFFUSE);
+    matDest.AddProperty<aiColor3D>(&matSrc.amb,1, AI_MATKEY_COLOR_AMBIENT);
+    matDest.AddProperty<aiColor3D>(&matSrc.emis,1,AI_MATKEY_COLOR_EMISSIVE);
+    matDest.AddProperty<aiColor3D>(&matSrc.spec,1,AI_MATKEY_COLOR_SPECULAR);
+
+    int n;
+    if (matSrc.shin)
+    {
+        n = aiShadingMode_Phong;
+        matDest.AddProperty<float>(&matSrc.shin,1,AI_MATKEY_SHININESS);
+    }
+    else n = aiShadingMode_Gouraud;
+    matDest.AddProperty<int>(&n,1,AI_MATKEY_SHADING_MODEL);
+
+    float f = 1.f - matSrc.trans;
+    matDest.AddProperty<float>(&f,1,AI_MATKEY_OPACITY);
 }
 
 // ------------------------------------------------------------------------------------------------
 // Converts the loaded data to the internal verbose representation
 aiNode* AC3DImporter::ConvertObjectSection(Object& object,
-	std::vector<aiMesh*>& meshes,
-	std::vector<aiMaterial*>& outMaterials,
-	const std::vector<Material>& materials,
-	aiNode* parent)
+    std::vector<aiMesh*>& meshes,
+    std::vector<aiMaterial*>& outMaterials,
+    const std::vector<Material>& materials,
+    aiNode* parent)
 {
-	aiNode* node = new aiNode();
-	node->mParent = parent;
-	if (object.vertices.size())
-	{
-		if (!object.surfaces.size() || !object.numRefs)
-		{
-			/* " An object with 7 vertices (no surfaces, no materials defined). 
-			     This is a good way of getting point data into AC3D. 
-			     The Vertex->create convex-surface/object can be used on these
-			     vertices to 'wrap' a 3d shape around them "
-				 (http://www.opencity.info/html/ac3dfileformat.html)
-
-				 therefore: if no surfaces are defined return point data only
-			 */
-
-			DefaultLogger::get()->info("AC3D: No surfaces defined in object definition, "
-				"a point list is returned");
-
-			meshes.push_back(new aiMesh());
-			aiMesh* mesh = meshes.back();
-
-			mesh->mNumFaces = mesh->mNumVertices = (unsigned int)object.vertices.size();
-			aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces];
-			aiVector3D* verts = mesh->mVertices = new aiVector3D[mesh->mNumVertices];
-
-			for (unsigned int i = 0; i < mesh->mNumVertices;++i,++faces,++verts)
-			{
-				*verts = object.vertices[i];
-				faces->mNumIndices = 1;
-				faces->mIndices = new unsigned int[1];
-				faces->mIndices[0] = i;
-			}
-
-			// use the primary material in this case. this should be the
-			// default material if all objects of the file contain points
-			// and no faces.
-			mesh->mMaterialIndex = 0;
-			outMaterials.push_back(new aiMaterial());
-			ConvertMaterial(object, materials[0], *outMaterials.back());
-		}
-		else
-		{
-			// need to generate one or more meshes for this object.
-			// find out how many different materials we have
-			typedef std::pair< unsigned int, unsigned int > IntPair;
-			typedef std::vector< IntPair > MatTable;
-			MatTable needMat(materials.size(),IntPair(0,0));
-
-			std::vector<Surface>::iterator it,end = object.surfaces.end();
-			std::vector<Surface::SurfaceEntry>::iterator it2,end2;
-
-			for (it = object.surfaces.begin(); it != end; ++it)
-			{
-				register unsigned int idx = (*it).mat;
-				if (idx >= needMat.size())
-				{
-					DefaultLogger::get()->error("AC3D: material index is out of range");
-					idx = 0;
-				}
-				if ((*it).entries.empty())
-				{
-					DefaultLogger::get()->warn("AC3D: surface her zero vertex references");
-				}
-
-				// validate all vertex indices to make sure we won't crash here
-				for (it2  = (*it).entries.begin(),
-					 end2 = (*it).entries.end(); it2 != end2; ++it2)
-				{
-					if ((*it2).first >= object.vertices.size())
-					{
-						DefaultLogger::get()->warn("AC3D: Invalid vertex reference");
-						(*it2).first = 0;
-					}
-				}
-
-				if (!needMat[idx].first)++node->mNumMeshes;
-
-				switch ((*it).flags & 0xf)
-				{
-					// closed line
-				case 0x1:
-
-					needMat[idx].first  += (unsigned int)(*it).entries.size();
-					needMat[idx].second += (unsigned int)(*it).entries.size()<<1u;
-					break;
-
-					// unclosed line
-				case 0x2:
-
-					needMat[idx].first  += (unsigned int)(*it).entries.size()-1;
-					needMat[idx].second += ((unsigned int)(*it).entries.size()-1)<<1u;
-					break;
-
-					// 0 == polygon, else unknown
-				default:
-
-					if ((*it).flags & 0xf)
-					{
-						DefaultLogger::get()->warn("AC3D: The type flag of a surface is unknown");
-						(*it).flags &= ~(0xf);
-					}
-
-					// the number of faces increments by one, the number
-					// of vertices by surface.numref.
-					needMat[idx].first++;
-					needMat[idx].second += (unsigned int)(*it).entries.size();
-				};
-			}
-			unsigned int* pip = node->mMeshes = new unsigned int[node->mNumMeshes];
-			unsigned int mat = 0;
-			const size_t oldm = meshes.size();
-			for (MatTable::const_iterator cit = needMat.begin(), cend = needMat.end();
-				cit != cend; ++cit, ++mat)
-			{
-				if (!(*cit).first)continue;
-
-				// allocate a new aiMesh object
-				*pip++ = (unsigned int)meshes.size();
-				aiMesh* mesh = new aiMesh();
-				meshes.push_back(mesh);
-
-				mesh->mMaterialIndex = (unsigned int)outMaterials.size();
-				outMaterials.push_back(new aiMaterial());
-				ConvertMaterial(object, materials[mat], *outMaterials.back());
-
-				// allocate storage for vertices and normals
-				mesh->mNumFaces = (*cit).first;
-				aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces];
-
-				mesh->mNumVertices = (*cit).second;
-				aiVector3D* vertices = mesh->mVertices = new aiVector3D[mesh->mNumVertices];
-				unsigned int cur = 0;
-
-				// allocate UV coordinates, but only if the texture name for the
-				// surface is not empty
-				aiVector3D* uv = NULL;
-				if(object.texture.length())
-				{
-					uv = mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
-					mesh->mNumUVComponents[0] = 2;
-				}
-
-				for (it = object.surfaces.begin(); it != end; ++it)
-				{
-					if (mat == (*it).mat)
-					{
-						const Surface& src = *it;
-
-						// closed polygon
-						unsigned int type = (*it).flags & 0xf; 
-						if (!type)
-						{
-							aiFace& face = *faces++;
-							if((face.mNumIndices = (unsigned int)src.entries.size()))
-							{
-								face.mIndices = new unsigned int[face.mNumIndices];
-								for (unsigned int i = 0; i < face.mNumIndices;++i,++vertices)
-								{
-									const Surface::SurfaceEntry& entry = src.entries[i];
-									face.mIndices[i] = cur++;
-
-									// copy vertex positions
-									*vertices = object.vertices[entry.first] + object.translation;
-
-
-									// copy texture coordinates 
-									if (uv)
-									{
-										uv->x =  entry.second.x;
-										uv->y =  entry.second.y;
-										++uv;
-									}
-								}
-							}
-						}
-						else
-						{
-							
-							it2  = (*it).entries.begin();
-
-							// either a closed or an unclosed line
-							register unsigned int tmp = (unsigned int)(*it).entries.size();
-							if (0x2 == type)--tmp;
-							for (unsigned int m = 0; m < tmp;++m)
-							{
-								aiFace& face = *faces++;
-
-								face.mNumIndices = 2;
-								face.mIndices = new unsigned int[2];
-								face.mIndices[0] = cur++;
-								face.mIndices[1] = cur++;
-
-								// copy vertex positions
-								*vertices++ = object.vertices[(*it2).first];
-								
-								// copy texture coordinates 
-								if (uv)
-								{
-									uv->x =  (*it2).second.x;
-									uv->y =  (*it2).second.y;
-									++uv;
-								}
-
-
-								if (0x1 == type && tmp-1 == m)
-								{
-									// if this is a closed line repeat its beginning now
-									it2  = (*it).entries.begin();
-								}
-								else ++it2;
-
-								// second point
-								*vertices++ = object.vertices[(*it2).first];
-
-								if (uv)
-								{
-									uv->x =  (*it2).second.x;
-									uv->y =  (*it2).second.y;
-									++uv;
-								}
-							}
-						}
-					}
-				}
-			}
-
-			// Now apply catmull clark subdivision if necessary. We split meshes into
-			// materials which is not done by AC3D during smoothing, so we need to
-			// collect all meshes using the same material group.
-			if (object.subDiv)	{
-				if (configEvalSubdivision) {
-					boost::scoped_ptr<Subdivider> div(Subdivider::Create(Subdivider::CATMULL_CLARKE));
-					DefaultLogger::get()->info("AC3D: Evaluating subdivision surface: "+object.name);
-
-					std::vector<aiMesh*> cpy(meshes.size()-oldm,NULL);
-					div->Subdivide(&meshes[oldm],cpy.size(),&cpy.front(),object.subDiv,true);
-					std::copy(cpy.begin(),cpy.end(),meshes.begin()+oldm);
-
-					// previous meshes are deleted vy Subdivide().
-				}
-				else {
-					DefaultLogger::get()->info("AC3D: Letting the subdivision surface untouched due to my configuration: "
-						+object.name);
-				}
-			}
-		}
-	}
-
-	if (object.name.length())
-		node->mName.Set(object.name);
-	else
-	{
-		// generate a name depending on the type of the node
-		switch (object.type)
-		{
-		case Object::Group:
-			node->mName.length = ::sprintf(node->mName.data,"ACGroup_%i",groups++);
-			break;
-		case Object::Poly:
-			node->mName.length = ::sprintf(node->mName.data,"ACPoly_%i",polys++);
-			break;
-		case Object::Light:
-			node->mName.length = ::sprintf(node->mName.data,"ACLight_%i",lights++);
-			break;
-
-			// there shouldn't be more than one world, but we don't care
-		case Object::World: 
-			node->mName.length = ::sprintf(node->mName.data,"ACWorld_%i",worlds++);
-			break;
-		}
-	}
-
-
-	// setup the local transformation matrix of the object
-	// compute the transformation offset to the parent node
-	node->mTransformation = aiMatrix4x4 ( object.rotation );
-
-	if (object.type == Object::Group || !object.numRefs)
-	{
-		node->mTransformation.a4 = object.translation.x;
-		node->mTransformation.b4 = object.translation.y;
-		node->mTransformation.c4 = object.translation.z;
-	}
-
-	// add children to the object
-	if (object.children.size())
-	{
-		node->mNumChildren = (unsigned int)object.children.size();
-		node->mChildren = new aiNode*[node->mNumChildren];
-		for (unsigned int i = 0; i < node->mNumChildren;++i)
-		{
-			node->mChildren[i] = ConvertObjectSection(object.children[i],meshes,outMaterials,materials,node);
-		}
-	}
-
-	return node;
+    aiNode* node = new aiNode();
+    node->mParent = parent;
+    if (object.vertices.size())
+    {
+        if (!object.surfaces.size() || !object.numRefs)
+        {
+            /* " An object with 7 vertices (no surfaces, no materials defined).
+                 This is a good way of getting point data into AC3D.
+                 The Vertex->create convex-surface/object can be used on these
+                 vertices to 'wrap' a 3d shape around them "
+                 (http://www.opencity.info/html/ac3dfileformat.html)
+
+                 therefore: if no surfaces are defined return point data only
+             */
+
+            DefaultLogger::get()->info("AC3D: No surfaces defined in object definition, "
+                "a point list is returned");
+
+            meshes.push_back(new aiMesh());
+            aiMesh* mesh = meshes.back();
+
+            mesh->mNumFaces = mesh->mNumVertices = (unsigned int)object.vertices.size();
+            aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces];
+            aiVector3D* verts = mesh->mVertices = new aiVector3D[mesh->mNumVertices];
+
+            for (unsigned int i = 0; i < mesh->mNumVertices;++i,++faces,++verts)
+            {
+                *verts = object.vertices[i];
+                faces->mNumIndices = 1;
+                faces->mIndices = new unsigned int[1];
+                faces->mIndices[0] = i;
+            }
+
+            // use the primary material in this case. this should be the
+            // default material if all objects of the file contain points
+            // and no faces.
+            mesh->mMaterialIndex = 0;
+            outMaterials.push_back(new aiMaterial());
+            ConvertMaterial(object, materials[0], *outMaterials.back());
+        }
+        else
+        {
+            // need to generate one or more meshes for this object.
+            // find out how many different materials we have
+            typedef std::pair< unsigned int, unsigned int > IntPair;
+            typedef std::vector< IntPair > MatTable;
+            MatTable needMat(materials.size(),IntPair(0,0));
+
+            std::vector<Surface>::iterator it,end = object.surfaces.end();
+            std::vector<Surface::SurfaceEntry>::iterator it2,end2;
+
+            for (it = object.surfaces.begin(); it != end; ++it)
+            {
+                unsigned int idx = (*it).mat;
+                if (idx >= needMat.size())
+                {
+                    DefaultLogger::get()->error("AC3D: material index is out of range");
+                    idx = 0;
+                }
+                if ((*it).entries.empty())
+                {
+                    DefaultLogger::get()->warn("AC3D: surface her zero vertex references");
+                }
+
+                // validate all vertex indices to make sure we won't crash here
+                for (it2  = (*it).entries.begin(),
+                     end2 = (*it).entries.end(); it2 != end2; ++it2)
+                {
+                    if ((*it2).first >= object.vertices.size())
+                    {
+                        DefaultLogger::get()->warn("AC3D: Invalid vertex reference");
+                        (*it2).first = 0;
+                    }
+                }
+
+                if (!needMat[idx].first)++node->mNumMeshes;
+
+                switch ((*it).flags & 0xf)
+                {
+                    // closed line
+                case 0x1:
+
+                    needMat[idx].first  += (unsigned int)(*it).entries.size();
+                    needMat[idx].second += (unsigned int)(*it).entries.size()<<1u;
+                    break;
+
+                    // unclosed line
+                case 0x2:
+
+                    needMat[idx].first  += (unsigned int)(*it).entries.size()-1;
+                    needMat[idx].second += ((unsigned int)(*it).entries.size()-1)<<1u;
+                    break;
+
+                    // 0 == polygon, else unknown
+                default:
+
+                    if ((*it).flags & 0xf)
+                    {
+                        DefaultLogger::get()->warn("AC3D: The type flag of a surface is unknown");
+                        (*it).flags &= ~(0xf);
+                    }
+
+                    // the number of faces increments by one, the number
+                    // of vertices by surface.numref.
+                    needMat[idx].first++;
+                    needMat[idx].second += (unsigned int)(*it).entries.size();
+                };
+            }
+            unsigned int* pip = node->mMeshes = new unsigned int[node->mNumMeshes];
+            unsigned int mat = 0;
+            const size_t oldm = meshes.size();
+            for (MatTable::const_iterator cit = needMat.begin(), cend = needMat.end();
+                cit != cend; ++cit, ++mat)
+            {
+                if (!(*cit).first)continue;
+
+                // allocate a new aiMesh object
+                *pip++ = (unsigned int)meshes.size();
+                aiMesh* mesh = new aiMesh();
+                meshes.push_back(mesh);
+
+                mesh->mMaterialIndex = (unsigned int)outMaterials.size();
+                outMaterials.push_back(new aiMaterial());
+                ConvertMaterial(object, materials[mat], *outMaterials.back());
+
+                // allocate storage for vertices and normals
+                mesh->mNumFaces = (*cit).first;
+                if (mesh->mNumFaces == 0) {
+                    throw DeadlyImportError("AC3D: No faces");
+                } else if (mesh->mNumFaces > AI_MAX_ALLOC(aiFace)) {
+                    throw DeadlyImportError("AC3D: Too many faces, would run out of memory");
+                }
+                aiFace* faces = mesh->mFaces = new aiFace[mesh->mNumFaces];
+
+                mesh->mNumVertices = (*cit).second;
+                if (mesh->mNumVertices == 0) {
+                    throw DeadlyImportError("AC3D: No vertices");
+                } else if (mesh->mNumVertices > AI_MAX_ALLOC(aiVector3D)) {
+                    throw DeadlyImportError("AC3D: Too many vertices, would run out of memory");
+                }
+                aiVector3D* vertices = mesh->mVertices = new aiVector3D[mesh->mNumVertices];
+                unsigned int cur = 0;
+
+                // allocate UV coordinates, but only if the texture name for the
+                // surface is not empty
+                aiVector3D* uv = NULL;
+                if(object.texture.length())
+                {
+                    uv = mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
+                    mesh->mNumUVComponents[0] = 2;
+                }
+
+                for (it = object.surfaces.begin(); it != end; ++it)
+                {
+                    if (mat == (*it).mat)
+                    {
+                        const Surface& src = *it;
+
+                        // closed polygon
+                        unsigned int type = (*it).flags & 0xf;
+                        if (!type)
+                        {
+                            aiFace& face = *faces++;
+                            if((face.mNumIndices = (unsigned int)src.entries.size()))
+                            {
+                                face.mIndices = new unsigned int[face.mNumIndices];
+                                for (unsigned int i = 0; i < face.mNumIndices;++i,++vertices)
+                                {
+                                    const Surface::SurfaceEntry& entry = src.entries[i];
+                                    face.mIndices[i] = cur++;
+
+                                    // copy vertex positions
+                                    if (static_cast<unsigned>(vertices - mesh->mVertices) >= mesh->mNumVertices) {
+                                        throw DeadlyImportError("AC3D: Invalid number of vertices");
+                                    }
+                                    *vertices = object.vertices[entry.first] + object.translation;
+
+
+                                    // copy texture coordinates
+                                    if (uv)
+                                    {
+                                        uv->x =  entry.second.x;
+                                        uv->y =  entry.second.y;
+                                        ++uv;
+                                    }
+                                }
+                            }
+                        }
+                        else
+                        {
+
+                            it2  = (*it).entries.begin();
+
+                            // either a closed or an unclosed line
+                            unsigned int tmp = (unsigned int)(*it).entries.size();
+                            if (0x2 == type)--tmp;
+                            for (unsigned int m = 0; m < tmp;++m)
+                            {
+                                aiFace& face = *faces++;
+
+                                face.mNumIndices = 2;
+                                face.mIndices = new unsigned int[2];
+                                face.mIndices[0] = cur++;
+                                face.mIndices[1] = cur++;
+
+                                // copy vertex positions
+                                if (it2 == (*it).entries.end() ) {
+                                    throw DeadlyImportError("AC3D: Bad line");
+                                }
+                                ai_assert((*it2).first < object.vertices.size());
+                                *vertices++ = object.vertices[(*it2).first];
+
+                                // copy texture coordinates
+                                if (uv)
+                                {
+                                    uv->x =  (*it2).second.x;
+                                    uv->y =  (*it2).second.y;
+                                    ++uv;
+                                }
+
+
+                                if (0x1 == type && tmp-1 == m)
+                                {
+                                    // if this is a closed line repeat its beginning now
+                                    it2  = (*it).entries.begin();
+                                }
+                                else ++it2;
+
+                                // second point
+                                *vertices++ = object.vertices[(*it2).first];
+
+                                if (uv)
+                                {
+                                    uv->x =  (*it2).second.x;
+                                    uv->y =  (*it2).second.y;
+                                    ++uv;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+
+            // Now apply catmull clark subdivision if necessary. We split meshes into
+            // materials which is not done by AC3D during smoothing, so we need to
+            // collect all meshes using the same material group.
+            if (object.subDiv)  {
+                if (configEvalSubdivision) {
+                    boost::scoped_ptr<Subdivider> div(Subdivider::Create(Subdivider::CATMULL_CLARKE));
+                    DefaultLogger::get()->info("AC3D: Evaluating subdivision surface: "+object.name);
+
+                    std::vector<aiMesh*> cpy(meshes.size()-oldm,NULL);
+                    div->Subdivide(&meshes[oldm],cpy.size(),&cpy.front(),object.subDiv,true);
+                    std::copy(cpy.begin(),cpy.end(),meshes.begin()+oldm);
+
+                    // previous meshes are deleted vy Subdivide().
+                }
+                else {
+                    DefaultLogger::get()->info("AC3D: Letting the subdivision surface untouched due to my configuration: "
+                        +object.name);
+                }
+            }
+        }
+    }
+
+    if (object.name.length())
+        node->mName.Set(object.name);
+    else
+    {
+        // generate a name depending on the type of the node
+        switch (object.type)
+        {
+        case Object::Group:
+            node->mName.length = ::sprintf(node->mName.data,"ACGroup_%i",groups++);
+            break;
+        case Object::Poly:
+            node->mName.length = ::sprintf(node->mName.data,"ACPoly_%i",polys++);
+            break;
+        case Object::Light:
+            node->mName.length = ::sprintf(node->mName.data,"ACLight_%i",lights++);
+            break;
+
+            // there shouldn't be more than one world, but we don't care
+        case Object::World:
+            node->mName.length = ::sprintf(node->mName.data,"ACWorld_%i",worlds++);
+            break;
+        }
+    }
+
+
+    // setup the local transformation matrix of the object
+    // compute the transformation offset to the parent node
+    node->mTransformation = aiMatrix4x4 ( object.rotation );
+
+    if (object.type == Object::Group || !object.numRefs)
+    {
+        node->mTransformation.a4 = object.translation.x;
+        node->mTransformation.b4 = object.translation.y;
+        node->mTransformation.c4 = object.translation.z;
+    }
+
+    // add children to the object
+    if (object.children.size())
+    {
+        node->mNumChildren = (unsigned int)object.children.size();
+        node->mChildren = new aiNode*[node->mNumChildren];
+        for (unsigned int i = 0; i < node->mNumChildren;++i)
+        {
+            node->mChildren[i] = ConvertObjectSection(object.children[i],meshes,outMaterials,materials,node);
+        }
+    }
+
+    return node;
 }
 
 // ------------------------------------------------------------------------------------------------
 void AC3DImporter::SetupProperties(const Importer* pImp)
 {
-	configSplitBFCull = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_AC_SEPARATE_BFCULL,1) ? true : false;
-	configEvalSubdivision =  pImp->GetPropertyInteger(AI_CONFIG_IMPORT_AC_EVAL_SUBDIVISION,1) ? true : false;
+    configSplitBFCull = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_AC_SEPARATE_BFCULL,1) ? true : false;
+    configEvalSubdivision =  pImp->GetPropertyInteger(AI_CONFIG_IMPORT_AC_EVAL_SUBDIVISION,1) ? true : false;
 }
 
 // ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure. 
-void AC3DImporter::InternReadFile( const std::string& pFile, 
-	aiScene* pScene, IOSystem* pIOHandler)
+// Imports the given file into the given scene structure.
+void AC3DImporter::InternReadFile( const std::string& pFile,
+    aiScene* pScene, IOSystem* pIOHandler)
 {
-	boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
-
-	// Check whether we can read from the file
-	if( file.get() == NULL)
-		throw DeadlyImportError( "Failed to open AC3D file " + pFile + ".");
-
-	// allocate storage and copy the contents of the file to a memory buffer
-	std::vector<char> mBuffer2;
-	TextFileToBuffer(file.get(),mBuffer2);
-
-	buffer = &mBuffer2[0];
-	mNumMeshes = 0;
-
-	lights = polys = worlds = groups = 0;
-
-	if (::strncmp(buffer,"AC3D",4)) {
-		throw DeadlyImportError("AC3D: No valid AC3D file, magic sequence not found");
-	}
-
-	// print the file format version to the console
-	unsigned int version = HexDigitToDecimal( buffer[4] );
-	char msg[3];
-	ASSIMP_itoa10(msg,3,version);
-	DefaultLogger::get()->info(std::string("AC3D file format version: ") + msg);
-
-	std::vector<Material> materials;
-	materials.reserve(5);
-
-	std::vector<Object> rootObjects;
-	rootObjects.reserve(5);
-
-	std::vector<aiLight*> lights;
-	mLights = & lights;
-
-	while (GetNextLine())
-	{
-		if (TokenMatch(buffer,"MATERIAL",8))
-		{
-			materials.push_back(Material());
-			Material& mat = materials.back();
-
-			// manually parse the material ... sscanf would use the buldin atof ...
-			// Format: (name) rgb %f %f %f  amb %f %f %f  emis %f %f %f  spec %f %f %f  shi %d  trans %f
-
-			AI_AC_SKIP_TO_NEXT_TOKEN();
-			if ('\"' == *buffer)
-			{
-				AI_AC_GET_STRING(mat.name);
-				AI_AC_SKIP_TO_NEXT_TOKEN();
-			}
-
-			AI_AC_CHECKED_LOAD_FLOAT_ARRAY("rgb",3,3,&mat.rgb);
-			AI_AC_CHECKED_LOAD_FLOAT_ARRAY("amb",3,3,&mat.amb);
-			AI_AC_CHECKED_LOAD_FLOAT_ARRAY("emis",4,3,&mat.emis);
-			AI_AC_CHECKED_LOAD_FLOAT_ARRAY("spec",4,3,&mat.spec);
-			AI_AC_CHECKED_LOAD_FLOAT_ARRAY("shi",3,1,&mat.shin);
-			AI_AC_CHECKED_LOAD_FLOAT_ARRAY("trans",5,1,&mat.trans);
-		}
-		LoadObjectSection(rootObjects);
-	}
-
-	if (rootObjects.empty() || !mNumMeshes)
-	{
-		throw DeadlyImportError("AC3D: No meshes have been loaded");
-	}
-	if (materials.empty())
-	{
-		DefaultLogger::get()->warn("AC3D: No material has been found");
-		materials.push_back(Material());
-	}
-
-	mNumMeshes += (mNumMeshes>>2u) + 1;
-	std::vector<aiMesh*> meshes;
-	meshes.reserve(mNumMeshes);
-
-	std::vector<aiMaterial*> omaterials;
-	materials.reserve(mNumMeshes);
-
-	// generate a dummy root if there are multiple objects on the top layer
-	Object* root;
-	if (1 == rootObjects.size())
-		root = &rootObjects[0];
-	else
-	{
-		root = new Object();
-	}
-
-	// now convert the imported stuff to our output data structure
-	pScene->mRootNode = ConvertObjectSection(*root,meshes,omaterials,materials);
-	if (1 != rootObjects.size())delete root;
-
-	if (!::strncmp( pScene->mRootNode->mName.data, "Node", 4))
-		pScene->mRootNode->mName.Set("<AC3DWorld>");
-
-	// copy meshes
-	if (meshes.empty())
-	{
-		throw DeadlyImportError("An unknown error occured during converting");
-	}
-	pScene->mNumMeshes = (unsigned int)meshes.size();
-	pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
-	::memcpy(pScene->mMeshes,&meshes[0],pScene->mNumMeshes*sizeof(void*));
-
-	// copy materials
-	pScene->mNumMaterials = (unsigned int)omaterials.size();
-	pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
-	::memcpy(pScene->mMaterials,&omaterials[0],pScene->mNumMaterials*sizeof(void*));
-
-	// copy lights
-	pScene->mNumLights = (unsigned int)lights.size();
-	if (lights.size())
-	{
-		pScene->mLights = new aiLight*[lights.size()];
-		::memcpy(pScene->mLights,&lights[0],lights.size()*sizeof(void*));
-	}
+    boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
+
+    // Check whether we can read from the file
+    if( file.get() == NULL)
+        throw DeadlyImportError( "Failed to open AC3D file " + pFile + ".");
+
+    // allocate storage and copy the contents of the file to a memory buffer
+    std::vector<char> mBuffer2;
+    TextFileToBuffer(file.get(),mBuffer2);
+
+    buffer = &mBuffer2[0];
+    mNumMeshes = 0;
+
+    lights = polys = worlds = groups = 0;
+
+    if (::strncmp(buffer,"AC3D",4)) {
+        throw DeadlyImportError("AC3D: No valid AC3D file, magic sequence not found");
+    }
+
+    // print the file format version to the console
+    unsigned int version = HexDigitToDecimal( buffer[4] );
+    char msg[3];
+    ASSIMP_itoa10(msg,3,version);
+    DefaultLogger::get()->info(std::string("AC3D file format version: ") + msg);
+
+    std::vector<Material> materials;
+    materials.reserve(5);
+
+    std::vector<Object> rootObjects;
+    rootObjects.reserve(5);
+
+    std::vector<aiLight*> lights;
+    mLights = & lights;
+
+    while (GetNextLine())
+    {
+        if (TokenMatch(buffer,"MATERIAL",8))
+        {
+            materials.push_back(Material());
+            Material& mat = materials.back();
+
+            // manually parse the material ... sscanf would use the buldin atof ...
+            // Format: (name) rgb %f %f %f  amb %f %f %f  emis %f %f %f  spec %f %f %f  shi %d  trans %f
+
+            AI_AC_SKIP_TO_NEXT_TOKEN();
+            if ('\"' == *buffer)
+            {
+                AI_AC_GET_STRING(mat.name);
+                AI_AC_SKIP_TO_NEXT_TOKEN();
+            }
+
+            AI_AC_CHECKED_LOAD_FLOAT_ARRAY("rgb",3,3,&mat.rgb);
+            AI_AC_CHECKED_LOAD_FLOAT_ARRAY("amb",3,3,&mat.amb);
+            AI_AC_CHECKED_LOAD_FLOAT_ARRAY("emis",4,3,&mat.emis);
+            AI_AC_CHECKED_LOAD_FLOAT_ARRAY("spec",4,3,&mat.spec);
+            AI_AC_CHECKED_LOAD_FLOAT_ARRAY("shi",3,1,&mat.shin);
+            AI_AC_CHECKED_LOAD_FLOAT_ARRAY("trans",5,1,&mat.trans);
+        }
+        LoadObjectSection(rootObjects);
+    }
+
+    if (rootObjects.empty() || !mNumMeshes)
+    {
+        throw DeadlyImportError("AC3D: No meshes have been loaded");
+    }
+    if (materials.empty())
+    {
+        DefaultLogger::get()->warn("AC3D: No material has been found");
+        materials.push_back(Material());
+    }
+
+    mNumMeshes += (mNumMeshes>>2u) + 1;
+    std::vector<aiMesh*> meshes;
+    meshes.reserve(mNumMeshes);
+
+    std::vector<aiMaterial*> omaterials;
+    materials.reserve(mNumMeshes);
+
+    // generate a dummy root if there are multiple objects on the top layer
+    Object* root;
+    if (1 == rootObjects.size())
+        root = &rootObjects[0];
+    else
+    {
+        root = new Object();
+    }
+
+    // now convert the imported stuff to our output data structure
+    pScene->mRootNode = ConvertObjectSection(*root,meshes,omaterials,materials);
+    if (1 != rootObjects.size())delete root;
+
+    if (!::strncmp( pScene->mRootNode->mName.data, "Node", 4))
+        pScene->mRootNode->mName.Set("<AC3DWorld>");
+
+    // copy meshes
+    if (meshes.empty())
+    {
+        throw DeadlyImportError("An unknown error occured during converting");
+    }
+    pScene->mNumMeshes = (unsigned int)meshes.size();
+    pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
+    ::memcpy(pScene->mMeshes,&meshes[0],pScene->mNumMeshes*sizeof(void*));
+
+    // copy materials
+    pScene->mNumMaterials = (unsigned int)omaterials.size();
+    pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
+    ::memcpy(pScene->mMaterials,&omaterials[0],pScene->mNumMaterials*sizeof(void*));
+
+    // copy lights
+    pScene->mNumLights = (unsigned int)lights.size();
+    if (lights.size())
+    {
+        pScene->mLights = new aiLight*[lights.size()];
+        ::memcpy(pScene->mLights,&lights[0],lights.size()*sizeof(void*));
+    }
 }
 
 #endif //!defined ASSIMP_BUILD_NO_AC_IMPORTER

+ 179 - 172
assimplib.mod/assimp/code/ACLoader.h

@@ -2,11 +2,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -23,16 +23,16 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -49,7 +49,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "BaseImporter.h"
 #include "../include/assimp/types.h"
 
-namespace Assimp	{
+struct aiNode;
+struct aiMesh;
+struct aiMaterial;
+struct aiLight;
+
+
+namespace Assimp    {
 
 // ---------------------------------------------------------------------------
 /** AC3D (*.ac) importer class
@@ -57,209 +63,210 @@ namespace Assimp	{
 class AC3DImporter : public BaseImporter
 {
 public:
-	AC3DImporter();
-	~AC3DImporter();
-
-
-
-	// Represents an AC3D material
-	struct Material
-	{
-		Material()
-			:	rgb		(0.6f,0.6f,0.6f)
-			,	spec	(1.f,1.f,1.f)
-			,	shin	(0.f)
-			,	trans	(0.f)
-		{}
+    AC3DImporter();
+    ~AC3DImporter();
+
+
+
+    // Represents an AC3D material
+    struct Material
+    {
+        Material()
+            :   rgb     (0.6f,0.6f,0.6f)
+            ,   spec    (1.f,1.f,1.f)
+            ,   shin    (0.f)
+            ,   trans   (0.f)
+        {}
 
-		// base color of the material
-		aiColor3D rgb;
+        // base color of the material
+        aiColor3D rgb;
 
-		// ambient color of the material
-		aiColor3D amb;
+        // ambient color of the material
+        aiColor3D amb;
 
-		// emissive color of the material
-		aiColor3D emis;
+        // emissive color of the material
+        aiColor3D emis;
 
-		// specular color of the material
-		aiColor3D spec;
+        // specular color of the material
+        aiColor3D spec;
 
-		// shininess exponent
-		float shin;
+        // shininess exponent
+        float shin;
 
-		// transparency. 0 == opaque
-		float trans;
+        // transparency. 0 == opaque
+        float trans;
 
-		// name of the material. optional.
-		std::string name;
-	};
+        // name of the material. optional.
+        std::string name;
+    };
 
-	// Represents an AC3D surface
-	struct Surface
-	{
-		Surface()
-			:	mat		(0)
-			,	flags	(0)
-		{}
+    // Represents an AC3D surface
+    struct Surface
+    {
+        Surface()
+            :   mat     (0)
+            ,   flags   (0)
+        {}
 
-		unsigned int mat,flags;
+        unsigned int mat,flags;
 
-		typedef std::pair<unsigned int, aiVector2D > SurfaceEntry;
-		std::vector< SurfaceEntry > entries;
-	};
+        typedef std::pair<unsigned int, aiVector2D > SurfaceEntry;
+        std::vector< SurfaceEntry > entries;
+    };
 
-	// Represents an AC3D object
-	struct Object
-	{
-		Object()
-			:	type	(World)
-			,	name( "" )
-			,	children()
-			,	texture( "" )
-			,	texRepeat( 1.f, 1.f )
-			,	texOffset( 0.0f, 0.0f )
-			,	rotation()
-			,	translation()
-			,	vertices()
-			,	surfaces()
-			,	numRefs (0)
-			,	subDiv	(0)                
-		{}
+    // Represents an AC3D object
+    struct Object
+    {
+        Object()
+            :   type    (World)
+            ,   name( "" )
+            ,   children()
+            ,   texture( "" )
+            ,   texRepeat( 1.f, 1.f )
+            ,   texOffset( 0.0f, 0.0f )
+            ,   rotation()
+            ,   translation()
+            ,   vertices()
+            ,   surfaces()
+            ,   numRefs (0)
+            ,   subDiv  (0)
+            ,   crease()
+        {}
 
-		// Type description
-		enum Type
-		{
-			World = 0x0,
-			Poly  = 0x1,
-			Group = 0x2,
-			Light = 0x4
-		} type;
+        // Type description
+        enum Type
+        {
+            World = 0x0,
+            Poly  = 0x1,
+            Group = 0x2,
+            Light = 0x4
+        } type;
 
-		// name of the object
-		std::string name;
+        // name of the object
+        std::string name;
 
-		// object children
-		std::vector<Object> children;
+        // object children
+        std::vector<Object> children;
 
-		// texture to be assigned to all surfaces of the object
-		std::string texture;
+        // texture to be assigned to all surfaces of the object
+        std::string texture;
 
-		// texture repat factors (scaling for all coordinates)
-		aiVector2D texRepeat, texOffset;
+        // texture repat factors (scaling for all coordinates)
+        aiVector2D texRepeat, texOffset;
 
-		// rotation matrix
-		aiMatrix3x3 rotation;
+        // rotation matrix
+        aiMatrix3x3 rotation;
 
-		// translation vector
-		aiVector3D translation;
+        // translation vector
+        aiVector3D translation;
 
-		// vertices
-		std::vector<aiVector3D> vertices;
+        // vertices
+        std::vector<aiVector3D> vertices;
 
-		// surfaces
-		std::vector<Surface> surfaces;
+        // surfaces
+        std::vector<Surface> surfaces;
 
-		// number of indices (= num verts in verbose format)
-		unsigned int numRefs;
-
-		// number of subdivisions to be performed on the 
-		// imported data
-		unsigned int subDiv;
-
-		// max angle limit for smoothing
-		float crease;
-	};
+        // number of indices (= num verts in verbose format)
+        unsigned int numRefs;
+
+        // number of subdivisions to be performed on the
+        // imported data
+        unsigned int subDiv;
+
+        // max angle limit for smoothing
+        float crease;
+    };
 
 
 public:
 
-	// -------------------------------------------------------------------
-	/** Returns whether the class can handle the format of the given file. 
-	 * See BaseImporter::CanRead() for details.
-	 */
-	bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
-		bool checkSig) const;
+    // -------------------------------------------------------------------
+    /** Returns whether the class can handle the format of the given file.
+     * See BaseImporter::CanRead() for details.
+     */
+    bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+        bool checkSig) const;
 
 protected:
 
-	// -------------------------------------------------------------------
-	/** Return importer meta information.
-	 * See #BaseImporter::GetInfo for the details */
-	const aiImporterDesc* GetInfo () const;
+    // -------------------------------------------------------------------
+    /** Return importer meta information.
+     * See #BaseImporter::GetInfo for the details */
+    const aiImporterDesc* GetInfo () const;
 
-	// -------------------------------------------------------------------
-	/** Imports the given file into the given scene structure. 
-	 * See BaseImporter::InternReadFile() for details*/
-	void InternReadFile( const std::string& pFile, aiScene* pScene, 
-		IOSystem* pIOHandler);
+    // -------------------------------------------------------------------
+    /** Imports the given file into the given scene structure.
+     * See BaseImporter::InternReadFile() for details*/
+    void InternReadFile( const std::string& pFile, aiScene* pScene,
+        IOSystem* pIOHandler);
 
-	// -------------------------------------------------------------------
-	/** Called prior to ReadFile().
-	* The function is a request to the importer to update its configuration
-	* basing on the Importer's configuration property list.*/
-	void SetupProperties(const Importer* pImp);
+    // -------------------------------------------------------------------
+    /** Called prior to ReadFile().
+    * The function is a request to the importer to update its configuration
+    * basing on the Importer's configuration property list.*/
+    void SetupProperties(const Importer* pImp);
 
 private:
 
-	// -------------------------------------------------------------------
-	/** Get the next line from the file.
-	 *  @return false if the end of the file was reached*/
-	bool GetNextLine();
-
-	// -------------------------------------------------------------------
-	/** Load the object section. This method is called recursively to
-	 *  load subobjects, the method returns after a 'kids 0' was 
-	 *  encountered.
-	 *  @objects List of output objects*/
-	void LoadObjectSection(std::vector<Object>& objects);
-
-	// -------------------------------------------------------------------
-	/** Convert all objects into meshes and nodes.
-	 *  @param object Current object to work on
-	 *  @param meshes Pointer to the list of output meshes
-	 *  @param outMaterials List of output materials
-	 *  @param materials Material list
-	 *  @param Scenegraph node for the object */
-	aiNode* ConvertObjectSection(Object& object,
-		std::vector<aiMesh*>& meshes,
-		std::vector<aiMaterial*>& outMaterials,
-		const std::vector<Material>& materials,
-		aiNode* parent = NULL);
-
-	// -------------------------------------------------------------------
-	/** Convert a material
-	 *  @param object Current object
-	 *  @param matSrc Source material description
-	 *  @param matDest Destination material to be filled */
-	void ConvertMaterial(const Object& object,
-		const Material& matSrc,
-		aiMaterial& matDest);
+    // -------------------------------------------------------------------
+    /** Get the next line from the file.
+     *  @return false if the end of the file was reached*/
+    bool GetNextLine();
+
+    // -------------------------------------------------------------------
+    /** Load the object section. This method is called recursively to
+     *  load subobjects, the method returns after a 'kids 0' was
+     *  encountered.
+     *  @objects List of output objects*/
+    void LoadObjectSection(std::vector<Object>& objects);
+
+    // -------------------------------------------------------------------
+    /** Convert all objects into meshes and nodes.
+     *  @param object Current object to work on
+     *  @param meshes Pointer to the list of output meshes
+     *  @param outMaterials List of output materials
+     *  @param materials Material list
+     *  @param Scenegraph node for the object */
+    aiNode* ConvertObjectSection(Object& object,
+        std::vector<aiMesh*>& meshes,
+        std::vector<aiMaterial*>& outMaterials,
+        const std::vector<Material>& materials,
+        aiNode* parent = NULL);
+
+    // -------------------------------------------------------------------
+    /** Convert a material
+     *  @param object Current object
+     *  @param matSrc Source material description
+     *  @param matDest Destination material to be filled */
+    void ConvertMaterial(const Object& object,
+        const Material& matSrc,
+        aiMaterial& matDest);
 
 private:
 
 
-	// points to the next data line
-	const char* buffer;
+    // points to the next data line
+    const char* buffer;
 
-	// Configuration option: if enabled, up to two meshes
-	// are generated per material: those faces who have 
-	// their bf cull flags set are separated.
-	bool configSplitBFCull;
+    // Configuration option: if enabled, up to two meshes
+    // are generated per material: those faces who have
+    // their bf cull flags set are separated.
+    bool configSplitBFCull;
 
-	// Configuration switch: subdivision surfaces are only
-	// evaluated if the value is true.
-	bool configEvalSubdivision;
+    // Configuration switch: subdivision surfaces are only
+    // evaluated if the value is true.
+    bool configEvalSubdivision;
 
-	// counts how many objects we have in the tree.
-	// basing on this information we can find a
-	// good estimate how many meshes we'll have in the final scene.
-	unsigned int mNumMeshes;
+    // counts how many objects we have in the tree.
+    // basing on this information we can find a
+    // good estimate how many meshes we'll have in the final scene.
+    unsigned int mNumMeshes;
 
-	// current list of light sources
-	std::vector<aiLight*>* mLights;
+    // current list of light sources
+    std::vector<aiLight*>* mLights;
 
-	// name counters
-	unsigned int lights, groups, polys, worlds;
+    // name counters
+    unsigned int lights, groups, polys, worlds;
 };
 
 } // end of namespace Assimp

+ 1165 - 1156
assimplib.mod/assimp/code/ASELoader.cpp

@@ -3,12 +3,12 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -25,16 +25,16 @@ conditions are met:
   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 
+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 
+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 
+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 
+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.
 ---------------------------------------------------------------------------
 */
@@ -43,7 +43,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *  @brief Implementation of the ASE importer class
  */
 
-#include "AssimpPCH.h"
 #ifndef ASSIMP_BUILD_NO_ASE_IMPORTER
 
 // internal headers
@@ -51,6 +50,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "StringComparison.h"
 #include "SkeletonMeshBuilder.h"
 #include "TargetAnimation.h"
+#include "../include/assimp/Importer.hpp"
+#include <boost/scoped_ptr.hpp>
+#include "../include/assimp/IOSystem.hpp"
+#include "../include/assimp/DefaultLogger.hpp"
+#include "../include/assimp/scene.h"
+
 
 // utilities
 #include "fast_atof.h"
@@ -59,1258 +64,1262 @@ using namespace Assimp;
 using namespace Assimp::ASE;
 
 static const aiImporterDesc desc = {
-	"ASE Importer",
-	"",
-	"",
-	"Similar to 3DS but text-encoded",
-	aiImporterFlags_SupportTextFlavour,
-	0,
-	0,
-	0,
-	0,
-	"ase ask" 
+    "ASE Importer",
+    "",
+    "",
+    "Similar to 3DS but text-encoded",
+    aiImporterFlags_SupportTextFlavour,
+    0,
+    0,
+    0,
+    0,
+    "ase ask"
 };
 
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 ASEImporter::ASEImporter()
-: noSkeletonMesh()
+    : mParser(),
+    mBuffer(),
+    pcScene(),
+    configRecomputeNormals(),
+    noSkeletonMesh()
 {}
 
 // ------------------------------------------------------------------------------------------------
-// Destructor, private as well 
+// Destructor, private as well
 ASEImporter::~ASEImporter()
 {}
 
 // ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file. 
+// Returns whether the class can handle the format of the given file.
 bool ASEImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool cs) const
 {
-	// check file extension 
-	const std::string extension = GetExtension(pFile);
-	
-	if( extension == "ase" || extension == "ask")
-		return true;
-
-	if ((!extension.length() || cs) && pIOHandler) {
-		const char* tokens[] = {"*3dsmax_asciiexport"};
-		return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
-	}
-	return false;
+    // check file extension
+    const std::string extension = GetExtension(pFile);
+
+    if( extension == "ase" || extension == "ask")
+        return true;
+
+    if ((!extension.length() || cs) && pIOHandler) {
+        const char* tokens[] = {"*3dsmax_asciiexport"};
+        return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
+    }
+    return false;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Loader meta information
 const aiImporterDesc* ASEImporter::GetInfo () const
 {
-	return &desc;
+    return &desc;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Setup configuration options
 void ASEImporter::SetupProperties(const Importer* pImp)
 {
-	configRecomputeNormals = (pImp->GetPropertyInteger(
-		AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS,1) ? true : false);
+    configRecomputeNormals = (pImp->GetPropertyInteger(
+        AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS,1) ? true : false);
 
-	noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
+    noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
 }
 
 // ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure. 
-void ASEImporter::InternReadFile( const std::string& pFile, 
-	aiScene* pScene, IOSystem* pIOHandler)
+// Imports the given file into the given scene structure.
+void ASEImporter::InternReadFile( const std::string& pFile,
+    aiScene* pScene, IOSystem* pIOHandler)
 {
-	boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
-
-	// Check whether we can read from the file
-	if( file.get() == NULL) {
-		throw DeadlyImportError( "Failed to open ASE file " + pFile + ".");
-	}
-
-	// Allocate storage and copy the contents of the file to a memory buffer
-	std::vector<char> mBuffer2;
-	TextFileToBuffer(file.get(),mBuffer2);
-
-	this->mBuffer = &mBuffer2[0];
-	this->pcScene = pScene;
-
-	// ------------------------------------------------------------------
-	// Guess the file format by looking at the extension
-	// ASC is considered to be the older format 110,
-	// ASE is the actual version 200 (that is currently written by max)
-	// ------------------------------------------------------------------
-	unsigned int defaultFormat;
-	std::string::size_type s = pFile.length()-1;
-	switch (pFile.c_str()[s])	{
-
-	case 'C':
-	case 'c':
-		defaultFormat = AI_ASE_OLD_FILE_FORMAT;
-		break;
-	default:
-		defaultFormat = AI_ASE_NEW_FILE_FORMAT;
-	};
-
-	// Construct an ASE parser and parse the file
-	ASE::Parser parser(mBuffer,defaultFormat);
-	mParser = &parser;
-	mParser->Parse();
-
-	//------------------------------------------------------------------
-	// Check whether we god at least one mesh. If we did - generate
-	// materials and copy meshes. 
-	// ------------------------------------------------------------------
-	if ( !mParser->m_vMeshes.empty())	{
-
-		// If absolutely no material has been loaded from the file
-		// we need to generate a default material
-		GenerateDefaultMaterial();
-
-		// process all meshes
-		bool tookNormals = false;
-		std::vector<aiMesh*> avOutMeshes;
-		avOutMeshes.reserve(mParser->m_vMeshes.size()*2);
-		for (std::vector<ASE::Mesh>::iterator i =  mParser->m_vMeshes.begin();i != mParser->m_vMeshes.end();++i)	{
-			if ((*i).bSkip) {
-				continue;
-			}
-			BuildUniqueRepresentation(*i);
-
-			// Need to generate proper vertex normals if necessary
-			if(GenerateNormals(*i)) {
-				tookNormals = true;
-			}
-
-			// Convert all meshes to aiMesh objects
-			ConvertMeshes(*i,avOutMeshes);
-		}
-		if (tookNormals)	{
-			DefaultLogger::get()->debug("ASE: Taking normals from the file. Use "
-				"the AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS setting if you "
-				"experience problems");
-		}
-
-		// Now build the output mesh list. Remove dummies
-		pScene->mNumMeshes = (unsigned int)avOutMeshes.size();
-		aiMesh** pp = pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
-		for (std::vector<aiMesh*>::const_iterator i =  avOutMeshes.begin();i != avOutMeshes.end();++i) {
-			if (!(*i)->mNumFaces) {
-				continue;
-			}
-			*pp++ = *i;
-		}
-		pScene->mNumMeshes = (unsigned int)(pp - pScene->mMeshes);
-
-		// Build final material indices (remove submaterials and setup
-		// the final list)
-		BuildMaterialIndices();
-	}
-
-	// ------------------------------------------------------------------
-	// Copy all scene graph nodes - lights, cameras, dummies and meshes
-	// into one huge list.
-	//------------------------------------------------------------------
-	std::vector<BaseNode*> nodes;
-	nodes.reserve(mParser->m_vMeshes.size() +mParser->m_vLights.size()
-		+ mParser->m_vCameras.size() + mParser->m_vDummies.size());
-
-	// Lights
-	for (std::vector<ASE::Light>::iterator it = mParser->m_vLights.begin(), 
-		 end = mParser->m_vLights.end();it != end; ++it)nodes.push_back(&(*it));
-	// Cameras
-	for (std::vector<ASE::Camera>::iterator it = mParser->m_vCameras.begin(), 
-		 end = mParser->m_vCameras.end();it != end; ++it)nodes.push_back(&(*it));
-	// Meshes
-	for (std::vector<ASE::Mesh>::iterator it = mParser->m_vMeshes.begin(),
-		end = mParser->m_vMeshes.end();it != end; ++it)nodes.push_back(&(*it));
-	// Dummies
-	for (std::vector<ASE::Dummy>::iterator it = mParser->m_vDummies.begin(),
-		end = mParser->m_vDummies.end();it != end; ++it)nodes.push_back(&(*it));
-
-	// build the final node graph
-	BuildNodes(nodes);
-
-	// build output animations
-	BuildAnimations(nodes);
-
-	// build output cameras
-	BuildCameras();
-
-	// build output lights
-	BuildLights();
-
-	// ------------------------------------------------------------------
-	// If we have no meshes use the SkeletonMeshBuilder helper class
-	// to build a mesh for the animation skeleton
-	// FIXME: very strange results
-	// ------------------------------------------------------------------
-	if (!pScene->mNumMeshes)	{
-		pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
-		if (!noSkeletonMesh) {
-			SkeletonMeshBuilder skeleton(pScene);
-		}
-	}
+    boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
+
+    // Check whether we can read from the file
+    if( file.get() == NULL) {
+        throw DeadlyImportError( "Failed to open ASE file " + pFile + ".");
+    }
+
+    // Allocate storage and copy the contents of the file to a memory buffer
+    std::vector<char> mBuffer2;
+    TextFileToBuffer(file.get(),mBuffer2);
+
+    this->mBuffer = &mBuffer2[0];
+    this->pcScene = pScene;
+
+    // ------------------------------------------------------------------
+    // Guess the file format by looking at the extension
+    // ASC is considered to be the older format 110,
+    // ASE is the actual version 200 (that is currently written by max)
+    // ------------------------------------------------------------------
+    unsigned int defaultFormat;
+    std::string::size_type s = pFile.length()-1;
+    switch (pFile.c_str()[s])   {
+
+    case 'C':
+    case 'c':
+        defaultFormat = AI_ASE_OLD_FILE_FORMAT;
+        break;
+    default:
+        defaultFormat = AI_ASE_NEW_FILE_FORMAT;
+    };
+
+    // Construct an ASE parser and parse the file
+    ASE::Parser parser(mBuffer,defaultFormat);
+    mParser = &parser;
+    mParser->Parse();
+
+    //------------------------------------------------------------------
+    // Check whether we god at least one mesh. If we did - generate
+    // materials and copy meshes.
+    // ------------------------------------------------------------------
+    if ( !mParser->m_vMeshes.empty())   {
+
+        // If absolutely no material has been loaded from the file
+        // we need to generate a default material
+        GenerateDefaultMaterial();
+
+        // process all meshes
+        bool tookNormals = false;
+        std::vector<aiMesh*> avOutMeshes;
+        avOutMeshes.reserve(mParser->m_vMeshes.size()*2);
+        for (std::vector<ASE::Mesh>::iterator i =  mParser->m_vMeshes.begin();i != mParser->m_vMeshes.end();++i)    {
+            if ((*i).bSkip) {
+                continue;
+            }
+            BuildUniqueRepresentation(*i);
+
+            // Need to generate proper vertex normals if necessary
+            if(GenerateNormals(*i)) {
+                tookNormals = true;
+            }
+
+            // Convert all meshes to aiMesh objects
+            ConvertMeshes(*i,avOutMeshes);
+        }
+        if (tookNormals)    {
+            DefaultLogger::get()->debug("ASE: Taking normals from the file. Use "
+                "the AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS setting if you "
+                "experience problems");
+        }
+
+        // Now build the output mesh list. Remove dummies
+        pScene->mNumMeshes = (unsigned int)avOutMeshes.size();
+        aiMesh** pp = pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
+        for (std::vector<aiMesh*>::const_iterator i =  avOutMeshes.begin();i != avOutMeshes.end();++i) {
+            if (!(*i)->mNumFaces) {
+                continue;
+            }
+            *pp++ = *i;
+        }
+        pScene->mNumMeshes = (unsigned int)(pp - pScene->mMeshes);
+
+        // Build final material indices (remove submaterials and setup
+        // the final list)
+        BuildMaterialIndices();
+    }
+
+    // ------------------------------------------------------------------
+    // Copy all scene graph nodes - lights, cameras, dummies and meshes
+    // into one huge list.
+    //------------------------------------------------------------------
+    std::vector<BaseNode*> nodes;
+    nodes.reserve(mParser->m_vMeshes.size() +mParser->m_vLights.size()
+        + mParser->m_vCameras.size() + mParser->m_vDummies.size());
+
+    // Lights
+    for (std::vector<ASE::Light>::iterator it = mParser->m_vLights.begin(),
+         end = mParser->m_vLights.end();it != end; ++it)nodes.push_back(&(*it));
+    // Cameras
+    for (std::vector<ASE::Camera>::iterator it = mParser->m_vCameras.begin(),
+         end = mParser->m_vCameras.end();it != end; ++it)nodes.push_back(&(*it));
+    // Meshes
+    for (std::vector<ASE::Mesh>::iterator it = mParser->m_vMeshes.begin(),
+        end = mParser->m_vMeshes.end();it != end; ++it)nodes.push_back(&(*it));
+    // Dummies
+    for (std::vector<ASE::Dummy>::iterator it = mParser->m_vDummies.begin(),
+        end = mParser->m_vDummies.end();it != end; ++it)nodes.push_back(&(*it));
+
+    // build the final node graph
+    BuildNodes(nodes);
+
+    // build output animations
+    BuildAnimations(nodes);
+
+    // build output cameras
+    BuildCameras();
+
+    // build output lights
+    BuildLights();
+
+    // ------------------------------------------------------------------
+    // If we have no meshes use the SkeletonMeshBuilder helper class
+    // to build a mesh for the animation skeleton
+    // FIXME: very strange results
+    // ------------------------------------------------------------------
+    if (!pScene->mNumMeshes)    {
+        pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
+        if (!noSkeletonMesh) {
+            SkeletonMeshBuilder skeleton(pScene);
+        }
+    }
 }
 // ------------------------------------------------------------------------------------------------
 void ASEImporter::GenerateDefaultMaterial()
 {
-	ai_assert(NULL != mParser);
-
-	bool bHas = false;
-	for (std::vector<ASE::Mesh>::iterator i =  mParser->m_vMeshes.begin();i != mParser->m_vMeshes.end();++i) {
-		if ((*i).bSkip)continue;
-		if (ASE::Face::DEFAULT_MATINDEX == (*i).iMaterialIndex)	{
-			(*i).iMaterialIndex = (unsigned int)mParser->m_vMaterials.size();
-			bHas = true;
-		}
-	}
-	if (bHas || mParser->m_vMaterials.empty())	{
-		// add a simple material without submaterials to the parser's list
-		mParser->m_vMaterials.push_back ( ASE::Material() );
-		ASE::Material& mat = mParser->m_vMaterials.back();
-
-		mat.mDiffuse  = aiColor3D(0.6f,0.6f,0.6f);
-		mat.mSpecular = aiColor3D(1.0f,1.0f,1.0f);
-		mat.mAmbient  = aiColor3D(0.05f,0.05f,0.05f);
-		mat.mShading  = Discreet3DS::Gouraud;
-		mat.mName     = AI_DEFAULT_MATERIAL_NAME;
-	}
+    ai_assert(NULL != mParser);
+
+    bool bHas = false;
+    for (std::vector<ASE::Mesh>::iterator i =  mParser->m_vMeshes.begin();i != mParser->m_vMeshes.end();++i) {
+        if ((*i).bSkip)continue;
+        if (ASE::Face::DEFAULT_MATINDEX == (*i).iMaterialIndex) {
+            (*i).iMaterialIndex = (unsigned int)mParser->m_vMaterials.size();
+            bHas = true;
+        }
+    }
+    if (bHas || mParser->m_vMaterials.empty())  {
+        // add a simple material without submaterials to the parser's list
+        mParser->m_vMaterials.push_back ( ASE::Material() );
+        ASE::Material& mat = mParser->m_vMaterials.back();
+
+        mat.mDiffuse  = aiColor3D(0.6f,0.6f,0.6f);
+        mat.mSpecular = aiColor3D(1.0f,1.0f,1.0f);
+        mat.mAmbient  = aiColor3D(0.05f,0.05f,0.05f);
+        mat.mShading  = Discreet3DS::Gouraud;
+        mat.mName     = AI_DEFAULT_MATERIAL_NAME;
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 void ASEImporter::BuildAnimations(const std::vector<BaseNode*>& nodes)
 {
-	// check whether we have at least one mesh which has animations
-	std::vector<ASE::BaseNode*>::const_iterator i =  nodes.begin();
-	unsigned int iNum = 0;
-	for (;i != nodes.end();++i)	{
-
-		// TODO: Implement Bezier & TCB support
-		if ((*i)->mAnim.mPositionType != ASE::Animation::TRACK)	{
-			DefaultLogger::get()->warn("ASE: Position controller uses Bezier/TCB keys. "
-				"This is not supported.");
-		}
-		if ((*i)->mAnim.mRotationType != ASE::Animation::TRACK)	{
-			DefaultLogger::get()->warn("ASE: Rotation controller uses Bezier/TCB keys. "
-				"This is not supported.");
-		}
-		if ((*i)->mAnim.mScalingType != ASE::Animation::TRACK)	{
-			DefaultLogger::get()->warn("ASE: Position controller uses Bezier/TCB keys. "
-				"This is not supported.");
-		}
-
-		// We compare against 1 here - firstly one key is not
-		// really an animation and secondly MAX writes dummies
-		// that represent the node transformation.
-		if ((*i)->mAnim.akeyPositions.size()>1 || (*i)->mAnim.akeyRotations.size()>1 || (*i)->mAnim.akeyScaling.size()>1){
-			++iNum;
-		}
-		if ((*i)->mTargetAnim.akeyPositions.size() > 1 && is_not_qnan( (*i)->mTargetPosition.x )) {
-			++iNum;
-		}
-	}
-	if (iNum)	{
-		// Generate a new animation channel and setup everything for it
-		pcScene->mNumAnimations = 1;
-		pcScene->mAnimations    = new aiAnimation*[1];
-		aiAnimation* pcAnim     = pcScene->mAnimations[0] = new aiAnimation();
-		pcAnim->mNumChannels    = iNum;
-		pcAnim->mChannels       = new aiNodeAnim*[iNum];
-		pcAnim->mTicksPerSecond = mParser->iFrameSpeed * mParser->iTicksPerFrame;
-
-		iNum = 0;
-		
-		// Now iterate through all meshes and collect all data we can find
-		for (i =  nodes.begin();i != nodes.end();++i)	{
-
-			ASE::BaseNode* me = *i;
-			if ( me->mTargetAnim.akeyPositions.size() > 1 && is_not_qnan( me->mTargetPosition.x ))	{
-				// Generate an extra channel for the camera/light target.
-				// BuildNodes() does also generate an extra node, named
-				// <baseName>.Target.
-				aiNodeAnim* nd = pcAnim->mChannels[iNum++] = new aiNodeAnim();
-				nd->mNodeName.Set(me->mName + ".Target");
-
-				// If there is no input position channel we will need
-				// to supply the default position from the node's
-				// local transformation matrix.
-				/*TargetAnimationHelper helper;
-				if (me->mAnim.akeyPositions.empty())
-				{
-					aiMatrix4x4& mat = (*i)->mTransform;
-					helper.SetFixedMainAnimationChannel(aiVector3D(
-						mat.a4, mat.b4, mat.c4));
-				}
-				else helper.SetMainAnimationChannel (&me->mAnim.akeyPositions);
-				helper.SetTargetAnimationChannel (&me->mTargetAnim.akeyPositions);
-				
-				helper.Process(&me->mTargetAnim.akeyPositions);*/
-
-				// Allocate the key array and fill it
-				nd->mNumPositionKeys = (unsigned int) me->mTargetAnim.akeyPositions.size();
-				nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys];
-
-				::memcpy(nd->mPositionKeys,&me->mTargetAnim.akeyPositions[0],
-					nd->mNumPositionKeys * sizeof(aiVectorKey));
-			}
-
-			if (me->mAnim.akeyPositions.size() > 1 || me->mAnim.akeyRotations.size() > 1 || me->mAnim.akeyScaling.size() > 1)	{
-				// Begin a new node animation channel for this node
-				aiNodeAnim* nd = pcAnim->mChannels[iNum++] = new aiNodeAnim();
-				nd->mNodeName.Set(me->mName);
-
-				// copy position keys
-				if (me->mAnim.akeyPositions.size() > 1 )
-				{
-					// Allocate the key array and fill it
-					nd->mNumPositionKeys = (unsigned int) me->mAnim.akeyPositions.size();
-					nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys];
-
-					::memcpy(nd->mPositionKeys,&me->mAnim.akeyPositions[0],
-						nd->mNumPositionKeys * sizeof(aiVectorKey));
-				}
-				// copy rotation keys
-				if (me->mAnim.akeyRotations.size() > 1 )	{
-					// Allocate the key array and fill it
-					nd->mNumRotationKeys = (unsigned int) me->mAnim.akeyRotations.size();
-					nd->mRotationKeys = new aiQuatKey[nd->mNumRotationKeys];
-
-					// --------------------------------------------------------------------
-					// Rotation keys are offsets to the previous keys.
-					// We have the quaternion representations of all 
-					// of them, so we just need to concatenate all
-					// (unit-length) quaternions to get the absolute
-					// rotations.
-					// Rotation keys are ABSOLUTE for older files
-					// --------------------------------------------------------------------
-
-					aiQuaternion cur;
-					for (unsigned int a = 0; a < nd->mNumRotationKeys;++a)	{
-						aiQuatKey q = me->mAnim.akeyRotations[a];
-
-						if (mParser->iFileFormat > 110)	{
-							cur = (a ? cur*q.mValue : q.mValue);
-							q.mValue = cur.Normalize();
-						}
-						nd->mRotationKeys[a] = q; 
-
-						// need this to get to Assimp quaternion conventions
-						nd->mRotationKeys[a].mValue.w *= -1.f;
-					}
-				}
-				// copy scaling keys
-				if (me->mAnim.akeyScaling.size() > 1 )	{
-					// Allocate the key array and fill it
-					nd->mNumScalingKeys = (unsigned int) me->mAnim.akeyScaling.size();
-					nd->mScalingKeys = new aiVectorKey[nd->mNumScalingKeys];
-
-					::memcpy(nd->mScalingKeys,&me->mAnim.akeyScaling[0],
-						nd->mNumScalingKeys * sizeof(aiVectorKey));
-				}
-			}
-		}
-	}
+    // check whether we have at least one mesh which has animations
+    std::vector<ASE::BaseNode*>::const_iterator i =  nodes.begin();
+    unsigned int iNum = 0;
+    for (;i != nodes.end();++i) {
+
+        // TODO: Implement Bezier & TCB support
+        if ((*i)->mAnim.mPositionType != ASE::Animation::TRACK) {
+            DefaultLogger::get()->warn("ASE: Position controller uses Bezier/TCB keys. "
+                "This is not supported.");
+        }
+        if ((*i)->mAnim.mRotationType != ASE::Animation::TRACK) {
+            DefaultLogger::get()->warn("ASE: Rotation controller uses Bezier/TCB keys. "
+                "This is not supported.");
+        }
+        if ((*i)->mAnim.mScalingType != ASE::Animation::TRACK)  {
+            DefaultLogger::get()->warn("ASE: Position controller uses Bezier/TCB keys. "
+                "This is not supported.");
+        }
+
+        // We compare against 1 here - firstly one key is not
+        // really an animation and secondly MAX writes dummies
+        // that represent the node transformation.
+        if ((*i)->mAnim.akeyPositions.size()>1 || (*i)->mAnim.akeyRotations.size()>1 || (*i)->mAnim.akeyScaling.size()>1){
+            ++iNum;
+        }
+        if ((*i)->mTargetAnim.akeyPositions.size() > 1 && is_not_qnan( (*i)->mTargetPosition.x )) {
+            ++iNum;
+        }
+    }
+    if (iNum)   {
+        // Generate a new animation channel and setup everything for it
+        pcScene->mNumAnimations = 1;
+        pcScene->mAnimations    = new aiAnimation*[1];
+        aiAnimation* pcAnim     = pcScene->mAnimations[0] = new aiAnimation();
+        pcAnim->mNumChannels    = iNum;
+        pcAnim->mChannels       = new aiNodeAnim*[iNum];
+        pcAnim->mTicksPerSecond = mParser->iFrameSpeed * mParser->iTicksPerFrame;
+
+        iNum = 0;
+
+        // Now iterate through all meshes and collect all data we can find
+        for (i =  nodes.begin();i != nodes.end();++i)   {
+
+            ASE::BaseNode* me = *i;
+            if ( me->mTargetAnim.akeyPositions.size() > 1 && is_not_qnan( me->mTargetPosition.x ))  {
+                // Generate an extra channel for the camera/light target.
+                // BuildNodes() does also generate an extra node, named
+                // <baseName>.Target.
+                aiNodeAnim* nd = pcAnim->mChannels[iNum++] = new aiNodeAnim();
+                nd->mNodeName.Set(me->mName + ".Target");
+
+                // If there is no input position channel we will need
+                // to supply the default position from the node's
+                // local transformation matrix.
+                /*TargetAnimationHelper helper;
+                if (me->mAnim.akeyPositions.empty())
+                {
+                    aiMatrix4x4& mat = (*i)->mTransform;
+                    helper.SetFixedMainAnimationChannel(aiVector3D(
+                        mat.a4, mat.b4, mat.c4));
+                }
+                else helper.SetMainAnimationChannel (&me->mAnim.akeyPositions);
+                helper.SetTargetAnimationChannel (&me->mTargetAnim.akeyPositions);
+
+                helper.Process(&me->mTargetAnim.akeyPositions);*/
+
+                // Allocate the key array and fill it
+                nd->mNumPositionKeys = (unsigned int) me->mTargetAnim.akeyPositions.size();
+                nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys];
+
+                ::memcpy(nd->mPositionKeys,&me->mTargetAnim.akeyPositions[0],
+                    nd->mNumPositionKeys * sizeof(aiVectorKey));
+            }
+
+            if (me->mAnim.akeyPositions.size() > 1 || me->mAnim.akeyRotations.size() > 1 || me->mAnim.akeyScaling.size() > 1)   {
+                // Begin a new node animation channel for this node
+                aiNodeAnim* nd = pcAnim->mChannels[iNum++] = new aiNodeAnim();
+                nd->mNodeName.Set(me->mName);
+
+                // copy position keys
+                if (me->mAnim.akeyPositions.size() > 1 )
+                {
+                    // Allocate the key array and fill it
+                    nd->mNumPositionKeys = (unsigned int) me->mAnim.akeyPositions.size();
+                    nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys];
+
+                    ::memcpy(nd->mPositionKeys,&me->mAnim.akeyPositions[0],
+                        nd->mNumPositionKeys * sizeof(aiVectorKey));
+                }
+                // copy rotation keys
+                if (me->mAnim.akeyRotations.size() > 1 )    {
+                    // Allocate the key array and fill it
+                    nd->mNumRotationKeys = (unsigned int) me->mAnim.akeyRotations.size();
+                    nd->mRotationKeys = new aiQuatKey[nd->mNumRotationKeys];
+
+                    // --------------------------------------------------------------------
+                    // Rotation keys are offsets to the previous keys.
+                    // We have the quaternion representations of all
+                    // of them, so we just need to concatenate all
+                    // (unit-length) quaternions to get the absolute
+                    // rotations.
+                    // Rotation keys are ABSOLUTE for older files
+                    // --------------------------------------------------------------------
+
+                    aiQuaternion cur;
+                    for (unsigned int a = 0; a < nd->mNumRotationKeys;++a)  {
+                        aiQuatKey q = me->mAnim.akeyRotations[a];
+
+                        if (mParser->iFileFormat > 110) {
+                            cur = (a ? cur*q.mValue : q.mValue);
+                            q.mValue = cur.Normalize();
+                        }
+                        nd->mRotationKeys[a] = q;
+
+                        // need this to get to Assimp quaternion conventions
+                        nd->mRotationKeys[a].mValue.w *= -1.f;
+                    }
+                }
+                // copy scaling keys
+                if (me->mAnim.akeyScaling.size() > 1 )  {
+                    // Allocate the key array and fill it
+                    nd->mNumScalingKeys = (unsigned int) me->mAnim.akeyScaling.size();
+                    nd->mScalingKeys = new aiVectorKey[nd->mNumScalingKeys];
+
+                    ::memcpy(nd->mScalingKeys,&me->mAnim.akeyScaling[0],
+                        nd->mNumScalingKeys * sizeof(aiVectorKey));
+                }
+            }
+        }
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 // Build output cameras
 void ASEImporter::BuildCameras()
 {
-	if (!mParser->m_vCameras.empty())	{
-		pcScene->mNumCameras = (unsigned int)mParser->m_vCameras.size();
-		pcScene->mCameras = new aiCamera*[pcScene->mNumCameras];
-
-		for (unsigned int i = 0; i < pcScene->mNumCameras;++i)	{
-			aiCamera* out = pcScene->mCameras[i] = new aiCamera();
-			ASE::Camera& in = mParser->m_vCameras[i];
-
-			// copy members
-			out->mClipPlaneFar  = in.mFar;
-			out->mClipPlaneNear = (in.mNear ? in.mNear : 0.1f); 
-			out->mHorizontalFOV = in.mFOV;
-
-			out->mName.Set(in.mName);
-		}
-	}
+    if (!mParser->m_vCameras.empty())   {
+        pcScene->mNumCameras = (unsigned int)mParser->m_vCameras.size();
+        pcScene->mCameras = new aiCamera*[pcScene->mNumCameras];
+
+        for (unsigned int i = 0; i < pcScene->mNumCameras;++i)  {
+            aiCamera* out = pcScene->mCameras[i] = new aiCamera();
+            ASE::Camera& in = mParser->m_vCameras[i];
+
+            // copy members
+            out->mClipPlaneFar  = in.mFar;
+            out->mClipPlaneNear = (in.mNear ? in.mNear : 0.1f);
+            out->mHorizontalFOV = in.mFOV;
+
+            out->mName.Set(in.mName);
+        }
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 // Build output lights
 void ASEImporter::BuildLights()
 {
-	if (!mParser->m_vLights.empty())	{
-		pcScene->mNumLights = (unsigned int)mParser->m_vLights.size();
-		pcScene->mLights    = new aiLight*[pcScene->mNumLights];
-
-		for (unsigned int i = 0; i < pcScene->mNumLights;++i)	{
-			aiLight* out = pcScene->mLights[i] = new aiLight();
-			ASE::Light& in = mParser->m_vLights[i];
-
-			// The direction is encoded in the transformation matrix of the node. 
-			// In 3DS MAX the light source points into negative Z direction if 
-			// the node transformation is the identity. 
-			out->mDirection = aiVector3D(0.f,0.f,-1.f);
-
-			out->mName.Set(in.mName);
-			switch (in.mLightType)
-			{
-			case ASE::Light::TARGET:
-				out->mType = aiLightSource_SPOT;
-				out->mAngleInnerCone = AI_DEG_TO_RAD(in.mAngle);
-				out->mAngleOuterCone = (in.mFalloff ? AI_DEG_TO_RAD(in.mFalloff) : out->mAngleInnerCone);
-				break;
-
-			case ASE::Light::DIRECTIONAL:
-				out->mType = aiLightSource_DIRECTIONAL;
-				break;
-
-			default:
-			//case ASE::Light::OMNI:
-				out->mType = aiLightSource_POINT;
-				break;
-			};
-			out->mColorDiffuse = out->mColorSpecular = in.mColor * in.mIntensity;
-		}
-	}
+    if (!mParser->m_vLights.empty())    {
+        pcScene->mNumLights = (unsigned int)mParser->m_vLights.size();
+        pcScene->mLights    = new aiLight*[pcScene->mNumLights];
+
+        for (unsigned int i = 0; i < pcScene->mNumLights;++i)   {
+            aiLight* out = pcScene->mLights[i] = new aiLight();
+            ASE::Light& in = mParser->m_vLights[i];
+
+            // The direction is encoded in the transformation matrix of the node.
+            // In 3DS MAX the light source points into negative Z direction if
+            // the node transformation is the identity.
+            out->mDirection = aiVector3D(0.f,0.f,-1.f);
+
+            out->mName.Set(in.mName);
+            switch (in.mLightType)
+            {
+            case ASE::Light::TARGET:
+                out->mType = aiLightSource_SPOT;
+                out->mAngleInnerCone = AI_DEG_TO_RAD(in.mAngle);
+                out->mAngleOuterCone = (in.mFalloff ? AI_DEG_TO_RAD(in.mFalloff) : out->mAngleInnerCone);
+                break;
+
+            case ASE::Light::DIRECTIONAL:
+                out->mType = aiLightSource_DIRECTIONAL;
+                break;
+
+            default:
+            //case ASE::Light::OMNI:
+                out->mType = aiLightSource_POINT;
+                break;
+            };
+            out->mColorDiffuse = out->mColorSpecular = in.mColor * in.mIntensity;
+        }
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 void ASEImporter::AddNodes(const std::vector<BaseNode*>& nodes,
-	aiNode* pcParent,const char* szName)
+    aiNode* pcParent,const char* szName)
 {
-	aiMatrix4x4 m;
-	AddNodes(nodes,pcParent,szName,m);
+    aiMatrix4x4 m;
+    AddNodes(nodes,pcParent,szName,m);
 }
 
 // ------------------------------------------------------------------------------------------------
 // Add meshes to a given node
 void ASEImporter::AddMeshes(const ASE::BaseNode* snode,aiNode* node)
 {
-	for (unsigned int i = 0; i < pcScene->mNumMeshes;++i)	{
-		// Get the name of the mesh (the mesh instance has been temporarily stored in the third vertex color)
-		const aiMesh* pcMesh  = pcScene->mMeshes[i];
-		const ASE::Mesh* mesh = (const ASE::Mesh*)pcMesh->mColors[2];
-
-		if (mesh == snode) {
-			++node->mNumMeshes;
-		}
-	}
-
-	if(node->mNumMeshes)	{
-		node->mMeshes = new unsigned int[node->mNumMeshes];
-		for (unsigned int i = 0, p = 0; i < pcScene->mNumMeshes;++i)	{
-
-			const aiMesh* pcMesh  = pcScene->mMeshes[i];
-			const ASE::Mesh* mesh = (const ASE::Mesh*)pcMesh->mColors[2];
-			if (mesh == snode)	{
-				node->mMeshes[p++] = i;
-
-				// Transform all vertices of the mesh back into their local space -> 
-				// at the moment they are pretransformed
-				aiMatrix4x4 m  = mesh->mTransform;
-				m.Inverse();
-
-				aiVector3D* pvCurPtr = pcMesh->mVertices;
-				const aiVector3D* pvEndPtr = pvCurPtr + pcMesh->mNumVertices;
-				while (pvCurPtr != pvEndPtr)	{
-					*pvCurPtr = m * (*pvCurPtr);
-					pvCurPtr++;
-				}
-
-				// Do the same for the normal vectors, if we have them.
-				// As always, inverse transpose.
-				if (pcMesh->mNormals)	{
-					aiMatrix3x3 m3 = aiMatrix3x3( mesh->mTransform );
-					m3.Transpose();
-
-					pvCurPtr = pcMesh->mNormals;
-					pvEndPtr = pvCurPtr + pcMesh->mNumVertices;
-					while (pvCurPtr != pvEndPtr)	{
-						*pvCurPtr = m3 * (*pvCurPtr);
-						pvCurPtr++;
-					}
-				}
-			}
-		}
-	}
+    for (unsigned int i = 0; i < pcScene->mNumMeshes;++i)   {
+        // Get the name of the mesh (the mesh instance has been temporarily stored in the third vertex color)
+        const aiMesh* pcMesh  = pcScene->mMeshes[i];
+        const ASE::Mesh* mesh = (const ASE::Mesh*)pcMesh->mColors[2];
+
+        if (mesh == snode) {
+            ++node->mNumMeshes;
+        }
+    }
+
+    if(node->mNumMeshes)    {
+        node->mMeshes = new unsigned int[node->mNumMeshes];
+        for (unsigned int i = 0, p = 0; i < pcScene->mNumMeshes;++i)    {
+
+            const aiMesh* pcMesh  = pcScene->mMeshes[i];
+            const ASE::Mesh* mesh = (const ASE::Mesh*)pcMesh->mColors[2];
+            if (mesh == snode)  {
+                node->mMeshes[p++] = i;
+
+                // Transform all vertices of the mesh back into their local space ->
+                // at the moment they are pretransformed
+                aiMatrix4x4 m  = mesh->mTransform;
+                m.Inverse();
+
+                aiVector3D* pvCurPtr = pcMesh->mVertices;
+                const aiVector3D* pvEndPtr = pvCurPtr + pcMesh->mNumVertices;
+                while (pvCurPtr != pvEndPtr)    {
+                    *pvCurPtr = m * (*pvCurPtr);
+                    pvCurPtr++;
+                }
+
+                // Do the same for the normal vectors, if we have them.
+                // As always, inverse transpose.
+                if (pcMesh->mNormals)   {
+                    aiMatrix3x3 m3 = aiMatrix3x3( mesh->mTransform );
+                    m3.Transpose();
+
+                    pvCurPtr = pcMesh->mNormals;
+                    pvEndPtr = pvCurPtr + pcMesh->mNumVertices;
+                    while (pvCurPtr != pvEndPtr)    {
+                        *pvCurPtr = m3 * (*pvCurPtr);
+                        pvCurPtr++;
+                    }
+                }
+            }
+        }
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 // Add child nodes to a given parent node
 void ASEImporter::AddNodes (const std::vector<BaseNode*>& nodes,
-	aiNode* pcParent, const char* szName,
-	const aiMatrix4x4& mat)
+    aiNode* pcParent, const char* szName,
+    const aiMatrix4x4& mat)
 {
-	const size_t len = szName ? ::strlen(szName) : 0;
-	ai_assert(4 <= AI_MAX_NUMBER_OF_COLOR_SETS);
-
-	// Receives child nodes for the pcParent node
-	std::vector<aiNode*> apcNodes;
-
-	// Now iterate through all nodes in the scene and search for one
-	// which has *us* as parent.
-	for (std::vector<BaseNode*>::const_iterator it = nodes.begin(), end = nodes.end(); it != end; ++it) {
-		const BaseNode* snode = *it;
-		if (szName)	{
-			if (len != snode->mParent.length() || ::strcmp(szName,snode->mParent.c_str()))
-				continue;
-		}
-		else if (snode->mParent.length())
-			continue;
-
-		(*it)->mProcessed = true;
-
-		// Allocate a new node and add it to the output data structure
-		apcNodes.push_back(new aiNode());
-		aiNode* node = apcNodes.back();
-
-		node->mName.Set((snode->mName.length() ? snode->mName.c_str() : "Unnamed_Node"));
-		node->mParent = pcParent;
-
-		// Setup the transformation matrix of the node
-		aiMatrix4x4 mParentAdjust  = mat;
-		mParentAdjust.Inverse();
-		node->mTransformation = mParentAdjust*snode->mTransform;
-
-		// Add sub nodes - prevent stack overflow due to recursive parenting
-		if (node->mName != node->mParent->mName) {
-			AddNodes(nodes,node,node->mName.data,snode->mTransform);
-		}
-
-		// Further processing depends on the type of the node
-		if (snode->mType == ASE::BaseNode::Mesh)	{
-			// If the type of this node is "Mesh" we need to search
-			// the list of output meshes in the data structure for
-			// all those that belonged to this node once. This is
-			// slightly inconvinient here and a better solution should
-			// be used when this code is refactored next.
-			AddMeshes(snode,node);
-		}
-		else if (is_not_qnan( snode->mTargetPosition.x ))	{
-			// If this is a target camera or light we generate a small
-			// child node which marks the position of the camera
-			// target (the direction information is contained in *this*
-			// node's animation track but the exact target position
-			// would be lost otherwise)
-			if (!node->mNumChildren)	{
-				node->mChildren = new aiNode*[1];
-			}
-
-			aiNode* nd = new aiNode();
-
-			nd->mName.Set ( snode->mName + ".Target" );
-
-			nd->mTransformation.a4 = snode->mTargetPosition.x - snode->mTransform.a4;
-			nd->mTransformation.b4 = snode->mTargetPosition.y - snode->mTransform.b4;
-			nd->mTransformation.c4 = snode->mTargetPosition.z - snode->mTransform.c4;
-
-			nd->mParent = node;
-
-			// The .Target node is always the first child node 
-			for (unsigned int m = 0; m < node->mNumChildren;++m)
-				node->mChildren[m+1] = node->mChildren[m]; 
-		
-			node->mChildren[0] = nd;
-			node->mNumChildren++;
-
-			// What we did is so great, it is at least worth a debug message
-			DefaultLogger::get()->debug("ASE: Generating separate target node ("+snode->mName+")");
-		}
-	}
-
-	// Allocate enough space for the child nodes
-	// We allocate one slot more  in case this is a target camera/light
-	pcParent->mNumChildren = (unsigned int)apcNodes.size();
-	if (pcParent->mNumChildren)	{
-		pcParent->mChildren = new aiNode*[apcNodes.size()+1 /* PLUS ONE !!! */];
-
-		// now build all nodes for our nice new children
-		for (unsigned int p = 0; p < apcNodes.size();++p)
-			pcParent->mChildren[p] = apcNodes[p];
-	}
-	return;
+    const size_t len = szName ? ::strlen(szName) : 0;
+    ai_assert(4 <= AI_MAX_NUMBER_OF_COLOR_SETS);
+
+    // Receives child nodes for the pcParent node
+    std::vector<aiNode*> apcNodes;
+
+    // Now iterate through all nodes in the scene and search for one
+    // which has *us* as parent.
+    for (std::vector<BaseNode*>::const_iterator it = nodes.begin(), end = nodes.end(); it != end; ++it) {
+        const BaseNode* snode = *it;
+        if (szName) {
+            if (len != snode->mParent.length() || ::strcmp(szName,snode->mParent.c_str()))
+                continue;
+        }
+        else if (snode->mParent.length())
+            continue;
+
+        (*it)->mProcessed = true;
+
+        // Allocate a new node and add it to the output data structure
+        apcNodes.push_back(new aiNode());
+        aiNode* node = apcNodes.back();
+
+        node->mName.Set((snode->mName.length() ? snode->mName.c_str() : "Unnamed_Node"));
+        node->mParent = pcParent;
+
+        // Setup the transformation matrix of the node
+        aiMatrix4x4 mParentAdjust  = mat;
+        mParentAdjust.Inverse();
+        node->mTransformation = mParentAdjust*snode->mTransform;
+
+        // Add sub nodes - prevent stack overflow due to recursive parenting
+        if (node->mName != node->mParent->mName) {
+            AddNodes(nodes,node,node->mName.data,snode->mTransform);
+        }
+
+        // Further processing depends on the type of the node
+        if (snode->mType == ASE::BaseNode::Mesh)    {
+            // If the type of this node is "Mesh" we need to search
+            // the list of output meshes in the data structure for
+            // all those that belonged to this node once. This is
+            // slightly inconvinient here and a better solution should
+            // be used when this code is refactored next.
+            AddMeshes(snode,node);
+        }
+        else if (is_not_qnan( snode->mTargetPosition.x ))   {
+            // If this is a target camera or light we generate a small
+            // child node which marks the position of the camera
+            // target (the direction information is contained in *this*
+            // node's animation track but the exact target position
+            // would be lost otherwise)
+            if (!node->mNumChildren)    {
+                node->mChildren = new aiNode*[1];
+            }
+
+            aiNode* nd = new aiNode();
+
+            nd->mName.Set ( snode->mName + ".Target" );
+
+            nd->mTransformation.a4 = snode->mTargetPosition.x - snode->mTransform.a4;
+            nd->mTransformation.b4 = snode->mTargetPosition.y - snode->mTransform.b4;
+            nd->mTransformation.c4 = snode->mTargetPosition.z - snode->mTransform.c4;
+
+            nd->mParent = node;
+
+            // The .Target node is always the first child node
+            for (unsigned int m = 0; m < node->mNumChildren;++m)
+                node->mChildren[m+1] = node->mChildren[m];
+
+            node->mChildren[0] = nd;
+            node->mNumChildren++;
+
+            // What we did is so great, it is at least worth a debug message
+            DefaultLogger::get()->debug("ASE: Generating separate target node ("+snode->mName+")");
+        }
+    }
+
+    // Allocate enough space for the child nodes
+    // We allocate one slot more  in case this is a target camera/light
+    pcParent->mNumChildren = (unsigned int)apcNodes.size();
+    if (pcParent->mNumChildren) {
+        pcParent->mChildren = new aiNode*[apcNodes.size()+1 /* PLUS ONE !!! */];
+
+        // now build all nodes for our nice new children
+        for (unsigned int p = 0; p < apcNodes.size();++p)
+            pcParent->mChildren[p] = apcNodes[p];
+    }
+    return;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Build the output node graph
-void ASEImporter::BuildNodes(std::vector<BaseNode*>& nodes)	{
-	ai_assert(NULL != pcScene);
-
-	// allocate the one and only root node
-	aiNode* root = pcScene->mRootNode = new aiNode();
-	root->mName.Set("<ASERoot>");
-
-	// Setup the coordinate system transformation
-	pcScene->mRootNode->mNumChildren = 1;
-	pcScene->mRootNode->mChildren = new aiNode*[1];
-	aiNode* ch = pcScene->mRootNode->mChildren[0] = new aiNode();
-	ch->mParent = root;
-
-	// Change the transformation matrix of all nodes
-	for (std::vector<BaseNode*>::iterator it = nodes.begin(), end = nodes.end();it != end; ++it)	{
-		aiMatrix4x4& m = (*it)->mTransform;
-		m.Transpose(); // row-order vs column-order
-	}
-
-	// add all nodes
-	AddNodes(nodes,ch,NULL);
-
-	// now iterate through al nodes and find those that have not yet
-	// been added to the nodegraph (= their parent could not be recognized)
-	std::vector<const BaseNode*> aiList;
-	for (std::vector<BaseNode*>::iterator it = nodes.begin(), end = nodes.end();it != end; ++it)	{
-		if ((*it)->mProcessed) {
-			continue;
-		}
-
-		// check whether our parent is known
-		bool bKnowParent = false;
-		
-		// search the list another time, starting *here* and try to find out whether
-		// there is a node that references *us* as a parent
-		for (std::vector<BaseNode*>::const_iterator it2 = nodes.begin();it2 != end; ++it2) {
-			if (it2 == it) {
-				continue;
-			}
-
-			if ((*it2)->mName == (*it)->mParent)	{
-				bKnowParent = true;
-				break;
-			}
-		}
-		if (!bKnowParent)	{
-			aiList.push_back(*it);
-		}
-	}
-
-	// Are there ane orphaned nodes?
-	if (!aiList.empty())	{
-		std::vector<aiNode*> apcNodes;
-		apcNodes.reserve(aiList.size() + pcScene->mRootNode->mNumChildren);
-
-		for (unsigned int i = 0; i < pcScene->mRootNode->mNumChildren;++i)
-			apcNodes.push_back(pcScene->mRootNode->mChildren[i]);
-
-		delete[] pcScene->mRootNode->mChildren;
-		for (std::vector<const BaseNode*>::/*const_*/iterator i =  aiList.begin();i != aiList.end();++i)	{
-			const ASE::BaseNode* src = *i;
-
-			// The parent is not known, so we can assume that we must add 
-			// this node to the root node of the whole scene
-			aiNode* pcNode = new aiNode();
-			pcNode->mParent = pcScene->mRootNode;
-			pcNode->mName.Set(src->mName);
-			AddMeshes(src,pcNode);
-			AddNodes(nodes,pcNode,pcNode->mName.data);
-			apcNodes.push_back(pcNode);
-		}
-
-		// Regenerate our output array
-		pcScene->mRootNode->mChildren = new aiNode*[apcNodes.size()];
-		for (unsigned int i = 0; i < apcNodes.size();++i)
-			pcScene->mRootNode->mChildren[i] = apcNodes[i];
-
-		pcScene->mRootNode->mNumChildren = (unsigned int)apcNodes.size();
-	}
-
-	// Reset the third color set to NULL - we used this field to store a temporary pointer
-	for (unsigned int i = 0; i < pcScene->mNumMeshes;++i)
-		pcScene->mMeshes[i]->mColors[2] = NULL;
-
-	// The root node should not have at least one child or the file is valid
-	if (!pcScene->mRootNode->mNumChildren) {
-		throw DeadlyImportError("ASE: No nodes loaded. The file is either empty or corrupt");
-	}
-	
-	// Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system
-	pcScene->mRootNode->mTransformation = aiMatrix4x4(1.f,0.f,0.f,0.f,
-		0.f,0.f,1.f,0.f,0.f,-1.f,0.f,0.f,0.f,0.f,0.f,1.f);
+void ASEImporter::BuildNodes(std::vector<BaseNode*>& nodes) {
+    ai_assert(NULL != pcScene);
+
+    // allocate the one and only root node
+    aiNode* root = pcScene->mRootNode = new aiNode();
+    root->mName.Set("<ASERoot>");
+
+    // Setup the coordinate system transformation
+    pcScene->mRootNode->mNumChildren = 1;
+    pcScene->mRootNode->mChildren = new aiNode*[1];
+    aiNode* ch = pcScene->mRootNode->mChildren[0] = new aiNode();
+    ch->mParent = root;
+
+    // Change the transformation matrix of all nodes
+    for (std::vector<BaseNode*>::iterator it = nodes.begin(), end = nodes.end();it != end; ++it)    {
+        aiMatrix4x4& m = (*it)->mTransform;
+        m.Transpose(); // row-order vs column-order
+    }
+
+    // add all nodes
+    AddNodes(nodes,ch,NULL);
+
+    // now iterate through al nodes and find those that have not yet
+    // been added to the nodegraph (= their parent could not be recognized)
+    std::vector<const BaseNode*> aiList;
+    for (std::vector<BaseNode*>::iterator it = nodes.begin(), end = nodes.end();it != end; ++it)    {
+        if ((*it)->mProcessed) {
+            continue;
+        }
+
+        // check whether our parent is known
+        bool bKnowParent = false;
+
+        // search the list another time, starting *here* and try to find out whether
+        // there is a node that references *us* as a parent
+        for (std::vector<BaseNode*>::const_iterator it2 = nodes.begin();it2 != end; ++it2) {
+            if (it2 == it) {
+                continue;
+            }
+
+            if ((*it2)->mName == (*it)->mParent)    {
+                bKnowParent = true;
+                break;
+            }
+        }
+        if (!bKnowParent)   {
+            aiList.push_back(*it);
+        }
+    }
+
+    // Are there ane orphaned nodes?
+    if (!aiList.empty())    {
+        std::vector<aiNode*> apcNodes;
+        apcNodes.reserve(aiList.size() + pcScene->mRootNode->mNumChildren);
+
+        for (unsigned int i = 0; i < pcScene->mRootNode->mNumChildren;++i)
+            apcNodes.push_back(pcScene->mRootNode->mChildren[i]);
+
+        delete[] pcScene->mRootNode->mChildren;
+        for (std::vector<const BaseNode*>::/*const_*/iterator i =  aiList.begin();i != aiList.end();++i)    {
+            const ASE::BaseNode* src = *i;
+
+            // The parent is not known, so we can assume that we must add
+            // this node to the root node of the whole scene
+            aiNode* pcNode = new aiNode();
+            pcNode->mParent = pcScene->mRootNode;
+            pcNode->mName.Set(src->mName);
+            AddMeshes(src,pcNode);
+            AddNodes(nodes,pcNode,pcNode->mName.data);
+            apcNodes.push_back(pcNode);
+        }
+
+        // Regenerate our output array
+        pcScene->mRootNode->mChildren = new aiNode*[apcNodes.size()];
+        for (unsigned int i = 0; i < apcNodes.size();++i)
+            pcScene->mRootNode->mChildren[i] = apcNodes[i];
+
+        pcScene->mRootNode->mNumChildren = (unsigned int)apcNodes.size();
+    }
+
+    // Reset the third color set to NULL - we used this field to store a temporary pointer
+    for (unsigned int i = 0; i < pcScene->mNumMeshes;++i)
+        pcScene->mMeshes[i]->mColors[2] = NULL;
+
+    // The root node should not have at least one child or the file is valid
+    if (!pcScene->mRootNode->mNumChildren) {
+        throw DeadlyImportError("ASE: No nodes loaded. The file is either empty or corrupt");
+    }
+
+    // Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system
+    pcScene->mRootNode->mTransformation = aiMatrix4x4(1.f,0.f,0.f,0.f,
+        0.f,0.f,1.f,0.f,0.f,-1.f,0.f,0.f,0.f,0.f,0.f,1.f);
 }
 
 // ------------------------------------------------------------------------------------------------
 // Convert the imported data to the internal verbose representation
-void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh)	{
-	// allocate output storage
-	std::vector<aiVector3D> mPositions;
-	std::vector<aiVector3D> amTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
-	std::vector<aiColor4D>  mVertexColors;
-	std::vector<aiVector3D> mNormals;
-	std::vector<BoneVertex> mBoneVertices;
-
-	unsigned int iSize = (unsigned int)mesh.mFaces.size() * 3;
-	mPositions.resize(iSize);
-
-	// optional texture coordinates
-	for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)	{
-		if (!mesh.amTexCoords[i].empty())	{
-			amTexCoords[i].resize(iSize);
-		}
-	}
-	// optional vertex colors
-	if (!mesh.mVertexColors.empty())	{
-		mVertexColors.resize(iSize);
-	}
-
-	// optional vertex normals (vertex normals can simply be copied)
-	if (!mesh.mNormals.empty())	{
-		mNormals.resize(iSize);
-	}
-	// bone vertices. There is no need to change the bone list
-	if (!mesh.mBoneVertices.empty())	{
-		mBoneVertices.resize(iSize);
-	}
-
-	// iterate through all faces in the mesh
-	unsigned int iCurrent = 0, fi = 0;
-	for (std::vector<ASE::Face>::iterator i =  mesh.mFaces.begin();i != mesh.mFaces.end();++i,++fi)	{
-		for (unsigned int n = 0; n < 3;++n,++iCurrent)
-		{
-			mPositions[iCurrent] = mesh.mPositions[(*i).mIndices[n]];
-
-			// add texture coordinates
-			for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)	{
-				if (mesh.amTexCoords[c].empty())break;
-				amTexCoords[c][iCurrent] = mesh.amTexCoords[c][(*i).amUVIndices[c][n]];
-			}
-			// add vertex colors
-			if (!mesh.mVertexColors.empty())	{
-				mVertexColors[iCurrent] = mesh.mVertexColors[(*i).mColorIndices[n]];
-			}
-			// add normal vectors
-			if (!mesh.mNormals.empty())	{
-				mNormals[iCurrent] = mesh.mNormals[fi*3+n];
-				mNormals[iCurrent].Normalize();
-			}
-
-			// handle bone vertices
-			if ((*i).mIndices[n] < mesh.mBoneVertices.size())	{
-				// (sometimes this will cause bone verts to be duplicated
-				//  however, I' quite sure Schrompf' JoinVerticesStep
-				//  will fix that again ...)
-				mBoneVertices[iCurrent] =  mesh.mBoneVertices[(*i).mIndices[n]];
-			}
-			(*i).mIndices[n] = iCurrent;
-		}
-	}
-
-	// replace the old arrays
-	mesh.mNormals = mNormals;
-	mesh.mPositions = mPositions;
-	mesh.mVertexColors = mVertexColors;
-
-	for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
-		mesh.amTexCoords[c] = amTexCoords[c];
+void ASEImporter::BuildUniqueRepresentation(ASE::Mesh& mesh)    {
+    // allocate output storage
+    std::vector<aiVector3D> mPositions;
+    std::vector<aiVector3D> amTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+    std::vector<aiColor4D>  mVertexColors;
+    std::vector<aiVector3D> mNormals;
+    std::vector<BoneVertex> mBoneVertices;
+
+    unsigned int iSize = (unsigned int)mesh.mFaces.size() * 3;
+    mPositions.resize(iSize);
+
+    // optional texture coordinates
+    for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)    {
+        if (!mesh.amTexCoords[i].empty())   {
+            amTexCoords[i].resize(iSize);
+        }
+    }
+    // optional vertex colors
+    if (!mesh.mVertexColors.empty())    {
+        mVertexColors.resize(iSize);
+    }
+
+    // optional vertex normals (vertex normals can simply be copied)
+    if (!mesh.mNormals.empty()) {
+        mNormals.resize(iSize);
+    }
+    // bone vertices. There is no need to change the bone list
+    if (!mesh.mBoneVertices.empty())    {
+        mBoneVertices.resize(iSize);
+    }
+
+    // iterate through all faces in the mesh
+    unsigned int iCurrent = 0, fi = 0;
+    for (std::vector<ASE::Face>::iterator i =  mesh.mFaces.begin();i != mesh.mFaces.end();++i,++fi) {
+        for (unsigned int n = 0; n < 3;++n,++iCurrent)
+        {
+            mPositions[iCurrent] = mesh.mPositions[(*i).mIndices[n]];
+
+            // add texture coordinates
+            for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)    {
+                if (mesh.amTexCoords[c].empty())break;
+                amTexCoords[c][iCurrent] = mesh.amTexCoords[c][(*i).amUVIndices[c][n]];
+            }
+            // add vertex colors
+            if (!mesh.mVertexColors.empty())    {
+                mVertexColors[iCurrent] = mesh.mVertexColors[(*i).mColorIndices[n]];
+            }
+            // add normal vectors
+            if (!mesh.mNormals.empty()) {
+                mNormals[iCurrent] = mesh.mNormals[fi*3+n];
+                mNormals[iCurrent].Normalize();
+            }
+
+            // handle bone vertices
+            if ((*i).mIndices[n] < mesh.mBoneVertices.size())   {
+                // (sometimes this will cause bone verts to be duplicated
+                //  however, I' quite sure Schrompf' JoinVerticesStep
+                //  will fix that again ...)
+                mBoneVertices[iCurrent] =  mesh.mBoneVertices[(*i).mIndices[n]];
+            }
+            (*i).mIndices[n] = iCurrent;
+        }
+    }
+
+    // replace the old arrays
+    mesh.mNormals = mNormals;
+    mesh.mPositions = mPositions;
+    mesh.mVertexColors = mVertexColors;
+
+    for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
+        mesh.amTexCoords[c] = amTexCoords[c];
 }
 
 // ------------------------------------------------------------------------------------------------
 // Copy a texture from the ASE structs to the output material
 void CopyASETexture(aiMaterial& mat, ASE::Texture& texture, aiTextureType type)
 {
-	// Setup the texture name
-	aiString tex;
-	tex.Set( texture.mMapName);
-	mat.AddProperty( &tex, AI_MATKEY_TEXTURE(type,0));
+    // Setup the texture name
+    aiString tex;
+    tex.Set( texture.mMapName);
+    mat.AddProperty( &tex, AI_MATKEY_TEXTURE(type,0));
 
-	// Setup the texture blend factor
-	if (is_not_qnan(texture.mTextureBlend))
-		mat.AddProperty<float>( &texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type,0));
+    // Setup the texture blend factor
+    if (is_not_qnan(texture.mTextureBlend))
+        mat.AddProperty<float>( &texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type,0));
 
-	// Setup texture UV transformations
-	mat.AddProperty<float>(&texture.mOffsetU,5,AI_MATKEY_UVTRANSFORM(type,0));
+    // Setup texture UV transformations
+    mat.AddProperty<float>(&texture.mOffsetU,5,AI_MATKEY_UVTRANSFORM(type,0));
 }
 
 // ------------------------------------------------------------------------------------------------
 // Convert from ASE material to output material
 void ASEImporter::ConvertMaterial(ASE::Material& mat)
 {
-	// LARGE TODO: Much code her is copied from 3DS ... join them maybe?
-
-	// Allocate the output material
-	mat.pcInstance = new aiMaterial();
-
-	// At first add the base ambient color of the
-	// scene to	the material
-	mat.mAmbient.r += mParser->m_clrAmbient.r;
-	mat.mAmbient.g += mParser->m_clrAmbient.g;
-	mat.mAmbient.b += mParser->m_clrAmbient.b;
-
-	aiString name;
-	name.Set( mat.mName);
-	mat.pcInstance->AddProperty( &name, AI_MATKEY_NAME);
-
-	// material colors
-	mat.pcInstance->AddProperty( &mat.mAmbient, 1, AI_MATKEY_COLOR_AMBIENT);
-	mat.pcInstance->AddProperty( &mat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
-	mat.pcInstance->AddProperty( &mat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR);
-	mat.pcInstance->AddProperty( &mat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE);
-
-	// shininess
-	if (0.0f != mat.mSpecularExponent && 0.0f != mat.mShininessStrength)
-	{
-		mat.pcInstance->AddProperty( &mat.mSpecularExponent, 1, AI_MATKEY_SHININESS);
-		mat.pcInstance->AddProperty( &mat.mShininessStrength, 1, AI_MATKEY_SHININESS_STRENGTH);
-	}
-	// If there is no shininess, we can disable phong lighting
-	else if (D3DS::Discreet3DS::Metal == mat.mShading ||
-		D3DS::Discreet3DS::Phong == mat.mShading ||
-		D3DS::Discreet3DS::Blinn == mat.mShading)
-	{
-		mat.mShading = D3DS::Discreet3DS::Gouraud;
-	}
-
-	// opacity
-	mat.pcInstance->AddProperty<float>( &mat.mTransparency,1,AI_MATKEY_OPACITY);
-
-	// Two sided rendering?
-	if (mat.mTwoSided)
-	{
-		int i = 1;
-		mat.pcInstance->AddProperty<int>(&i,1,AI_MATKEY_TWOSIDED);
-	}
-
-	// shading mode
-	aiShadingMode eShading = aiShadingMode_NoShading;
-	switch (mat.mShading)
-	{
-		case D3DS::Discreet3DS::Flat:
-			eShading = aiShadingMode_Flat; break;
-		case D3DS::Discreet3DS::Phong :
-			eShading = aiShadingMode_Phong; break;
-		case D3DS::Discreet3DS::Blinn :
-			eShading = aiShadingMode_Blinn; break;
-
-			// I don't know what "Wire" shading should be,
-			// assume it is simple lambertian diffuse (L dot N) shading
-		case D3DS::Discreet3DS::Wire:
-			{
-				// set the wireframe flag
-				unsigned int iWire = 1;
-				mat.pcInstance->AddProperty<int>( (int*)&iWire,1,AI_MATKEY_ENABLE_WIREFRAME);
-			}
-		case D3DS::Discreet3DS::Gouraud:
-			eShading = aiShadingMode_Gouraud; break;
-		case D3DS::Discreet3DS::Metal :
-			eShading = aiShadingMode_CookTorrance; break;
-	}
-	mat.pcInstance->AddProperty<int>( (int*)&eShading,1,AI_MATKEY_SHADING_MODEL);
-
-	// DIFFUSE texture
-	if( mat.sTexDiffuse.mMapName.length() > 0)
-		CopyASETexture(*mat.pcInstance,mat.sTexDiffuse, aiTextureType_DIFFUSE);
-
-	// SPECULAR texture
-	if( mat.sTexSpecular.mMapName.length() > 0)
-		CopyASETexture(*mat.pcInstance,mat.sTexSpecular, aiTextureType_SPECULAR);
-
-	// AMBIENT texture
-	if( mat.sTexAmbient.mMapName.length() > 0)
-		CopyASETexture(*mat.pcInstance,mat.sTexAmbient, aiTextureType_AMBIENT);
-
-	// OPACITY texture
-	if( mat.sTexOpacity.mMapName.length() > 0)
-		CopyASETexture(*mat.pcInstance,mat.sTexOpacity, aiTextureType_OPACITY);
-
-	// EMISSIVE texture
-	if( mat.sTexEmissive.mMapName.length() > 0)
-		CopyASETexture(*mat.pcInstance,mat.sTexEmissive, aiTextureType_EMISSIVE);
-
-	// BUMP texture
-	if( mat.sTexBump.mMapName.length() > 0)
-		CopyASETexture(*mat.pcInstance,mat.sTexBump, aiTextureType_HEIGHT);
-
-	// SHININESS texture
-	if( mat.sTexShininess.mMapName.length() > 0)
-		CopyASETexture(*mat.pcInstance,mat.sTexShininess, aiTextureType_SHININESS);
-
-	// store the name of the material itself, too
-	if( mat.mName.length() > 0)	{
-		aiString tex;tex.Set( mat.mName);
-		mat.pcInstance->AddProperty( &tex, AI_MATKEY_NAME);
-	}
-	return;
+    // LARGE TODO: Much code her is copied from 3DS ... join them maybe?
+
+    // Allocate the output material
+    mat.pcInstance = new aiMaterial();
+
+    // At first add the base ambient color of the
+    // scene to the material
+    mat.mAmbient.r += mParser->m_clrAmbient.r;
+    mat.mAmbient.g += mParser->m_clrAmbient.g;
+    mat.mAmbient.b += mParser->m_clrAmbient.b;
+
+    aiString name;
+    name.Set( mat.mName);
+    mat.pcInstance->AddProperty( &name, AI_MATKEY_NAME);
+
+    // material colors
+    mat.pcInstance->AddProperty( &mat.mAmbient, 1, AI_MATKEY_COLOR_AMBIENT);
+    mat.pcInstance->AddProperty( &mat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
+    mat.pcInstance->AddProperty( &mat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR);
+    mat.pcInstance->AddProperty( &mat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE);
+
+    // shininess
+    if (0.0f != mat.mSpecularExponent && 0.0f != mat.mShininessStrength)
+    {
+        mat.pcInstance->AddProperty( &mat.mSpecularExponent, 1, AI_MATKEY_SHININESS);
+        mat.pcInstance->AddProperty( &mat.mShininessStrength, 1, AI_MATKEY_SHININESS_STRENGTH);
+    }
+    // If there is no shininess, we can disable phong lighting
+    else if (D3DS::Discreet3DS::Metal == mat.mShading ||
+        D3DS::Discreet3DS::Phong == mat.mShading ||
+        D3DS::Discreet3DS::Blinn == mat.mShading)
+    {
+        mat.mShading = D3DS::Discreet3DS::Gouraud;
+    }
+
+    // opacity
+    mat.pcInstance->AddProperty<float>( &mat.mTransparency,1,AI_MATKEY_OPACITY);
+
+    // Two sided rendering?
+    if (mat.mTwoSided)
+    {
+        int i = 1;
+        mat.pcInstance->AddProperty<int>(&i,1,AI_MATKEY_TWOSIDED);
+    }
+
+    // shading mode
+    aiShadingMode eShading = aiShadingMode_NoShading;
+    switch (mat.mShading)
+    {
+        case D3DS::Discreet3DS::Flat:
+            eShading = aiShadingMode_Flat; break;
+        case D3DS::Discreet3DS::Phong :
+            eShading = aiShadingMode_Phong; break;
+        case D3DS::Discreet3DS::Blinn :
+            eShading = aiShadingMode_Blinn; break;
+
+            // I don't know what "Wire" shading should be,
+            // assume it is simple lambertian diffuse (L dot N) shading
+        case D3DS::Discreet3DS::Wire:
+            {
+                // set the wireframe flag
+                unsigned int iWire = 1;
+                mat.pcInstance->AddProperty<int>( (int*)&iWire,1,AI_MATKEY_ENABLE_WIREFRAME);
+            }
+        case D3DS::Discreet3DS::Gouraud:
+            eShading = aiShadingMode_Gouraud; break;
+        case D3DS::Discreet3DS::Metal :
+            eShading = aiShadingMode_CookTorrance; break;
+    }
+    mat.pcInstance->AddProperty<int>( (int*)&eShading,1,AI_MATKEY_SHADING_MODEL);
+
+    // DIFFUSE texture
+    if( mat.sTexDiffuse.mMapName.length() > 0)
+        CopyASETexture(*mat.pcInstance,mat.sTexDiffuse, aiTextureType_DIFFUSE);
+
+    // SPECULAR texture
+    if( mat.sTexSpecular.mMapName.length() > 0)
+        CopyASETexture(*mat.pcInstance,mat.sTexSpecular, aiTextureType_SPECULAR);
+
+    // AMBIENT texture
+    if( mat.sTexAmbient.mMapName.length() > 0)
+        CopyASETexture(*mat.pcInstance,mat.sTexAmbient, aiTextureType_AMBIENT);
+
+    // OPACITY texture
+    if( mat.sTexOpacity.mMapName.length() > 0)
+        CopyASETexture(*mat.pcInstance,mat.sTexOpacity, aiTextureType_OPACITY);
+
+    // EMISSIVE texture
+    if( mat.sTexEmissive.mMapName.length() > 0)
+        CopyASETexture(*mat.pcInstance,mat.sTexEmissive, aiTextureType_EMISSIVE);
+
+    // BUMP texture
+    if( mat.sTexBump.mMapName.length() > 0)
+        CopyASETexture(*mat.pcInstance,mat.sTexBump, aiTextureType_HEIGHT);
+
+    // SHININESS texture
+    if( mat.sTexShininess.mMapName.length() > 0)
+        CopyASETexture(*mat.pcInstance,mat.sTexShininess, aiTextureType_SHININESS);
+
+    // store the name of the material itself, too
+    if( mat.mName.length() > 0) {
+        aiString tex;tex.Set( mat.mName);
+        mat.pcInstance->AddProperty( &tex, AI_MATKEY_NAME);
+    }
+    return;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Build output meshes
 void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMeshes)
 {
-	// validate the material index of the mesh
-	if (mesh.iMaterialIndex >= mParser->m_vMaterials.size())	{
-		mesh.iMaterialIndex = (unsigned int)mParser->m_vMaterials.size()-1;
-		DefaultLogger::get()->warn("Material index is out of range");
-	}
-
-	// If the material the mesh is assigned to is consisting of submeshes, split it
-	if (!mParser->m_vMaterials[mesh.iMaterialIndex].avSubMaterials.empty())	{
-		std::vector<ASE::Material> vSubMaterials = mParser->
-			m_vMaterials[mesh.iMaterialIndex].avSubMaterials;
-
-		std::vector<unsigned int>* aiSplit = new std::vector<unsigned int>[vSubMaterials.size()];
-
-		// build a list of all faces per submaterial
-		for (unsigned int i = 0; i < mesh.mFaces.size();++i)	{
-			// check range
-			if (mesh.mFaces[i].iMaterial >= vSubMaterials.size()) {
-				DefaultLogger::get()->warn("Submaterial index is out of range");
-
-				// use the last material instead
-				aiSplit[vSubMaterials.size()-1].push_back(i);
-			}
-			else aiSplit[mesh.mFaces[i].iMaterial].push_back(i);
-		}
-
-		// now generate submeshes
-		for (unsigned int p = 0; p < vSubMaterials.size();++p)	{
-			if (!aiSplit[p].empty())	{
-
-				aiMesh* p_pcOut = new aiMesh();
-				p_pcOut->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
-
-				// let the sub material index
-				p_pcOut->mMaterialIndex = p;
-
-				// we will need this material
-				mParser->m_vMaterials[mesh.iMaterialIndex].avSubMaterials[p].bNeed = true;
-
-				// store the real index here ... color channel 3
-				p_pcOut->mColors[3] = (aiColor4D*)(uintptr_t)mesh.iMaterialIndex;
-
-				// store a pointer to the mesh in color channel 2
-				p_pcOut->mColors[2] = (aiColor4D*) &mesh;
-				avOutMeshes.push_back(p_pcOut);
-
-				// convert vertices
-				p_pcOut->mNumVertices = (unsigned int)aiSplit[p].size()*3;
-				p_pcOut->mNumFaces = (unsigned int)aiSplit[p].size();
-
-				// receive output vertex weights
-				std::vector<std::pair<unsigned int, float> > *avOutputBones = NULL;
-				if (!mesh.mBones.empty())	{
-					avOutputBones = new std::vector<std::pair<unsigned int, float> >[mesh.mBones.size()];
-				}
-				
-				// allocate enough storage for faces
-				p_pcOut->mFaces = new aiFace[p_pcOut->mNumFaces];
-
-				unsigned int iBase = 0,iIndex;
-				if (p_pcOut->mNumVertices)	{
-					p_pcOut->mVertices = new aiVector3D[p_pcOut->mNumVertices];
-					p_pcOut->mNormals  = new aiVector3D[p_pcOut->mNumVertices];
-					for (unsigned int q = 0; q < aiSplit[p].size();++q)	{
-
-						iIndex = aiSplit[p][q];
-
-						p_pcOut->mFaces[q].mIndices = new unsigned int[3];
-						p_pcOut->mFaces[q].mNumIndices = 3;
-
-						for (unsigned int t = 0; t < 3;++t, ++iBase)	{
-							const uint32_t iIndex2 = mesh.mFaces[iIndex].mIndices[t];
-
-							p_pcOut->mVertices[iBase] = mesh.mPositions [iIndex2];
-							p_pcOut->mNormals [iBase] = mesh.mNormals   [iIndex2];
-
-							// convert bones, if existing
-							if (!mesh.mBones.empty()) {
-								// check whether there is a vertex weight for this vertex index
-								if (iIndex2 < mesh.mBoneVertices.size())	{
-
-									for (std::vector<std::pair<int,float> >::const_iterator
-										blubb =  mesh.mBoneVertices[iIndex2].mBoneWeights.begin();
-										blubb != mesh.mBoneVertices[iIndex2].mBoneWeights.end();++blubb)	{
-
-										// NOTE: illegal cases have already been filtered out
-										avOutputBones[(*blubb).first].push_back(std::pair<unsigned int, float>(
-											iBase,(*blubb).second));
-									}
-								}
-							}
-							p_pcOut->mFaces[q].mIndices[t] = iBase;
-						}
-					}
-				}
-				// convert texture coordinates (up to AI_MAX_NUMBER_OF_TEXTURECOORDS sets supported)
-				for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) {
-					if (!mesh.amTexCoords[c].empty())
-					{
-						p_pcOut->mTextureCoords[c] = new aiVector3D[p_pcOut->mNumVertices];
-						iBase = 0;
-						for (unsigned int q = 0; q < aiSplit[p].size();++q)	{
-							iIndex = aiSplit[p][q];
-							for (unsigned int t = 0; t < 3;++t)	{
-								p_pcOut->mTextureCoords[c][iBase++] = mesh.amTexCoords[c][mesh.mFaces[iIndex].mIndices[t]];
-							}
-						}
-						// Setup the number of valid vertex components
-						p_pcOut->mNumUVComponents[c] = mesh.mNumUVComponents[c];
-					}
-				}
-
-				// Convert vertex colors (only one set supported)
-				if (!mesh.mVertexColors.empty()){
-					p_pcOut->mColors[0] = new aiColor4D[p_pcOut->mNumVertices];
-					iBase = 0;
-					for (unsigned int q = 0; q < aiSplit[p].size();++q)	{
-						iIndex = aiSplit[p][q];
-						for (unsigned int t = 0; t < 3;++t)	{
-							p_pcOut->mColors[0][iBase++] = mesh.mVertexColors[mesh.mFaces[iIndex].mIndices[t]];
-						}
-					}
-				}
-				// Copy bones
-				if (!mesh.mBones.empty())	{
-					p_pcOut->mNumBones = 0;
-					for (unsigned int mrspock = 0; mrspock < mesh.mBones.size();++mrspock)
-						if (!avOutputBones[mrspock].empty())p_pcOut->mNumBones++;
-
-					p_pcOut->mBones = new aiBone* [ p_pcOut->mNumBones ];
-					aiBone** pcBone = p_pcOut->mBones;
-					for (unsigned int mrspock = 0; mrspock < mesh.mBones.size();++mrspock)
-					{
-						if (!avOutputBones[mrspock].empty())	{
-							// we will need this bone. add it to the output mesh and
-							// add all per-vertex weights
-							aiBone* pc = *pcBone = new aiBone();
-							pc->mName.Set(mesh.mBones[mrspock].mName);
-
-							pc->mNumWeights = (unsigned int)avOutputBones[mrspock].size();
-							pc->mWeights = new aiVertexWeight[pc->mNumWeights];
-
-							for (unsigned int captainkirk = 0; captainkirk < pc->mNumWeights;++captainkirk)
-							{
-								const std::pair<unsigned int,float>& ref = avOutputBones[mrspock][captainkirk];
-								pc->mWeights[captainkirk].mVertexId = ref.first;
-								pc->mWeights[captainkirk].mWeight = ref.second;
-							}
-							++pcBone;
-						}
-					}
-					// delete allocated storage
-					delete[] avOutputBones;
-				}
-			}
-		}
-		// delete storage
-		delete[] aiSplit;
-	}
-	else
-	{
-		// Otherwise we can simply copy the data to one output mesh
-		// This codepath needs less memory and uses fast memcpy()s
-		// to do the actual copying. So I think it is worth the 
-		// effort here.
-
-		aiMesh* p_pcOut = new aiMesh();
-		p_pcOut->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
-
-		// set an empty sub material index
-		p_pcOut->mMaterialIndex = ASE::Face::DEFAULT_MATINDEX;
-		mParser->m_vMaterials[mesh.iMaterialIndex].bNeed = true;
-
-		// store the real index here ... in color channel 3
-		p_pcOut->mColors[3] = (aiColor4D*)(uintptr_t)mesh.iMaterialIndex;
-
-		// store a pointer to the mesh in color channel 2
-		p_pcOut->mColors[2] = (aiColor4D*) &mesh;
-		avOutMeshes.push_back(p_pcOut);
-
-		// If the mesh hasn't faces or vertices, there are two cases
-		// possible: 1. the model is invalid. 2. This is a dummy
-		// helper object which we are going to remove later ...
-		if (mesh.mFaces.empty() || mesh.mPositions.empty())	{
-			return;
-		}
-
-		// convert vertices
-		p_pcOut->mNumVertices = (unsigned int)mesh.mPositions.size();
-		p_pcOut->mNumFaces = (unsigned int)mesh.mFaces.size();
-
-		// allocate enough storage for faces
-		p_pcOut->mFaces = new aiFace[p_pcOut->mNumFaces];
-
-		// copy vertices
-		p_pcOut->mVertices = new aiVector3D[mesh.mPositions.size()];
-		memcpy(p_pcOut->mVertices,&mesh.mPositions[0],
-			mesh.mPositions.size() * sizeof(aiVector3D));
-
-		// copy normals
-		p_pcOut->mNormals = new aiVector3D[mesh.mNormals.size()];
-		memcpy(p_pcOut->mNormals,&mesh.mNormals[0],
-			mesh.mNormals.size() * sizeof(aiVector3D));
-
-		// copy texture coordinates
-		for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)	{
-			if (!mesh.amTexCoords[c].empty())	{
-				p_pcOut->mTextureCoords[c] = new aiVector3D[mesh.amTexCoords[c].size()];
-				memcpy(p_pcOut->mTextureCoords[c],&mesh.amTexCoords[c][0],
-					mesh.amTexCoords[c].size() * sizeof(aiVector3D));
-
-				// setup the number of valid vertex components
-				p_pcOut->mNumUVComponents[c] = mesh.mNumUVComponents[c];
-			}
-		}
-
-		// copy vertex colors
-		if (!mesh.mVertexColors.empty())	{
-			p_pcOut->mColors[0] = new aiColor4D[mesh.mVertexColors.size()];
-			memcpy(p_pcOut->mColors[0],&mesh.mVertexColors[0],
-				mesh.mVertexColors.size() * sizeof(aiColor4D));
-		}
-
-		// copy faces
-		for (unsigned int iFace = 0; iFace < p_pcOut->mNumFaces;++iFace)	{
-			p_pcOut->mFaces[iFace].mNumIndices = 3;
-			p_pcOut->mFaces[iFace].mIndices = new unsigned int[3];
-
-			// copy indices 
-			p_pcOut->mFaces[iFace].mIndices[0] = mesh.mFaces[iFace].mIndices[0];
-			p_pcOut->mFaces[iFace].mIndices[1] = mesh.mFaces[iFace].mIndices[1];
-			p_pcOut->mFaces[iFace].mIndices[2] = mesh.mFaces[iFace].mIndices[2];
-		}
-
-		// copy vertex bones
-		if (!mesh.mBones.empty() && !mesh.mBoneVertices.empty())	{
-			std::vector<std::vector<aiVertexWeight> > avBonesOut( mesh.mBones.size() );
-
-			// find all vertex weights for this bone
-			unsigned int quak = 0;
-			for (std::vector<BoneVertex>::const_iterator harrypotter =  mesh.mBoneVertices.begin();
-				harrypotter != mesh.mBoneVertices.end();++harrypotter,++quak)	{
-
-				for (std::vector<std::pair<int,float> >::const_iterator
-					ronaldweasley  = (*harrypotter).mBoneWeights.begin();
-					ronaldweasley != (*harrypotter).mBoneWeights.end();++ronaldweasley)
-				{
-					aiVertexWeight weight;
-					weight.mVertexId = quak;
-					weight.mWeight = (*ronaldweasley).second;
-					avBonesOut[(*ronaldweasley).first].push_back(weight);
-				}
-			}
-
-			// now build a final bone list
-			p_pcOut->mNumBones = 0;
-			for (unsigned int jfkennedy = 0; jfkennedy < mesh.mBones.size();++jfkennedy)
-				if (!avBonesOut[jfkennedy].empty())p_pcOut->mNumBones++;
-
-			p_pcOut->mBones = new aiBone*[p_pcOut->mNumBones];
-			aiBone** pcBone = p_pcOut->mBones;
-			for (unsigned int jfkennedy = 0; jfkennedy < mesh.mBones.size();++jfkennedy)	{
-				if (!avBonesOut[jfkennedy].empty())	{
-					aiBone* pc = *pcBone = new aiBone();
-					pc->mName.Set(mesh.mBones[jfkennedy].mName);
-					pc->mNumWeights = (unsigned int)avBonesOut[jfkennedy].size();
-					pc->mWeights = new aiVertexWeight[pc->mNumWeights];
-					::memcpy(pc->mWeights,&avBonesOut[jfkennedy][0],
-						sizeof(aiVertexWeight) * pc->mNumWeights);
-					++pcBone;
-				}
-			}
-		}
-	}
+    // validate the material index of the mesh
+    if (mesh.iMaterialIndex >= mParser->m_vMaterials.size())    {
+        mesh.iMaterialIndex = (unsigned int)mParser->m_vMaterials.size()-1;
+        DefaultLogger::get()->warn("Material index is out of range");
+    }
+
+    // If the material the mesh is assigned to is consisting of submeshes, split it
+    if (!mParser->m_vMaterials[mesh.iMaterialIndex].avSubMaterials.empty()) {
+        std::vector<ASE::Material> vSubMaterials = mParser->
+            m_vMaterials[mesh.iMaterialIndex].avSubMaterials;
+
+        std::vector<unsigned int>* aiSplit = new std::vector<unsigned int>[vSubMaterials.size()];
+
+        // build a list of all faces per submaterial
+        for (unsigned int i = 0; i < mesh.mFaces.size();++i)    {
+            // check range
+            if (mesh.mFaces[i].iMaterial >= vSubMaterials.size()) {
+                DefaultLogger::get()->warn("Submaterial index is out of range");
+
+                // use the last material instead
+                aiSplit[vSubMaterials.size()-1].push_back(i);
+            }
+            else aiSplit[mesh.mFaces[i].iMaterial].push_back(i);
+        }
+
+        // now generate submeshes
+        for (unsigned int p = 0; p < vSubMaterials.size();++p)  {
+            if (!aiSplit[p].empty())    {
+
+                aiMesh* p_pcOut = new aiMesh();
+                p_pcOut->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
+
+                // let the sub material index
+                p_pcOut->mMaterialIndex = p;
+
+                // we will need this material
+                mParser->m_vMaterials[mesh.iMaterialIndex].avSubMaterials[p].bNeed = true;
+
+                // store the real index here ... color channel 3
+                p_pcOut->mColors[3] = (aiColor4D*)(uintptr_t)mesh.iMaterialIndex;
+
+                // store a pointer to the mesh in color channel 2
+                p_pcOut->mColors[2] = (aiColor4D*) &mesh;
+                avOutMeshes.push_back(p_pcOut);
+
+                // convert vertices
+                p_pcOut->mNumVertices = (unsigned int)aiSplit[p].size()*3;
+                p_pcOut->mNumFaces = (unsigned int)aiSplit[p].size();
+
+                // receive output vertex weights
+                std::vector<std::pair<unsigned int, float> > *avOutputBones = NULL;
+                if (!mesh.mBones.empty())   {
+                    avOutputBones = new std::vector<std::pair<unsigned int, float> >[mesh.mBones.size()];
+                }
+
+                // allocate enough storage for faces
+                p_pcOut->mFaces = new aiFace[p_pcOut->mNumFaces];
+
+                unsigned int iBase = 0,iIndex;
+                if (p_pcOut->mNumVertices)  {
+                    p_pcOut->mVertices = new aiVector3D[p_pcOut->mNumVertices];
+                    p_pcOut->mNormals  = new aiVector3D[p_pcOut->mNumVertices];
+                    for (unsigned int q = 0; q < aiSplit[p].size();++q) {
+
+                        iIndex = aiSplit[p][q];
+
+                        p_pcOut->mFaces[q].mIndices = new unsigned int[3];
+                        p_pcOut->mFaces[q].mNumIndices = 3;
+
+                        for (unsigned int t = 0; t < 3;++t, ++iBase)    {
+                            const uint32_t iIndex2 = mesh.mFaces[iIndex].mIndices[t];
+
+                            p_pcOut->mVertices[iBase] = mesh.mPositions [iIndex2];
+                            p_pcOut->mNormals [iBase] = mesh.mNormals   [iIndex2];
+
+                            // convert bones, if existing
+                            if (!mesh.mBones.empty()) {
+                                // check whether there is a vertex weight for this vertex index
+                                if (iIndex2 < mesh.mBoneVertices.size())    {
+
+                                    for (std::vector<std::pair<int,float> >::const_iterator
+                                        blubb =  mesh.mBoneVertices[iIndex2].mBoneWeights.begin();
+                                        blubb != mesh.mBoneVertices[iIndex2].mBoneWeights.end();++blubb)    {
+
+                                        // NOTE: illegal cases have already been filtered out
+                                        avOutputBones[(*blubb).first].push_back(std::pair<unsigned int, float>(
+                                            iBase,(*blubb).second));
+                                    }
+                                }
+                            }
+                            p_pcOut->mFaces[q].mIndices[t] = iBase;
+                        }
+                    }
+                }
+                // convert texture coordinates (up to AI_MAX_NUMBER_OF_TEXTURECOORDS sets supported)
+                for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) {
+                    if (!mesh.amTexCoords[c].empty())
+                    {
+                        p_pcOut->mTextureCoords[c] = new aiVector3D[p_pcOut->mNumVertices];
+                        iBase = 0;
+                        for (unsigned int q = 0; q < aiSplit[p].size();++q) {
+                            iIndex = aiSplit[p][q];
+                            for (unsigned int t = 0; t < 3;++t) {
+                                p_pcOut->mTextureCoords[c][iBase++] = mesh.amTexCoords[c][mesh.mFaces[iIndex].mIndices[t]];
+                            }
+                        }
+                        // Setup the number of valid vertex components
+                        p_pcOut->mNumUVComponents[c] = mesh.mNumUVComponents[c];
+                    }
+                }
+
+                // Convert vertex colors (only one set supported)
+                if (!mesh.mVertexColors.empty()){
+                    p_pcOut->mColors[0] = new aiColor4D[p_pcOut->mNumVertices];
+                    iBase = 0;
+                    for (unsigned int q = 0; q < aiSplit[p].size();++q) {
+                        iIndex = aiSplit[p][q];
+                        for (unsigned int t = 0; t < 3;++t) {
+                            p_pcOut->mColors[0][iBase++] = mesh.mVertexColors[mesh.mFaces[iIndex].mIndices[t]];
+                        }
+                    }
+                }
+                // Copy bones
+                if (!mesh.mBones.empty())   {
+                    p_pcOut->mNumBones = 0;
+                    for (unsigned int mrspock = 0; mrspock < mesh.mBones.size();++mrspock)
+                        if (!avOutputBones[mrspock].empty())p_pcOut->mNumBones++;
+
+                    p_pcOut->mBones = new aiBone* [ p_pcOut->mNumBones ];
+                    aiBone** pcBone = p_pcOut->mBones;
+                    for (unsigned int mrspock = 0; mrspock < mesh.mBones.size();++mrspock)
+                    {
+                        if (!avOutputBones[mrspock].empty())    {
+                            // we will need this bone. add it to the output mesh and
+                            // add all per-vertex weights
+                            aiBone* pc = *pcBone = new aiBone();
+                            pc->mName.Set(mesh.mBones[mrspock].mName);
+
+                            pc->mNumWeights = (unsigned int)avOutputBones[mrspock].size();
+                            pc->mWeights = new aiVertexWeight[pc->mNumWeights];
+
+                            for (unsigned int captainkirk = 0; captainkirk < pc->mNumWeights;++captainkirk)
+                            {
+                                const std::pair<unsigned int,float>& ref = avOutputBones[mrspock][captainkirk];
+                                pc->mWeights[captainkirk].mVertexId = ref.first;
+                                pc->mWeights[captainkirk].mWeight = ref.second;
+                            }
+                            ++pcBone;
+                        }
+                    }
+                    // delete allocated storage
+                    delete[] avOutputBones;
+                }
+            }
+        }
+        // delete storage
+        delete[] aiSplit;
+    }
+    else
+    {
+        // Otherwise we can simply copy the data to one output mesh
+        // This codepath needs less memory and uses fast memcpy()s
+        // to do the actual copying. So I think it is worth the
+        // effort here.
+
+        aiMesh* p_pcOut = new aiMesh();
+        p_pcOut->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
+
+        // set an empty sub material index
+        p_pcOut->mMaterialIndex = ASE::Face::DEFAULT_MATINDEX;
+        mParser->m_vMaterials[mesh.iMaterialIndex].bNeed = true;
+
+        // store the real index here ... in color channel 3
+        p_pcOut->mColors[3] = (aiColor4D*)(uintptr_t)mesh.iMaterialIndex;
+
+        // store a pointer to the mesh in color channel 2
+        p_pcOut->mColors[2] = (aiColor4D*) &mesh;
+        avOutMeshes.push_back(p_pcOut);
+
+        // If the mesh hasn't faces or vertices, there are two cases
+        // possible: 1. the model is invalid. 2. This is a dummy
+        // helper object which we are going to remove later ...
+        if (mesh.mFaces.empty() || mesh.mPositions.empty()) {
+            return;
+        }
+
+        // convert vertices
+        p_pcOut->mNumVertices = (unsigned int)mesh.mPositions.size();
+        p_pcOut->mNumFaces = (unsigned int)mesh.mFaces.size();
+
+        // allocate enough storage for faces
+        p_pcOut->mFaces = new aiFace[p_pcOut->mNumFaces];
+
+        // copy vertices
+        p_pcOut->mVertices = new aiVector3D[mesh.mPositions.size()];
+        memcpy(p_pcOut->mVertices,&mesh.mPositions[0],
+            mesh.mPositions.size() * sizeof(aiVector3D));
+
+        // copy normals
+        p_pcOut->mNormals = new aiVector3D[mesh.mNormals.size()];
+        memcpy(p_pcOut->mNormals,&mesh.mNormals[0],
+            mesh.mNormals.size() * sizeof(aiVector3D));
+
+        // copy texture coordinates
+        for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)    {
+            if (!mesh.amTexCoords[c].empty())   {
+                p_pcOut->mTextureCoords[c] = new aiVector3D[mesh.amTexCoords[c].size()];
+                memcpy(p_pcOut->mTextureCoords[c],&mesh.amTexCoords[c][0],
+                    mesh.amTexCoords[c].size() * sizeof(aiVector3D));
+
+                // setup the number of valid vertex components
+                p_pcOut->mNumUVComponents[c] = mesh.mNumUVComponents[c];
+            }
+        }
+
+        // copy vertex colors
+        if (!mesh.mVertexColors.empty())    {
+            p_pcOut->mColors[0] = new aiColor4D[mesh.mVertexColors.size()];
+            memcpy(p_pcOut->mColors[0],&mesh.mVertexColors[0],
+                mesh.mVertexColors.size() * sizeof(aiColor4D));
+        }
+
+        // copy faces
+        for (unsigned int iFace = 0; iFace < p_pcOut->mNumFaces;++iFace)    {
+            p_pcOut->mFaces[iFace].mNumIndices = 3;
+            p_pcOut->mFaces[iFace].mIndices = new unsigned int[3];
+
+            // copy indices
+            p_pcOut->mFaces[iFace].mIndices[0] = mesh.mFaces[iFace].mIndices[0];
+            p_pcOut->mFaces[iFace].mIndices[1] = mesh.mFaces[iFace].mIndices[1];
+            p_pcOut->mFaces[iFace].mIndices[2] = mesh.mFaces[iFace].mIndices[2];
+        }
+
+        // copy vertex bones
+        if (!mesh.mBones.empty() && !mesh.mBoneVertices.empty())    {
+            std::vector<std::vector<aiVertexWeight> > avBonesOut( mesh.mBones.size() );
+
+            // find all vertex weights for this bone
+            unsigned int quak = 0;
+            for (std::vector<BoneVertex>::const_iterator harrypotter =  mesh.mBoneVertices.begin();
+                harrypotter != mesh.mBoneVertices.end();++harrypotter,++quak)   {
+
+                for (std::vector<std::pair<int,float> >::const_iterator
+                    ronaldweasley  = (*harrypotter).mBoneWeights.begin();
+                    ronaldweasley != (*harrypotter).mBoneWeights.end();++ronaldweasley)
+                {
+                    aiVertexWeight weight;
+                    weight.mVertexId = quak;
+                    weight.mWeight = (*ronaldweasley).second;
+                    avBonesOut[(*ronaldweasley).first].push_back(weight);
+                }
+            }
+
+            // now build a final bone list
+            p_pcOut->mNumBones = 0;
+            for (unsigned int jfkennedy = 0; jfkennedy < mesh.mBones.size();++jfkennedy)
+                if (!avBonesOut[jfkennedy].empty())p_pcOut->mNumBones++;
+
+            p_pcOut->mBones = new aiBone*[p_pcOut->mNumBones];
+            aiBone** pcBone = p_pcOut->mBones;
+            for (unsigned int jfkennedy = 0; jfkennedy < mesh.mBones.size();++jfkennedy)    {
+                if (!avBonesOut[jfkennedy].empty()) {
+                    aiBone* pc = *pcBone = new aiBone();
+                    pc->mName.Set(mesh.mBones[jfkennedy].mName);
+                    pc->mNumWeights = (unsigned int)avBonesOut[jfkennedy].size();
+                    pc->mWeights = new aiVertexWeight[pc->mNumWeights];
+                    ::memcpy(pc->mWeights,&avBonesOut[jfkennedy][0],
+                        sizeof(aiVertexWeight) * pc->mNumWeights);
+                    ++pcBone;
+                }
+            }
+        }
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 // Setup proper material indices and build output materials
 void ASEImporter::BuildMaterialIndices()
 {
-	ai_assert(NULL != pcScene);
-
-	// iterate through all materials and check whether we need them
-	for (unsigned int iMat = 0; iMat < mParser->m_vMaterials.size();++iMat)
-	{
-		ASE::Material& mat = mParser->m_vMaterials[iMat];
-		if (mat.bNeed)	{
-			// Convert it to the aiMaterial layout
-			ConvertMaterial(mat);
-			++pcScene->mNumMaterials;
-		}
-		for (unsigned int iSubMat = 0; iSubMat < mat.avSubMaterials.size();++iSubMat)
-		{
-			ASE::Material& submat = mat.avSubMaterials[iSubMat];
-			if (submat.bNeed)	{
-				// Convert it to the aiMaterial layout
-				ConvertMaterial(submat);
-				++pcScene->mNumMaterials;
-			}
-		}
-	}
-
-	// allocate the output material array
-	pcScene->mMaterials = new aiMaterial*[pcScene->mNumMaterials];
-	D3DS::Material** pcIntMaterials = new D3DS::Material*[pcScene->mNumMaterials];
-
-	unsigned int iNum = 0;
-	for (unsigned int iMat = 0; iMat < mParser->m_vMaterials.size();++iMat) {
-		ASE::Material& mat = mParser->m_vMaterials[iMat];
-		if (mat.bNeed)
-		{
-			ai_assert(NULL != mat.pcInstance);
-			pcScene->mMaterials[iNum] = mat.pcInstance;
-
-			// Store the internal material, too
-			pcIntMaterials[iNum] = &mat;
-
-			// Iterate through all meshes and search for one which is using
-			// this top-level material index
-			for (unsigned int iMesh = 0; iMesh < pcScene->mNumMeshes;++iMesh)
-			{
-				aiMesh* mesh = pcScene->mMeshes[iMesh];
-				if (ASE::Face::DEFAULT_MATINDEX == mesh->mMaterialIndex &&
-					iMat == (uintptr_t)mesh->mColors[3])
-				{
-					mesh->mMaterialIndex = iNum;
-					mesh->mColors[3] = NULL;
-				}
-			}
-			iNum++;
-		}
-		for (unsigned int iSubMat = 0; iSubMat < mat.avSubMaterials.size();++iSubMat)	{
-			ASE::Material& submat = mat.avSubMaterials[iSubMat];
-			if (submat.bNeed)	{
-				ai_assert(NULL != submat.pcInstance);
-				pcScene->mMaterials[iNum] = submat.pcInstance;
-
-				// Store the internal material, too
-				pcIntMaterials[iNum] = &submat;
-
-				// Iterate through all meshes and search for one which is using
-				// this sub-level material index
-				for (unsigned int iMesh = 0; iMesh < pcScene->mNumMeshes;++iMesh)	{
-					aiMesh* mesh = pcScene->mMeshes[iMesh];
-
-					if (iSubMat == mesh->mMaterialIndex && iMat == (uintptr_t)mesh->mColors[3])	{
-						mesh->mMaterialIndex = iNum;
-						mesh->mColors[3]     = NULL;
-					}
-				}
-				iNum++;
-			}
-		}
-	}
-
-	// Dekete our temporary array
-	delete[] pcIntMaterials;
+    ai_assert(NULL != pcScene);
+
+    // iterate through all materials and check whether we need them
+    for (unsigned int iMat = 0; iMat < mParser->m_vMaterials.size();++iMat)
+    {
+        ASE::Material& mat = mParser->m_vMaterials[iMat];
+        if (mat.bNeed)  {
+            // Convert it to the aiMaterial layout
+            ConvertMaterial(mat);
+            ++pcScene->mNumMaterials;
+        }
+        for (unsigned int iSubMat = 0; iSubMat < mat.avSubMaterials.size();++iSubMat)
+        {
+            ASE::Material& submat = mat.avSubMaterials[iSubMat];
+            if (submat.bNeed)   {
+                // Convert it to the aiMaterial layout
+                ConvertMaterial(submat);
+                ++pcScene->mNumMaterials;
+            }
+        }
+    }
+
+    // allocate the output material array
+    pcScene->mMaterials = new aiMaterial*[pcScene->mNumMaterials];
+    D3DS::Material** pcIntMaterials = new D3DS::Material*[pcScene->mNumMaterials];
+
+    unsigned int iNum = 0;
+    for (unsigned int iMat = 0; iMat < mParser->m_vMaterials.size();++iMat) {
+        ASE::Material& mat = mParser->m_vMaterials[iMat];
+        if (mat.bNeed)
+        {
+            ai_assert(NULL != mat.pcInstance);
+            pcScene->mMaterials[iNum] = mat.pcInstance;
+
+            // Store the internal material, too
+            pcIntMaterials[iNum] = &mat;
+
+            // Iterate through all meshes and search for one which is using
+            // this top-level material index
+            for (unsigned int iMesh = 0; iMesh < pcScene->mNumMeshes;++iMesh)
+            {
+                aiMesh* mesh = pcScene->mMeshes[iMesh];
+                if (ASE::Face::DEFAULT_MATINDEX == mesh->mMaterialIndex &&
+                    iMat == (uintptr_t)mesh->mColors[3])
+                {
+                    mesh->mMaterialIndex = iNum;
+                    mesh->mColors[3] = NULL;
+                }
+            }
+            iNum++;
+        }
+        for (unsigned int iSubMat = 0; iSubMat < mat.avSubMaterials.size();++iSubMat)   {
+            ASE::Material& submat = mat.avSubMaterials[iSubMat];
+            if (submat.bNeed)   {
+                ai_assert(NULL != submat.pcInstance);
+                pcScene->mMaterials[iNum] = submat.pcInstance;
+
+                // Store the internal material, too
+                pcIntMaterials[iNum] = &submat;
+
+                // Iterate through all meshes and search for one which is using
+                // this sub-level material index
+                for (unsigned int iMesh = 0; iMesh < pcScene->mNumMeshes;++iMesh)   {
+                    aiMesh* mesh = pcScene->mMeshes[iMesh];
+
+                    if (iSubMat == mesh->mMaterialIndex && iMat == (uintptr_t)mesh->mColors[3]) {
+                        mesh->mMaterialIndex = iNum;
+                        mesh->mColors[3]     = NULL;
+                    }
+                }
+                iNum++;
+            }
+        }
+    }
+
+    // Dekete our temporary array
+    delete[] pcIntMaterials;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Generate normal vectors basing on smoothing groups
-bool ASEImporter::GenerateNormals(ASE::Mesh& mesh)	{
-
-	if (!mesh.mNormals.empty() && !configRecomputeNormals)
-	{
-		// Check whether there are only uninitialized normals. If there are
-		// some, skip all normals from the file and compute them on our own
-		for (std::vector<aiVector3D>::const_iterator qq =  mesh.mNormals.begin();qq != mesh.mNormals.end();++qq) {
-			if ((*qq).x || (*qq).y || (*qq).z)
-			{
-				return true;
-			}
-		}
-	}
-	// The array is reused.
-	ComputeNormalsWithSmoothingsGroups<ASE::Face>(mesh);
-	return false;
+bool ASEImporter::GenerateNormals(ASE::Mesh& mesh)  {
+
+    if (!mesh.mNormals.empty() && !configRecomputeNormals)
+    {
+        // Check whether there are only uninitialized normals. If there are
+        // some, skip all normals from the file and compute them on our own
+        for (std::vector<aiVector3D>::const_iterator qq =  mesh.mNormals.begin();qq != mesh.mNormals.end();++qq) {
+            if ((*qq).x || (*qq).y || (*qq).z)
+            {
+                return true;
+            }
+        }
+    }
+    // The array is reused.
+    ComputeNormalsWithSmoothingsGroups<ASE::Face>(mesh);
+    return false;
 }
 
 #endif // !! ASSIMP_BUILD_NO_BASE_IMPORTER

+ 108 - 108
assimplib.mod/assimp/code/ASELoader.h

@@ -2,11 +2,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -23,16 +23,16 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -57,147 +57,147 @@ namespace Assimp {
 /** Importer class for the 3DS ASE ASCII format.
  *
  */
-class ASEImporter : public BaseImporter	{
+class ASEImporter : public BaseImporter {
 public:
-	ASEImporter();
-	~ASEImporter();
+    ASEImporter();
+    ~ASEImporter();
 
 
 public:
 
-	// -------------------------------------------------------------------
-	/** Returns whether the class can handle the format of the given file. 
-	 * See BaseImporter::CanRead() for details.	
-	 */
-	bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
-		bool checkSig) const;
+    // -------------------------------------------------------------------
+    /** Returns whether the class can handle the format of the given file.
+     * See BaseImporter::CanRead() for details.
+     */
+    bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+        bool checkSig) const;
 
 protected:
 
-	// -------------------------------------------------------------------
-	/** Return importer meta information.
-	 * See #BaseImporter::GetInfo for the details
-	 */
-	const aiImporterDesc* GetInfo () const;
+    // -------------------------------------------------------------------
+    /** Return importer meta information.
+     * See #BaseImporter::GetInfo for the details
+     */
+    const aiImporterDesc* GetInfo () const;
 
 
-	// -------------------------------------------------------------------
-	/** Imports the given file into the given scene structure. 
-	* See BaseImporter::InternReadFile() for details
-	*/
-	void InternReadFile( const std::string& pFile, aiScene* pScene,
-		IOSystem* pIOHandler);
+    // -------------------------------------------------------------------
+    /** Imports the given file into the given scene structure.
+    * See BaseImporter::InternReadFile() for details
+    */
+    void InternReadFile( const std::string& pFile, aiScene* pScene,
+        IOSystem* pIOHandler);
 
 
-	// -------------------------------------------------------------------
-	/** Called prior to ReadFile().
-	* The function is a request to the importer to update its configuration
-	* basing on the Importer's configuration property list.
-	*/
-	void SetupProperties(const Importer* pImp);
+    // -------------------------------------------------------------------
+    /** Called prior to ReadFile().
+    * The function is a request to the importer to update its configuration
+    * basing on the Importer's configuration property list.
+    */
+    void SetupProperties(const Importer* pImp);
 
 
 private:
 
-	// -------------------------------------------------------------------
-	/** Generate normal vectors basing on smoothing groups
-	 * (in some cases the normal are already contained in the file)
-	 * \param mesh Mesh to work on
-	 * \return false if the normals have been recomputed
-	 */
-	bool GenerateNormals(ASE::Mesh& mesh);
+    // -------------------------------------------------------------------
+    /** Generate normal vectors basing on smoothing groups
+     * (in some cases the normal are already contained in the file)
+     * \param mesh Mesh to work on
+     * \return false if the normals have been recomputed
+     */
+    bool GenerateNormals(ASE::Mesh& mesh);
 
 
-	// -------------------------------------------------------------------
-	/** Create valid vertex/normal/UV/color/face lists.
-	 *  All elements are unique, faces have only one set of indices
-	 *  after this step occurs.
-	 * \param mesh Mesh to work on
-	 */
-	void BuildUniqueRepresentation(ASE::Mesh& mesh);
+    // -------------------------------------------------------------------
+    /** Create valid vertex/normal/UV/color/face lists.
+     *  All elements are unique, faces have only one set of indices
+     *  after this step occurs.
+     * \param mesh Mesh to work on
+     */
+    void BuildUniqueRepresentation(ASE::Mesh& mesh);
 
 
-	/** Create one-material-per-mesh meshes ;-)
-	 * \param mesh Mesh to work with
-	 *  \param Receives the list of all created meshes
-	 */
-	void ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOut);
+    /** Create one-material-per-mesh meshes ;-)
+     * \param mesh Mesh to work with
+     *  \param Receives the list of all created meshes
+     */
+    void ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOut);
 
 
-	// -------------------------------------------------------------------
-	/** Convert a material to a aiMaterial object
-	 * \param mat Input material
-	 */
-	void ConvertMaterial(ASE::Material& mat);
+    // -------------------------------------------------------------------
+    /** Convert a material to a aiMaterial object
+     * \param mat Input material
+     */
+    void ConvertMaterial(ASE::Material& mat);
 
 
-	// -------------------------------------------------------------------
-	/** Setup the final material indices for each mesh
-	 */
-	void BuildMaterialIndices();
+    // -------------------------------------------------------------------
+    /** Setup the final material indices for each mesh
+     */
+    void BuildMaterialIndices();
 
 
-	// -------------------------------------------------------------------
-	/** Build the node graph
-	 */
-	void BuildNodes(std::vector<ASE::BaseNode*>& nodes);
+    // -------------------------------------------------------------------
+    /** Build the node graph
+     */
+    void BuildNodes(std::vector<ASE::BaseNode*>& nodes);
 
 
-	// -------------------------------------------------------------------
-	/** Build output cameras
-	 */
-	void BuildCameras();
+    // -------------------------------------------------------------------
+    /** Build output cameras
+     */
+    void BuildCameras();
 
 
-	// -------------------------------------------------------------------
-	/** Build output lights
-	 */
-	void BuildLights();
+    // -------------------------------------------------------------------
+    /** Build output lights
+     */
+    void BuildLights();
 
 
-	// -------------------------------------------------------------------
-	/** Build output animations
-	 */
-	void BuildAnimations(const std::vector<ASE::BaseNode*>& nodes);
+    // -------------------------------------------------------------------
+    /** Build output animations
+     */
+    void BuildAnimations(const std::vector<ASE::BaseNode*>& nodes);
 
 
-	// -------------------------------------------------------------------
-	/** Add sub nodes to a node
-	 *  \param pcParent parent node to be filled
-	 *  \param szName Name of the parent node
-	 *  \param matrix Current transform
-	 */
-	void AddNodes(const std::vector<ASE::BaseNode*>& nodes,
-		aiNode* pcParent,const char* szName);
+    // -------------------------------------------------------------------
+    /** Add sub nodes to a node
+     *  \param pcParent parent node to be filled
+     *  \param szName Name of the parent node
+     *  \param matrix Current transform
+     */
+    void AddNodes(const std::vector<ASE::BaseNode*>& nodes,
+        aiNode* pcParent,const char* szName);
 
-	void AddNodes(const std::vector<ASE::BaseNode*>& nodes,
-		aiNode* pcParent,const char* szName,
-		const aiMatrix4x4& matrix);
+    void AddNodes(const std::vector<ASE::BaseNode*>& nodes,
+        aiNode* pcParent,const char* szName,
+        const aiMatrix4x4& matrix);
 
-	void AddMeshes(const ASE::BaseNode* snode,aiNode* node);
+    void AddMeshes(const ASE::BaseNode* snode,aiNode* node);
 
-	// -------------------------------------------------------------------
-	/** Generate a default material and add it to the parser's list
-	 *  Called if no material has been found in the file (rare for ASE,
-	 *  but not impossible)
-	 */
-	void GenerateDefaultMaterial();
+    // -------------------------------------------------------------------
+    /** Generate a default material and add it to the parser's list
+     *  Called if no material has been found in the file (rare for ASE,
+     *  but not impossible)
+     */
+    void GenerateDefaultMaterial();
 
 protected:
 
-	/** Parser instance */
-	ASE::Parser* mParser;
+    /** Parser instance */
+    ASE::Parser* mParser;
 
-	/** Buffer to hold the loaded file */
-	char* mBuffer;
+    /** Buffer to hold the loaded file */
+    char* mBuffer;
 
-	/** Scene to be filled */
-	aiScene* pcScene;
+    /** Scene to be filled */
+    aiScene* pcScene;
 
-	/** Config options: Recompute the normals in every case - WA
-	    for 3DS Max broken ASE normal export */
-	bool configRecomputeNormals;
-	bool noSkeletonMesh;
+    /** Config options: Recompute the normals in every case - WA
+        for 3DS Max broken ASE normal export */
+    bool configRecomputeNormals;
+    bool noSkeletonMesh;
 };
 
 } // end of namespace Assimp

+ 1895 - 1894
assimplib.mod/assimp/code/ASEParser.cpp

@@ -3,12 +3,12 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -25,25 +25,25 @@ conditions are met:
   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 
+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 
+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 
+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 
+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  ASEParser.cpp
- *  @brief Implementation of the ASE parser class 
+ *  @brief Implementation of the ASE parser class
  */
 
-#include "AssimpPCH.h"
+
 #ifndef ASSIMP_BUILD_NO_ASE_IMPORTER
 
 // internal headers
@@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "ASELoader.h"
 #include "MaterialSystem.h"
 #include "fast_atof.h"
+#include "../include/assimp/DefaultLogger.hpp"
 
 using namespace Assimp;
 using namespace Assimp::ASE;
@@ -60,32 +61,32 @@ using namespace Assimp::ASE;
 // Begin an ASE parsing function
 
 #define AI_ASE_PARSER_INIT() \
-	int iDepth = 0;
+    int iDepth = 0;
 
 // ------------------------------------------------------------------------------------------------
 // Handle a "top-level" section in the file. EOF is no error in this case.
 
 #define AI_ASE_HANDLE_TOP_LEVEL_SECTION() \
-	else if ('{' == *filePtr)iDepth++; \
-	else if ('}' == *filePtr) \
-	{ \
-		if (0 == --iDepth) \
-		{ \
-			++filePtr; \
-			SkipToNextToken(); \
-			return; \
-		} \
-	} \
-	else if ('\0' == *filePtr) \
-	{ \
-		return; \
-	} \
-	if(IsLineEnd(*filePtr) && !bLastWasEndLine) \
-	{ \
-		++iLineNumber; \
-		bLastWasEndLine = true; \
-	} else bLastWasEndLine = false; \
-	++filePtr; 
+    else if ('{' == *filePtr)iDepth++; \
+    else if ('}' == *filePtr) \
+    { \
+        if (0 == --iDepth) \
+        { \
+            ++filePtr; \
+            SkipToNextToken(); \
+            return; \
+        } \
+    } \
+    else if ('\0' == *filePtr) \
+    { \
+        return; \
+    } \
+    if(IsLineEnd(*filePtr) && !bLastWasEndLine) \
+    { \
+        ++iLineNumber; \
+        bLastWasEndLine = true; \
+    } else bLastWasEndLine = false; \
+    ++filePtr;
 
 // ------------------------------------------------------------------------------------------------
 // Handle a nested section in the file. EOF is an error in this case
@@ -93,2061 +94,2061 @@ using namespace Assimp::ASE;
 // @param msg Full name of the section (including the asterisk)
 
 #define AI_ASE_HANDLE_SECTION(level, msg) \
-	if ('{' == *filePtr)iDepth++; \
-	else if ('}' == *filePtr) \
-	{ \
-		if (0 == --iDepth) \
-		{ \
-			++filePtr; \
-			SkipToNextToken(); \
-			return; \
-		} \
-	} \
-	else if ('\0' == *filePtr) \
-	{ \
-		LogError("Encountered unexpected EOL while parsing a " msg \
-		" chunk (Level " level ")"); \
-	} \
-	if(IsLineEnd(*filePtr) && !bLastWasEndLine) \
-		{ \
-		++iLineNumber; \
-		bLastWasEndLine = true; \
-	} else bLastWasEndLine = false; \
-	++filePtr; 
+    if ('{' == *filePtr)iDepth++; \
+    else if ('}' == *filePtr) \
+    { \
+        if (0 == --iDepth) \
+        { \
+            ++filePtr; \
+            SkipToNextToken(); \
+            return; \
+        } \
+    } \
+    else if ('\0' == *filePtr) \
+    { \
+        LogError("Encountered unexpected EOL while parsing a " msg \
+        " chunk (Level " level ")"); \
+    } \
+    if(IsLineEnd(*filePtr) && !bLastWasEndLine) \
+        { \
+        ++iLineNumber; \
+        bLastWasEndLine = true; \
+    } else bLastWasEndLine = false; \
+    ++filePtr;
 
 // ------------------------------------------------------------------------------------------------
 Parser::Parser (const char* szFile, unsigned int fileFormatDefault)
 {
-	ai_assert(NULL != szFile);
-	filePtr = szFile;
-	iFileFormat = fileFormatDefault;
-
-	// make sure that the color values are invalid
-	m_clrBackground.r = get_qnan();
-	m_clrAmbient.r    = get_qnan();
-
-	// setup some default values
-	iLineNumber = 0;
-	iFirstFrame = 0;
-	iLastFrame = 0;
-	iFrameSpeed = 30;        // use 30 as default value for this property
-	iTicksPerFrame = 1;      // use 1 as default value for this property
-	bLastWasEndLine = false; // need to handle \r\n seqs due to binary file mapping
+    ai_assert(NULL != szFile);
+    filePtr = szFile;
+    iFileFormat = fileFormatDefault;
+
+    // make sure that the color values are invalid
+    m_clrBackground.r = get_qnan();
+    m_clrAmbient.r    = get_qnan();
+
+    // setup some default values
+    iLineNumber = 0;
+    iFirstFrame = 0;
+    iLastFrame = 0;
+    iFrameSpeed = 30;        // use 30 as default value for this property
+    iTicksPerFrame = 1;      // use 1 as default value for this property
+    bLastWasEndLine = false; // need to handle \r\n seqs due to binary file mapping
 }
 
 // ------------------------------------------------------------------------------------------------
 void Parser::LogWarning(const char* szWarn)
 {
-	ai_assert(NULL != szWarn);
+    ai_assert(NULL != szWarn);
 
-	char szTemp[1024];
+    char szTemp[1024];
 #if _MSC_VER >= 1400
-	sprintf_s(szTemp,"Line %i: %s",iLineNumber,szWarn);
+    sprintf_s(szTemp,"Line %u: %s",iLineNumber,szWarn);
 #else
-	snprintf(szTemp,1024,"Line %i: %s",iLineNumber,szWarn);
+    snprintf(szTemp,1024,"Line %u: %s",iLineNumber,szWarn);
 #endif
 
-	// output the warning to the logger ...
-	DefaultLogger::get()->warn(szTemp);
+    // output the warning to the logger ...
+    DefaultLogger::get()->warn(szTemp);
 }
 
 // ------------------------------------------------------------------------------------------------
 void Parser::LogInfo(const char* szWarn)
 {
-	ai_assert(NULL != szWarn);
+    ai_assert(NULL != szWarn);
 
-	char szTemp[1024];
+    char szTemp[1024];
 #if _MSC_VER >= 1400
-	sprintf_s(szTemp,"Line %i: %s",iLineNumber,szWarn);
+    sprintf_s(szTemp,"Line %u: %s",iLineNumber,szWarn);
 #else
-	snprintf(szTemp,1024,"Line %i: %s",iLineNumber,szWarn);
+    snprintf(szTemp,1024,"Line %u: %s",iLineNumber,szWarn);
 #endif
 
-	// output the information to the logger ...
-	DefaultLogger::get()->info(szTemp);
+    // output the information to the logger ...
+    DefaultLogger::get()->info(szTemp);
 }
 
 // ------------------------------------------------------------------------------------------------
-void Parser::LogError(const char* szWarn)
+AI_WONT_RETURN void Parser::LogError(const char* szWarn)
 {
-	ai_assert(NULL != szWarn);
+    ai_assert(NULL != szWarn);
 
-	char szTemp[1024];
+    char szTemp[1024];
 #if _MSC_VER >= 1400
-	sprintf_s(szTemp,"Line %i: %s",iLineNumber,szWarn);
+    sprintf_s(szTemp,"Line %u: %s",iLineNumber,szWarn);
 #else
-	snprintf(szTemp,1024,"Line %i: %s",iLineNumber,szWarn);
+    snprintf(szTemp,1024,"Line %u: %s",iLineNumber,szWarn);
 #endif
 
-	// throw an exception
-	throw DeadlyImportError(szTemp);
+    // throw an exception
+    throw DeadlyImportError(szTemp);
 }
 
 // ------------------------------------------------------------------------------------------------
 bool Parser::SkipToNextToken()
 {
-	while (true)
-	{
-		char me = *filePtr;
-
-		// increase the line number counter if necessary
-		if (IsLineEnd(me) && !bLastWasEndLine)
-		{
-			++iLineNumber;
-			bLastWasEndLine = true;
-		}
-		else bLastWasEndLine = false;
-		if ('*' == me || '}' == me || '{' == me)return true;
-		if ('\0' == me)return false;
-
-		++filePtr;
-	}
+    while (true)
+    {
+        char me = *filePtr;
+
+        // increase the line number counter if necessary
+        if (IsLineEnd(me) && !bLastWasEndLine)
+        {
+            ++iLineNumber;
+            bLastWasEndLine = true;
+        }
+        else bLastWasEndLine = false;
+        if ('*' == me || '}' == me || '{' == me)return true;
+        if ('\0' == me)return false;
+
+        ++filePtr;
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 bool Parser::SkipSection()
 {
-	// must handle subsections ...
-	int iCnt = 0;
-	while (true)
-	{
-		if ('}' == *filePtr)
-		{
-			--iCnt;
-			if (0 == iCnt)
-			{
-				// go to the next valid token ...
-				++filePtr;
-				SkipToNextToken();
-				return true;
-			}
-		}
-		else if ('{' == *filePtr)
-		{
-			++iCnt;
-		}
-		else if ('\0' == *filePtr)
-		{
-			LogWarning("Unable to parse block: Unexpected EOF, closing bracket \'}\' was expected [#1]");	
-			return false;
-		}
-		else if(IsLineEnd(*filePtr))++iLineNumber;
-		++filePtr;
-	}
+    // must handle subsections ...
+    int iCnt = 0;
+    while (true)
+    {
+        if ('}' == *filePtr)
+        {
+            --iCnt;
+            if (0 == iCnt)
+            {
+                // go to the next valid token ...
+                ++filePtr;
+                SkipToNextToken();
+                return true;
+            }
+        }
+        else if ('{' == *filePtr)
+        {
+            ++iCnt;
+        }
+        else if ('\0' == *filePtr)
+        {
+            LogWarning("Unable to parse block: Unexpected EOF, closing bracket \'}\' was expected [#1]");
+            return false;
+        }
+        else if(IsLineEnd(*filePtr))++iLineNumber;
+        ++filePtr;
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 void Parser::Parse()
 {
-	AI_ASE_PARSER_INIT();
-	while (true)
-	{
-		if ('*' == *filePtr)
-		{
-			++filePtr;
-
-			// Version should be 200. Validate this ...
-			if (TokenMatch(filePtr,"3DSMAX_ASCIIEXPORT",18))
-			{
-				unsigned int fmt;
-				ParseLV4MeshLong(fmt);
-
-				if (fmt > 200)
-				{
-					LogWarning("Unknown file format version: *3DSMAX_ASCIIEXPORT should \
-							   be <= 200");
-				}
-				// *************************************************************
-				// - fmt will be 0 if we're unable to read the version number
-				// there are some faulty files without a version number ...
-				// in this case we'll guess the exact file format by looking
-				// at the file extension (ASE, ASK, ASC)
-				// *************************************************************
-
-				if (fmt)iFileFormat = fmt;
-				continue;
-			}
-			// main scene information
-			if (TokenMatch(filePtr,"SCENE",5))
-			{
-				ParseLV1SceneBlock();
-				continue;
-			}
-			// "group" - no implementation yet, in facte
-			// we're just ignoring them for the moment
-			if (TokenMatch(filePtr,"GROUP",5)) 
-			{
-				Parse();
-				continue;
-			}
-			// material list
-			if (TokenMatch(filePtr,"MATERIAL_LIST",13)) 
-			{
-				ParseLV1MaterialListBlock();
-				continue;
-			}
-			// geometric object (mesh)
-			if (TokenMatch(filePtr,"GEOMOBJECT",10)) 
-				
-			{
-				m_vMeshes.push_back(Mesh());
-				ParseLV1ObjectBlock(m_vMeshes.back());
-				continue;
-			}
-			// helper object = dummy in the hierarchy
-			if (TokenMatch(filePtr,"HELPEROBJECT",12)) 
-				
-			{
-				m_vDummies.push_back(Dummy());
-				ParseLV1ObjectBlock(m_vDummies.back());
-				continue;
-			}
-			// light object
-			if (TokenMatch(filePtr,"LIGHTOBJECT",11)) 
-				
-			{
-				m_vLights.push_back(Light());
-				ParseLV1ObjectBlock(m_vLights.back());
-				continue;
-			}
-			// camera object
-			if (TokenMatch(filePtr,"CAMERAOBJECT",12)) 
-			{
-				m_vCameras.push_back(Camera());
-				ParseLV1ObjectBlock(m_vCameras.back());
-				continue;
-			}
-			// comment - print it on the console
-			if (TokenMatch(filePtr,"COMMENT",7)) 
-			{
-				std::string out = "<unknown>";
-				ParseString(out,"*COMMENT");
-				LogInfo(("Comment: " + out).c_str());
-				continue;
-			}
-			// ASC bone weights
-			if (AI_ASE_IS_OLD_FILE_FORMAT() && TokenMatch(filePtr,"MESH_SOFTSKINVERTS",18)) 
-			{
-				ParseLV1SoftSkinBlock();
-			}
-		}
-		AI_ASE_HANDLE_TOP_LEVEL_SECTION();
-	}
-	return;
+    AI_ASE_PARSER_INIT();
+    while (true)
+    {
+        if ('*' == *filePtr)
+        {
+            ++filePtr;
+
+            // Version should be 200. Validate this ...
+            if (TokenMatch(filePtr,"3DSMAX_ASCIIEXPORT",18))
+            {
+                unsigned int fmt;
+                ParseLV4MeshLong(fmt);
+
+                if (fmt > 200)
+                {
+                    LogWarning("Unknown file format version: *3DSMAX_ASCIIEXPORT should \
+                               be <= 200");
+                }
+                // *************************************************************
+                // - fmt will be 0 if we're unable to read the version number
+                // there are some faulty files without a version number ...
+                // in this case we'll guess the exact file format by looking
+                // at the file extension (ASE, ASK, ASC)
+                // *************************************************************
+
+                if (fmt)iFileFormat = fmt;
+                continue;
+            }
+            // main scene information
+            if (TokenMatch(filePtr,"SCENE",5))
+            {
+                ParseLV1SceneBlock();
+                continue;
+            }
+            // "group" - no implementation yet, in facte
+            // we're just ignoring them for the moment
+            if (TokenMatch(filePtr,"GROUP",5))
+            {
+                Parse();
+                continue;
+            }
+            // material list
+            if (TokenMatch(filePtr,"MATERIAL_LIST",13))
+            {
+                ParseLV1MaterialListBlock();
+                continue;
+            }
+            // geometric object (mesh)
+            if (TokenMatch(filePtr,"GEOMOBJECT",10))
+
+            {
+                m_vMeshes.push_back(Mesh());
+                ParseLV1ObjectBlock(m_vMeshes.back());
+                continue;
+            }
+            // helper object = dummy in the hierarchy
+            if (TokenMatch(filePtr,"HELPEROBJECT",12))
+
+            {
+                m_vDummies.push_back(Dummy());
+                ParseLV1ObjectBlock(m_vDummies.back());
+                continue;
+            }
+            // light object
+            if (TokenMatch(filePtr,"LIGHTOBJECT",11))
+
+            {
+                m_vLights.push_back(Light());
+                ParseLV1ObjectBlock(m_vLights.back());
+                continue;
+            }
+            // camera object
+            if (TokenMatch(filePtr,"CAMERAOBJECT",12))
+            {
+                m_vCameras.push_back(Camera());
+                ParseLV1ObjectBlock(m_vCameras.back());
+                continue;
+            }
+            // comment - print it on the console
+            if (TokenMatch(filePtr,"COMMENT",7))
+            {
+                std::string out = "<unknown>";
+                ParseString(out,"*COMMENT");
+                LogInfo(("Comment: " + out).c_str());
+                continue;
+            }
+            // ASC bone weights
+            if (AI_ASE_IS_OLD_FILE_FORMAT() && TokenMatch(filePtr,"MESH_SOFTSKINVERTS",18))
+            {
+                ParseLV1SoftSkinBlock();
+            }
+        }
+        AI_ASE_HANDLE_TOP_LEVEL_SECTION();
+    }
+    return;
 }
 
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV1SoftSkinBlock()
 {
-	// TODO: fix line counting here
-
-	// **************************************************************
-	// The soft skin block is formatted differently. There are no
-	// nested sections supported and the single elements aren't
-	// marked by keywords starting with an asterisk.
-
-	/** 
-	FORMAT BEGIN
-
-	*MESH_SOFTSKINVERTS {
-	<nodename>
-	<number of vertices>
-
-	[for <number of vertices> times:]
-		<number of weights>	[for <number of weights> times:] <bone name> <weight>
-	}
-
-	FORMAT END 
-	*/
-	// **************************************************************
-	while (true)
-	{
-		if (*filePtr == '}'      )	{++filePtr;return;}
-		else if (*filePtr == '\0')	return;
-		else if (*filePtr == '{' )	++filePtr;
-
-		else // if (!IsSpace(*filePtr) && !IsLineEnd(*filePtr))
-		{
-			ASE::Mesh* curMesh		= NULL;
-			unsigned int numVerts	= 0;
-
-			const char* sz = filePtr;
-			while (!IsSpaceOrNewLine(*filePtr))++filePtr;
-
-			const unsigned int diff = (unsigned int)(filePtr-sz);
-			if (diff)
-			{
-				std::string name = std::string(sz,diff);
-				for (std::vector<ASE::Mesh>::iterator it = m_vMeshes.begin();
-					it != m_vMeshes.end(); ++it)
-				{
-					if ((*it).mName == name)
-					{
-						curMesh = & (*it);
-						break;
-					}
-				}
-				if (!curMesh)
-				{
-					LogWarning("Encountered unknown mesh in *MESH_SOFTSKINVERTS section");
-
-					// Skip the mesh data - until we find a new mesh
-					// or the end of the *MESH_SOFTSKINVERTS section
-					while (true)
-					{
-						SkipSpacesAndLineEnd(&filePtr);
-						if (*filePtr == '}')
-							{++filePtr;return;}
-						else if (!IsNumeric(*filePtr))
-							break;
-
-						SkipLine(&filePtr);
-					}
-				}
-				else
-				{
-					SkipSpacesAndLineEnd(&filePtr);
-					ParseLV4MeshLong(numVerts);
-
-					// Reserve enough storage
-					curMesh->mBoneVertices.reserve(numVerts);
-
-					for (unsigned int i = 0; i < numVerts;++i)
-					{
-						SkipSpacesAndLineEnd(&filePtr);
-						unsigned int numWeights;
-						ParseLV4MeshLong(numWeights);
-
-						curMesh->mBoneVertices.push_back(ASE::BoneVertex());
-						ASE::BoneVertex& vert = curMesh->mBoneVertices.back();
-
-						// Reserve enough storage
-						vert.mBoneWeights.reserve(numWeights);
-
-						for (unsigned int w = 0; w < numWeights;++w)
-						{
-							std::string bone;
-							ParseString(bone,"*MESH_SOFTSKINVERTS.Bone");
-
-							// Find the bone in the mesh's list
-							std::pair<int,float> me;
-							me.first = -1;
-							
-							for (unsigned int n = 0; n < curMesh->mBones.size();++n)
-							{
-								if (curMesh->mBones[n].mName == bone)
-								{
-									me.first = n;
-									break;
-								}
-							}
-							if (-1 == me.first)
-							{
-								// We don't have this bone yet, so add it to the list
-								me.first = (int)curMesh->mBones.size();
-								curMesh->mBones.push_back(ASE::Bone(bone));
-							}
-							ParseLV4MeshFloat( me.second );
-
-							// Add the new bone weight to list
-							vert.mBoneWeights.push_back(me);
-						}
-					}
-				}
-			}
-		}
-		++filePtr;
-		SkipSpacesAndLineEnd(&filePtr);
-	}
+    // TODO: fix line counting here
+
+    // **************************************************************
+    // The soft skin block is formatted differently. There are no
+    // nested sections supported and the single elements aren't
+    // marked by keywords starting with an asterisk.
+
+    /**
+    FORMAT BEGIN
+
+    *MESH_SOFTSKINVERTS {
+    <nodename>
+    <number of vertices>
+
+    [for <number of vertices> times:]
+        <number of weights> [for <number of weights> times:] <bone name> <weight>
+    }
+
+    FORMAT END
+    */
+    // **************************************************************
+    while (true)
+    {
+        if (*filePtr == '}'      )  {++filePtr;return;}
+        else if (*filePtr == '\0')  return;
+        else if (*filePtr == '{' )  ++filePtr;
+
+        else // if (!IsSpace(*filePtr) && !IsLineEnd(*filePtr))
+        {
+            ASE::Mesh* curMesh      = NULL;
+            unsigned int numVerts   = 0;
+
+            const char* sz = filePtr;
+            while (!IsSpaceOrNewLine(*filePtr))++filePtr;
+
+            const unsigned int diff = (unsigned int)(filePtr-sz);
+            if (diff)
+            {
+                std::string name = std::string(sz,diff);
+                for (std::vector<ASE::Mesh>::iterator it = m_vMeshes.begin();
+                    it != m_vMeshes.end(); ++it)
+                {
+                    if ((*it).mName == name)
+                    {
+                        curMesh = & (*it);
+                        break;
+                    }
+                }
+                if (!curMesh)
+                {
+                    LogWarning("Encountered unknown mesh in *MESH_SOFTSKINVERTS section");
+
+                    // Skip the mesh data - until we find a new mesh
+                    // or the end of the *MESH_SOFTSKINVERTS section
+                    while (true)
+                    {
+                        SkipSpacesAndLineEnd(&filePtr);
+                        if (*filePtr == '}')
+                            {++filePtr;return;}
+                        else if (!IsNumeric(*filePtr))
+                            break;
+
+                        SkipLine(&filePtr);
+                    }
+                }
+                else
+                {
+                    SkipSpacesAndLineEnd(&filePtr);
+                    ParseLV4MeshLong(numVerts);
+
+                    // Reserve enough storage
+                    curMesh->mBoneVertices.reserve(numVerts);
+
+                    for (unsigned int i = 0; i < numVerts;++i)
+                    {
+                        SkipSpacesAndLineEnd(&filePtr);
+                        unsigned int numWeights;
+                        ParseLV4MeshLong(numWeights);
+
+                        curMesh->mBoneVertices.push_back(ASE::BoneVertex());
+                        ASE::BoneVertex& vert = curMesh->mBoneVertices.back();
+
+                        // Reserve enough storage
+                        vert.mBoneWeights.reserve(numWeights);
+
+                        for (unsigned int w = 0; w < numWeights;++w)
+                        {
+                            std::string bone;
+                            ParseString(bone,"*MESH_SOFTSKINVERTS.Bone");
+
+                            // Find the bone in the mesh's list
+                            std::pair<int,float> me;
+                            me.first = -1;
+
+                            for (unsigned int n = 0; n < curMesh->mBones.size();++n)
+                            {
+                                if (curMesh->mBones[n].mName == bone)
+                                {
+                                    me.first = n;
+                                    break;
+                                }
+                            }
+                            if (-1 == me.first)
+                            {
+                                // We don't have this bone yet, so add it to the list
+                                me.first = (int)curMesh->mBones.size();
+                                curMesh->mBones.push_back(ASE::Bone(bone));
+                            }
+                            ParseLV4MeshFloat( me.second );
+
+                            // Add the new bone weight to list
+                            vert.mBoneWeights.push_back(me);
+                        }
+                    }
+                }
+            }
+        }
+        ++filePtr;
+        SkipSpacesAndLineEnd(&filePtr);
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV1SceneBlock()
 {
-	AI_ASE_PARSER_INIT();
-	while (true)
-	{
-		if ('*' == *filePtr)
-		{
-			++filePtr;
-			if (TokenMatch(filePtr,"SCENE_BACKGROUND_STATIC",23)) 
-				
-			{
-				// parse a color triple and assume it is really the bg color
-				ParseLV4MeshFloatTriple( &m_clrBackground.r );
-				continue;
-			}
-			if (TokenMatch(filePtr,"SCENE_AMBIENT_STATIC",20)) 
-				
-			{
-				// parse a color triple and assume it is really the bg color
-				ParseLV4MeshFloatTriple( &m_clrAmbient.r );
-				continue;
-			}
-			if (TokenMatch(filePtr,"SCENE_FIRSTFRAME",16)) 
-			{
-				ParseLV4MeshLong(iFirstFrame);
-				continue;
-			}
-			if (TokenMatch(filePtr,"SCENE_LASTFRAME",15))
-			{
-				ParseLV4MeshLong(iLastFrame);
-				continue;
-			}
-			if (TokenMatch(filePtr,"SCENE_FRAMESPEED",16)) 
-			{
-				ParseLV4MeshLong(iFrameSpeed);
-				continue;
-			}
-			if (TokenMatch(filePtr,"SCENE_TICKSPERFRAME",19))
-			{
-				ParseLV4MeshLong(iTicksPerFrame);
-				continue;
-			}
-		}
-		AI_ASE_HANDLE_TOP_LEVEL_SECTION();
-	}
+    AI_ASE_PARSER_INIT();
+    while (true)
+    {
+        if ('*' == *filePtr)
+        {
+            ++filePtr;
+            if (TokenMatch(filePtr,"SCENE_BACKGROUND_STATIC",23))
+
+            {
+                // parse a color triple and assume it is really the bg color
+                ParseLV4MeshFloatTriple( &m_clrBackground.r );
+                continue;
+            }
+            if (TokenMatch(filePtr,"SCENE_AMBIENT_STATIC",20))
+
+            {
+                // parse a color triple and assume it is really the bg color
+                ParseLV4MeshFloatTriple( &m_clrAmbient.r );
+                continue;
+            }
+            if (TokenMatch(filePtr,"SCENE_FIRSTFRAME",16))
+            {
+                ParseLV4MeshLong(iFirstFrame);
+                continue;
+            }
+            if (TokenMatch(filePtr,"SCENE_LASTFRAME",15))
+            {
+                ParseLV4MeshLong(iLastFrame);
+                continue;
+            }
+            if (TokenMatch(filePtr,"SCENE_FRAMESPEED",16))
+            {
+                ParseLV4MeshLong(iFrameSpeed);
+                continue;
+            }
+            if (TokenMatch(filePtr,"SCENE_TICKSPERFRAME",19))
+            {
+                ParseLV4MeshLong(iTicksPerFrame);
+                continue;
+            }
+        }
+        AI_ASE_HANDLE_TOP_LEVEL_SECTION();
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV1MaterialListBlock()
 {
-	AI_ASE_PARSER_INIT();
-
-	unsigned int iMaterialCount = 0;
-	unsigned int iOldMaterialCount = (unsigned int)m_vMaterials.size();
-	while (true)
-	{
-		if ('*' == *filePtr)
-		{
-			++filePtr;
-			if (TokenMatch(filePtr,"MATERIAL_COUNT",14))
-			{
-				ParseLV4MeshLong(iMaterialCount);
-
-				// now allocate enough storage to hold all materials
-				m_vMaterials.resize(iOldMaterialCount+iMaterialCount);
-				continue;
-			}
-			if (TokenMatch(filePtr,"MATERIAL",8))
-			{
-				unsigned int iIndex = 0;
-				ParseLV4MeshLong(iIndex);
-
-				if (iIndex >= iMaterialCount)
-				{
-					LogWarning("Out of range: material index is too large");
-					iIndex = iMaterialCount-1;
-				}
-
-				// get a reference to the material
-				Material& sMat = m_vMaterials[iIndex+iOldMaterialCount];
-				// parse the material block
-				ParseLV2MaterialBlock(sMat);
-				continue;
-			}
-		}
-		AI_ASE_HANDLE_TOP_LEVEL_SECTION();
-	}
+    AI_ASE_PARSER_INIT();
+
+    unsigned int iMaterialCount = 0;
+    unsigned int iOldMaterialCount = (unsigned int)m_vMaterials.size();
+    while (true)
+    {
+        if ('*' == *filePtr)
+        {
+            ++filePtr;
+            if (TokenMatch(filePtr,"MATERIAL_COUNT",14))
+            {
+                ParseLV4MeshLong(iMaterialCount);
+
+                // now allocate enough storage to hold all materials
+                m_vMaterials.resize(iOldMaterialCount+iMaterialCount);
+                continue;
+            }
+            if (TokenMatch(filePtr,"MATERIAL",8))
+            {
+                unsigned int iIndex = 0;
+                ParseLV4MeshLong(iIndex);
+
+                if (iIndex >= iMaterialCount)
+                {
+                    LogWarning("Out of range: material index is too large");
+                    iIndex = iMaterialCount-1;
+                }
+
+                // get a reference to the material
+                Material& sMat = m_vMaterials[iIndex+iOldMaterialCount];
+                // parse the material block
+                ParseLV2MaterialBlock(sMat);
+                continue;
+            }
+        }
+        AI_ASE_HANDLE_TOP_LEVEL_SECTION();
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV2MaterialBlock(ASE::Material& mat)
 {
-	AI_ASE_PARSER_INIT();
-
-	unsigned int iNumSubMaterials = 0;
-	while (true)
-	{
-		if ('*' == *filePtr)
-		{
-			++filePtr;
-			if (TokenMatch(filePtr,"MATERIAL_NAME",13))
-			{
-				if (!ParseString(mat.mName,"*MATERIAL_NAME"))
-					SkipToNextToken();
-				continue;
-			}
-			// ambient material color
-			if (TokenMatch(filePtr,"MATERIAL_AMBIENT",16))
-			{
-				ParseLV4MeshFloatTriple(&mat.mAmbient.r);
-				continue;
-			}
-			// diffuse material color
-			if (TokenMatch(filePtr,"MATERIAL_DIFFUSE",16) )
-			{
-				ParseLV4MeshFloatTriple(&mat.mDiffuse.r);
-				continue;
-			}
-			// specular material color
-			if (TokenMatch(filePtr,"MATERIAL_SPECULAR",17))
-			{
-				ParseLV4MeshFloatTriple(&mat.mSpecular.r);
-				continue;
-			}
-			// material shading type
-			if (TokenMatch(filePtr,"MATERIAL_SHADING",16))
-			{
-				if (TokenMatch(filePtr,"Blinn",5))
-				{
-					mat.mShading = Discreet3DS::Blinn;
-				}
-				else if (TokenMatch(filePtr,"Phong",5))
-				{
-					mat.mShading = Discreet3DS::Phong;
-				}
-				else if (TokenMatch(filePtr,"Flat",4))
-				{
-					mat.mShading = Discreet3DS::Flat;
-				}
-				else if (TokenMatch(filePtr,"Wire",4))
-				{
-					mat.mShading = Discreet3DS::Wire;
-				}
-				else
-				{
-					// assume gouraud shading
-					mat.mShading = Discreet3DS::Gouraud;
-					SkipToNextToken();
-				}
-				continue;
-			}
-			// material transparency
-			if (TokenMatch(filePtr,"MATERIAL_TRANSPARENCY",21))
-			{
-				ParseLV4MeshFloat(mat.mTransparency);
-				mat.mTransparency = 1.0f - mat.mTransparency;continue;
-			}
-			// material self illumination
-			if (TokenMatch(filePtr,"MATERIAL_SELFILLUM",18))
-			{
-				float f = 0.0f;
-				ParseLV4MeshFloat(f);
-
-				mat.mEmissive.r = f;
-				mat.mEmissive.g = f;
-				mat.mEmissive.b = f;
-				continue;
-			}
-			// material shininess
-			if (TokenMatch(filePtr,"MATERIAL_SHINE",14) )
-			{
-				ParseLV4MeshFloat(mat.mSpecularExponent);
-				mat.mSpecularExponent *= 15;
-				continue;
-			}
-			// two-sided material
-			if (TokenMatch(filePtr,"MATERIAL_TWOSIDED",17) )
-			{
-				mat.mTwoSided = true;
-				continue;
-			}
-			// material shininess strength
-			if (TokenMatch(filePtr,"MATERIAL_SHINESTRENGTH",22))
-			{
-				ParseLV4MeshFloat(mat.mShininessStrength);
-				continue;
-			}
-			// diffuse color map
-			if (TokenMatch(filePtr,"MAP_DIFFUSE",11))
-			{
-				// parse the texture block
-				ParseLV3MapBlock(mat.sTexDiffuse);
-				continue;
-			}
-			// ambient color map
-			if (TokenMatch(filePtr,"MAP_AMBIENT",11))
-			{
-				// parse the texture block
-				ParseLV3MapBlock(mat.sTexAmbient);
-				continue;
-			}
-			// specular color map
-			if (TokenMatch(filePtr,"MAP_SPECULAR",12))
-			{
-				// parse the texture block
-				ParseLV3MapBlock(mat.sTexSpecular);
-				continue;
-			}
-			// opacity map
-			if (TokenMatch(filePtr,"MAP_OPACITY",11))
-			{
-				// parse the texture block
-				ParseLV3MapBlock(mat.sTexOpacity);
-				continue;
-			}
-			// emissive map
-			if (TokenMatch(filePtr,"MAP_SELFILLUM",13))
-			{
-				// parse the texture block
-				ParseLV3MapBlock(mat.sTexEmissive);
-				continue;
-			}
-			// bump map
-			if (TokenMatch(filePtr,"MAP_BUMP",8))
-			{
-				// parse the texture block
-				ParseLV3MapBlock(mat.sTexBump);
-			}
-			// specular/shininess map
-			if (TokenMatch(filePtr,"MAP_SHINESTRENGTH",17))
-			{
-				// parse the texture block
-				ParseLV3MapBlock(mat.sTexShininess);
-				continue;
-			}
-			// number of submaterials
-			if (TokenMatch(filePtr,"NUMSUBMTLS",10))
-			{
-				ParseLV4MeshLong(iNumSubMaterials);
-
-				// allocate enough storage
-				mat.avSubMaterials.resize(iNumSubMaterials);
-			}
-			// submaterial chunks
-			if (TokenMatch(filePtr,"SUBMATERIAL",11))
-			{
-			
-				unsigned int iIndex = 0;
-				ParseLV4MeshLong(iIndex);
-
-				if (iIndex >= iNumSubMaterials)
-				{
-					LogWarning("Out of range: submaterial index is too large");
-					iIndex = iNumSubMaterials-1;
-				}
-
-				// get a reference to the material
-				Material& sMat = mat.avSubMaterials[iIndex];
-
-				// parse the material block
-				ParseLV2MaterialBlock(sMat);
-				continue;
-			}
-		}
-		AI_ASE_HANDLE_SECTION("2","*MATERIAL");
-	}
+    AI_ASE_PARSER_INIT();
+
+    unsigned int iNumSubMaterials = 0;
+    while (true)
+    {
+        if ('*' == *filePtr)
+        {
+            ++filePtr;
+            if (TokenMatch(filePtr,"MATERIAL_NAME",13))
+            {
+                if (!ParseString(mat.mName,"*MATERIAL_NAME"))
+                    SkipToNextToken();
+                continue;
+            }
+            // ambient material color
+            if (TokenMatch(filePtr,"MATERIAL_AMBIENT",16))
+            {
+                ParseLV4MeshFloatTriple(&mat.mAmbient.r);
+                continue;
+            }
+            // diffuse material color
+            if (TokenMatch(filePtr,"MATERIAL_DIFFUSE",16) )
+            {
+                ParseLV4MeshFloatTriple(&mat.mDiffuse.r);
+                continue;
+            }
+            // specular material color
+            if (TokenMatch(filePtr,"MATERIAL_SPECULAR",17))
+            {
+                ParseLV4MeshFloatTriple(&mat.mSpecular.r);
+                continue;
+            }
+            // material shading type
+            if (TokenMatch(filePtr,"MATERIAL_SHADING",16))
+            {
+                if (TokenMatch(filePtr,"Blinn",5))
+                {
+                    mat.mShading = Discreet3DS::Blinn;
+                }
+                else if (TokenMatch(filePtr,"Phong",5))
+                {
+                    mat.mShading = Discreet3DS::Phong;
+                }
+                else if (TokenMatch(filePtr,"Flat",4))
+                {
+                    mat.mShading = Discreet3DS::Flat;
+                }
+                else if (TokenMatch(filePtr,"Wire",4))
+                {
+                    mat.mShading = Discreet3DS::Wire;
+                }
+                else
+                {
+                    // assume gouraud shading
+                    mat.mShading = Discreet3DS::Gouraud;
+                    SkipToNextToken();
+                }
+                continue;
+            }
+            // material transparency
+            if (TokenMatch(filePtr,"MATERIAL_TRANSPARENCY",21))
+            {
+                ParseLV4MeshFloat(mat.mTransparency);
+                mat.mTransparency = 1.0f - mat.mTransparency;continue;
+            }
+            // material self illumination
+            if (TokenMatch(filePtr,"MATERIAL_SELFILLUM",18))
+            {
+                float f = 0.0f;
+                ParseLV4MeshFloat(f);
+
+                mat.mEmissive.r = f;
+                mat.mEmissive.g = f;
+                mat.mEmissive.b = f;
+                continue;
+            }
+            // material shininess
+            if (TokenMatch(filePtr,"MATERIAL_SHINE",14) )
+            {
+                ParseLV4MeshFloat(mat.mSpecularExponent);
+                mat.mSpecularExponent *= 15;
+                continue;
+            }
+            // two-sided material
+            if (TokenMatch(filePtr,"MATERIAL_TWOSIDED",17) )
+            {
+                mat.mTwoSided = true;
+                continue;
+            }
+            // material shininess strength
+            if (TokenMatch(filePtr,"MATERIAL_SHINESTRENGTH",22))
+            {
+                ParseLV4MeshFloat(mat.mShininessStrength);
+                continue;
+            }
+            // diffuse color map
+            if (TokenMatch(filePtr,"MAP_DIFFUSE",11))
+            {
+                // parse the texture block
+                ParseLV3MapBlock(mat.sTexDiffuse);
+                continue;
+            }
+            // ambient color map
+            if (TokenMatch(filePtr,"MAP_AMBIENT",11))
+            {
+                // parse the texture block
+                ParseLV3MapBlock(mat.sTexAmbient);
+                continue;
+            }
+            // specular color map
+            if (TokenMatch(filePtr,"MAP_SPECULAR",12))
+            {
+                // parse the texture block
+                ParseLV3MapBlock(mat.sTexSpecular);
+                continue;
+            }
+            // opacity map
+            if (TokenMatch(filePtr,"MAP_OPACITY",11))
+            {
+                // parse the texture block
+                ParseLV3MapBlock(mat.sTexOpacity);
+                continue;
+            }
+            // emissive map
+            if (TokenMatch(filePtr,"MAP_SELFILLUM",13))
+            {
+                // parse the texture block
+                ParseLV3MapBlock(mat.sTexEmissive);
+                continue;
+            }
+            // bump map
+            if (TokenMatch(filePtr,"MAP_BUMP",8))
+            {
+                // parse the texture block
+                ParseLV3MapBlock(mat.sTexBump);
+            }
+            // specular/shininess map
+            if (TokenMatch(filePtr,"MAP_SHINESTRENGTH",17))
+            {
+                // parse the texture block
+                ParseLV3MapBlock(mat.sTexShininess);
+                continue;
+            }
+            // number of submaterials
+            if (TokenMatch(filePtr,"NUMSUBMTLS",10))
+            {
+                ParseLV4MeshLong(iNumSubMaterials);
+
+                // allocate enough storage
+                mat.avSubMaterials.resize(iNumSubMaterials);
+            }
+            // submaterial chunks
+            if (TokenMatch(filePtr,"SUBMATERIAL",11))
+            {
+
+                unsigned int iIndex = 0;
+                ParseLV4MeshLong(iIndex);
+
+                if (iIndex >= iNumSubMaterials)
+                {
+                    LogWarning("Out of range: submaterial index is too large");
+                    iIndex = iNumSubMaterials-1;
+                }
+
+                // get a reference to the material
+                Material& sMat = mat.avSubMaterials[iIndex];
+
+                // parse the material block
+                ParseLV2MaterialBlock(sMat);
+                continue;
+            }
+        }
+        AI_ASE_HANDLE_SECTION("2","*MATERIAL");
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV3MapBlock(Texture& map)
 {
-	AI_ASE_PARSER_INIT();
-
-	// ***********************************************************
-	// *BITMAP should not be there if *MAP_CLASS is not BITMAP,
-	// but we need to expect that case ... if the path is
-	// empty the texture won't be used later.
-	// ***********************************************************
-	bool parsePath = true; 
-	while (true)
-	{
-		if ('*' == *filePtr)
-		{
-			++filePtr;
-			// type of map
-			if (TokenMatch(filePtr,"MAP_CLASS" ,9))
-			{
-				std::string temp;
-				if(!ParseString(temp,"*MAP_CLASS"))
-					SkipToNextToken();
-				if (temp != "Bitmap" && temp != "Normal Bump")
-				{
-					DefaultLogger::get()->warn("ASE: Skipping unknown map type: " + temp);
-					parsePath = false; 
-				}
-				continue;
-			}
-			// path to the texture
-			if (parsePath && TokenMatch(filePtr,"BITMAP" ,6))
-			{
-				if(!ParseString(map.mMapName,"*BITMAP"))
-					SkipToNextToken();
-
-				if (map.mMapName == "None")
-				{
-					// Files with 'None' as map name are produced by
-					// an Maja to ASE exporter which name I forgot ..
-					DefaultLogger::get()->warn("ASE: Skipping invalid map entry");
-					map.mMapName = "";
-				}
-
-				continue;
-			}
-			// offset on the u axis
-			if (TokenMatch(filePtr,"UVW_U_OFFSET" ,12))
-			{
-				ParseLV4MeshFloat(map.mOffsetU);
-				continue;
-			}
-			// offset on the v axis
-			if (TokenMatch(filePtr,"UVW_V_OFFSET" ,12))
-			{
-				ParseLV4MeshFloat(map.mOffsetV);
-				continue;
-			}
-			// tiling on the u axis
-			if (TokenMatch(filePtr,"UVW_U_TILING" ,12))
-			{
-				ParseLV4MeshFloat(map.mScaleU);
-				continue;
-			}
-			// tiling on the v axis
-			if (TokenMatch(filePtr,"UVW_V_TILING" ,12))
-			{
-				ParseLV4MeshFloat(map.mScaleV);
-				continue;
-			}
-			// rotation around the z-axis
-			if (TokenMatch(filePtr,"UVW_ANGLE" ,9))
-			{
-				ParseLV4MeshFloat(map.mRotation);
-				continue;
-			}
-			// map blending factor
-			if (TokenMatch(filePtr,"MAP_AMOUNT" ,10))
-			{
-				ParseLV4MeshFloat(map.mTextureBlend);
-				continue;
-			}
-		}
-		AI_ASE_HANDLE_SECTION("3","*MAP_XXXXXX");
-	}
-	return;
+    AI_ASE_PARSER_INIT();
+
+    // ***********************************************************
+    // *BITMAP should not be there if *MAP_CLASS is not BITMAP,
+    // but we need to expect that case ... if the path is
+    // empty the texture won't be used later.
+    // ***********************************************************
+    bool parsePath = true;
+    while (true)
+    {
+        if ('*' == *filePtr)
+        {
+            ++filePtr;
+            // type of map
+            if (TokenMatch(filePtr,"MAP_CLASS" ,9))
+            {
+                std::string temp;
+                if(!ParseString(temp,"*MAP_CLASS"))
+                    SkipToNextToken();
+                if (temp != "Bitmap" && temp != "Normal Bump")
+                {
+                    DefaultLogger::get()->warn("ASE: Skipping unknown map type: " + temp);
+                    parsePath = false;
+                }
+                continue;
+            }
+            // path to the texture
+            if (parsePath && TokenMatch(filePtr,"BITMAP" ,6))
+            {
+                if(!ParseString(map.mMapName,"*BITMAP"))
+                    SkipToNextToken();
+
+                if (map.mMapName == "None")
+                {
+                    // Files with 'None' as map name are produced by
+                    // an Maja to ASE exporter which name I forgot ..
+                    DefaultLogger::get()->warn("ASE: Skipping invalid map entry");
+                    map.mMapName = "";
+                }
+
+                continue;
+            }
+            // offset on the u axis
+            if (TokenMatch(filePtr,"UVW_U_OFFSET" ,12))
+            {
+                ParseLV4MeshFloat(map.mOffsetU);
+                continue;
+            }
+            // offset on the v axis
+            if (TokenMatch(filePtr,"UVW_V_OFFSET" ,12))
+            {
+                ParseLV4MeshFloat(map.mOffsetV);
+                continue;
+            }
+            // tiling on the u axis
+            if (TokenMatch(filePtr,"UVW_U_TILING" ,12))
+            {
+                ParseLV4MeshFloat(map.mScaleU);
+                continue;
+            }
+            // tiling on the v axis
+            if (TokenMatch(filePtr,"UVW_V_TILING" ,12))
+            {
+                ParseLV4MeshFloat(map.mScaleV);
+                continue;
+            }
+            // rotation around the z-axis
+            if (TokenMatch(filePtr,"UVW_ANGLE" ,9))
+            {
+                ParseLV4MeshFloat(map.mRotation);
+                continue;
+            }
+            // map blending factor
+            if (TokenMatch(filePtr,"MAP_AMOUNT" ,10))
+            {
+                ParseLV4MeshFloat(map.mTextureBlend);
+                continue;
+            }
+        }
+        AI_ASE_HANDLE_SECTION("3","*MAP_XXXXXX");
+    }
+    return;
 }
 
 // ------------------------------------------------------------------------------------------------
 bool Parser::ParseString(std::string& out,const char* szName)
 {
-	char szBuffer[1024];
-	if (!SkipSpaces(&filePtr))
-	{
-
-		sprintf(szBuffer,"Unable to parse %s block: Unexpected EOL",szName);
-		LogWarning(szBuffer);
-		return false;
-	}
-	// there must be '"'
-	if ('\"' != *filePtr)
-	{
-
-		sprintf(szBuffer,"Unable to parse %s block: Strings are expected "
-			"to be enclosed in double quotation marks",szName);
-		LogWarning(szBuffer);
-		return false;
-	}
-	++filePtr;
-	const char* sz = filePtr;
-	while (true)
-	{
-		if ('\"' == *sz)break;
-		else if ('\0' == *sz)
-		{			
-			sprintf(szBuffer,"Unable to parse %s block: Strings are expected to "
-				"be enclosed in double quotation marks but EOF was reached before "
-				"a closing quotation mark was encountered",szName);
-			LogWarning(szBuffer);
-			return false;
-		}
-		sz++;
-	}
-	out = std::string(filePtr,(uintptr_t)sz-(uintptr_t)filePtr);
-	filePtr = sz+1;
-	return true;
+    char szBuffer[1024];
+    if (!SkipSpaces(&filePtr))
+    {
+
+        sprintf(szBuffer,"Unable to parse %s block: Unexpected EOL",szName);
+        LogWarning(szBuffer);
+        return false;
+    }
+    // there must be '"'
+    if ('\"' != *filePtr)
+    {
+
+        sprintf(szBuffer,"Unable to parse %s block: Strings are expected "
+            "to be enclosed in double quotation marks",szName);
+        LogWarning(szBuffer);
+        return false;
+    }
+    ++filePtr;
+    const char* sz = filePtr;
+    while (true)
+    {
+        if ('\"' == *sz)break;
+        else if ('\0' == *sz)
+        {
+            sprintf(szBuffer,"Unable to parse %s block: Strings are expected to "
+                "be enclosed in double quotation marks but EOF was reached before "
+                "a closing quotation mark was encountered",szName);
+            LogWarning(szBuffer);
+            return false;
+        }
+        sz++;
+    }
+    out = std::string(filePtr,(uintptr_t)sz-(uintptr_t)filePtr);
+    filePtr = sz+1;
+    return true;
 }
 
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV1ObjectBlock(ASE::BaseNode& node)
 {
-	AI_ASE_PARSER_INIT();
-	while (true)
-	{
-		if ('*' == *filePtr)
-		{
-			++filePtr;
-
-			// first process common tokens such as node name and transform
-			// name of the mesh/node
-			if (TokenMatch(filePtr,"NODE_NAME" ,9))
-			{
-				if(!ParseString(node.mName,"*NODE_NAME"))
-					SkipToNextToken();
-				continue;
-			}
-			// name of the parent of the node
-			if (TokenMatch(filePtr,"NODE_PARENT" ,11) )
-			{
-				if(!ParseString(node.mParent,"*NODE_PARENT"))
-					SkipToNextToken();
-				continue;
-			}
-			// transformation matrix of the node
-			if (TokenMatch(filePtr,"NODE_TM" ,7))
-			{
-				ParseLV2NodeTransformBlock(node);
-				continue;
-			}
-			// animation data of the node
-			if (TokenMatch(filePtr,"TM_ANIMATION" ,12))
-			{
-				ParseLV2AnimationBlock(node);
-				continue;
-			}
-
-			if (node.mType == BaseNode::Light)
-			{
-				// light settings
-				if (TokenMatch(filePtr,"LIGHT_SETTINGS" ,14))
-				{
-					ParseLV2LightSettingsBlock((ASE::Light&)node);
-					continue;
-				}
-				// type of the light source
-				if (TokenMatch(filePtr,"LIGHT_TYPE" ,10))
-				{
-					if (!ASSIMP_strincmp("omni",filePtr,4))
-					{
-						((ASE::Light&)node).mLightType = ASE::Light::OMNI;
-					}
-					else if (!ASSIMP_strincmp("target",filePtr,6))
-					{
-						((ASE::Light&)node).mLightType = ASE::Light::TARGET;
-					}
-					else if (!ASSIMP_strincmp("free",filePtr,4))
-					{
-						((ASE::Light&)node).mLightType = ASE::Light::FREE;
-					}
-					else if (!ASSIMP_strincmp("directional",filePtr,11))
-					{
-						((ASE::Light&)node).mLightType = ASE::Light::DIRECTIONAL;
-					}
-					else
-					{
-						LogWarning("Unknown kind of light source");
-					}
-					continue;
-				}
-			}
-			else if (node.mType == BaseNode::Camera)
-			{
-				// Camera settings
-				if (TokenMatch(filePtr,"CAMERA_SETTINGS" ,15))
-				{
-					ParseLV2CameraSettingsBlock((ASE::Camera&)node);
-					continue;
-				}
-				else if (TokenMatch(filePtr,"CAMERA_TYPE" ,11))
-				{
-					if (!ASSIMP_strincmp("target",filePtr,6))
-					{
-						((ASE::Camera&)node).mCameraType = ASE::Camera::TARGET;
-					}
-					else if (!ASSIMP_strincmp("free",filePtr,4))
-					{
-						((ASE::Camera&)node).mCameraType = ASE::Camera::FREE;
-					}
-					else
-					{
-						LogWarning("Unknown kind of camera");
-					}
-					continue;
-				}
-			}
-			else if (node.mType == BaseNode::Mesh)
-			{
-				// mesh data
-				// FIX: Older files use MESH_SOFTSKIN
-				if (TokenMatch(filePtr,"MESH" ,4) || 
-					TokenMatch(filePtr,"MESH_SOFTSKIN",13))
-				{
-					ParseLV2MeshBlock((ASE::Mesh&)node);
-					continue;
-				}
-				// mesh material index
-				if (TokenMatch(filePtr,"MATERIAL_REF" ,12))
-				{
-					ParseLV4MeshLong(((ASE::Mesh&)node).iMaterialIndex);
-					continue;
-				}
-			}
-		}
-		AI_ASE_HANDLE_TOP_LEVEL_SECTION();
-	}
-	return;
+    AI_ASE_PARSER_INIT();
+    while (true)
+    {
+        if ('*' == *filePtr)
+        {
+            ++filePtr;
+
+            // first process common tokens such as node name and transform
+            // name of the mesh/node
+            if (TokenMatch(filePtr,"NODE_NAME" ,9))
+            {
+                if(!ParseString(node.mName,"*NODE_NAME"))
+                    SkipToNextToken();
+                continue;
+            }
+            // name of the parent of the node
+            if (TokenMatch(filePtr,"NODE_PARENT" ,11) )
+            {
+                if(!ParseString(node.mParent,"*NODE_PARENT"))
+                    SkipToNextToken();
+                continue;
+            }
+            // transformation matrix of the node
+            if (TokenMatch(filePtr,"NODE_TM" ,7))
+            {
+                ParseLV2NodeTransformBlock(node);
+                continue;
+            }
+            // animation data of the node
+            if (TokenMatch(filePtr,"TM_ANIMATION" ,12))
+            {
+                ParseLV2AnimationBlock(node);
+                continue;
+            }
+
+            if (node.mType == BaseNode::Light)
+            {
+                // light settings
+                if (TokenMatch(filePtr,"LIGHT_SETTINGS" ,14))
+                {
+                    ParseLV2LightSettingsBlock((ASE::Light&)node);
+                    continue;
+                }
+                // type of the light source
+                if (TokenMatch(filePtr,"LIGHT_TYPE" ,10))
+                {
+                    if (!ASSIMP_strincmp("omni",filePtr,4))
+                    {
+                        ((ASE::Light&)node).mLightType = ASE::Light::OMNI;
+                    }
+                    else if (!ASSIMP_strincmp("target",filePtr,6))
+                    {
+                        ((ASE::Light&)node).mLightType = ASE::Light::TARGET;
+                    }
+                    else if (!ASSIMP_strincmp("free",filePtr,4))
+                    {
+                        ((ASE::Light&)node).mLightType = ASE::Light::FREE;
+                    }
+                    else if (!ASSIMP_strincmp("directional",filePtr,11))
+                    {
+                        ((ASE::Light&)node).mLightType = ASE::Light::DIRECTIONAL;
+                    }
+                    else
+                    {
+                        LogWarning("Unknown kind of light source");
+                    }
+                    continue;
+                }
+            }
+            else if (node.mType == BaseNode::Camera)
+            {
+                // Camera settings
+                if (TokenMatch(filePtr,"CAMERA_SETTINGS" ,15))
+                {
+                    ParseLV2CameraSettingsBlock((ASE::Camera&)node);
+                    continue;
+                }
+                else if (TokenMatch(filePtr,"CAMERA_TYPE" ,11))
+                {
+                    if (!ASSIMP_strincmp("target",filePtr,6))
+                    {
+                        ((ASE::Camera&)node).mCameraType = ASE::Camera::TARGET;
+                    }
+                    else if (!ASSIMP_strincmp("free",filePtr,4))
+                    {
+                        ((ASE::Camera&)node).mCameraType = ASE::Camera::FREE;
+                    }
+                    else
+                    {
+                        LogWarning("Unknown kind of camera");
+                    }
+                    continue;
+                }
+            }
+            else if (node.mType == BaseNode::Mesh)
+            {
+                // mesh data
+                // FIX: Older files use MESH_SOFTSKIN
+                if (TokenMatch(filePtr,"MESH" ,4) ||
+                    TokenMatch(filePtr,"MESH_SOFTSKIN",13))
+                {
+                    ParseLV2MeshBlock((ASE::Mesh&)node);
+                    continue;
+                }
+                // mesh material index
+                if (TokenMatch(filePtr,"MATERIAL_REF" ,12))
+                {
+                    ParseLV4MeshLong(((ASE::Mesh&)node).iMaterialIndex);
+                    continue;
+                }
+            }
+        }
+        AI_ASE_HANDLE_TOP_LEVEL_SECTION();
+    }
+    return;
 }
 
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV2CameraSettingsBlock(ASE::Camera& camera)
 {
-	AI_ASE_PARSER_INIT();
-	while (true)
-	{
-		if ('*' == *filePtr)
-		{
-			++filePtr;
-			if (TokenMatch(filePtr,"CAMERA_NEAR" ,11))
-			{
-				ParseLV4MeshFloat(camera.mNear);
-				continue;
-			}
-			if (TokenMatch(filePtr,"CAMERA_FAR" ,10))
-			{
-				ParseLV4MeshFloat(camera.mFar);
-				continue;
-			}
-			if (TokenMatch(filePtr,"CAMERA_FOV" ,10))
-			{
-				ParseLV4MeshFloat(camera.mFOV);
-				continue;
-			}
-		}
-		AI_ASE_HANDLE_SECTION("2","CAMERA_SETTINGS");
-	}
-	return;
+    AI_ASE_PARSER_INIT();
+    while (true)
+    {
+        if ('*' == *filePtr)
+        {
+            ++filePtr;
+            if (TokenMatch(filePtr,"CAMERA_NEAR" ,11))
+            {
+                ParseLV4MeshFloat(camera.mNear);
+                continue;
+            }
+            if (TokenMatch(filePtr,"CAMERA_FAR" ,10))
+            {
+                ParseLV4MeshFloat(camera.mFar);
+                continue;
+            }
+            if (TokenMatch(filePtr,"CAMERA_FOV" ,10))
+            {
+                ParseLV4MeshFloat(camera.mFOV);
+                continue;
+            }
+        }
+        AI_ASE_HANDLE_SECTION("2","CAMERA_SETTINGS");
+    }
+    return;
 }
 
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV2LightSettingsBlock(ASE::Light& light)
 {
-	AI_ASE_PARSER_INIT();
-	while (true)
-	{
-		if ('*' == *filePtr)
-		{
-			++filePtr;
-			if (TokenMatch(filePtr,"LIGHT_COLOR" ,11))
-			{
-				ParseLV4MeshFloatTriple(&light.mColor.r);
-				continue;
-			}
-			if (TokenMatch(filePtr,"LIGHT_INTENS" ,12))
-			{
-				ParseLV4MeshFloat(light.mIntensity);
-				continue;
-			}
-			if (TokenMatch(filePtr,"LIGHT_HOTSPOT" ,13))
-			{
-				ParseLV4MeshFloat(light.mAngle);
-				continue;
-			}
-			if (TokenMatch(filePtr,"LIGHT_FALLOFF" ,13))
-			{
-				ParseLV4MeshFloat(light.mFalloff);
-				continue;
-			}
-		}
-		AI_ASE_HANDLE_SECTION("2","LIGHT_SETTINGS");
-	}
-	return;
+    AI_ASE_PARSER_INIT();
+    while (true)
+    {
+        if ('*' == *filePtr)
+        {
+            ++filePtr;
+            if (TokenMatch(filePtr,"LIGHT_COLOR" ,11))
+            {
+                ParseLV4MeshFloatTriple(&light.mColor.r);
+                continue;
+            }
+            if (TokenMatch(filePtr,"LIGHT_INTENS" ,12))
+            {
+                ParseLV4MeshFloat(light.mIntensity);
+                continue;
+            }
+            if (TokenMatch(filePtr,"LIGHT_HOTSPOT" ,13))
+            {
+                ParseLV4MeshFloat(light.mAngle);
+                continue;
+            }
+            if (TokenMatch(filePtr,"LIGHT_FALLOFF" ,13))
+            {
+                ParseLV4MeshFloat(light.mFalloff);
+                continue;
+            }
+        }
+        AI_ASE_HANDLE_SECTION("2","LIGHT_SETTINGS");
+    }
+    return;
 }
 
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV2AnimationBlock(ASE::BaseNode& mesh)
 {
-	AI_ASE_PARSER_INIT();
-
-	ASE::Animation* anim = &mesh.mAnim;
-	while (true)
-	{
-		if ('*' == *filePtr)
-		{
-			++filePtr;
-			if (TokenMatch(filePtr,"NODE_NAME" ,9))
-			{
-				std::string temp;
-				if(!ParseString(temp,"*NODE_NAME"))
-					SkipToNextToken();
-
-				// If the name of the node contains .target it 
-				// represents an animated camera or spot light
-				// target.
-				if (std::string::npos != temp.find(".Target"))
-				{
-					if  ((mesh.mType != BaseNode::Camera || ((ASE::Camera&)mesh).mCameraType != ASE::Camera::TARGET)  &&
-						( mesh.mType != BaseNode::Light  || ((ASE::Light&)mesh).mLightType   != ASE::Light::TARGET))
-					{   
-
-						DefaultLogger::get()->error("ASE: Found target animation channel "
-							"but the node is neither a camera nor a spot light");
-						anim = NULL;
-					}
-					else anim = &mesh.mTargetAnim;
-				}
-				continue;
-			}
-
-			// position keyframes
-			if (TokenMatch(filePtr,"CONTROL_POS_TRACK"  ,17)  ||
-				TokenMatch(filePtr,"CONTROL_POS_BEZIER" ,18)  ||
-				TokenMatch(filePtr,"CONTROL_POS_TCB"    ,15))
-			{
-				if (!anim)SkipSection();
-				else ParseLV3PosAnimationBlock(*anim);
-				continue;
-			}
-			// scaling keyframes
-			if (TokenMatch(filePtr,"CONTROL_SCALE_TRACK"  ,19) ||
-				TokenMatch(filePtr,"CONTROL_SCALE_BEZIER" ,20) ||
-				TokenMatch(filePtr,"CONTROL_SCALE_TCB"    ,17))
-			{
-				if (!anim || anim == &mesh.mTargetAnim)
-				{
-					// Target animation channels may have no rotation channels
-					DefaultLogger::get()->error("ASE: Ignoring scaling channel in target animation");
-					SkipSection();
-				}
-				else ParseLV3ScaleAnimationBlock(*anim);
-				continue;
-			}
-			// rotation keyframes
-			if (TokenMatch(filePtr,"CONTROL_ROT_TRACK"  ,17) ||
-				TokenMatch(filePtr,"CONTROL_ROT_BEZIER" ,18) ||
-				TokenMatch(filePtr,"CONTROL_ROT_TCB"    ,15))
-			{
-				if (!anim || anim == &mesh.mTargetAnim)
-				{
-					// Target animation channels may have no rotation channels
-					DefaultLogger::get()->error("ASE: Ignoring rotation channel in target animation");
-					SkipSection();
-				}
-				else ParseLV3RotAnimationBlock(*anim);
-				continue;
-			}
-		}
-		AI_ASE_HANDLE_SECTION("2","TM_ANIMATION");
-	}
+    AI_ASE_PARSER_INIT();
+
+    ASE::Animation* anim = &mesh.mAnim;
+    while (true)
+    {
+        if ('*' == *filePtr)
+        {
+            ++filePtr;
+            if (TokenMatch(filePtr,"NODE_NAME" ,9))
+            {
+                std::string temp;
+                if(!ParseString(temp,"*NODE_NAME"))
+                    SkipToNextToken();
+
+                // If the name of the node contains .target it
+                // represents an animated camera or spot light
+                // target.
+                if (std::string::npos != temp.find(".Target"))
+                {
+                    if  ((mesh.mType != BaseNode::Camera || ((ASE::Camera&)mesh).mCameraType != ASE::Camera::TARGET)  &&
+                        ( mesh.mType != BaseNode::Light  || ((ASE::Light&)mesh).mLightType   != ASE::Light::TARGET))
+                    {
+
+                        DefaultLogger::get()->error("ASE: Found target animation channel "
+                            "but the node is neither a camera nor a spot light");
+                        anim = NULL;
+                    }
+                    else anim = &mesh.mTargetAnim;
+                }
+                continue;
+            }
+
+            // position keyframes
+            if (TokenMatch(filePtr,"CONTROL_POS_TRACK"  ,17)  ||
+                TokenMatch(filePtr,"CONTROL_POS_BEZIER" ,18)  ||
+                TokenMatch(filePtr,"CONTROL_POS_TCB"    ,15))
+            {
+                if (!anim)SkipSection();
+                else ParseLV3PosAnimationBlock(*anim);
+                continue;
+            }
+            // scaling keyframes
+            if (TokenMatch(filePtr,"CONTROL_SCALE_TRACK"  ,19) ||
+                TokenMatch(filePtr,"CONTROL_SCALE_BEZIER" ,20) ||
+                TokenMatch(filePtr,"CONTROL_SCALE_TCB"    ,17))
+            {
+                if (!anim || anim == &mesh.mTargetAnim)
+                {
+                    // Target animation channels may have no rotation channels
+                    DefaultLogger::get()->error("ASE: Ignoring scaling channel in target animation");
+                    SkipSection();
+                }
+                else ParseLV3ScaleAnimationBlock(*anim);
+                continue;
+            }
+            // rotation keyframes
+            if (TokenMatch(filePtr,"CONTROL_ROT_TRACK"  ,17) ||
+                TokenMatch(filePtr,"CONTROL_ROT_BEZIER" ,18) ||
+                TokenMatch(filePtr,"CONTROL_ROT_TCB"    ,15))
+            {
+                if (!anim || anim == &mesh.mTargetAnim)
+                {
+                    // Target animation channels may have no rotation channels
+                    DefaultLogger::get()->error("ASE: Ignoring rotation channel in target animation");
+                    SkipSection();
+                }
+                else ParseLV3RotAnimationBlock(*anim);
+                continue;
+            }
+        }
+        AI_ASE_HANDLE_SECTION("2","TM_ANIMATION");
+    }
 }
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV3ScaleAnimationBlock(ASE::Animation& anim)
 {
-	AI_ASE_PARSER_INIT();
-	unsigned int iIndex;
-
-	while (true)
-	{
-		if ('*' == *filePtr)
-		{
-			++filePtr;
-
-			bool b = false;
-
-			// For the moment we're just reading the three floats -
-			// we ignore the ádditional information for bezier's and TCBs
-
-			// simple scaling keyframe
-			if (TokenMatch(filePtr,"CONTROL_SCALE_SAMPLE" ,20))
-			{
-				b = true;
-				anim.mScalingType = ASE::Animation::TRACK;
-			}
-
-			// Bezier scaling keyframe
-			if (TokenMatch(filePtr,"CONTROL_BEZIER_SCALE_KEY" ,24))
-			{
-				b = true;
-				anim.mScalingType = ASE::Animation::BEZIER;
-			}
-			// TCB scaling keyframe
-			if (TokenMatch(filePtr,"CONTROL_TCB_SCALE_KEY" ,21))
-			{
-				b = true;
-				anim.mScalingType = ASE::Animation::TCB;
-			}
-			if (b)
-			{
-				anim.akeyScaling.push_back(aiVectorKey());
-				aiVectorKey& key = anim.akeyScaling.back();
-				ParseLV4MeshFloatTriple(&key.mValue.x,iIndex);
-				key.mTime = (double)iIndex;
-			}
-		}
-		AI_ASE_HANDLE_SECTION("3","*CONTROL_POS_TRACK");
-	}
+    AI_ASE_PARSER_INIT();
+    unsigned int iIndex;
+
+    while (true)
+    {
+        if ('*' == *filePtr)
+        {
+            ++filePtr;
+
+            bool b = false;
+
+            // For the moment we're just reading the three floats -
+            // we ignore the ádditional information for bezier's and TCBs
+
+            // simple scaling keyframe
+            if (TokenMatch(filePtr,"CONTROL_SCALE_SAMPLE" ,20))
+            {
+                b = true;
+                anim.mScalingType = ASE::Animation::TRACK;
+            }
+
+            // Bezier scaling keyframe
+            if (TokenMatch(filePtr,"CONTROL_BEZIER_SCALE_KEY" ,24))
+            {
+                b = true;
+                anim.mScalingType = ASE::Animation::BEZIER;
+            }
+            // TCB scaling keyframe
+            if (TokenMatch(filePtr,"CONTROL_TCB_SCALE_KEY" ,21))
+            {
+                b = true;
+                anim.mScalingType = ASE::Animation::TCB;
+            }
+            if (b)
+            {
+                anim.akeyScaling.push_back(aiVectorKey());
+                aiVectorKey& key = anim.akeyScaling.back();
+                ParseLV4MeshFloatTriple(&key.mValue.x,iIndex);
+                key.mTime = (double)iIndex;
+            }
+        }
+        AI_ASE_HANDLE_SECTION("3","*CONTROL_POS_TRACK");
+    }
 }
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV3PosAnimationBlock(ASE::Animation& anim)
 {
-	AI_ASE_PARSER_INIT();
-	unsigned int iIndex;
-	while (true)
-	{
-		if ('*' == *filePtr)
-		{
-			++filePtr;
-			
-			bool b = false;
-
-			// For the moment we're just reading the three floats -
-			// we ignore the ádditional information for bezier's and TCBs
-
-			// simple scaling keyframe
-			if (TokenMatch(filePtr,"CONTROL_POS_SAMPLE" ,18))
-			{
-				b = true;
-				anim.mPositionType = ASE::Animation::TRACK;
-			}
-
-			// Bezier scaling keyframe
-			if (TokenMatch(filePtr,"CONTROL_BEZIER_POS_KEY" ,22))
-			{
-				b = true;
-				anim.mPositionType = ASE::Animation::BEZIER;
-			}
-			// TCB scaling keyframe
-			if (TokenMatch(filePtr,"CONTROL_TCB_POS_KEY" ,19))
-			{
-				b = true;
-				anim.mPositionType = ASE::Animation::TCB;
-			}
-			if (b)
-			{
-				anim.akeyPositions.push_back(aiVectorKey());
-				aiVectorKey& key = anim.akeyPositions.back();
-				ParseLV4MeshFloatTriple(&key.mValue.x,iIndex);
-				key.mTime = (double)iIndex;
-			}
-		}
-		AI_ASE_HANDLE_SECTION("3","*CONTROL_POS_TRACK");
-	}
+    AI_ASE_PARSER_INIT();
+    unsigned int iIndex;
+    while (true)
+    {
+        if ('*' == *filePtr)
+        {
+            ++filePtr;
+
+            bool b = false;
+
+            // For the moment we're just reading the three floats -
+            // we ignore the ádditional information for bezier's and TCBs
+
+            // simple scaling keyframe
+            if (TokenMatch(filePtr,"CONTROL_POS_SAMPLE" ,18))
+            {
+                b = true;
+                anim.mPositionType = ASE::Animation::TRACK;
+            }
+
+            // Bezier scaling keyframe
+            if (TokenMatch(filePtr,"CONTROL_BEZIER_POS_KEY" ,22))
+            {
+                b = true;
+                anim.mPositionType = ASE::Animation::BEZIER;
+            }
+            // TCB scaling keyframe
+            if (TokenMatch(filePtr,"CONTROL_TCB_POS_KEY" ,19))
+            {
+                b = true;
+                anim.mPositionType = ASE::Animation::TCB;
+            }
+            if (b)
+            {
+                anim.akeyPositions.push_back(aiVectorKey());
+                aiVectorKey& key = anim.akeyPositions.back();
+                ParseLV4MeshFloatTriple(&key.mValue.x,iIndex);
+                key.mTime = (double)iIndex;
+            }
+        }
+        AI_ASE_HANDLE_SECTION("3","*CONTROL_POS_TRACK");
+    }
 }
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV3RotAnimationBlock(ASE::Animation& anim)
 {
-	AI_ASE_PARSER_INIT();
-	unsigned int iIndex;
-	while (true)
-	{
-		if ('*' == *filePtr)
-		{
-			++filePtr;
-
-			bool b = false;
-
-			// For the moment we're just reading the  floats -
-			// we ignore the ádditional information for bezier's and TCBs
-
-			// simple scaling keyframe
-			if (TokenMatch(filePtr,"CONTROL_ROT_SAMPLE" ,18))
-			{
-				b = true;
-				anim.mRotationType = ASE::Animation::TRACK;
-			}
-
-			// Bezier scaling keyframe
-			if (TokenMatch(filePtr,"CONTROL_BEZIER_ROT_KEY" ,22))
-			{
-				b = true;
-				anim.mRotationType = ASE::Animation::BEZIER;
-			}
-			// TCB scaling keyframe
-			if (TokenMatch(filePtr,"CONTROL_TCB_ROT_KEY" ,19))
-			{
-				b = true;
-				anim.mRotationType = ASE::Animation::TCB;
-			}
-			if (b)
-			{
-				anim.akeyRotations.push_back(aiQuatKey());
-				aiQuatKey& key = anim.akeyRotations.back();
-				aiVector3D v;float f;
-				ParseLV4MeshFloatTriple(&v.x,iIndex);
-				ParseLV4MeshFloat(f);
-				key.mTime = (double)iIndex;
-				key.mValue = aiQuaternion(v,f);
-			}
-		}
-		AI_ASE_HANDLE_SECTION("3","*CONTROL_ROT_TRACK");
-	}
+    AI_ASE_PARSER_INIT();
+    unsigned int iIndex;
+    while (true)
+    {
+        if ('*' == *filePtr)
+        {
+            ++filePtr;
+
+            bool b = false;
+
+            // For the moment we're just reading the  floats -
+            // we ignore the ádditional information for bezier's and TCBs
+
+            // simple scaling keyframe
+            if (TokenMatch(filePtr,"CONTROL_ROT_SAMPLE" ,18))
+            {
+                b = true;
+                anim.mRotationType = ASE::Animation::TRACK;
+            }
+
+            // Bezier scaling keyframe
+            if (TokenMatch(filePtr,"CONTROL_BEZIER_ROT_KEY" ,22))
+            {
+                b = true;
+                anim.mRotationType = ASE::Animation::BEZIER;
+            }
+            // TCB scaling keyframe
+            if (TokenMatch(filePtr,"CONTROL_TCB_ROT_KEY" ,19))
+            {
+                b = true;
+                anim.mRotationType = ASE::Animation::TCB;
+            }
+            if (b)
+            {
+                anim.akeyRotations.push_back(aiQuatKey());
+                aiQuatKey& key = anim.akeyRotations.back();
+                aiVector3D v;float f;
+                ParseLV4MeshFloatTriple(&v.x,iIndex);
+                ParseLV4MeshFloat(f);
+                key.mTime = (double)iIndex;
+                key.mValue = aiQuaternion(v,f);
+            }
+        }
+        AI_ASE_HANDLE_SECTION("3","*CONTROL_ROT_TRACK");
+    }
 }
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV2NodeTransformBlock(ASE::BaseNode& mesh)
 {
-	AI_ASE_PARSER_INIT();
-	int mode   = 0; 
-	while (true)
-	{
-		if ('*' == *filePtr)
-		{
-			++filePtr;
-			// name of the node
-			if (TokenMatch(filePtr,"NODE_NAME" ,9))
-			{
-				std::string temp;
-				if(!ParseString(temp,"*NODE_NAME"))
-					SkipToNextToken();
-
-				std::string::size_type s;
-				if (temp == mesh.mName)
-				{
-					mode = 1;
-				}
-				else if (std::string::npos != (s = temp.find(".Target")) &&
-					mesh.mName == temp.substr(0,s))
-				{
-					// This should be either a target light or a target camera
-					if ( (mesh.mType == BaseNode::Light &&  ((ASE::Light&)mesh) .mLightType  == ASE::Light::TARGET) ||
-						 (mesh.mType == BaseNode::Camera && ((ASE::Camera&)mesh).mCameraType == ASE::Camera::TARGET))
-					{
-						mode = 2;
-					}
-					else DefaultLogger::get()->error("ASE: Ignoring target transform, "
-						"this is no spot light or target camera");
-				}
-				else
-				{
-					DefaultLogger::get()->error("ASE: Unknown node transformation: " + temp);
-					// mode = 0
-				}
-				continue;
-			}
-			if (mode)
-			{
-				// fourth row of the transformation matrix - and also the 
-				// only information here that is interesting for targets
-				if (TokenMatch(filePtr,"TM_ROW3" ,7))
-				{
-					ParseLV4MeshFloatTriple((mode == 1 ? mesh.mTransform[3] : &mesh.mTargetPosition.x));
-					continue;
-				}
-				if (mode == 1)
-				{
-					// first row of the transformation matrix
-					if (TokenMatch(filePtr,"TM_ROW0" ,7))
-					{
-						ParseLV4MeshFloatTriple(mesh.mTransform[0]);
-						continue;
-					}
-					// second row of the transformation matrix
-					if (TokenMatch(filePtr,"TM_ROW1" ,7))
-					{
-						ParseLV4MeshFloatTriple(mesh.mTransform[1]);
-						continue;
-					}
-					// third row of the transformation matrix
-					if (TokenMatch(filePtr,"TM_ROW2" ,7))
-					{
-						ParseLV4MeshFloatTriple(mesh.mTransform[2]);
-						continue;
-					}
-					// inherited position axes
-					if (TokenMatch(filePtr,"INHERIT_POS" ,11))
-					{
-						unsigned int aiVal[3];
-						ParseLV4MeshLongTriple(aiVal);
-
-						for (unsigned int i = 0; i < 3;++i)
-							mesh.inherit.abInheritPosition[i] = aiVal[i] != 0;
-						continue;
-					}
-					// inherited rotation axes
-					if (TokenMatch(filePtr,"INHERIT_ROT" ,11))
-					{
-						unsigned int aiVal[3];
-						ParseLV4MeshLongTriple(aiVal);
-
-						for (unsigned int i = 0; i < 3;++i)
-							mesh.inherit.abInheritRotation[i] = aiVal[i] != 0;
-						continue;
-					}
-					// inherited scaling axes
-					if (TokenMatch(filePtr,"INHERIT_SCL" ,11))
-					{
-						unsigned int aiVal[3];
-						ParseLV4MeshLongTriple(aiVal);
-
-						for (unsigned int i = 0; i < 3;++i)
-							mesh.inherit.abInheritScaling[i] = aiVal[i] != 0;
-						continue;
-					}
-				}
-			}
-		}
-		AI_ASE_HANDLE_SECTION("2","*NODE_TM");
-	}
-	return;
+    AI_ASE_PARSER_INIT();
+    int mode   = 0;
+    while (true)
+    {
+        if ('*' == *filePtr)
+        {
+            ++filePtr;
+            // name of the node
+            if (TokenMatch(filePtr,"NODE_NAME" ,9))
+            {
+                std::string temp;
+                if(!ParseString(temp,"*NODE_NAME"))
+                    SkipToNextToken();
+
+                std::string::size_type s;
+                if (temp == mesh.mName)
+                {
+                    mode = 1;
+                }
+                else if (std::string::npos != (s = temp.find(".Target")) &&
+                    mesh.mName == temp.substr(0,s))
+                {
+                    // This should be either a target light or a target camera
+                    if ( (mesh.mType == BaseNode::Light &&  ((ASE::Light&)mesh) .mLightType  == ASE::Light::TARGET) ||
+                         (mesh.mType == BaseNode::Camera && ((ASE::Camera&)mesh).mCameraType == ASE::Camera::TARGET))
+                    {
+                        mode = 2;
+                    }
+                    else DefaultLogger::get()->error("ASE: Ignoring target transform, "
+                        "this is no spot light or target camera");
+                }
+                else
+                {
+                    DefaultLogger::get()->error("ASE: Unknown node transformation: " + temp);
+                    // mode = 0
+                }
+                continue;
+            }
+            if (mode)
+            {
+                // fourth row of the transformation matrix - and also the
+                // only information here that is interesting for targets
+                if (TokenMatch(filePtr,"TM_ROW3" ,7))
+                {
+                    ParseLV4MeshFloatTriple((mode == 1 ? mesh.mTransform[3] : &mesh.mTargetPosition.x));
+                    continue;
+                }
+                if (mode == 1)
+                {
+                    // first row of the transformation matrix
+                    if (TokenMatch(filePtr,"TM_ROW0" ,7))
+                    {
+                        ParseLV4MeshFloatTriple(mesh.mTransform[0]);
+                        continue;
+                    }
+                    // second row of the transformation matrix
+                    if (TokenMatch(filePtr,"TM_ROW1" ,7))
+                    {
+                        ParseLV4MeshFloatTriple(mesh.mTransform[1]);
+                        continue;
+                    }
+                    // third row of the transformation matrix
+                    if (TokenMatch(filePtr,"TM_ROW2" ,7))
+                    {
+                        ParseLV4MeshFloatTriple(mesh.mTransform[2]);
+                        continue;
+                    }
+                    // inherited position axes
+                    if (TokenMatch(filePtr,"INHERIT_POS" ,11))
+                    {
+                        unsigned int aiVal[3];
+                        ParseLV4MeshLongTriple(aiVal);
+
+                        for (unsigned int i = 0; i < 3;++i)
+                            mesh.inherit.abInheritPosition[i] = aiVal[i] != 0;
+                        continue;
+                    }
+                    // inherited rotation axes
+                    if (TokenMatch(filePtr,"INHERIT_ROT" ,11))
+                    {
+                        unsigned int aiVal[3];
+                        ParseLV4MeshLongTriple(aiVal);
+
+                        for (unsigned int i = 0; i < 3;++i)
+                            mesh.inherit.abInheritRotation[i] = aiVal[i] != 0;
+                        continue;
+                    }
+                    // inherited scaling axes
+                    if (TokenMatch(filePtr,"INHERIT_SCL" ,11))
+                    {
+                        unsigned int aiVal[3];
+                        ParseLV4MeshLongTriple(aiVal);
+
+                        for (unsigned int i = 0; i < 3;++i)
+                            mesh.inherit.abInheritScaling[i] = aiVal[i] != 0;
+                        continue;
+                    }
+                }
+            }
+        }
+        AI_ASE_HANDLE_SECTION("2","*NODE_TM");
+    }
+    return;
 }
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV2MeshBlock(ASE::Mesh& mesh)
 {
-	AI_ASE_PARSER_INIT();
-
-	unsigned int iNumVertices = 0;
-	unsigned int iNumFaces = 0;
-	unsigned int iNumTVertices = 0;
-	unsigned int iNumTFaces = 0;
-	unsigned int iNumCVertices = 0;
-	unsigned int iNumCFaces = 0;
-	while (true)
-	{
-		if ('*' == *filePtr)
-		{
-			++filePtr;
-			// Number of vertices in the mesh
-			if (TokenMatch(filePtr,"MESH_NUMVERTEX" ,14))
-			{
-				ParseLV4MeshLong(iNumVertices);
-				continue;
-			}
-			// Number of texture coordinates in the mesh
-			if (TokenMatch(filePtr,"MESH_NUMTVERTEX" ,15))
-			{
-				ParseLV4MeshLong(iNumTVertices);
-				continue;
-			}
-			// Number of vertex colors in the mesh
-			if (TokenMatch(filePtr,"MESH_NUMCVERTEX" ,15))
-			{
-				ParseLV4MeshLong(iNumCVertices);
-				continue;
-			}
-			// Number of regular faces in the mesh
-			if (TokenMatch(filePtr,"MESH_NUMFACES" ,13))
-			{
-				ParseLV4MeshLong(iNumFaces);
-				continue;
-			}
-			// Number of UVWed faces in the mesh
-			if (TokenMatch(filePtr,"MESH_NUMTVFACES" ,15))
-			{
-				ParseLV4MeshLong(iNumTFaces);
-				continue;
-			}
-			// Number of colored faces in the mesh
-			if (TokenMatch(filePtr,"MESH_NUMCVFACES" ,15))
-			{
-				ParseLV4MeshLong(iNumCFaces);
-				continue;
-			}
-			// mesh vertex list block
-			if (TokenMatch(filePtr,"MESH_VERTEX_LIST" ,16))
-			{
-				ParseLV3MeshVertexListBlock(iNumVertices,mesh);
-				continue;
-			}
-			// mesh face list block
-			if (TokenMatch(filePtr,"MESH_FACE_LIST" ,14))
-			{
-				ParseLV3MeshFaceListBlock(iNumFaces,mesh);
-				continue;
-			}
-			// mesh texture vertex list block
-			if (TokenMatch(filePtr,"MESH_TVERTLIST" ,14))
-			{
-				ParseLV3MeshTListBlock(iNumTVertices,mesh);
-				continue;
-			}
-			// mesh texture face block
-			if (TokenMatch(filePtr,"MESH_TFACELIST" ,14))
-			{
-				ParseLV3MeshTFaceListBlock(iNumTFaces,mesh);
-				continue;
-			}
-			// mesh color vertex list block
-			if (TokenMatch(filePtr,"MESH_CVERTLIST" ,14))
-			{
-				ParseLV3MeshCListBlock(iNumCVertices,mesh);
-				continue;
-			}
-			// mesh color face block
-			if (TokenMatch(filePtr,"MESH_CFACELIST" ,14))
-			{
-				ParseLV3MeshCFaceListBlock(iNumCFaces,mesh);
-				continue;
-			}
-			// mesh normals
-			if (TokenMatch(filePtr,"MESH_NORMALS" ,12))
-			{
-				ParseLV3MeshNormalListBlock(mesh);
-				continue;
-			}
-			// another mesh UV channel ...
-			if (TokenMatch(filePtr,"MESH_MAPPINGCHANNEL" ,19))
-			{
-
-				unsigned int iIndex = 0;
-				ParseLV4MeshLong(iIndex);
-
-				if (iIndex < 2)
-				{
-					LogWarning("Mapping channel has an invalid index. Skipping UV channel");
-					// skip it ...
-					SkipSection();
-				}
-				if (iIndex > AI_MAX_NUMBER_OF_TEXTURECOORDS)
-				{
-					LogWarning("Too many UV channels specified. Skipping channel ..");
-					// skip it ...
-					SkipSection();
-				}
-				else
-				{
-					// parse the mapping channel
-					ParseLV3MappingChannel(iIndex-1,mesh);
-				}
-				continue;
-			}
-			// mesh animation keyframe. Not supported
-			if (TokenMatch(filePtr,"MESH_ANIMATION" ,14))
-			{
-				
-				LogWarning("Found *MESH_ANIMATION element in ASE/ASK file. "
-					"Keyframe animation is not supported by Assimp, this element "
-					"will be ignored");
-				//SkipSection();
-				continue;
-			}
-			if (TokenMatch(filePtr,"MESH_WEIGHTS" ,12))
-			{
-				ParseLV3MeshWeightsBlock(mesh);continue;
-			}
-		}
-		AI_ASE_HANDLE_SECTION("2","*MESH");
-	}
-	return;
+    AI_ASE_PARSER_INIT();
+
+    unsigned int iNumVertices = 0;
+    unsigned int iNumFaces = 0;
+    unsigned int iNumTVertices = 0;
+    unsigned int iNumTFaces = 0;
+    unsigned int iNumCVertices = 0;
+    unsigned int iNumCFaces = 0;
+    while (true)
+    {
+        if ('*' == *filePtr)
+        {
+            ++filePtr;
+            // Number of vertices in the mesh
+            if (TokenMatch(filePtr,"MESH_NUMVERTEX" ,14))
+            {
+                ParseLV4MeshLong(iNumVertices);
+                continue;
+            }
+            // Number of texture coordinates in the mesh
+            if (TokenMatch(filePtr,"MESH_NUMTVERTEX" ,15))
+            {
+                ParseLV4MeshLong(iNumTVertices);
+                continue;
+            }
+            // Number of vertex colors in the mesh
+            if (TokenMatch(filePtr,"MESH_NUMCVERTEX" ,15))
+            {
+                ParseLV4MeshLong(iNumCVertices);
+                continue;
+            }
+            // Number of regular faces in the mesh
+            if (TokenMatch(filePtr,"MESH_NUMFACES" ,13))
+            {
+                ParseLV4MeshLong(iNumFaces);
+                continue;
+            }
+            // Number of UVWed faces in the mesh
+            if (TokenMatch(filePtr,"MESH_NUMTVFACES" ,15))
+            {
+                ParseLV4MeshLong(iNumTFaces);
+                continue;
+            }
+            // Number of colored faces in the mesh
+            if (TokenMatch(filePtr,"MESH_NUMCVFACES" ,15))
+            {
+                ParseLV4MeshLong(iNumCFaces);
+                continue;
+            }
+            // mesh vertex list block
+            if (TokenMatch(filePtr,"MESH_VERTEX_LIST" ,16))
+            {
+                ParseLV3MeshVertexListBlock(iNumVertices,mesh);
+                continue;
+            }
+            // mesh face list block
+            if (TokenMatch(filePtr,"MESH_FACE_LIST" ,14))
+            {
+                ParseLV3MeshFaceListBlock(iNumFaces,mesh);
+                continue;
+            }
+            // mesh texture vertex list block
+            if (TokenMatch(filePtr,"MESH_TVERTLIST" ,14))
+            {
+                ParseLV3MeshTListBlock(iNumTVertices,mesh);
+                continue;
+            }
+            // mesh texture face block
+            if (TokenMatch(filePtr,"MESH_TFACELIST" ,14))
+            {
+                ParseLV3MeshTFaceListBlock(iNumTFaces,mesh);
+                continue;
+            }
+            // mesh color vertex list block
+            if (TokenMatch(filePtr,"MESH_CVERTLIST" ,14))
+            {
+                ParseLV3MeshCListBlock(iNumCVertices,mesh);
+                continue;
+            }
+            // mesh color face block
+            if (TokenMatch(filePtr,"MESH_CFACELIST" ,14))
+            {
+                ParseLV3MeshCFaceListBlock(iNumCFaces,mesh);
+                continue;
+            }
+            // mesh normals
+            if (TokenMatch(filePtr,"MESH_NORMALS" ,12))
+            {
+                ParseLV3MeshNormalListBlock(mesh);
+                continue;
+            }
+            // another mesh UV channel ...
+            if (TokenMatch(filePtr,"MESH_MAPPINGCHANNEL" ,19))
+            {
+
+                unsigned int iIndex = 0;
+                ParseLV4MeshLong(iIndex);
+
+                if (iIndex < 2)
+                {
+                    LogWarning("Mapping channel has an invalid index. Skipping UV channel");
+                    // skip it ...
+                    SkipSection();
+                }
+                if (iIndex > AI_MAX_NUMBER_OF_TEXTURECOORDS)
+                {
+                    LogWarning("Too many UV channels specified. Skipping channel ..");
+                    // skip it ...
+                    SkipSection();
+                }
+                else
+                {
+                    // parse the mapping channel
+                    ParseLV3MappingChannel(iIndex-1,mesh);
+                }
+                continue;
+            }
+            // mesh animation keyframe. Not supported
+            if (TokenMatch(filePtr,"MESH_ANIMATION" ,14))
+            {
+
+                LogWarning("Found *MESH_ANIMATION element in ASE/ASK file. "
+                    "Keyframe animation is not supported by Assimp, this element "
+                    "will be ignored");
+                //SkipSection();
+                continue;
+            }
+            if (TokenMatch(filePtr,"MESH_WEIGHTS" ,12))
+            {
+                ParseLV3MeshWeightsBlock(mesh);continue;
+            }
+        }
+        AI_ASE_HANDLE_SECTION("2","*MESH");
+    }
+    return;
 }
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV3MeshWeightsBlock(ASE::Mesh& mesh)
 {
-	AI_ASE_PARSER_INIT();
-
-	unsigned int iNumVertices = 0, iNumBones = 0;
-	while (true)
-	{
-		if ('*' == *filePtr)
-		{
-			++filePtr;
-
-			// Number of bone vertices ...
-			if (TokenMatch(filePtr,"MESH_NUMVERTEX" ,14))
-			{
-				ParseLV4MeshLong(iNumVertices);
-				continue;
-			}
-			// Number of bones
-			if (TokenMatch(filePtr,"MESH_NUMBONE" ,11))
-			{
-				ParseLV4MeshLong(iNumBones);
-				continue;
-			}
-			// parse the list of bones
-			if (TokenMatch(filePtr,"MESH_BONE_LIST" ,14))
-			{
-				ParseLV4MeshBones(iNumBones,mesh);
-				continue;
-			}
-			// parse the list of bones vertices
-			if (TokenMatch(filePtr,"MESH_BONE_VERTEX_LIST" ,21) )
-			{
-				ParseLV4MeshBonesVertices(iNumVertices,mesh);
-				continue;
-			}
-		}
-		AI_ASE_HANDLE_SECTION("3","*MESH_WEIGHTS");
-	}
-	return;
+    AI_ASE_PARSER_INIT();
+
+    unsigned int iNumVertices = 0, iNumBones = 0;
+    while (true)
+    {
+        if ('*' == *filePtr)
+        {
+            ++filePtr;
+
+            // Number of bone vertices ...
+            if (TokenMatch(filePtr,"MESH_NUMVERTEX" ,14))
+            {
+                ParseLV4MeshLong(iNumVertices);
+                continue;
+            }
+            // Number of bones
+            if (TokenMatch(filePtr,"MESH_NUMBONE" ,12))
+            {
+                ParseLV4MeshLong(iNumBones);
+                continue;
+            }
+            // parse the list of bones
+            if (TokenMatch(filePtr,"MESH_BONE_LIST" ,14))
+            {
+                ParseLV4MeshBones(iNumBones,mesh);
+                continue;
+            }
+            // parse the list of bones vertices
+            if (TokenMatch(filePtr,"MESH_BONE_VERTEX_LIST" ,21) )
+            {
+                ParseLV4MeshBonesVertices(iNumVertices,mesh);
+                continue;
+            }
+        }
+        AI_ASE_HANDLE_SECTION("3","*MESH_WEIGHTS");
+    }
+    return;
 }
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV4MeshBones(unsigned int iNumBones,ASE::Mesh& mesh)
 {
-	AI_ASE_PARSER_INIT();
-	mesh.mBones.resize(iNumBones);
-	while (true)
-	{
-		if ('*' == *filePtr)
-		{
-			++filePtr;
-
-			// Mesh bone with name ...
-			if (TokenMatch(filePtr,"MESH_BONE_NAME" ,16))
-			{
-				// parse an index ...
-				if(SkipSpaces(&filePtr))
-				{
-					unsigned int iIndex = strtoul10(filePtr,&filePtr);
-					if (iIndex >= iNumBones)
-					{
-						LogWarning("Bone index is out of bounds");
-						continue;
-					}
-					if (!ParseString(mesh.mBones[iIndex].mName,"*MESH_BONE_NAME"))						
-						SkipToNextToken();
-					continue;
-				}
-			}
-		}
-		AI_ASE_HANDLE_SECTION("3","*MESH_BONE_LIST");
-	}
+    AI_ASE_PARSER_INIT();
+    mesh.mBones.resize(iNumBones);
+    while (true)
+    {
+        if ('*' == *filePtr)
+        {
+            ++filePtr;
+
+            // Mesh bone with name ...
+            if (TokenMatch(filePtr,"MESH_BONE_NAME" ,14))
+            {
+                // parse an index ...
+                if(SkipSpaces(&filePtr))
+                {
+                    unsigned int iIndex = strtoul10(filePtr,&filePtr);
+                    if (iIndex >= iNumBones)
+                    {
+                        LogWarning("Bone index is out of bounds");
+                        continue;
+                    }
+                    if (!ParseString(mesh.mBones[iIndex].mName,"*MESH_BONE_NAME"))
+                        SkipToNextToken();
+                    continue;
+                }
+            }
+        }
+        AI_ASE_HANDLE_SECTION("3","*MESH_BONE_LIST");
+    }
 }
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV4MeshBonesVertices(unsigned int iNumVertices,ASE::Mesh& mesh)
 {
-	AI_ASE_PARSER_INIT();
-	mesh.mBoneVertices.resize(iNumVertices);
-	while (true)
-	{
-		if ('*' == *filePtr)
-		{
-			++filePtr;
-
-			// Mesh bone vertex
-			if (TokenMatch(filePtr,"MESH_BONE_VERTEX" ,16))
-			{
-				// read the vertex index
-				unsigned int iIndex = strtoul10(filePtr,&filePtr);
-				if (iIndex >= mesh.mPositions.size())
-				{
-					iIndex = (unsigned int)mesh.mPositions.size()-1;
-					LogWarning("Bone vertex index is out of bounds. Using the largest valid "
-						"bone vertex index instead");
-				}
-
-				// --- ignored
-				float afVert[3];
-				ParseLV4MeshFloatTriple(afVert);
-
-				std::pair<int,float> pairOut;
-				while (true)
-				{
-					// first parse the bone index ...
-					if (!SkipSpaces(&filePtr))break;
-					pairOut.first = strtoul10(filePtr,&filePtr);
-
-					// then parse the vertex weight
-					if (!SkipSpaces(&filePtr))break;
-					filePtr = fast_atoreal_move<float>(filePtr,pairOut.second);
-
-					// -1 marks unused entries
-					if (-1 != pairOut.first)
-					{
-						mesh.mBoneVertices[iIndex].mBoneWeights.push_back(pairOut);
-					}
-				}
-				continue;
-			}
-		}
-		AI_ASE_HANDLE_SECTION("4","*MESH_BONE_VERTEX");
-	}
-	return;
+    AI_ASE_PARSER_INIT();
+    mesh.mBoneVertices.resize(iNumVertices);
+    while (true)
+    {
+        if ('*' == *filePtr)
+        {
+            ++filePtr;
+
+            // Mesh bone vertex
+            if (TokenMatch(filePtr,"MESH_BONE_VERTEX" ,16))
+            {
+                // read the vertex index
+                unsigned int iIndex = strtoul10(filePtr,&filePtr);
+                if (iIndex >= mesh.mPositions.size())
+                {
+                    iIndex = (unsigned int)mesh.mPositions.size()-1;
+                    LogWarning("Bone vertex index is out of bounds. Using the largest valid "
+                        "bone vertex index instead");
+                }
+
+                // --- ignored
+                float afVert[3];
+                ParseLV4MeshFloatTriple(afVert);
+
+                std::pair<int,float> pairOut;
+                while (true)
+                {
+                    // first parse the bone index ...
+                    if (!SkipSpaces(&filePtr))break;
+                    pairOut.first = strtoul10(filePtr,&filePtr);
+
+                    // then parse the vertex weight
+                    if (!SkipSpaces(&filePtr))break;
+                    filePtr = fast_atoreal_move<float>(filePtr,pairOut.second);
+
+                    // -1 marks unused entries
+                    if (-1 != pairOut.first)
+                    {
+                        mesh.mBoneVertices[iIndex].mBoneWeights.push_back(pairOut);
+                    }
+                }
+                continue;
+            }
+        }
+        AI_ASE_HANDLE_SECTION("4","*MESH_BONE_VERTEX");
+    }
+    return;
 }
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV3MeshVertexListBlock(
-	unsigned int iNumVertices, ASE::Mesh& mesh)
+    unsigned int iNumVertices, ASE::Mesh& mesh)
 {
-	AI_ASE_PARSER_INIT();
-
-	// allocate enough storage in the array
-	mesh.mPositions.resize(iNumVertices);
-	while (true)
-	{
-		if ('*' == *filePtr)
-		{
-			++filePtr;
-
-			// Vertex entry
-			if (TokenMatch(filePtr,"MESH_VERTEX" ,11))
-			{
-				
-				aiVector3D vTemp;
-				unsigned int iIndex;
-				ParseLV4MeshFloatTriple(&vTemp.x,iIndex);
-
-				if (iIndex >= iNumVertices)
-				{
-					LogWarning("Invalid vertex index. It will be ignored");
-				}
-				else mesh.mPositions[iIndex] = vTemp;
-				continue;
-			}
-		}
-		AI_ASE_HANDLE_SECTION("3","*MESH_VERTEX_LIST");
-	}
-	return;
+    AI_ASE_PARSER_INIT();
+
+    // allocate enough storage in the array
+    mesh.mPositions.resize(iNumVertices);
+    while (true)
+    {
+        if ('*' == *filePtr)
+        {
+            ++filePtr;
+
+            // Vertex entry
+            if (TokenMatch(filePtr,"MESH_VERTEX" ,11))
+            {
+
+                aiVector3D vTemp;
+                unsigned int iIndex;
+                ParseLV4MeshFloatTriple(&vTemp.x,iIndex);
+
+                if (iIndex >= iNumVertices)
+                {
+                    LogWarning("Invalid vertex index. It will be ignored");
+                }
+                else mesh.mPositions[iIndex] = vTemp;
+                continue;
+            }
+        }
+        AI_ASE_HANDLE_SECTION("3","*MESH_VERTEX_LIST");
+    }
+    return;
 }
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV3MeshFaceListBlock(unsigned int iNumFaces, ASE::Mesh& mesh)
 {
-	AI_ASE_PARSER_INIT();
-
-	// allocate enough storage in the face array
-	mesh.mFaces.resize(iNumFaces);
-	while (true)
-	{
-		if ('*' == *filePtr)
-		{
-			++filePtr;
-
-			// Face entry
-			if (TokenMatch(filePtr,"MESH_FACE" ,9))
-			{
-
-				ASE::Face mFace;
-				ParseLV4MeshFace(mFace);
-
-				if (mFace.iFace >= iNumFaces)
-				{
-					LogWarning("Face has an invalid index. It will be ignored");
-				}
-				else mesh.mFaces[mFace.iFace] = mFace;
-				continue;
-			}
-		}
-		AI_ASE_HANDLE_SECTION("3","*MESH_FACE_LIST");
-	}
-	return;
+    AI_ASE_PARSER_INIT();
+
+    // allocate enough storage in the face array
+    mesh.mFaces.resize(iNumFaces);
+    while (true)
+    {
+        if ('*' == *filePtr)
+        {
+            ++filePtr;
+
+            // Face entry
+            if (TokenMatch(filePtr,"MESH_FACE" ,9))
+            {
+
+                ASE::Face mFace;
+                ParseLV4MeshFace(mFace);
+
+                if (mFace.iFace >= iNumFaces)
+                {
+                    LogWarning("Face has an invalid index. It will be ignored");
+                }
+                else mesh.mFaces[mFace.iFace] = mFace;
+                continue;
+            }
+        }
+        AI_ASE_HANDLE_SECTION("3","*MESH_FACE_LIST");
+    }
+    return;
 }
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV3MeshTListBlock(unsigned int iNumVertices,
-	ASE::Mesh& mesh, unsigned int iChannel)
+    ASE::Mesh& mesh, unsigned int iChannel)
 {
-	AI_ASE_PARSER_INIT();
-
-	// allocate enough storage in the array
-	mesh.amTexCoords[iChannel].resize(iNumVertices);
-	while (true)
-	{
-		if ('*' == *filePtr)
-		{
-			++filePtr;
-
-			// Vertex entry
-			if (TokenMatch(filePtr,"MESH_TVERT" ,10))
-			{
-				aiVector3D vTemp;
-				unsigned int iIndex;
-				ParseLV4MeshFloatTriple(&vTemp.x,iIndex);
-
-				if (iIndex >= iNumVertices)
-				{
-					LogWarning("Tvertex has an invalid index. It will be ignored");
-				}
-				else mesh.amTexCoords[iChannel][iIndex] = vTemp;
-
-				if (0.0f != vTemp.z)
-				{
-					// we need 3 coordinate channels
-					mesh.mNumUVComponents[iChannel] = 3;
-				}
-				continue;
-			}
-		}
-		AI_ASE_HANDLE_SECTION("3","*MESH_TVERT_LIST");
-	}
-	return;
+    AI_ASE_PARSER_INIT();
+
+    // allocate enough storage in the array
+    mesh.amTexCoords[iChannel].resize(iNumVertices);
+    while (true)
+    {
+        if ('*' == *filePtr)
+        {
+            ++filePtr;
+
+            // Vertex entry
+            if (TokenMatch(filePtr,"MESH_TVERT" ,10))
+            {
+                aiVector3D vTemp;
+                unsigned int iIndex;
+                ParseLV4MeshFloatTriple(&vTemp.x,iIndex);
+
+                if (iIndex >= iNumVertices)
+                {
+                    LogWarning("Tvertex has an invalid index. It will be ignored");
+                }
+                else mesh.amTexCoords[iChannel][iIndex] = vTemp;
+
+                if (0.0f != vTemp.z)
+                {
+                    // we need 3 coordinate channels
+                    mesh.mNumUVComponents[iChannel] = 3;
+                }
+                continue;
+            }
+        }
+        AI_ASE_HANDLE_SECTION("3","*MESH_TVERT_LIST");
+    }
+    return;
 }
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV3MeshTFaceListBlock(unsigned int iNumFaces,
-	ASE::Mesh& mesh, unsigned int iChannel)
+    ASE::Mesh& mesh, unsigned int iChannel)
 {
-	AI_ASE_PARSER_INIT();
-	while (true)
-	{
-		if ('*' == *filePtr)
-		{
-			++filePtr;
-
-			// Face entry
-			if (TokenMatch(filePtr,"MESH_TFACE" ,10))
-			{
-				unsigned int aiValues[3];
-				unsigned int iIndex = 0;
-
-				ParseLV4MeshLongTriple(aiValues,iIndex);
-				if (iIndex >= iNumFaces || iIndex >= mesh.mFaces.size())
-				{
-					LogWarning("UV-Face has an invalid index. It will be ignored");
-				}
-				else
-				{
-					// copy UV indices
-					mesh.mFaces[iIndex].amUVIndices[iChannel][0] = aiValues[0];
-					mesh.mFaces[iIndex].amUVIndices[iChannel][1] = aiValues[1];
-					mesh.mFaces[iIndex].amUVIndices[iChannel][2] = aiValues[2];
-				}
-				continue;
-			}
-		}
-		AI_ASE_HANDLE_SECTION("3","*MESH_TFACE_LIST");
-	}
-	return;
+    AI_ASE_PARSER_INIT();
+    while (true)
+    {
+        if ('*' == *filePtr)
+        {
+            ++filePtr;
+
+            // Face entry
+            if (TokenMatch(filePtr,"MESH_TFACE" ,10))
+            {
+                unsigned int aiValues[3];
+                unsigned int iIndex = 0;
+
+                ParseLV4MeshLongTriple(aiValues,iIndex);
+                if (iIndex >= iNumFaces || iIndex >= mesh.mFaces.size())
+                {
+                    LogWarning("UV-Face has an invalid index. It will be ignored");
+                }
+                else
+                {
+                    // copy UV indices
+                    mesh.mFaces[iIndex].amUVIndices[iChannel][0] = aiValues[0];
+                    mesh.mFaces[iIndex].amUVIndices[iChannel][1] = aiValues[1];
+                    mesh.mFaces[iIndex].amUVIndices[iChannel][2] = aiValues[2];
+                }
+                continue;
+            }
+        }
+        AI_ASE_HANDLE_SECTION("3","*MESH_TFACE_LIST");
+    }
+    return;
 }
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV3MappingChannel(unsigned int iChannel, ASE::Mesh& mesh)
 {
-	AI_ASE_PARSER_INIT();
-
-	unsigned int iNumTVertices = 0;
-	unsigned int iNumTFaces = 0;
-	while (true)
-	{
-		if ('*' == *filePtr)
-		{
-			++filePtr;
-
-			// Number of texture coordinates in the mesh
-			if (TokenMatch(filePtr,"MESH_NUMTVERTEX" ,15))
-			{
-				ParseLV4MeshLong(iNumTVertices);
-				continue;
-			}
-			// Number of UVWed faces in the mesh
-			if (TokenMatch(filePtr,"MESH_NUMTVFACES" ,15))
-			{
-				ParseLV4MeshLong(iNumTFaces);
-				continue;
-			}
-			// mesh texture vertex list block
-			if (TokenMatch(filePtr,"MESH_TVERTLIST" ,14))
-			{
-				ParseLV3MeshTListBlock(iNumTVertices,mesh,iChannel);
-				continue;
-			}
-			// mesh texture face block
-			if (TokenMatch(filePtr,"MESH_TFACELIST" ,14))
-			{
-				ParseLV3MeshTFaceListBlock(iNumTFaces,mesh, iChannel);
-				continue;
-			}
-		}
-		AI_ASE_HANDLE_SECTION("3","*MESH_MAPPING_CHANNEL");
-	}
-	return;
+    AI_ASE_PARSER_INIT();
+
+    unsigned int iNumTVertices = 0;
+    unsigned int iNumTFaces = 0;
+    while (true)
+    {
+        if ('*' == *filePtr)
+        {
+            ++filePtr;
+
+            // Number of texture coordinates in the mesh
+            if (TokenMatch(filePtr,"MESH_NUMTVERTEX" ,15))
+            {
+                ParseLV4MeshLong(iNumTVertices);
+                continue;
+            }
+            // Number of UVWed faces in the mesh
+            if (TokenMatch(filePtr,"MESH_NUMTVFACES" ,15))
+            {
+                ParseLV4MeshLong(iNumTFaces);
+                continue;
+            }
+            // mesh texture vertex list block
+            if (TokenMatch(filePtr,"MESH_TVERTLIST" ,14))
+            {
+                ParseLV3MeshTListBlock(iNumTVertices,mesh,iChannel);
+                continue;
+            }
+            // mesh texture face block
+            if (TokenMatch(filePtr,"MESH_TFACELIST" ,14))
+            {
+                ParseLV3MeshTFaceListBlock(iNumTFaces,mesh, iChannel);
+                continue;
+            }
+        }
+        AI_ASE_HANDLE_SECTION("3","*MESH_MAPPING_CHANNEL");
+    }
+    return;
 }
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV3MeshCListBlock(unsigned int iNumVertices, ASE::Mesh& mesh)
 {
-	AI_ASE_PARSER_INIT();
-
-	// allocate enough storage in the array
-	mesh.mVertexColors.resize(iNumVertices);
-	while (true)
-	{
-		if ('*' == *filePtr)
-		{
-			++filePtr;
-
-			// Vertex entry
-			if (TokenMatch(filePtr,"MESH_VERTCOL" ,12))
-			{
-				aiColor4D vTemp;
-				vTemp.a = 1.0f;
-				unsigned int iIndex;
-				ParseLV4MeshFloatTriple(&vTemp.r,iIndex);
-
-				if (iIndex >= iNumVertices)
-				{
-					LogWarning("Vertex color has an invalid index. It will be ignored");
-				}
-				else mesh.mVertexColors[iIndex] = vTemp;
-				continue;
-			}
-		}
-		AI_ASE_HANDLE_SECTION("3","*MESH_CVERTEX_LIST");
-	}
-	return;
+    AI_ASE_PARSER_INIT();
+
+    // allocate enough storage in the array
+    mesh.mVertexColors.resize(iNumVertices);
+    while (true)
+    {
+        if ('*' == *filePtr)
+        {
+            ++filePtr;
+
+            // Vertex entry
+            if (TokenMatch(filePtr,"MESH_VERTCOL" ,12))
+            {
+                aiColor4D vTemp;
+                vTemp.a = 1.0f;
+                unsigned int iIndex;
+                ParseLV4MeshFloatTriple(&vTemp.r,iIndex);
+
+                if (iIndex >= iNumVertices)
+                {
+                    LogWarning("Vertex color has an invalid index. It will be ignored");
+                }
+                else mesh.mVertexColors[iIndex] = vTemp;
+                continue;
+            }
+        }
+        AI_ASE_HANDLE_SECTION("3","*MESH_CVERTEX_LIST");
+    }
+    return;
 }
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV3MeshCFaceListBlock(unsigned int iNumFaces, ASE::Mesh& mesh)
 {
-	AI_ASE_PARSER_INIT();
-	while (true)
-	{
-		if ('*' == *filePtr)
-		{
-			++filePtr;
-
-			// Face entry
-			if (TokenMatch(filePtr,"MESH_CFACE" ,11))
-			{
-				unsigned int aiValues[3];
-				unsigned int iIndex = 0;
-
-				ParseLV4MeshLongTriple(aiValues,iIndex);
-				if (iIndex >= iNumFaces || iIndex >= mesh.mFaces.size())
-				{
-					LogWarning("UV-Face has an invalid index. It will be ignored");
-				}
-				else
-				{
-					// copy color indices
-					mesh.mFaces[iIndex].mColorIndices[0] = aiValues[0];
-					mesh.mFaces[iIndex].mColorIndices[1] = aiValues[1];
-					mesh.mFaces[iIndex].mColorIndices[2] = aiValues[2];
-				}
-				continue;
-			}
-		}
-		AI_ASE_HANDLE_SECTION("3","*MESH_CFACE_LIST");
-	}
-	return;
+    AI_ASE_PARSER_INIT();
+    while (true)
+    {
+        if ('*' == *filePtr)
+        {
+            ++filePtr;
+
+            // Face entry
+            if (TokenMatch(filePtr,"MESH_CFACE" ,11))
+            {
+                unsigned int aiValues[3];
+                unsigned int iIndex = 0;
+
+                ParseLV4MeshLongTriple(aiValues,iIndex);
+                if (iIndex >= iNumFaces || iIndex >= mesh.mFaces.size())
+                {
+                    LogWarning("UV-Face has an invalid index. It will be ignored");
+                }
+                else
+                {
+                    // copy color indices
+                    mesh.mFaces[iIndex].mColorIndices[0] = aiValues[0];
+                    mesh.mFaces[iIndex].mColorIndices[1] = aiValues[1];
+                    mesh.mFaces[iIndex].mColorIndices[2] = aiValues[2];
+                }
+                continue;
+            }
+        }
+        AI_ASE_HANDLE_SECTION("3","*MESH_CFACE_LIST");
+    }
+    return;
 }
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh)
 {
-	AI_ASE_PARSER_INIT();
-
-	// Allocate enough storage for the normals
-	sMesh.mNormals.resize(sMesh.mFaces.size()*3,aiVector3D( 0.f, 0.f, 0.f ));
-	unsigned int index, faceIdx = UINT_MAX;
-
-	// FIXME: rewrite this and find out how to interpret the normals
-	// correctly. This is crap.
-
-	// Smooth the vertex and face normals together. The result
-	// will be edgy then, but otherwise everything would be soft ...
-	while (true)	{
-		if ('*' == *filePtr)	{
-			++filePtr;
-			if (faceIdx != UINT_MAX && TokenMatch(filePtr,"MESH_VERTEXNORMAL",17))	{
-				aiVector3D vNormal;
-				ParseLV4MeshFloatTriple(&vNormal.x,index);
-				if (faceIdx >=  sMesh.mFaces.size())
-					continue;
-					
-				// Make sure we assign it to the correct face
-				const ASE::Face& face = sMesh.mFaces[faceIdx];
-				if (index == face.mIndices[0])
-					index = 0;
-				else if (index == face.mIndices[1])
-					index = 1;
-				else if (index == face.mIndices[2])
-					index = 2;
-				else	{
-					DefaultLogger::get()->error("ASE: Invalid vertex index in MESH_VERTEXNORMAL section");
-					continue;
-				}
-				// We'll renormalize later
-				sMesh.mNormals[faceIdx*3+index] += vNormal;
-				continue;
-			}
-			if (TokenMatch(filePtr,"MESH_FACENORMAL",15))	{
-				aiVector3D vNormal;
-				ParseLV4MeshFloatTriple(&vNormal.x,faceIdx);
-
-				if (faceIdx >= sMesh.mFaces.size())	{
-					DefaultLogger::get()->error("ASE: Invalid vertex index in MESH_FACENORMAL section");
-					continue;
-				}
-
-				// We'll renormalize later
-				sMesh.mNormals[faceIdx*3] += vNormal;
-				sMesh.mNormals[faceIdx*3+1] += vNormal;
-				sMesh.mNormals[faceIdx*3+2] += vNormal;
-				continue;
-			}
-		}
-		AI_ASE_HANDLE_SECTION("3","*MESH_NORMALS");
-	}
-	return;
+    AI_ASE_PARSER_INIT();
+
+    // Allocate enough storage for the normals
+    sMesh.mNormals.resize(sMesh.mFaces.size()*3,aiVector3D( 0.f, 0.f, 0.f ));
+    unsigned int index, faceIdx = UINT_MAX;
+
+    // FIXME: rewrite this and find out how to interpret the normals
+    // correctly. This is crap.
+
+    // Smooth the vertex and face normals together. The result
+    // will be edgy then, but otherwise everything would be soft ...
+    while (true)    {
+        if ('*' == *filePtr)    {
+            ++filePtr;
+            if (faceIdx != UINT_MAX && TokenMatch(filePtr,"MESH_VERTEXNORMAL",17))  {
+                aiVector3D vNormal;
+                ParseLV4MeshFloatTriple(&vNormal.x,index);
+                if (faceIdx >=  sMesh.mFaces.size())
+                    continue;
+
+                // Make sure we assign it to the correct face
+                const ASE::Face& face = sMesh.mFaces[faceIdx];
+                if (index == face.mIndices[0])
+                    index = 0;
+                else if (index == face.mIndices[1])
+                    index = 1;
+                else if (index == face.mIndices[2])
+                    index = 2;
+                else    {
+                    DefaultLogger::get()->error("ASE: Invalid vertex index in MESH_VERTEXNORMAL section");
+                    continue;
+                }
+                // We'll renormalize later
+                sMesh.mNormals[faceIdx*3+index] += vNormal;
+                continue;
+            }
+            if (TokenMatch(filePtr,"MESH_FACENORMAL",15))   {
+                aiVector3D vNormal;
+                ParseLV4MeshFloatTriple(&vNormal.x,faceIdx);
+
+                if (faceIdx >= sMesh.mFaces.size()) {
+                    DefaultLogger::get()->error("ASE: Invalid vertex index in MESH_FACENORMAL section");
+                    continue;
+                }
+
+                // We'll renormalize later
+                sMesh.mNormals[faceIdx*3] += vNormal;
+                sMesh.mNormals[faceIdx*3+1] += vNormal;
+                sMesh.mNormals[faceIdx*3+2] += vNormal;
+                continue;
+            }
+        }
+        AI_ASE_HANDLE_SECTION("3","*MESH_NORMALS");
+    }
+    return;
 }
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV4MeshFace(ASE::Face& out)
-{	
-	// skip spaces and tabs
-	if(!SkipSpaces(&filePtr))
-	{
-		LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL [#1]");
-		SkipToNextToken();
-		return;
-	}
-
-	// parse the face index
-	out.iFace = strtoul10(filePtr,&filePtr);
-
-	// next character should be ':'
-	if(!SkipSpaces(&filePtr))
-	{
-		// FIX: there are some ASE files which haven't got : here ....
-		LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. \':\' expected [#2]");
-		SkipToNextToken();
-		return;
-	}
-	// FIX: There are some ASE files which haven't got ':' here 
-	if(':' == *filePtr)++filePtr;
-
-	// Parse all mesh indices
-	for (unsigned int i = 0; i < 3;++i)
-	{
-		unsigned int iIndex = 0;
-		if(!SkipSpaces(&filePtr))
-		{
-			LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL");
-			SkipToNextToken();
-			return;
-		}
-		switch (*filePtr)
-		{
-		case 'A':
-		case 'a':
-			break;
-		case 'B':
-		case 'b':
-			iIndex = 1;
-			break;
-		case 'C':
-		case 'c':
-			iIndex = 2;
-			break;
-		default: 
-			LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. "
-				"A,B or C expected [#3]");
-			SkipToNextToken();
-			return;
-		};
-		++filePtr;
-
-		// next character should be ':'
-		if(!SkipSpaces(&filePtr) || ':' != *filePtr)
-		{
-			LogWarning("Unable to parse *MESH_FACE Element: "
-				"Unexpected EOL. \':\' expected [#2]");
-			SkipToNextToken();
-			return;
-		}
-
-		++filePtr;
-		if(!SkipSpaces(&filePtr))
-		{
-			LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. "
-				"Vertex index ecpected [#4]");
-			SkipToNextToken();
-			return;
-		}
-		out.mIndices[iIndex] = strtoul10(filePtr,&filePtr);
-	}
-
-	// now we need to skip the AB, BC, CA blocks. 
-	while (true)
-	{
-		if ('*' == *filePtr)break;
-		if (IsLineEnd(*filePtr))
-		{
-			//iLineNumber++;
-			return;
-		}
-		filePtr++;
-	}
-
-	// parse the smoothing group of the face
-	if (TokenMatch(filePtr,"*MESH_SMOOTHING",15))
-	{
-		if(!SkipSpaces(&filePtr))
-		{
-			LogWarning("Unable to parse *MESH_SMOOTHING Element: "
-				"Unexpected EOL. Smoothing group(s) expected [#5]");
-			SkipToNextToken();
-			return;
-		}
-		
-		// Parse smoothing groups until we don't anymore see commas
-		// FIX: There needn't always be a value, sad but true
-		while (true)
-		{
-			if (*filePtr < '9' && *filePtr >= '0')
-			{
-				out.iSmoothGroup |= (1 << strtoul10(filePtr,&filePtr));
-			}
-			SkipSpaces(&filePtr);
-			if (',' != *filePtr)
-			{
-				break;
-			}
-			++filePtr;
-			SkipSpaces(&filePtr);
-		}
-	}
-
-	// *MESH_MTLID  is optional, too
-	while (true)
-	{
-		if ('*' == *filePtr)break;
-		if (IsLineEnd(*filePtr))
-		{
-			return;
-		}
-		filePtr++;
-	}
-
-	if (TokenMatch(filePtr,"*MESH_MTLID",11))
-	{
-		if(!SkipSpaces(&filePtr))
-		{
-			LogWarning("Unable to parse *MESH_MTLID Element: Unexpected EOL. "
-				"Material index expected [#6]");
-			SkipToNextToken();
-			return;
-		}
-		out.iMaterial = strtoul10(filePtr,&filePtr);
-	}
-	return;
+{
+    // skip spaces and tabs
+    if(!SkipSpaces(&filePtr))
+    {
+        LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL [#1]");
+        SkipToNextToken();
+        return;
+    }
+
+    // parse the face index
+    out.iFace = strtoul10(filePtr,&filePtr);
+
+    // next character should be ':'
+    if(!SkipSpaces(&filePtr))
+    {
+        // FIX: there are some ASE files which haven't got : here ....
+        LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. \':\' expected [#2]");
+        SkipToNextToken();
+        return;
+    }
+    // FIX: There are some ASE files which haven't got ':' here
+    if(':' == *filePtr)++filePtr;
+
+    // Parse all mesh indices
+    for (unsigned int i = 0; i < 3;++i)
+    {
+        unsigned int iIndex = 0;
+        if(!SkipSpaces(&filePtr))
+        {
+            LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL");
+            SkipToNextToken();
+            return;
+        }
+        switch (*filePtr)
+        {
+        case 'A':
+        case 'a':
+            break;
+        case 'B':
+        case 'b':
+            iIndex = 1;
+            break;
+        case 'C':
+        case 'c':
+            iIndex = 2;
+            break;
+        default:
+            LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. "
+                "A,B or C expected [#3]");
+            SkipToNextToken();
+            return;
+        };
+        ++filePtr;
+
+        // next character should be ':'
+        if(!SkipSpaces(&filePtr) || ':' != *filePtr)
+        {
+            LogWarning("Unable to parse *MESH_FACE Element: "
+                "Unexpected EOL. \':\' expected [#2]");
+            SkipToNextToken();
+            return;
+        }
+
+        ++filePtr;
+        if(!SkipSpaces(&filePtr))
+        {
+            LogWarning("Unable to parse *MESH_FACE Element: Unexpected EOL. "
+                "Vertex index ecpected [#4]");
+            SkipToNextToken();
+            return;
+        }
+        out.mIndices[iIndex] = strtoul10(filePtr,&filePtr);
+    }
+
+    // now we need to skip the AB, BC, CA blocks.
+    while (true)
+    {
+        if ('*' == *filePtr)break;
+        if (IsLineEnd(*filePtr))
+        {
+            //iLineNumber++;
+            return;
+        }
+        filePtr++;
+    }
+
+    // parse the smoothing group of the face
+    if (TokenMatch(filePtr,"*MESH_SMOOTHING",15))
+    {
+        if(!SkipSpaces(&filePtr))
+        {
+            LogWarning("Unable to parse *MESH_SMOOTHING Element: "
+                "Unexpected EOL. Smoothing group(s) expected [#5]");
+            SkipToNextToken();
+            return;
+        }
+
+        // Parse smoothing groups until we don't anymore see commas
+        // FIX: There needn't always be a value, sad but true
+        while (true)
+        {
+            if (*filePtr < '9' && *filePtr >= '0')
+            {
+                out.iSmoothGroup |= (1 << strtoul10(filePtr,&filePtr));
+            }
+            SkipSpaces(&filePtr);
+            if (',' != *filePtr)
+            {
+                break;
+            }
+            ++filePtr;
+            SkipSpaces(&filePtr);
+        }
+    }
+
+    // *MESH_MTLID  is optional, too
+    while (true)
+    {
+        if ('*' == *filePtr)break;
+        if (IsLineEnd(*filePtr))
+        {
+            return;
+        }
+        filePtr++;
+    }
+
+    if (TokenMatch(filePtr,"*MESH_MTLID",11))
+    {
+        if(!SkipSpaces(&filePtr))
+        {
+            LogWarning("Unable to parse *MESH_MTLID Element: Unexpected EOL. "
+                "Material index expected [#6]");
+            SkipToNextToken();
+            return;
+        }
+        out.iMaterial = strtoul10(filePtr,&filePtr);
+    }
+    return;
 }
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV4MeshLongTriple(unsigned int* apOut)
 {
-	ai_assert(NULL != apOut);
+    ai_assert(NULL != apOut);
 
-	for (unsigned int i = 0; i < 3;++i)
-		ParseLV4MeshLong(apOut[i]);
+    for (unsigned int i = 0; i < 3;++i)
+        ParseLV4MeshLong(apOut[i]);
 }
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV4MeshLongTriple(unsigned int* apOut, unsigned int& rIndexOut)
 {
-	ai_assert(NULL != apOut);
+    ai_assert(NULL != apOut);
 
-	// parse the index
-	ParseLV4MeshLong(rIndexOut);
+    // parse the index
+    ParseLV4MeshLong(rIndexOut);
 
-	// parse the three others
-	ParseLV4MeshLongTriple(apOut);
+    // parse the three others
+    ParseLV4MeshLongTriple(apOut);
 }
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV4MeshFloatTriple(float* apOut, unsigned int& rIndexOut)
 {
-	ai_assert(NULL != apOut);
+    ai_assert(NULL != apOut);
+
+    // parse the index
+    ParseLV4MeshLong(rIndexOut);
 
-	// parse the index
-	ParseLV4MeshLong(rIndexOut);
-	
-	// parse the three others
-	ParseLV4MeshFloatTriple(apOut);
+    // parse the three others
+    ParseLV4MeshFloatTriple(apOut);
 }
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV4MeshFloatTriple(float* apOut)
 {
-	ai_assert(NULL != apOut);
+    ai_assert(NULL != apOut);
 
-	for (unsigned int i = 0; i < 3;++i)
-		ParseLV4MeshFloat(apOut[i]);
+    for (unsigned int i = 0; i < 3;++i)
+        ParseLV4MeshFloat(apOut[i]);
 }
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV4MeshFloat(float& fOut)
 {
-	// skip spaces and tabs
-	if(!SkipSpaces(&filePtr))
-	{
-		// LOG 
-		LogWarning("Unable to parse float: unexpected EOL [#1]");
-		fOut = 0.0f;
-		++iLineNumber;
-		return;
-	}
-	// parse the first float
-	filePtr = fast_atoreal_move<float>(filePtr,fOut);
+    // skip spaces and tabs
+    if(!SkipSpaces(&filePtr))
+    {
+        // LOG
+        LogWarning("Unable to parse float: unexpected EOL [#1]");
+        fOut = 0.0f;
+        ++iLineNumber;
+        return;
+    }
+    // parse the first float
+    filePtr = fast_atoreal_move<float>(filePtr,fOut);
 }
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV4MeshLong(unsigned int& iOut)
 {
-	// Skip spaces and tabs
-	if(!SkipSpaces(&filePtr))
-	{
-		// LOG 
-		LogWarning("Unable to parse long: unexpected EOL [#1]");
-		iOut = 0;
-		++iLineNumber;
-		return;
-	}
-	// parse the value
-	iOut = strtoul10(filePtr,&filePtr);
+    // Skip spaces and tabs
+    if(!SkipSpaces(&filePtr))
+    {
+        // LOG
+        LogWarning("Unable to parse long: unexpected EOL [#1]");
+        iOut = 0;
+        ++iLineNumber;
+        return;
+    }
+    // parse the value
+    iOut = strtoul10(filePtr,&filePtr);
 }
 
 #endif // !! ASSIMP_BUILD_NO_BASE_IMPORTER

+ 467 - 467
assimplib.mod/assimp/code/ASEParser.h

@@ -2,11 +2,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -23,16 +23,16 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -60,8 +60,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 // ASE is quite similar to 3ds. We can reuse some structures
 #include "3DSLoader.h"
 
-namespace Assimp	{
-namespace ASE	{
+namespace Assimp    {
+namespace ASE   {
 
 using namespace D3DS;
 
@@ -69,121 +69,121 @@ using namespace D3DS;
 /** Helper structure representing an ASE material */
 struct Material : public D3DS::Material
 {
-	//! Default constructor
-	Material() : pcInstance(NULL), bNeed (false)
-	{}
+    //! Default constructor
+    Material() : pcInstance(NULL), bNeed (false)
+    {}
 
-	//! Contains all sub materials of this material
-	std::vector<Material> avSubMaterials;
+    //! Contains all sub materials of this material
+    std::vector<Material> avSubMaterials;
 
-	//! aiMaterial object
-	aiMaterial* pcInstance;
+    //! aiMaterial object
+    aiMaterial* pcInstance;
 
-	//! Can we remove this material?
-	bool bNeed;
+    //! Can we remove this material?
+    bool bNeed;
 };
 
 // ---------------------------------------------------------------------------
 /** Helper structure to represent an ASE file face */
 struct Face : public FaceWithSmoothingGroup
 {
-	//! Default constructor. Initializes everything with 0
-	Face()
-	{
-		mColorIndices[0] = mColorIndices[1] = mColorIndices[2] = 0;
-		for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
-		{
-			amUVIndices[i][0] = amUVIndices[i][1] = amUVIndices[i][2] = 0;
-		}
+    //! Default constructor. Initializes everything with 0
+    Face()
+    {
+        mColorIndices[0] = mColorIndices[1] = mColorIndices[2] = 0;
+        for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
+        {
+            amUVIndices[i][0] = amUVIndices[i][1] = amUVIndices[i][2] = 0;
+        }
 
-		iMaterial = DEFAULT_MATINDEX;
-		iFace = 0;
-	}
+        iMaterial = DEFAULT_MATINDEX;
+        iFace = 0;
+    }
 
-	//! special value to indicate that no material index has
-	//! been assigned to a face. The default material index
-	//! will replace this value later.
-	static const unsigned int DEFAULT_MATINDEX = 0xFFFFFFFF;
+    //! special value to indicate that no material index has
+    //! been assigned to a face. The default material index
+    //! will replace this value later.
+    static const unsigned int DEFAULT_MATINDEX = 0xFFFFFFFF;
 
 
 
-	//! Indices into each list of texture coordinates
-	unsigned int amUVIndices[AI_MAX_NUMBER_OF_TEXTURECOORDS][3];
+    //! Indices into each list of texture coordinates
+    unsigned int amUVIndices[AI_MAX_NUMBER_OF_TEXTURECOORDS][3];
 
-	//! Index into the list of vertex colors
-	unsigned int mColorIndices[3];
+    //! Index into the list of vertex colors
+    unsigned int mColorIndices[3];
 
-	//! (Sub)Material index to be assigned to this face
-	unsigned int iMaterial;
+    //! (Sub)Material index to be assigned to this face
+    unsigned int iMaterial;
 
-	//! Index of the face. It is not specified whether it is
-	//! a requirement of the file format that all faces are
-	//! written in sequential order, so we have to expect this case
-	unsigned int iFace;
+    //! Index of the face. It is not specified whether it is
+    //! a requirement of the file format that all faces are
+    //! written in sequential order, so we have to expect this case
+    unsigned int iFace;
 };
 
 // ---------------------------------------------------------------------------
 /** Helper structure to represent an ASE file bone */
 struct Bone
 {
-	//! Constructor
-	Bone()
-	{
-		static int iCnt = 0;
-		
-		// Generate a default name for the bone
-		char szTemp[128];
-		::sprintf(szTemp,"UNNAMED_%i",iCnt++);
-		mName = szTemp;
-	}
-
-	//! Construction from an existing name
-	Bone( const std::string& name)
-		:	mName	(name)
-	{}
-
-	//! Name of the bone
-	std::string mName;
+    //! Constructor
+    Bone()
+    {
+        static int iCnt = 0;
+
+        // Generate a default name for the bone
+        char szTemp[128];
+        ::sprintf(szTemp,"UNNAMED_%i",iCnt++);
+        mName = szTemp;
+    }
+
+    //! Construction from an existing name
+    explicit Bone( const std::string& name)
+        :   mName   (name)
+    {}
+
+    //! Name of the bone
+    std::string mName;
 };
 
 // ---------------------------------------------------------------------------
 /** Helper structure to represent an ASE file bone vertex */
 struct BoneVertex
 {
-	//! Bone and corresponding vertex weight.
-	//! -1 for unrequired bones ....
-	std::vector<std::pair<int,float> > mBoneWeights;
+    //! Bone and corresponding vertex weight.
+    //! -1 for unrequired bones ....
+    std::vector<std::pair<int,float> > mBoneWeights;
 
-	//! Position of the bone vertex.
-	//! MUST be identical to the vertex position
-	//aiVector3D mPosition;
+    //! Position of the bone vertex.
+    //! MUST be identical to the vertex position
+    //aiVector3D mPosition;
 };
 
 // ---------------------------------------------------------------------------
 /** Helper structure to represent an ASE file animation */
 struct Animation
 {
-	enum Type
-	{
-		TRACK   = 0x0,
-		BEZIER  = 0x1,
-		TCB		= 0x2
-	} mRotationType, mScalingType, mPositionType;
+    enum Type
+    {
+        TRACK   = 0x0,
+        BEZIER  = 0x1,
+        TCB     = 0x2
+    } mRotationType, mScalingType, mPositionType;
 
-	Animation()
-		:	mRotationType	(TRACK)
-		,	mScalingType	(TRACK)
-		,	mPositionType	(TRACK)
-	{}
+    Animation()
+        :   mRotationType   (TRACK)
+        ,   mScalingType    (TRACK)
+        ,   mPositionType   (TRACK)
+    {}
 
-	//! List of track rotation keyframes
-	std::vector< aiQuatKey > akeyRotations;
+    //! List of track rotation keyframes
+    std::vector< aiQuatKey > akeyRotations;
 
-	//! List of track position keyframes
-	std::vector< aiVectorKey > akeyPositions;
+    //! List of track position keyframes
+    std::vector< aiVectorKey > akeyPositions;
 
-	//! List of track scaling keyframes
-	std::vector< aiVectorKey > akeyScaling;
+    //! List of track scaling keyframes
+    std::vector< aiVectorKey > akeyScaling;
 
 };
 
@@ -191,175 +191,175 @@ struct Animation
 /** Helper structure to represent the inheritance information of an ASE node */
 struct InheritanceInfo
 {
-	//! Default constructor
-	InheritanceInfo()
-	{
-		// set the inheritance flag for all axes by default to true
-		for (unsigned int i = 0; i < 3;++i)
-			abInheritPosition[i] = abInheritRotation[i] = abInheritScaling[i] = true;
-	}
-
-	//! Inherit the parent's position?, axis order is x,y,z
-	bool abInheritPosition[3];
-
-	//! Inherit the parent's rotation?, axis order is x,y,z
-	bool abInheritRotation[3];
-
-	//! Inherit the parent's scaling?, axis order is x,y,z
-	bool abInheritScaling[3];
+    //! Default constructor
+    InheritanceInfo()
+    {
+        // set the inheritance flag for all axes by default to true
+        for (unsigned int i = 0; i < 3;++i)
+            abInheritPosition[i] = abInheritRotation[i] = abInheritScaling[i] = true;
+    }
+
+    //! Inherit the parent's position?, axis order is x,y,z
+    bool abInheritPosition[3];
+
+    //! Inherit the parent's rotation?, axis order is x,y,z
+    bool abInheritRotation[3];
+
+    //! Inherit the parent's scaling?, axis order is x,y,z
+    bool abInheritScaling[3];
 };
 
 // ---------------------------------------------------------------------------
 /** Represents an ASE file node. Base class for mesh, light and cameras */
 struct BaseNode
 {
-	enum Type {Light, Camera, Mesh, Dummy} mType;
+    enum Type {Light, Camera, Mesh, Dummy} mType;
 
-	//! Constructor. Creates a default name for the node
-	BaseNode(Type _mType)
-		: mType			(_mType)
-		, mProcessed	(false)
-	{
-		// generate a default name for the  node
-		static int iCnt = 0;
-		char szTemp[128]; // should be sufficiently large
-		::sprintf(szTemp,"UNNAMED_%i",iCnt++);
-		mName = szTemp;
+    //! Constructor. Creates a default name for the node
+    explicit BaseNode(Type _mType)
+        : mType         (_mType)
+        , mProcessed    (false)
+    {
+        // generate a default name for the  node
+        static int iCnt = 0;
+        char szTemp[128]; // should be sufficiently large
+        ::sprintf(szTemp,"UNNAMED_%i",iCnt++);
+        mName = szTemp;
 
-		// Set mTargetPosition to qnan
-		const float qnan = get_qnan();
-		mTargetPosition.x = qnan;
-	}
+        // Set mTargetPosition to qnan
+        const float qnan = get_qnan();
+        mTargetPosition.x = qnan;
+    }
 
-	//! Name of the mesh
-	std::string mName;
+    //! Name of the mesh
+    std::string mName;
 
-	//! Name of the parent of the node
-	//! "" if there is no parent ...
-	std::string mParent;
+    //! Name of the parent of the node
+    //! "" if there is no parent ...
+    std::string mParent;
 
-	//! Transformation matrix of the node
-	aiMatrix4x4 mTransform;
+    //! Transformation matrix of the node
+    aiMatrix4x4 mTransform;
 
-	//! Target position (target lights and cameras)
-	aiVector3D mTargetPosition;
+    //! Target position (target lights and cameras)
+    aiVector3D mTargetPosition;
 
-	//! Specifies which axes transformations a node inherits
-	//! from its parent ...
-	InheritanceInfo inherit;
+    //! Specifies which axes transformations a node inherits
+    //! from its parent ...
+    InheritanceInfo inherit;
 
-	//! Animation channels for the node
-	Animation mAnim;
+    //! Animation channels for the node
+    Animation mAnim;
 
-	//! Needed for lights and cameras: target animation channel
-	//! Should contain position keys only.
-	Animation mTargetAnim;
+    //! Needed for lights and cameras: target animation channel
+    //! Should contain position keys only.
+    Animation mTargetAnim;
 
-	bool mProcessed;
+    bool mProcessed;
 };
 
 // ---------------------------------------------------------------------------
 /** Helper structure to represent an ASE file mesh */
 struct Mesh : public MeshWithSmoothingGroups<ASE::Face>, public BaseNode
 {
-	//! Constructor.
-	Mesh() 
-		: BaseNode	(BaseNode::Mesh)
-		, bSkip		(false)
-	{
-		// use 2 texture vertex components by default
-		for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
-			this->mNumUVComponents[c] = 2;
+    //! Constructor.
+    Mesh()
+        : BaseNode  (BaseNode::Mesh)
+        , bSkip     (false)
+    {
+        // use 2 texture vertex components by default
+        for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
+            this->mNumUVComponents[c] = 2;
 
-		// setup the default material index by default
-		iMaterialIndex = Face::DEFAULT_MATINDEX;
-	}
+        // setup the default material index by default
+        iMaterialIndex = Face::DEFAULT_MATINDEX;
+    }
 
-	//! List of all texture coordinate sets
-	std::vector<aiVector3D> amTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+    //! List of all texture coordinate sets
+    std::vector<aiVector3D> amTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
 
-	//! List of all vertex color sets.
-	std::vector<aiColor4D> mVertexColors;
+    //! List of all vertex color sets.
+    std::vector<aiColor4D> mVertexColors;
 
-	//! List of all bone vertices
-	std::vector<BoneVertex> mBoneVertices;
+    //! List of all bone vertices
+    std::vector<BoneVertex> mBoneVertices;
 
-	//! List of all bones
-	std::vector<Bone> mBones;
+    //! List of all bones
+    std::vector<Bone> mBones;
 
-	//! Material index of the mesh
-	unsigned int iMaterialIndex;
+    //! Material index of the mesh
+    unsigned int iMaterialIndex;
 
-	//! Number of vertex components for each UVW set
-	unsigned int mNumUVComponents[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+    //! Number of vertex components for each UVW set
+    unsigned int mNumUVComponents[AI_MAX_NUMBER_OF_TEXTURECOORDS];
 
-	//! used internally
-	bool bSkip;
+    //! used internally
+    bool bSkip;
 };
 
 // ---------------------------------------------------------------------------
 /** Helper structure to represent an ASE light source */
 struct Light : public BaseNode
 {
-	enum LightType
-	{
-		OMNI,
-		TARGET,
-		FREE,
-		DIRECTIONAL
-	};
-
-	//! Constructor. 
-	Light() 
-		: BaseNode	 (BaseNode::Light)
-		, mLightType (OMNI)
-		, mColor	 (1.f,1.f,1.f)
-		, mIntensity (1.f) // light is white by default
-		, mAngle	 (45.f)
-		, mFalloff	 (0.f)
-	{	
-	}
-
-	LightType mLightType;
-	aiColor3D mColor;
-	float mIntensity;
-	float mAngle; // in degrees
-	float mFalloff;
+    enum LightType
+    {
+        OMNI,
+        TARGET,
+        FREE,
+        DIRECTIONAL
+    };
+
+    //! Constructor.
+    Light()
+        : BaseNode   (BaseNode::Light)
+        , mLightType (OMNI)
+        , mColor     (1.f,1.f,1.f)
+        , mIntensity (1.f) // light is white by default
+        , mAngle     (45.f)
+        , mFalloff   (0.f)
+    {
+    }
+
+    LightType mLightType;
+    aiColor3D mColor;
+    float mIntensity;
+    float mAngle; // in degrees
+    float mFalloff;
 };
 
 // ---------------------------------------------------------------------------
 /** Helper structure to represent an ASE camera */
 struct Camera : public BaseNode
 {
-	enum CameraType
-	{
-		FREE,
-		TARGET
-	};
-
-	//! Constructor
-	Camera() 
-		: BaseNode	  (BaseNode::Camera)
-		, mFOV        (0.75f)   // in radians
-		, mNear       (0.1f) 
-		, mFar        (1000.f)  // could be zero
-		, mCameraType (FREE)
-	{
-	}
-
-	float mFOV, mNear, mFar;
-	CameraType mCameraType;
+    enum CameraType
+    {
+        FREE,
+        TARGET
+    };
+
+    //! Constructor
+    Camera()
+        : BaseNode    (BaseNode::Camera)
+        , mFOV        (0.75f)   // in radians
+        , mNear       (0.1f)
+        , mFar        (1000.f)  // could be zero
+        , mCameraType (FREE)
+    {
+    }
+
+    float mFOV, mNear, mFar;
+    CameraType mCameraType;
 };
 
 // ---------------------------------------------------------------------------
 /** Helper structure to represent an ASE helper object (dummy) */
 struct Dummy : public BaseNode
 {
-	//! Constructor
-	Dummy() 
-		: BaseNode	(BaseNode::Dummy)
-	{
-	}
+    //! Constructor
+    Dummy()
+        : BaseNode  (BaseNode::Dummy)
+    {
+    }
 };
 
 // Parameters to Parser::Parse()
@@ -367,8 +367,8 @@ struct Dummy : public BaseNode
 #define AI_ASE_OLD_FILE_FORMAT 110
 
 // Internally we're a little bit more tolerant
-#define AI_ASE_IS_NEW_FILE_FORMAT()	(iFileFormat >= 200)
-#define AI_ASE_IS_OLD_FILE_FORMAT()	(iFileFormat < 200)
+#define AI_ASE_IS_NEW_FILE_FORMAT() (iFileFormat >= 200)
+#define AI_ASE_IS_OLD_FILE_FORMAT() (iFileFormat < 200)
 
 // -------------------------------------------------------------------------------
 /** \brief Class to parse ASE files
@@ -378,288 +378,288 @@ class Parser
 
 private:
 
-	Parser() {}
+    Parser() {}
 
 public:
 
-	// -------------------------------------------------------------------
-	//! Construct a parser from a given input file which is
-	//! guaranted to be terminated with zero.
-	//! @param szFile Input file
-	//! @param fileFormatDefault Assumed file format version. If the
-	//!   file format is specified in the file the new value replaces
-	//!   the default value.
-	Parser (const char* szFile, unsigned int fileFormatDefault);
+    // -------------------------------------------------------------------
+    //! Construct a parser from a given input file which is
+    //! guaranted to be terminated with zero.
+    //! @param szFile Input file
+    //! @param fileFormatDefault Assumed file format version. If the
+    //!   file format is specified in the file the new value replaces
+    //!   the default value.
+    Parser (const char* szFile, unsigned int fileFormatDefault);
 
-	// -------------------------------------------------------------------
-	//! Parses the file into the parsers internal representation
-	void Parse();
+    // -------------------------------------------------------------------
+    //! Parses the file into the parsers internal representation
+    void Parse();
 
 
 private:
 
-	// -------------------------------------------------------------------
-	//! Parse the *SCENE block in a file
-	void ParseLV1SceneBlock();
-
-	// -------------------------------------------------------------------
-	//! Parse the *MESH_SOFTSKINVERTS block in a file
-	void ParseLV1SoftSkinBlock();
-
-	// -------------------------------------------------------------------
-	//! Parse the *MATERIAL_LIST block in a file
-	void ParseLV1MaterialListBlock();
-
-	// -------------------------------------------------------------------
-	//! Parse a *<xxx>OBJECT block in a file
-	//! \param mesh Node to be filled
-	void ParseLV1ObjectBlock(BaseNode& mesh);
-
-	// -------------------------------------------------------------------
-	//! Parse a *MATERIAL blocks in a material list
-	//! \param mat Material structure to be filled
-	void ParseLV2MaterialBlock(Material& mat);
-
-	// -------------------------------------------------------------------
-	//! Parse a *NODE_TM block in a file
-	//! \param mesh Node (!) object to be filled
-	void ParseLV2NodeTransformBlock(BaseNode& mesh);
-
-	// -------------------------------------------------------------------
-	//! Parse a *TM_ANIMATION block in a file
-	//! \param mesh Mesh object to be filled
-	void ParseLV2AnimationBlock(BaseNode& mesh);
-	void ParseLV3PosAnimationBlock(ASE::Animation& anim);
-	void ParseLV3ScaleAnimationBlock(ASE::Animation& anim);
-	void ParseLV3RotAnimationBlock(ASE::Animation& anim);
-
-	// -------------------------------------------------------------------
-	//! Parse a *MESH block in a file
-	//! \param mesh Mesh object to be filled
-	void ParseLV2MeshBlock(Mesh& mesh);
-
-	// -------------------------------------------------------------------
-	//! Parse a *LIGHT_SETTINGS block in a file
-	//! \param light Light object to be filled
-	void ParseLV2LightSettingsBlock(Light& light);
-
-	// -------------------------------------------------------------------
-	//! Parse a *CAMERA_SETTINGS block in a file
-	//! \param cam Camera object to be filled
-	void ParseLV2CameraSettingsBlock(Camera& cam);
-
-	// -------------------------------------------------------------------
-	//! Parse the *MAP_XXXXXX blocks in a material
-	//! \param map Texture structure to be filled
-	void ParseLV3MapBlock(Texture& map);
-
-	// -------------------------------------------------------------------
-	//! Parse a *MESH_VERTEX_LIST block in a file
-	//! \param iNumVertices Value of *MESH_NUMVERTEX, if present.
-	//! Otherwise zero. This is used to check the consistency of the file.
-	//! A warning is sent to the logger if the validations fails.
-	//! \param mesh Mesh object to be filled
-	void ParseLV3MeshVertexListBlock(
-		unsigned int iNumVertices,Mesh& mesh);
-
-	// -------------------------------------------------------------------
-	//! Parse a *MESH_FACE_LIST block in a file
-	//! \param iNumFaces Value of *MESH_NUMFACES, if present.
-	//! Otherwise zero. This is used to check the consistency of the file.
-	//! A warning is sent to the logger if the validations fails.
-	//! \param mesh Mesh object to be filled
-	void ParseLV3MeshFaceListBlock(
-		unsigned int iNumFaces,Mesh& mesh);
-
-	// -------------------------------------------------------------------
-	//! Parse a *MESH_TVERT_LIST block in a file
-	//! \param iNumVertices Value of *MESH_NUMTVERTEX, if present.
-	//! Otherwise zero. This is used to check the consistency of the file.
-	//! A warning is sent to the logger if the validations fails.
-	//! \param mesh Mesh object to be filled
-	//! \param iChannel Output UVW channel
-	void ParseLV3MeshTListBlock(
-		unsigned int iNumVertices,Mesh& mesh, unsigned int iChannel = 0);
-
-	// -------------------------------------------------------------------
-	//! Parse a *MESH_TFACELIST block in a file
-	//! \param iNumFaces Value of *MESH_NUMTVFACES, if present.
-	//! Otherwise zero. This is used to check the consistency of the file.
-	//! A warning is sent to the logger if the validations fails.
-	//! \param mesh Mesh object to be filled
-	//! \param iChannel Output UVW channel
-	void ParseLV3MeshTFaceListBlock(
-		unsigned int iNumFaces,Mesh& mesh, unsigned int iChannel = 0);
-
-	// -------------------------------------------------------------------
-	//! Parse an additional mapping channel 
-	//! (specified via *MESH_MAPPINGCHANNEL)
-	//! \param iChannel Channel index to be filled
-	//! \param mesh Mesh object to be filled
-	void ParseLV3MappingChannel(
-		unsigned int iChannel, Mesh& mesh);
-
-	// -------------------------------------------------------------------
-	//! Parse a *MESH_CVERTLIST block in a file
-	//! \param iNumVertices Value of *MESH_NUMCVERTEX, if present.
-	//! Otherwise zero. This is used to check the consistency of the file.
-	//! A warning is sent to the logger if the validations fails.
-	//! \param mesh Mesh object to be filled
-	void ParseLV3MeshCListBlock(
-		unsigned int iNumVertices, Mesh& mesh);
-
-	// -------------------------------------------------------------------
-	//! Parse a *MESH_CFACELIST block in a file
-	//! \param iNumFaces Value of *MESH_NUMCVFACES, if present.
-	//! Otherwise zero. This is used to check the consistency of the file.
-	//! A warning is sent to the logger if the validations fails.
-	//! \param mesh Mesh object to be filled
-	void ParseLV3MeshCFaceListBlock(
-		unsigned int iNumFaces, Mesh& mesh);
-
-	// -------------------------------------------------------------------
-	//! Parse a *MESH_NORMALS block in a file
-	//! \param mesh Mesh object to be filled
-	void ParseLV3MeshNormalListBlock(Mesh& mesh);
-
-	// -------------------------------------------------------------------
-	//! Parse a *MESH_WEIGHTSblock in a file
-	//! \param mesh Mesh object to be filled
-	void ParseLV3MeshWeightsBlock(Mesh& mesh);
-
-	// -------------------------------------------------------------------
-	//! Parse the bone list of a file
-	//! \param mesh Mesh object to be filled
-	//! \param iNumBones Number of bones in the mesh
-	void ParseLV4MeshBones(unsigned int iNumBones,Mesh& mesh);
-
-	// -------------------------------------------------------------------
-	//! Parse the bone vertices list of a file
-	//! \param mesh Mesh object to be filled
-	//! \param iNumVertices Number of vertices to be parsed
-	void ParseLV4MeshBonesVertices(unsigned int iNumVertices,Mesh& mesh);
-
-	// -------------------------------------------------------------------
-	//! Parse a *MESH_FACE block in a file
-	//! \param out receive the face data
-	void ParseLV4MeshFace(ASE::Face& out);
-
-	// -------------------------------------------------------------------
-	//! Parse a *MESH_VERT block in a file
-	//! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL  ...)
-	//! \param apOut Output buffer (3 floats)
-	//! \param rIndexOut Output index
-	void ParseLV4MeshFloatTriple(float* apOut, unsigned int& rIndexOut);
-
-	// -------------------------------------------------------------------
-	//! Parse a *MESH_VERT block in a file
-	//! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL  ...)
-	//! \param apOut Output buffer (3 floats)
-	void ParseLV4MeshFloatTriple(float* apOut);
-
-	// -------------------------------------------------------------------
-	//! Parse a *MESH_TFACE block in a file
-	//! (also works for MESH_CFACE)
-	//! \param apOut Output buffer (3 ints)
-	//! \param rIndexOut Output index
-	void ParseLV4MeshLongTriple(unsigned int* apOut, unsigned int& rIndexOut);
-
-	// -------------------------------------------------------------------
-	//! Parse a *MESH_TFACE block in a file
-	//! (also works for MESH_CFACE)
-	//! \param apOut Output buffer (3 ints)
-	void ParseLV4MeshLongTriple(unsigned int* apOut);
-
-	// -------------------------------------------------------------------
-	//! Parse a single float element 
-	//! \param fOut Output float
-	void ParseLV4MeshFloat(float& fOut);
-
-	// -------------------------------------------------------------------
-	//! Parse a single int element 
-	//! \param iOut Output integer
-	void ParseLV4MeshLong(unsigned int& iOut);
-
-	// -------------------------------------------------------------------
-	//! Skip everything to the next: '*' or '\0'
-	bool SkipToNextToken();
-
-	// -------------------------------------------------------------------
-	//! Skip the current section until the token after the closing }.
-	//! This function handles embedded subsections correctly
-	bool SkipSection();
-
-	// -------------------------------------------------------------------
-	//! Output a warning to the logger
-	//! \param szWarn Warn message
-	void LogWarning(const char* szWarn);
-
-	// -------------------------------------------------------------------
-	//! Output a message to the logger
-	//! \param szWarn Message
-	void LogInfo(const char* szWarn);
-
-	// -------------------------------------------------------------------
-	//! Output an error to the logger
-	//! \param szWarn Error message
-	void LogError(const char* szWarn);
-
-	// -------------------------------------------------------------------
-	//! Parse a string, enclosed in double quotation marks
-	//! \param out Output string
-	//! \param szName Name of the enclosing element -> used in error
-	//! messages.
-	//! \return false if an error occured
-	bool ParseString(std::string& out,const char* szName);
+    // -------------------------------------------------------------------
+    //! Parse the *SCENE block in a file
+    void ParseLV1SceneBlock();
+
+    // -------------------------------------------------------------------
+    //! Parse the *MESH_SOFTSKINVERTS block in a file
+    void ParseLV1SoftSkinBlock();
+
+    // -------------------------------------------------------------------
+    //! Parse the *MATERIAL_LIST block in a file
+    void ParseLV1MaterialListBlock();
+
+    // -------------------------------------------------------------------
+    //! Parse a *<xxx>OBJECT block in a file
+    //! \param mesh Node to be filled
+    void ParseLV1ObjectBlock(BaseNode& mesh);
+
+    // -------------------------------------------------------------------
+    //! Parse a *MATERIAL blocks in a material list
+    //! \param mat Material structure to be filled
+    void ParseLV2MaterialBlock(Material& mat);
+
+    // -------------------------------------------------------------------
+    //! Parse a *NODE_TM block in a file
+    //! \param mesh Node (!) object to be filled
+    void ParseLV2NodeTransformBlock(BaseNode& mesh);
+
+    // -------------------------------------------------------------------
+    //! Parse a *TM_ANIMATION block in a file
+    //! \param mesh Mesh object to be filled
+    void ParseLV2AnimationBlock(BaseNode& mesh);
+    void ParseLV3PosAnimationBlock(ASE::Animation& anim);
+    void ParseLV3ScaleAnimationBlock(ASE::Animation& anim);
+    void ParseLV3RotAnimationBlock(ASE::Animation& anim);
+
+    // -------------------------------------------------------------------
+    //! Parse a *MESH block in a file
+    //! \param mesh Mesh object to be filled
+    void ParseLV2MeshBlock(Mesh& mesh);
+
+    // -------------------------------------------------------------------
+    //! Parse a *LIGHT_SETTINGS block in a file
+    //! \param light Light object to be filled
+    void ParseLV2LightSettingsBlock(Light& light);
+
+    // -------------------------------------------------------------------
+    //! Parse a *CAMERA_SETTINGS block in a file
+    //! \param cam Camera object to be filled
+    void ParseLV2CameraSettingsBlock(Camera& cam);
+
+    // -------------------------------------------------------------------
+    //! Parse the *MAP_XXXXXX blocks in a material
+    //! \param map Texture structure to be filled
+    void ParseLV3MapBlock(Texture& map);
+
+    // -------------------------------------------------------------------
+    //! Parse a *MESH_VERTEX_LIST block in a file
+    //! \param iNumVertices Value of *MESH_NUMVERTEX, if present.
+    //! Otherwise zero. This is used to check the consistency of the file.
+    //! A warning is sent to the logger if the validations fails.
+    //! \param mesh Mesh object to be filled
+    void ParseLV3MeshVertexListBlock(
+        unsigned int iNumVertices,Mesh& mesh);
+
+    // -------------------------------------------------------------------
+    //! Parse a *MESH_FACE_LIST block in a file
+    //! \param iNumFaces Value of *MESH_NUMFACES, if present.
+    //! Otherwise zero. This is used to check the consistency of the file.
+    //! A warning is sent to the logger if the validations fails.
+    //! \param mesh Mesh object to be filled
+    void ParseLV3MeshFaceListBlock(
+        unsigned int iNumFaces,Mesh& mesh);
+
+    // -------------------------------------------------------------------
+    //! Parse a *MESH_TVERT_LIST block in a file
+    //! \param iNumVertices Value of *MESH_NUMTVERTEX, if present.
+    //! Otherwise zero. This is used to check the consistency of the file.
+    //! A warning is sent to the logger if the validations fails.
+    //! \param mesh Mesh object to be filled
+    //! \param iChannel Output UVW channel
+    void ParseLV3MeshTListBlock(
+        unsigned int iNumVertices,Mesh& mesh, unsigned int iChannel = 0);
+
+    // -------------------------------------------------------------------
+    //! Parse a *MESH_TFACELIST block in a file
+    //! \param iNumFaces Value of *MESH_NUMTVFACES, if present.
+    //! Otherwise zero. This is used to check the consistency of the file.
+    //! A warning is sent to the logger if the validations fails.
+    //! \param mesh Mesh object to be filled
+    //! \param iChannel Output UVW channel
+    void ParseLV3MeshTFaceListBlock(
+        unsigned int iNumFaces,Mesh& mesh, unsigned int iChannel = 0);
+
+    // -------------------------------------------------------------------
+    //! Parse an additional mapping channel
+    //! (specified via *MESH_MAPPINGCHANNEL)
+    //! \param iChannel Channel index to be filled
+    //! \param mesh Mesh object to be filled
+    void ParseLV3MappingChannel(
+        unsigned int iChannel, Mesh& mesh);
+
+    // -------------------------------------------------------------------
+    //! Parse a *MESH_CVERTLIST block in a file
+    //! \param iNumVertices Value of *MESH_NUMCVERTEX, if present.
+    //! Otherwise zero. This is used to check the consistency of the file.
+    //! A warning is sent to the logger if the validations fails.
+    //! \param mesh Mesh object to be filled
+    void ParseLV3MeshCListBlock(
+        unsigned int iNumVertices, Mesh& mesh);
+
+    // -------------------------------------------------------------------
+    //! Parse a *MESH_CFACELIST block in a file
+    //! \param iNumFaces Value of *MESH_NUMCVFACES, if present.
+    //! Otherwise zero. This is used to check the consistency of the file.
+    //! A warning is sent to the logger if the validations fails.
+    //! \param mesh Mesh object to be filled
+    void ParseLV3MeshCFaceListBlock(
+        unsigned int iNumFaces, Mesh& mesh);
+
+    // -------------------------------------------------------------------
+    //! Parse a *MESH_NORMALS block in a file
+    //! \param mesh Mesh object to be filled
+    void ParseLV3MeshNormalListBlock(Mesh& mesh);
+
+    // -------------------------------------------------------------------
+    //! Parse a *MESH_WEIGHTSblock in a file
+    //! \param mesh Mesh object to be filled
+    void ParseLV3MeshWeightsBlock(Mesh& mesh);
+
+    // -------------------------------------------------------------------
+    //! Parse the bone list of a file
+    //! \param mesh Mesh object to be filled
+    //! \param iNumBones Number of bones in the mesh
+    void ParseLV4MeshBones(unsigned int iNumBones,Mesh& mesh);
+
+    // -------------------------------------------------------------------
+    //! Parse the bone vertices list of a file
+    //! \param mesh Mesh object to be filled
+    //! \param iNumVertices Number of vertices to be parsed
+    void ParseLV4MeshBonesVertices(unsigned int iNumVertices,Mesh& mesh);
+
+    // -------------------------------------------------------------------
+    //! Parse a *MESH_FACE block in a file
+    //! \param out receive the face data
+    void ParseLV4MeshFace(ASE::Face& out);
+
+    // -------------------------------------------------------------------
+    //! Parse a *MESH_VERT block in a file
+    //! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL  ...)
+    //! \param apOut Output buffer (3 floats)
+    //! \param rIndexOut Output index
+    void ParseLV4MeshFloatTriple(float* apOut, unsigned int& rIndexOut);
+
+    // -------------------------------------------------------------------
+    //! Parse a *MESH_VERT block in a file
+    //! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL  ...)
+    //! \param apOut Output buffer (3 floats)
+    void ParseLV4MeshFloatTriple(float* apOut);
+
+    // -------------------------------------------------------------------
+    //! Parse a *MESH_TFACE block in a file
+    //! (also works for MESH_CFACE)
+    //! \param apOut Output buffer (3 ints)
+    //! \param rIndexOut Output index
+    void ParseLV4MeshLongTriple(unsigned int* apOut, unsigned int& rIndexOut);
+
+    // -------------------------------------------------------------------
+    //! Parse a *MESH_TFACE block in a file
+    //! (also works for MESH_CFACE)
+    //! \param apOut Output buffer (3 ints)
+    void ParseLV4MeshLongTriple(unsigned int* apOut);
+
+    // -------------------------------------------------------------------
+    //! Parse a single float element
+    //! \param fOut Output float
+    void ParseLV4MeshFloat(float& fOut);
+
+    // -------------------------------------------------------------------
+    //! Parse a single int element
+    //! \param iOut Output integer
+    void ParseLV4MeshLong(unsigned int& iOut);
+
+    // -------------------------------------------------------------------
+    //! Skip everything to the next: '*' or '\0'
+    bool SkipToNextToken();
+
+    // -------------------------------------------------------------------
+    //! Skip the current section until the token after the closing }.
+    //! This function handles embedded subsections correctly
+    bool SkipSection();
+
+    // -------------------------------------------------------------------
+    //! Output a warning to the logger
+    //! \param szWarn Warn message
+    void LogWarning(const char* szWarn);
+
+    // -------------------------------------------------------------------
+    //! Output a message to the logger
+    //! \param szWarn Message
+    void LogInfo(const char* szWarn);
+
+    // -------------------------------------------------------------------
+    //! Output an error to the logger
+    //! \param szWarn Error message
+    AI_WONT_RETURN void LogError(const char* szWarn) AI_WONT_RETURN_SUFFIX;
+
+    // -------------------------------------------------------------------
+    //! Parse a string, enclosed in double quotation marks
+    //! \param out Output string
+    //! \param szName Name of the enclosing element -> used in error
+    //! messages.
+    //! \return false if an error occured
+    bool ParseString(std::string& out,const char* szName);
 
 public:
 
-	//! Pointer to current data
-	const char* filePtr;
+    //! Pointer to current data
+    const char* filePtr;
 
-	//! background color to be passed to the viewer
-	//! QNAN if none was found
-	aiColor3D m_clrBackground;
+    //! background color to be passed to the viewer
+    //! QNAN if none was found
+    aiColor3D m_clrBackground;
 
-	//! Base ambient color to be passed to all materials
-	//! QNAN if none was found
-	aiColor3D m_clrAmbient;
+    //! Base ambient color to be passed to all materials
+    //! QNAN if none was found
+    aiColor3D m_clrAmbient;
 
-	//! List of all materials found in the file
-	std::vector<Material> m_vMaterials;
+    //! List of all materials found in the file
+    std::vector<Material> m_vMaterials;
 
-	//! List of all meshes found in the file
-	std::vector<Mesh> m_vMeshes;
+    //! List of all meshes found in the file
+    std::vector<Mesh> m_vMeshes;
 
-	//! List of all dummies found in the file
-	std::vector<Dummy> m_vDummies;
+    //! List of all dummies found in the file
+    std::vector<Dummy> m_vDummies;
 
-	//! List of all lights found in the file
-	std::vector<Light> m_vLights;
+    //! List of all lights found in the file
+    std::vector<Light> m_vLights;
 
-	//! List of all cameras found in the file
-	std::vector<Camera> m_vCameras;
+    //! List of all cameras found in the file
+    std::vector<Camera> m_vCameras;
 
-	//! Current line in the file
-	unsigned int iLineNumber;
+    //! Current line in the file
+    unsigned int iLineNumber;
 
-	//! First frame
-	unsigned int iFirstFrame;
+    //! First frame
+    unsigned int iFirstFrame;
 
-	//! Last frame
-	unsigned int iLastFrame;
+    //! Last frame
+    unsigned int iLastFrame;
 
-	//! Frame speed - frames per second
-	unsigned int iFrameSpeed;
+    //! Frame speed - frames per second
+    unsigned int iFrameSpeed;
 
-	//! Ticks per frame
-	unsigned int iTicksPerFrame;
+    //! Ticks per frame
+    unsigned int iTicksPerFrame;
 
-	//! true if the last character read was an end-line character
-	bool bLastWasEndLine;
+    //! true if the last character read was an end-line character
+    bool bLastWasEndLine;
 
-	//! File format version
-	unsigned int iFileFormat;
+    //! File format version
+    unsigned int iFileFormat;
 };
 
 

+ 769 - 0
assimplib.mod/assimp/code/AssbinExporter.cpp

@@ -0,0 +1,769 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2015, 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  AssbinExporter.cpp
+ *  ASSBIN exporter main code
+ */
+#include "assbin_chunks.h"
+#include "../include/assimp/version.h"
+#include "../include/assimp/IOStream.hpp"
+#include "../include/assimp/IOSystem.hpp"
+#include "../include/assimp/Exporter.hpp"
+#include "ProcessHelper.h"
+#include "Exceptional.h"
+#include <boost/static_assert.hpp>
+
+#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
+#   include <zlib.h>
+#else
+#   include "../contrib/zlib/zlib.h"
+#endif
+
+#include <time.h>
+
+
+#ifndef ASSIMP_BUILD_NO_EXPORT
+#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER
+
+using namespace Assimp;
+
+namespace Assimp    {
+
+template <typename T>
+size_t Write(IOStream * stream, const T& v)
+{
+    return stream->Write( &v, sizeof(T), 1 );
+}
+
+
+// -----------------------------------------------------------------------------------
+// Serialize an aiString
+template <>
+inline size_t Write<aiString>(IOStream * stream, const aiString& s)
+{
+    const size_t s2 = (uint32_t)s.length;
+    stream->Write(&s,4,1);
+    stream->Write(s.data,s2,1);
+    return s2+4;
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize an unsigned int as uint32_t
+template <>
+inline size_t Write<unsigned int>(IOStream * stream, const unsigned int& w)
+{
+    const uint32_t t = (uint32_t)w;
+    if (w > t) {
+        // this shouldn't happen, integers in Assimp data structures never exceed 2^32
+        throw new DeadlyExportError("loss of data due to 64 -> 32 bit integer conversion");
+    }
+
+    stream->Write(&t,4,1);
+    return 4;
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize an unsigned int as uint16_t
+template <>
+inline size_t Write<uint16_t>(IOStream * stream, const uint16_t& w)
+{
+    BOOST_STATIC_ASSERT(sizeof(uint16_t)==2);
+    stream->Write(&w,2,1);
+    return 2;
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize a float
+template <>
+inline size_t Write<float>(IOStream * stream, const float& f)
+{
+    BOOST_STATIC_ASSERT(sizeof(float)==4);
+    stream->Write(&f,4,1);
+    return 4;
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize a double
+template <>
+inline size_t Write<double>(IOStream * stream, const double& f)
+{
+    BOOST_STATIC_ASSERT(sizeof(double)==8);
+    stream->Write(&f,8,1);
+    return 8;
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize a vec3
+template <>
+inline size_t Write<aiVector3D>(IOStream * stream, const aiVector3D& v)
+{
+    size_t t = Write<float>(stream,v.x);
+    t += Write<float>(stream,v.y);
+    t += Write<float>(stream,v.z);
+    return t;
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize a color value
+template <>
+inline size_t Write<aiColor4D>(IOStream * stream, const aiColor4D& v)
+{
+    size_t t = Write<float>(stream,v.r);
+    t += Write<float>(stream,v.g);
+    t += Write<float>(stream,v.b);
+    t += Write<float>(stream,v.a);
+    return t;
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize a quaternion
+template <>
+inline size_t Write<aiQuaternion>(IOStream * stream, const aiQuaternion& v)
+{
+    size_t t = Write<float>(stream,v.w);
+    t += Write<float>(stream,v.x);
+    t += Write<float>(stream,v.y);
+    t += Write<float>(stream,v.z);
+    return 16;
+}
+
+
+// -----------------------------------------------------------------------------------
+// Serialize a vertex weight
+template <>
+inline size_t Write<aiVertexWeight>(IOStream * stream, const aiVertexWeight& v)
+{
+    size_t t = Write<unsigned int>(stream,v.mVertexId);
+    return t+Write<float>(stream,v.mWeight);
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize a mat4x4
+template <>
+inline size_t Write<aiMatrix4x4>(IOStream * stream, const aiMatrix4x4& m)
+{
+    for (unsigned int i = 0; i < 4;++i) {
+        for (unsigned int i2 = 0; i2 < 4;++i2) {
+            Write<float>(stream,m[i][i2]);
+        }
+    }
+    return 64;
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize an aiVectorKey
+template <>
+inline size_t Write<aiVectorKey>(IOStream * stream, const aiVectorKey& v)
+{
+    const size_t t = Write<double>(stream,v.mTime);
+    return t + Write<aiVector3D>(stream,v.mValue);
+}
+
+// -----------------------------------------------------------------------------------
+// Serialize an aiQuatKey
+template <>
+inline size_t Write<aiQuatKey>(IOStream * stream, const aiQuatKey& v)
+{
+    const size_t t = Write<double>(stream,v.mTime);
+    return t + Write<aiQuaternion>(stream,v.mValue);
+}
+
+template <typename T>
+inline size_t WriteBounds(IOStream * stream, const T* in, unsigned int size)
+{
+    T minc,maxc;
+    ArrayBounds(in,size,minc,maxc);
+
+    const size_t t = Write<T>(stream,minc);
+    return t + Write<T>(stream,maxc);
+}
+
+// We use this to write out non-byte arrays so that we write using the specializations.
+// This way we avoid writing out extra bytes that potentially come from struct alignment.
+template <typename T>
+inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
+{
+    size_t n = 0;
+    for (unsigned int i=0; i<size; i++) n += Write<T>(stream,in[i]);
+    return n;
+}
+
+    // ----------------------------------------------------------------------------------
+    /** @class  AssbinChunkWriter
+     *  @brief  Chunk writer mechanism for the .assbin file structure
+     *
+     *  This is a standard in-memory IOStream (most of the code is based on BlobIOStream),
+     *  the difference being that this takes another IOStream as a "container" in the
+     *  constructor, and when it is destroyed, it appends the magic number, the chunk size,
+     *  and the chunk contents to the container stream. This allows relatively easy chunk
+     *  chunk construction, even recursively.
+     */
+    class AssbinChunkWriter : public IOStream
+    {
+    private:
+
+        uint8_t* buffer;
+        uint32_t magic;
+        IOStream * container;
+        size_t cur_size, cursor, initial;
+
+    private:
+        // -------------------------------------------------------------------
+        void Grow(size_t need = 0)
+        {
+            size_t new_size = std::max(initial, std::max( need, cur_size+(cur_size>>1) ));
+
+            const uint8_t* const old = buffer;
+            buffer = new uint8_t[new_size];
+
+            if (old) {
+                memcpy(buffer,old,cur_size);
+                delete[] old;
+            }
+
+            cur_size = new_size;
+        }
+
+    public:
+
+        AssbinChunkWriter( IOStream * container, uint32_t magic, size_t initial = 4096)
+            : buffer(NULL), magic(magic), container(container), cur_size(0), cursor(0), initial(initial)
+        {
+        }
+
+        virtual ~AssbinChunkWriter()
+        {
+            if (container) {
+                container->Write( &magic, sizeof(uint32_t), 1 );
+                container->Write( &cursor, sizeof(uint32_t), 1 );
+                container->Write( buffer, 1, cursor );
+            }
+            if (buffer) delete[] buffer;
+        }
+
+        void * GetBufferPointer() { return buffer; }
+
+        // -------------------------------------------------------------------
+        virtual size_t Read(void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) { return 0; }
+        virtual aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/) { return aiReturn_FAILURE; }
+        virtual size_t Tell() const { return cursor; }
+        virtual void Flush() { }
+
+        virtual size_t FileSize() const
+        {
+            return cursor;
+        }
+
+        // -------------------------------------------------------------------
+        virtual size_t Write(const void* pvBuffer, size_t pSize, size_t pCount)
+        {
+            pSize *= pCount;
+            if (cursor + pSize > cur_size) {
+                Grow(cursor + pSize);
+            }
+
+            memcpy(buffer+cursor, pvBuffer, pSize);
+            cursor += pSize;
+
+            return pCount;
+        }
+
+    };
+
+    // ----------------------------------------------------------------------------------
+    /** @class  AssbinExport
+     *  @brief  Assbin exporter class
+     *
+     *  This class performs the .assbin exporting, and is responsible for the file layout.
+     */
+    class AssbinExport
+    {
+    private:
+        bool shortened;
+        bool compressed;
+
+    protected:
+
+        // -----------------------------------------------------------------------------------
+        void WriteBinaryNode( IOStream * container, const aiNode* node)
+        {
+            AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AINODE );
+
+            Write<aiString>(&chunk,node->mName);
+            Write<aiMatrix4x4>(&chunk,node->mTransformation);
+            Write<unsigned int>(&chunk,node->mNumChildren);
+            Write<unsigned int>(&chunk,node->mNumMeshes);
+
+            for (unsigned int i = 0; i < node->mNumMeshes;++i) {
+                Write<unsigned int>(&chunk,node->mMeshes[i]);
+            }
+
+            for (unsigned int i = 0; i < node->mNumChildren;++i) {
+                WriteBinaryNode( &chunk, node->mChildren[i] );
+            }
+        }
+
+        // -----------------------------------------------------------------------------------
+        void WriteBinaryTexture(IOStream * container, const aiTexture* tex)
+        {
+            AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AITEXTURE );
+
+            Write<unsigned int>(&chunk,tex->mWidth);
+            Write<unsigned int>(&chunk,tex->mHeight);
+            chunk.Write( tex->achFormatHint, sizeof(char), 4 );
+
+            if(!shortened) {
+                if (!tex->mHeight) {
+                    chunk.Write(tex->pcData,1,tex->mWidth);
+                }
+                else {
+                    chunk.Write(tex->pcData,1,tex->mWidth*tex->mHeight*4);
+                }
+            }
+
+        }
+
+        // -----------------------------------------------------------------------------------
+        void WriteBinaryBone(IOStream * container, const aiBone* b)
+        {
+            AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIBONE );
+
+            Write<aiString>(&chunk,b->mName);
+            Write<unsigned int>(&chunk,b->mNumWeights);
+            Write<aiMatrix4x4>(&chunk,b->mOffsetMatrix);
+
+            // for the moment we write dumb min/max values for the bones, too.
+            // maybe I'll add a better, hash-like solution later
+            if (shortened) {
+                WriteBounds(&chunk,b->mWeights,b->mNumWeights);
+            } // else write as usual
+            else WriteArray<aiVertexWeight>(&chunk,b->mWeights,b->mNumWeights);
+        }
+
+        // -----------------------------------------------------------------------------------
+        void WriteBinaryMesh(IOStream * container, const aiMesh* mesh)
+        {
+            AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIMESH );
+
+            Write<unsigned int>(&chunk,mesh->mPrimitiveTypes);
+            Write<unsigned int>(&chunk,mesh->mNumVertices);
+            Write<unsigned int>(&chunk,mesh->mNumFaces);
+            Write<unsigned int>(&chunk,mesh->mNumBones);
+            Write<unsigned int>(&chunk,mesh->mMaterialIndex);
+
+            // first of all, write bits for all existent vertex components
+            unsigned int c = 0;
+            if (mesh->mVertices) {
+                c |= ASSBIN_MESH_HAS_POSITIONS;
+            }
+            if (mesh->mNormals) {
+                c |= ASSBIN_MESH_HAS_NORMALS;
+            }
+            if (mesh->mTangents && mesh->mBitangents) {
+                c |= ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS;
+            }
+            for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) {
+                if (!mesh->mTextureCoords[n]) {
+                    break;
+                }
+                c |= ASSBIN_MESH_HAS_TEXCOORD(n);
+            }
+            for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) {
+                if (!mesh->mColors[n]) {
+                    break;
+                }
+                c |= ASSBIN_MESH_HAS_COLOR(n);
+            }
+            Write<unsigned int>(&chunk,c);
+
+            aiVector3D minVec, maxVec;
+            if (mesh->mVertices) {
+                if (shortened) {
+                    WriteBounds(&chunk,mesh->mVertices,mesh->mNumVertices);
+                } // else write as usual
+                else WriteArray<aiVector3D>(&chunk,mesh->mVertices,mesh->mNumVertices);
+            }
+            if (mesh->mNormals) {
+                if (shortened) {
+                    WriteBounds(&chunk,mesh->mNormals,mesh->mNumVertices);
+                } // else write as usual
+                else WriteArray<aiVector3D>(&chunk,mesh->mNormals,mesh->mNumVertices);
+            }
+            if (mesh->mTangents && mesh->mBitangents) {
+                if (shortened) {
+                    WriteBounds(&chunk,mesh->mTangents,mesh->mNumVertices);
+                    WriteBounds(&chunk,mesh->mBitangents,mesh->mNumVertices);
+                } // else write as usual
+                else {
+                    WriteArray<aiVector3D>(&chunk,mesh->mTangents,mesh->mNumVertices);
+                    WriteArray<aiVector3D>(&chunk,mesh->mBitangents,mesh->mNumVertices);
+                }
+            }
+            for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n) {
+                if (!mesh->mColors[n])
+                    break;
+
+                if (shortened) {
+                    WriteBounds(&chunk,mesh->mColors[n],mesh->mNumVertices);
+                } // else write as usual
+                else WriteArray<aiColor4D>(&chunk,mesh->mColors[n],mesh->mNumVertices);
+            }
+            for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n) {
+                if (!mesh->mTextureCoords[n])
+                    break;
+
+                // write number of UV components
+                Write<unsigned int>(&chunk,mesh->mNumUVComponents[n]);
+
+                if (shortened) {
+                    WriteBounds(&chunk,mesh->mTextureCoords[n],mesh->mNumVertices);
+                } // else write as usual
+                else WriteArray<aiVector3D>(&chunk,mesh->mTextureCoords[n],mesh->mNumVertices);
+            }
+
+            // write faces. There are no floating-point calculations involved
+            // in these, so we can write a simple hash over the face data
+            // to the dump file. We generate a single 32 Bit hash for 512 faces
+            // using Assimp's standard hashing function.
+            if (shortened) {
+                unsigned int processed = 0;
+                for (unsigned int job;(job = std::min(mesh->mNumFaces-processed,512u));processed += job) {
+
+                    uint32_t hash = 0;
+                    for (unsigned int a = 0; a < job;++a) {
+
+                        const aiFace& f = mesh->mFaces[processed+a];
+                        uint32_t tmp = f.mNumIndices;
+                        hash = SuperFastHash(reinterpret_cast<const char*>(&tmp),sizeof tmp,hash);
+                        for (unsigned int i = 0; i < f.mNumIndices; ++i) {
+                            BOOST_STATIC_ASSERT(AI_MAX_VERTICES <= 0xffffffff);
+                            tmp = static_cast<uint32_t>( f.mIndices[i] );
+                            hash = SuperFastHash(reinterpret_cast<const char*>(&tmp),sizeof tmp,hash);
+                        }
+                    }
+                    Write<unsigned int>(&chunk,hash);
+                }
+            }
+            else // else write as usual
+            {
+                // if there are less than 2^16 vertices, we can simply use 16 bit integers ...
+                for (unsigned int i = 0; i < mesh->mNumFaces;++i) {
+                    const aiFace& f = mesh->mFaces[i];
+
+                    BOOST_STATIC_ASSERT(AI_MAX_FACE_INDICES <= 0xffff);
+                    Write<uint16_t>(&chunk,f.mNumIndices);
+
+                    for (unsigned int a = 0; a < f.mNumIndices;++a) {
+                        if (mesh->mNumVertices < (1u<<16)) {
+                            Write<uint16_t>(&chunk,f.mIndices[a]);
+                        }
+                        else Write<unsigned int>(&chunk,f.mIndices[a]);
+                    }
+                }
+            }
+
+            // write bones
+            if (mesh->mNumBones) {
+                for (unsigned int a = 0; a < mesh->mNumBones;++a) {
+                    const aiBone* b = mesh->mBones[a];
+                    WriteBinaryBone(&chunk,b);
+                }
+            }
+        }
+
+        // -----------------------------------------------------------------------------------
+        void WriteBinaryMaterialProperty(IOStream * container, const aiMaterialProperty* prop)
+        {
+            AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIMATERIALPROPERTY );
+
+            Write<aiString>(&chunk,prop->mKey);
+            Write<unsigned int>(&chunk,prop->mSemantic);
+            Write<unsigned int>(&chunk,prop->mIndex);
+
+            Write<unsigned int>(&chunk,prop->mDataLength);
+            Write<unsigned int>(&chunk,(unsigned int)prop->mType);
+            chunk.Write(prop->mData,1,prop->mDataLength);
+        }
+
+        // -----------------------------------------------------------------------------------
+        void WriteBinaryMaterial(IOStream * container, const aiMaterial* mat)
+        {
+            AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIMATERIAL);
+
+            Write<unsigned int>(&chunk,mat->mNumProperties);
+            for (unsigned int i = 0; i < mat->mNumProperties;++i) {
+                WriteBinaryMaterialProperty( &chunk, mat->mProperties[i]);
+            }
+        }
+
+        // -----------------------------------------------------------------------------------
+        void WriteBinaryNodeAnim(IOStream * container, const aiNodeAnim* nd)
+        {
+            AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AINODEANIM );
+
+            Write<aiString>(&chunk,nd->mNodeName);
+            Write<unsigned int>(&chunk,nd->mNumPositionKeys);
+            Write<unsigned int>(&chunk,nd->mNumRotationKeys);
+            Write<unsigned int>(&chunk,nd->mNumScalingKeys);
+            Write<unsigned int>(&chunk,nd->mPreState);
+            Write<unsigned int>(&chunk,nd->mPostState);
+
+            if (nd->mPositionKeys) {
+                if (shortened) {
+                    WriteBounds(&chunk,nd->mPositionKeys,nd->mNumPositionKeys);
+
+                } // else write as usual
+                else WriteArray<aiVectorKey>(&chunk,nd->mPositionKeys,nd->mNumPositionKeys);
+            }
+            if (nd->mRotationKeys) {
+                if (shortened) {
+                    WriteBounds(&chunk,nd->mRotationKeys,nd->mNumRotationKeys);
+
+                } // else write as usual
+                else WriteArray<aiQuatKey>(&chunk,nd->mRotationKeys,nd->mNumRotationKeys);
+            }
+            if (nd->mScalingKeys) {
+                if (shortened) {
+                    WriteBounds(&chunk,nd->mScalingKeys,nd->mNumScalingKeys);
+
+                } // else write as usual
+                else WriteArray<aiVectorKey>(&chunk,nd->mScalingKeys,nd->mNumScalingKeys);
+            }
+        }
+
+
+        // -----------------------------------------------------------------------------------
+        void WriteBinaryAnim( IOStream * container, const aiAnimation* anim )
+        {
+            AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AIANIMATION );
+
+            Write<aiString>(&chunk,anim->mName);
+            Write<double>(&chunk,anim->mDuration);
+            Write<double>(&chunk,anim->mTicksPerSecond);
+            Write<unsigned int>(&chunk,anim->mNumChannels);
+
+            for (unsigned int a = 0; a < anim->mNumChannels;++a) {
+                const aiNodeAnim* nd = anim->mChannels[a];
+                WriteBinaryNodeAnim(&chunk,nd);
+            }
+        }
+
+        // -----------------------------------------------------------------------------------
+        void WriteBinaryLight( IOStream * container, const aiLight* l )
+        {
+            AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AILIGHT );
+
+            Write<aiString>(&chunk,l->mName);
+            Write<unsigned int>(&chunk,l->mType);
+
+            if (l->mType != aiLightSource_DIRECTIONAL) {
+                Write<float>(&chunk,l->mAttenuationConstant);
+                Write<float>(&chunk,l->mAttenuationLinear);
+                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);
+
+            if (l->mType == aiLightSource_SPOT) {
+                Write<float>(&chunk,l->mAngleInnerCone);
+                Write<float>(&chunk,l->mAngleOuterCone);
+            }
+
+        }
+
+        // -----------------------------------------------------------------------------------
+        void WriteBinaryCamera( IOStream * container, const aiCamera* cam )
+        {
+            AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AICAMERA );
+
+            Write<aiString>(&chunk,cam->mName);
+            Write<aiVector3D>(&chunk,cam->mPosition);
+            Write<aiVector3D>(&chunk,cam->mLookAt);
+            Write<aiVector3D>(&chunk,cam->mUp);
+            Write<float>(&chunk,cam->mHorizontalFOV);
+            Write<float>(&chunk,cam->mClipPlaneNear);
+            Write<float>(&chunk,cam->mClipPlaneFar);
+            Write<float>(&chunk,cam->mAspect);
+        }
+
+        // -----------------------------------------------------------------------------------
+        void WriteBinaryScene( IOStream * container, const aiScene* scene)
+        {
+            AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AISCENE );
+
+            // basic scene information
+            Write<unsigned int>(&chunk,scene->mFlags);
+            Write<unsigned int>(&chunk,scene->mNumMeshes);
+            Write<unsigned int>(&chunk,scene->mNumMaterials);
+            Write<unsigned int>(&chunk,scene->mNumAnimations);
+            Write<unsigned int>(&chunk,scene->mNumTextures);
+            Write<unsigned int>(&chunk,scene->mNumLights);
+            Write<unsigned int>(&chunk,scene->mNumCameras);
+
+            // write node graph
+            WriteBinaryNode( &chunk, scene->mRootNode );
+
+            // write all meshes
+            for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
+                const aiMesh* mesh = scene->mMeshes[i];
+                WriteBinaryMesh( &chunk,mesh);
+            }
+
+            // write materials
+            for (unsigned int i = 0; i< scene->mNumMaterials; ++i) {
+                const aiMaterial* mat = scene->mMaterials[i];
+                WriteBinaryMaterial(&chunk,mat);
+            }
+
+            // write all animations
+            for (unsigned int i = 0; i < scene->mNumAnimations;++i) {
+                const aiAnimation* anim = scene->mAnimations[i];
+                WriteBinaryAnim(&chunk,anim);
+            }
+
+
+            // write all textures
+            for (unsigned int i = 0; i < scene->mNumTextures;++i) {
+                const aiTexture* mesh = scene->mTextures[i];
+                WriteBinaryTexture(&chunk,mesh);
+            }
+
+            // write lights
+            for (unsigned int i = 0; i < scene->mNumLights;++i) {
+                const aiLight* l = scene->mLights[i];
+                WriteBinaryLight(&chunk,l);
+            }
+
+            // write cameras
+            for (unsigned int i = 0; i < scene->mNumCameras;++i) {
+                const aiCamera* cam = scene->mCameras[i];
+                WriteBinaryCamera(&chunk,cam);
+            }
+
+        }
+
+    public:
+        AssbinExport()
+            : shortened(false), compressed(false) // temporary settings until properties are introduced for exporters
+        {
+        }
+
+        // -----------------------------------------------------------------------------------
+        // Write a binary model dump
+        void WriteBinaryDump(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene)
+        {
+            IOStream * out = pIOSystem->Open( pFile, "wb" );
+            if (!out) return;
+
+            time_t tt = time(NULL);
+            tm* p     = gmtime(&tt);
+
+            // header
+            char s[64];
+            memset( s, 0, 64 );
+#if _MSC_VER >= 1400
+            sprintf_s(s,"ASSIMP.binary-dump.%s",asctime(p));
+#else
+            snprintf(s,64,"ASSIMP.binary-dump.%s",asctime(p));
+#endif
+            out->Write( s, 44, 1 );
+            // == 44 bytes
+
+            Write<unsigned int>( out, ASSBIN_VERSION_MAJOR );
+            Write<unsigned int>( out, ASSBIN_VERSION_MINOR );
+            Write<unsigned int>( out, aiGetVersionRevision() );
+            Write<unsigned int>( out, aiGetCompileFlags() );
+            Write<uint16_t>( out, shortened );
+            Write<uint16_t>( out, compressed );
+            // ==  20 bytes
+
+            char buff[256];
+            strncpy(buff,pFile,256);
+            out->Write(buff,sizeof(char),256);
+
+            char cmd[] = "\0";
+            strncpy(buff,cmd,128);
+            out->Write(buff,sizeof(char),128);
+
+            // leave 64 bytes free for future extensions
+            memset(buff,0xcd,64);
+            out->Write(buff,sizeof(char),64);
+            // == 435 bytes
+
+            // ==== total header size: 512 bytes
+            ai_assert( out->Tell() == ASSBIN_HEADER_LENGTH );
+
+            // Up to here the data is uncompressed. For compressed files, the rest
+            // is compressed using standard DEFLATE from zlib.
+            if (compressed)
+            {
+                AssbinChunkWriter uncompressedStream( NULL, 0 );
+                WriteBinaryScene( &uncompressedStream, pScene );
+
+                uLongf uncompressedSize = uncompressedStream.Tell();
+                uLongf compressedSize = (uLongf)(uncompressedStream.Tell() * 1.001 + 12.);
+                uint8_t* compressedBuffer = new uint8_t[ compressedSize ];
+
+                compress2( compressedBuffer, &compressedSize, (const Bytef*)uncompressedStream.GetBufferPointer(), uncompressedSize, 9 );
+
+                out->Write( &uncompressedSize, sizeof(uint32_t), 1 );
+                out->Write( compressedBuffer, sizeof(char), compressedSize );
+
+                delete[] compressedBuffer;
+            }
+            else
+            {
+                WriteBinaryScene( out, pScene );
+            }
+
+            pIOSystem->Close( out );
+        }
+    };
+
+void ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
+{
+    AssbinExport exporter;
+    exporter.WriteBinaryDump( pFile, pIOSystem, pScene );
+}
+} // end of namespace Assimp
+
+#endif // ASSIMP_BUILD_NO_ASSBIN_EXPORTER
+#endif // ASSIMP_BUILD_NO_EXPORT

+ 49 - 0
assimplib.mod/assimp/code/AssbinExporter.h

@@ -0,0 +1,49 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2015, 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 AssbinExporter.h
+ * ASSBIN Exporter Main Header
+ */
+#ifndef AI_ASSBINEXPORTER_H_INC
+#define AI_ASSBINEXPORTER_H_INC
+
+// nothing really needed here - reserved for future use like properties
+
+#endif

+ 687 - 0
assimplib.mod/assimp/code/AssbinLoader.cpp

@@ -0,0 +1,687 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2015, 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  AssbinLoader.cpp
+ *  @brief Implementation of the .assbin importer class
+ *
+ *  see assbin_chunks.h
+ */
+
+#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER
+
+// internal headers
+#include "AssbinLoader.h"
+#include "assbin_chunks.h"
+#include "MemoryIOWrapper.h"
+#include "../include/assimp/mesh.h"
+#include "../include/assimp/anim.h"
+#include "../include/assimp/scene.h"
+#include <boost/static_assert.hpp>
+
+#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
+#   include <zlib.h>
+#else
+#   include "../contrib/zlib/zlib.h"
+#endif
+
+using namespace Assimp;
+
+static const aiImporterDesc desc = {
+    ".assbin Importer",
+    "Gargaj / Conspiracy",
+    "",
+    "",
+    aiImporterFlags_SupportBinaryFlavour | aiImporterFlags_SupportCompressedFlavour,
+    0,
+    0,
+    0,
+    0,
+    "assbin"
+};
+
+const aiImporterDesc* AssbinImporter::GetInfo() const
+{
+    return &desc;
+}
+
+bool AssbinImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/ ) const
+{
+    IOStream * in = pIOHandler->Open(pFile);
+    if (!in)
+        return false;
+
+    char s[32];
+    in->Read( s, sizeof(char), 32 );
+
+    pIOHandler->Close(in);
+
+    return strncmp( s, "ASSIMP.binary-dump.", 19 ) == 0;
+}
+
+template <typename T>
+T Read(IOStream * stream)
+{
+    T t;
+    stream->Read( &t, sizeof(T), 1 );
+    return t;
+}
+
+template <>
+aiVector3D Read<aiVector3D>(IOStream * stream)
+{
+    aiVector3D v;
+    v.x = Read<float>(stream);
+    v.y = Read<float>(stream);
+    v.z = Read<float>(stream);
+    return v;
+}
+
+template <>
+aiColor4D Read<aiColor4D>(IOStream * stream)
+{
+    aiColor4D c;
+    c.r = Read<float>(stream);
+    c.g = Read<float>(stream);
+    c.b = Read<float>(stream);
+    c.a = Read<float>(stream);
+    return c;
+}
+
+template <>
+aiQuaternion Read<aiQuaternion>(IOStream * stream)
+{
+    aiQuaternion v;
+    v.w = Read<float>(stream);
+    v.x = Read<float>(stream);
+    v.y = Read<float>(stream);
+    v.z = Read<float>(stream);
+    return v;
+}
+
+template <>
+aiString Read<aiString>(IOStream * stream)
+{
+    aiString s;
+    stream->Read(&s.length,4,1);
+    stream->Read(s.data,s.length,1);
+    s.data[s.length] = 0;
+    return s;
+}
+
+template <>
+aiVertexWeight Read<aiVertexWeight>(IOStream * stream)
+{
+    aiVertexWeight w;
+    w.mVertexId = Read<unsigned int>(stream);
+    w.mWeight = Read<float>(stream);
+    return w;
+}
+
+template <>
+aiMatrix4x4 Read<aiMatrix4x4>(IOStream * stream)
+{
+    aiMatrix4x4 m;
+    for (unsigned int i = 0; i < 4;++i) {
+        for (unsigned int i2 = 0; i2 < 4;++i2) {
+            m[i][i2] = Read<float>(stream);
+        }
+    }
+    return m;
+}
+
+template <>
+aiVectorKey Read<aiVectorKey>(IOStream * stream)
+{
+    aiVectorKey v;
+    v.mTime = Read<double>(stream);
+    v.mValue = Read<aiVector3D>(stream);
+    return v;
+}
+
+template <>
+aiQuatKey Read<aiQuatKey>(IOStream * stream)
+{
+    aiQuatKey v;
+    v.mTime = Read<double>(stream);
+    v.mValue = Read<aiQuaternion>(stream);
+    return v;
+}
+
+template <typename T>
+void ReadArray(IOStream * stream, T * out, unsigned int size)
+{
+    for (unsigned int i=0; i<size; i++) out[i] = Read<T>(stream);
+}
+
+template <typename T> void ReadBounds( IOStream * stream, T* /*p*/, unsigned int n )
+{
+    // not sure what to do here, the data isn't really useful.
+    stream->Seek( sizeof(T) * n, aiOrigin_CUR );
+}
+
+void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** node )
+{
+    uint32_t chunkID = Read<uint32_t>(stream);
+    ai_assert(chunkID == ASSBIN_CHUNK_AINODE);
+    /*uint32_t size =*/ Read<uint32_t>(stream);
+
+    *node = new aiNode();
+
+    (*node)->mName = Read<aiString>(stream);
+    (*node)->mTransformation = Read<aiMatrix4x4>(stream);
+    (*node)->mNumChildren = Read<unsigned int>(stream);
+    (*node)->mNumMeshes = Read<unsigned int>(stream);
+
+    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)
+    {
+        (*node)->mChildren = new aiNode*[(*node)->mNumChildren];
+        for (unsigned int i = 0; i < (*node)->mNumChildren; ++i) {
+            ReadBinaryNode( stream, &(*node)->mChildren[i] );
+        }
+    }
+
+}
+
+// -----------------------------------------------------------------------------------
+void AssbinImporter::ReadBinaryBone( IOStream * stream, aiBone* b )
+{
+    uint32_t chunkID = Read<uint32_t>(stream);
+    ai_assert(chunkID == ASSBIN_CHUNK_AIBONE);
+    /*uint32_t size =*/ Read<uint32_t>(stream);
+
+    b->mName = Read<aiString>(stream);
+    b->mNumWeights = Read<unsigned int>(stream);
+    b->mOffsetMatrix = Read<aiMatrix4x4>(stream);
+
+    // for the moment we write dumb min/max values for the bones, too.
+    // maybe I'll add a better, hash-like solution later
+    if (shortened)
+    {
+        ReadBounds(stream,b->mWeights,b->mNumWeights);
+    } // else write as usual
+    else
+    {
+        b->mWeights = new aiVertexWeight[b->mNumWeights];
+        ReadArray<aiVertexWeight>(stream,b->mWeights,b->mNumWeights);
+    }
+}
+
+
+void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh )
+{
+    uint32_t chunkID = Read<uint32_t>(stream);
+    ai_assert(chunkID == ASSBIN_CHUNK_AIMESH);
+    /*uint32_t size =*/ Read<uint32_t>(stream);
+
+    mesh->mPrimitiveTypes = Read<unsigned int>(stream);
+    mesh->mNumVertices = Read<unsigned int>(stream);
+    mesh->mNumFaces = Read<unsigned int>(stream);
+    mesh->mNumBones = Read<unsigned int>(stream);
+    mesh->mMaterialIndex = Read<unsigned int>(stream);
+
+    // first of all, write bits for all existent vertex components
+    unsigned int c = Read<unsigned int>(stream);
+
+    if (c & ASSBIN_MESH_HAS_POSITIONS)
+    {
+        if (shortened) {
+            ReadBounds(stream,mesh->mVertices,mesh->mNumVertices);
+        } // else write as usual
+        else
+        {
+            mesh->mVertices = new aiVector3D[mesh->mNumVertices];
+            ReadArray<aiVector3D>(stream,mesh->mVertices,mesh->mNumVertices);
+        }
+    }
+    if (c & ASSBIN_MESH_HAS_NORMALS)
+    {
+        if (shortened) {
+            ReadBounds(stream,mesh->mNormals,mesh->mNumVertices);
+        } // else write as usual
+        else
+        {
+            mesh->mNormals = new aiVector3D[mesh->mNumVertices];
+            ReadArray<aiVector3D>(stream,mesh->mNormals,mesh->mNumVertices);
+        }
+    }
+    if (c & ASSBIN_MESH_HAS_TANGENTS_AND_BITANGENTS)
+    {
+        if (shortened) {
+            ReadBounds(stream,mesh->mTangents,mesh->mNumVertices);
+            ReadBounds(stream,mesh->mBitangents,mesh->mNumVertices);
+        } // else write as usual
+        else
+        {
+            mesh->mTangents = new aiVector3D[mesh->mNumVertices];
+            ReadArray<aiVector3D>(stream,mesh->mTangents,mesh->mNumVertices);
+            mesh->mBitangents = new aiVector3D[mesh->mNumVertices];
+            ReadArray<aiVector3D>(stream,mesh->mBitangents,mesh->mNumVertices);
+        }
+    }
+    for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_COLOR_SETS;++n)
+    {
+        if (!(c & ASSBIN_MESH_HAS_COLOR(n)))
+            break;
+
+        if (shortened)
+        {
+            ReadBounds(stream,mesh->mColors[n],mesh->mNumVertices);
+        } // else write as usual
+        else
+        {
+            mesh->mColors[n] = new aiColor4D[mesh->mNumVertices];
+            ReadArray<aiColor4D>(stream,mesh->mColors[n],mesh->mNumVertices);
+        }
+    }
+    for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n)
+    {
+        if (!(c & ASSBIN_MESH_HAS_TEXCOORD(n)))
+            break;
+
+        // write number of UV components
+        mesh->mNumUVComponents[n] = Read<unsigned int>(stream);
+
+        if (shortened) {
+            ReadBounds(stream,mesh->mTextureCoords[n],mesh->mNumVertices);
+        } // else write as usual
+        else
+        {
+            mesh->mTextureCoords[n] = new aiVector3D[mesh->mNumVertices];
+            ReadArray<aiVector3D>(stream,mesh->mTextureCoords[n],mesh->mNumVertices);
+        }
+    }
+
+    // write faces. There are no floating-point calculations involved
+    // in these, so we can write a simple hash over the face data
+    // to the dump file. We generate a single 32 Bit hash for 512 faces
+    // using Assimp's standard hashing function.
+    if (shortened) {
+        Read<unsigned int>(stream);
+    }
+    else // else write as usual
+    {
+        // if there are less than 2^16 vertices, we can simply use 16 bit integers ...
+        mesh->mFaces = new aiFace[mesh->mNumFaces];
+        for (unsigned int i = 0; i < mesh->mNumFaces;++i) {
+            aiFace& f = mesh->mFaces[i];
+
+            BOOST_STATIC_ASSERT(AI_MAX_FACE_INDICES <= 0xffff);
+            f.mNumIndices = Read<uint16_t>(stream);
+            f.mIndices = new unsigned int[f.mNumIndices];
+
+            for (unsigned int a = 0; a < f.mNumIndices;++a) {
+                if (mesh->mNumVertices < (1u<<16))
+                {
+                    f.mIndices[a] = Read<uint16_t>(stream);
+                }
+                else
+                {
+                    f.mIndices[a] = Read<unsigned int>(stream);
+                }
+            }
+        }
+    }
+
+    // write bones
+    if (mesh->mNumBones) {
+        mesh->mBones = new C_STRUCT aiBone*[mesh->mNumBones];
+        for (unsigned int a = 0; a < mesh->mNumBones;++a) {
+            mesh->mBones[a] = new aiBone();
+            ReadBinaryBone(stream,mesh->mBones[a]);
+        }
+    }
+}
+
+void AssbinImporter::ReadBinaryMaterialProperty(IOStream * stream, aiMaterialProperty* prop)
+{
+    uint32_t chunkID = Read<uint32_t>(stream);
+    ai_assert(chunkID == ASSBIN_CHUNK_AIMATERIALPROPERTY);
+    /*uint32_t size =*/ Read<uint32_t>(stream);
+
+    prop->mKey = Read<aiString>(stream);
+    prop->mSemantic = Read<unsigned int>(stream);
+    prop->mIndex = Read<unsigned int>(stream);
+
+    prop->mDataLength = Read<unsigned int>(stream);
+    prop->mType = (aiPropertyTypeInfo)Read<unsigned int>(stream);
+    prop->mData = new char [ prop->mDataLength ];
+    stream->Read(prop->mData,1,prop->mDataLength);
+}
+
+// -----------------------------------------------------------------------------------
+void AssbinImporter::ReadBinaryMaterial(IOStream * stream, aiMaterial* mat)
+{
+    uint32_t chunkID = Read<uint32_t>(stream);
+    ai_assert(chunkID == ASSBIN_CHUNK_AIMATERIAL);
+    /*uint32_t size =*/ Read<uint32_t>(stream);
+
+    mat->mNumAllocated = mat->mNumProperties = Read<unsigned int>(stream);
+    if (mat->mNumProperties)
+    {
+        if (mat->mProperties)
+        {
+            delete[] mat->mProperties;
+        }
+        mat->mProperties = new aiMaterialProperty*[mat->mNumProperties];
+        for (unsigned int i = 0; i < mat->mNumProperties;++i) {
+            mat->mProperties[i] = new aiMaterialProperty();
+            ReadBinaryMaterialProperty( stream, mat->mProperties[i]);
+        }
+    }
+}
+
+// -----------------------------------------------------------------------------------
+void AssbinImporter::ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd)
+{
+    uint32_t chunkID = Read<uint32_t>(stream);
+    ai_assert(chunkID == ASSBIN_CHUNK_AINODEANIM);
+    /*uint32_t size =*/ Read<uint32_t>(stream);
+
+    nd->mNodeName = Read<aiString>(stream);
+    nd->mNumPositionKeys = Read<unsigned int>(stream);
+    nd->mNumRotationKeys = Read<unsigned int>(stream);
+    nd->mNumScalingKeys = Read<unsigned int>(stream);
+    nd->mPreState = (aiAnimBehaviour)Read<unsigned int>(stream);
+    nd->mPostState = (aiAnimBehaviour)Read<unsigned int>(stream);
+
+    if (nd->mNumPositionKeys) {
+        if (shortened) {
+            ReadBounds(stream,nd->mPositionKeys,nd->mNumPositionKeys);
+
+        } // else write as usual
+        else {
+            nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys];
+            ReadArray<aiVectorKey>(stream,nd->mPositionKeys,nd->mNumPositionKeys);
+        }
+    }
+    if (nd->mNumRotationKeys) {
+        if (shortened) {
+            ReadBounds(stream,nd->mRotationKeys,nd->mNumRotationKeys);
+
+        } // else write as usual
+        else
+        {
+            nd->mRotationKeys = new aiQuatKey[nd->mNumRotationKeys];
+            ReadArray<aiQuatKey>(stream,nd->mRotationKeys,nd->mNumRotationKeys);
+        }
+    }
+    if (nd->mNumScalingKeys) {
+        if (shortened) {
+            ReadBounds(stream,nd->mScalingKeys,nd->mNumScalingKeys);
+
+        } // else write as usual
+        else
+        {
+            nd->mScalingKeys = new aiVectorKey[nd->mNumScalingKeys];
+            ReadArray<aiVectorKey>(stream,nd->mScalingKeys,nd->mNumScalingKeys);
+        }
+    }
+}
+
+
+// -----------------------------------------------------------------------------------
+void AssbinImporter::ReadBinaryAnim( IOStream * stream, aiAnimation* anim )
+{
+    uint32_t chunkID = Read<uint32_t>(stream);
+    ai_assert(chunkID == ASSBIN_CHUNK_AIANIMATION);
+    /*uint32_t size =*/ Read<uint32_t>(stream);
+
+    anim->mName = Read<aiString> (stream);
+    anim->mDuration = Read<double> (stream);
+    anim->mTicksPerSecond = Read<double> (stream);
+    anim->mNumChannels = Read<unsigned int>(stream);
+
+    if (anim->mNumChannels)
+    {
+        anim->mChannels = new aiNodeAnim*[ anim->mNumChannels ];
+        for (unsigned int a = 0; a < anim->mNumChannels;++a) {
+            anim->mChannels[a] = new aiNodeAnim();
+            ReadBinaryNodeAnim(stream,anim->mChannels[a]);
+        }
+    }
+}
+
+void AssbinImporter::ReadBinaryTexture(IOStream * stream, aiTexture* tex)
+{
+    uint32_t chunkID = Read<uint32_t>(stream);
+    ai_assert(chunkID == ASSBIN_CHUNK_AITEXTURE);
+    /*uint32_t size =*/ Read<uint32_t>(stream);
+
+    tex->mWidth = Read<unsigned int>(stream);
+    tex->mHeight = Read<unsigned int>(stream);
+    stream->Read( tex->achFormatHint, sizeof(char), 4 );
+
+    if(!shortened) {
+        if (!tex->mHeight) {
+            tex->pcData = new aiTexel[ tex->mWidth ];
+            stream->Read(tex->pcData,1,tex->mWidth);
+        }
+        else {
+            tex->pcData = new aiTexel[ tex->mWidth*tex->mHeight ];
+            stream->Read(tex->pcData,1,tex->mWidth*tex->mHeight*4);
+        }
+    }
+
+}
+
+// -----------------------------------------------------------------------------------
+void AssbinImporter::ReadBinaryLight( IOStream * stream, aiLight* l )
+{
+    uint32_t chunkID = Read<uint32_t>(stream);
+    ai_assert(chunkID == ASSBIN_CHUNK_AILIGHT);
+    /*uint32_t size =*/ Read<uint32_t>(stream);
+
+    l->mName = Read<aiString>(stream);
+    l->mType = (aiLightSourceType)Read<unsigned int>(stream);
+
+    if (l->mType != aiLightSource_DIRECTIONAL) {
+        l->mAttenuationConstant = Read<float>(stream);
+        l->mAttenuationLinear = Read<float>(stream);
+        l->mAttenuationQuadratic = Read<float>(stream);
+    }
+
+    l->mColorDiffuse = Read<aiColor3D>(stream);
+    l->mColorSpecular = Read<aiColor3D>(stream);
+    l->mColorAmbient = Read<aiColor3D>(stream);
+
+    if (l->mType == aiLightSource_SPOT) {
+        l->mAngleInnerCone = Read<float>(stream);
+        l->mAngleOuterCone = Read<float>(stream);
+    }
+
+}
+
+// -----------------------------------------------------------------------------------
+void AssbinImporter::ReadBinaryCamera( IOStream * stream, aiCamera* cam )
+{
+    uint32_t chunkID = Read<uint32_t>(stream);
+    ai_assert(chunkID == ASSBIN_CHUNK_AICAMERA);
+    /*uint32_t size =*/ Read<uint32_t>(stream);
+
+    cam->mName = Read<aiString>(stream);
+    cam->mPosition = Read<aiVector3D>(stream);
+    cam->mLookAt = Read<aiVector3D>(stream);
+    cam->mUp = Read<aiVector3D>(stream);
+    cam->mHorizontalFOV = Read<float>(stream);
+    cam->mClipPlaneNear = Read<float>(stream);
+    cam->mClipPlaneFar = Read<float>(stream);
+    cam->mAspect = Read<float>(stream);
+}
+
+void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene )
+{
+    uint32_t chunkID = Read<uint32_t>(stream);
+    ai_assert(chunkID == ASSBIN_CHUNK_AISCENE);
+    /*uint32_t size =*/ Read<uint32_t>(stream);
+
+    scene->mFlags         = Read<unsigned int>(stream);
+    scene->mNumMeshes     = Read<unsigned int>(stream);
+    scene->mNumMaterials  = Read<unsigned int>(stream);
+    scene->mNumAnimations = Read<unsigned int>(stream);
+    scene->mNumTextures   = Read<unsigned int>(stream);
+    scene->mNumLights     = Read<unsigned int>(stream);
+    scene->mNumCameras    = Read<unsigned int>(stream);
+
+    // Read node graph
+    scene->mRootNode = new aiNode[1];
+    ReadBinaryNode( stream, &scene->mRootNode );
+
+    // Read all meshes
+    if (scene->mNumMeshes)
+    {
+        scene->mMeshes = new aiMesh*[scene->mNumMeshes];
+        for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
+            scene->mMeshes[i] = new aiMesh();
+            ReadBinaryMesh( stream,scene->mMeshes[i]);
+        }
+    }
+
+    // Read materials
+    if (scene->mNumMaterials)
+    {
+        scene->mMaterials = new aiMaterial*[scene->mNumMaterials];
+        for (unsigned int i = 0; i< scene->mNumMaterials; ++i) {
+            scene->mMaterials[i] = new aiMaterial();
+            ReadBinaryMaterial(stream,scene->mMaterials[i]);
+        }
+    }
+
+    // Read all animations
+    if (scene->mNumAnimations)
+    {
+        scene->mAnimations = new aiAnimation*[scene->mNumAnimations];
+        for (unsigned int i = 0; i < scene->mNumAnimations;++i) {
+            scene->mAnimations[i] = new aiAnimation();
+            ReadBinaryAnim(stream,scene->mAnimations[i]);
+        }
+    }
+
+    // Read all textures
+    if (scene->mNumTextures)
+    {
+        scene->mTextures = new aiTexture*[scene->mNumTextures];
+        for (unsigned int i = 0; i < scene->mNumTextures;++i) {
+            scene->mTextures[i] = new aiTexture();
+            ReadBinaryTexture(stream,scene->mTextures[i]);
+        }
+    }
+
+    // Read lights
+    if (scene->mNumLights)
+    {
+        scene->mLights = new aiLight*[scene->mNumLights];
+        for (unsigned int i = 0; i < scene->mNumLights;++i) {
+            scene->mLights[i] = new aiLight();
+            ReadBinaryLight(stream,scene->mLights[i]);
+        }
+    }
+
+    // Read cameras
+    if (scene->mNumCameras)
+    {
+        scene->mCameras = new aiCamera*[scene->mNumCameras];
+        for (unsigned int i = 0; i < scene->mNumCameras;++i) {
+            scene->mCameras[i] = new aiCamera();
+            ReadBinaryCamera(stream,scene->mCameras[i]);
+        }
+    }
+
+}
+
+void AssbinImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler )
+{
+    IOStream * stream = pIOHandler->Open(pFile,"rb");
+    if (!stream)
+        return;
+
+    stream->Seek( 44, aiOrigin_CUR ); // signature
+
+    /*unsigned int versionMajor =*/ Read<unsigned int>(stream);
+    /*unsigned int versionMinor =*/ Read<unsigned int>(stream);
+    /*unsigned int versionRevision =*/ Read<unsigned int>(stream);
+    /*unsigned int compileFlags =*/ Read<unsigned int>(stream);
+
+    shortened = Read<uint16_t>(stream) > 0;
+    compressed = Read<uint16_t>(stream) > 0;
+
+    if (shortened)
+        throw DeadlyImportError( "Shortened binaries are not supported!" );
+
+    stream->Seek( 256, aiOrigin_CUR ); // original filename
+    stream->Seek( 128, aiOrigin_CUR ); // options
+    stream->Seek( 64, aiOrigin_CUR ); // padding
+
+    if (compressed)
+    {
+        uLongf uncompressedSize = Read<uint32_t>(stream);
+        uLongf compressedSize = stream->FileSize() - stream->Tell();
+
+        unsigned char * compressedData = new unsigned char[ compressedSize ];
+        stream->Read( compressedData, 1, compressedSize );
+
+        unsigned char * uncompressedData = new unsigned char[ uncompressedSize ];
+
+        uncompress( uncompressedData, &uncompressedSize, compressedData, compressedSize );
+
+        MemoryIOStream io( uncompressedData, uncompressedSize );
+
+        ReadBinaryScene(&io,pScene);
+
+        delete[] uncompressedData;
+        delete[] compressedData;
+    }
+    else
+    {
+        ReadBinaryScene(stream,pScene);
+    }
+
+    pIOHandler->Close(stream);
+}
+
+#endif // !! ASSIMP_BUILD_NO_ASSBIN_IMPORTER

+ 105 - 0
assimplib.mod/assimp/code/AssbinLoader.h

@@ -0,0 +1,105 @@
+
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2015, 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  AssbinLoader.h
+ *  @brief .assbin File format loader
+ */
+#ifndef AI_ASSBINIMPORTER_H_INC
+#define AI_ASSBINIMPORTER_H_INC
+
+#include "BaseImporter.h"
+#include "../include/assimp/types.h"
+
+struct aiMesh;
+struct aiNode;
+struct aiBone;
+struct aiMaterial;
+struct aiMaterialProperty;
+struct aiNodeAnim;
+struct aiAnimation;
+struct aiTexture;
+struct aiLight;
+struct aiCamera;
+
+#ifndef ASSIMP_BUILD_NO_ASSBIN_IMPORTER
+
+namespace Assimp    {
+
+// ---------------------------------------------------------------------------------
+/** Importer class for 3D Studio r3 and r4 3DS files
+ */
+class AssbinImporter : public BaseImporter
+{
+private:
+  bool shortened;
+  bool compressed;
+protected:
+
+public:
+  virtual bool CanRead(
+    const std::string& pFile,
+    IOSystem* pIOHandler,
+    bool checkSig
+    ) const;
+  virtual const aiImporterDesc* GetInfo() const;
+  virtual void InternReadFile(
+    const std::string& pFile,
+    aiScene* pScene,
+    IOSystem* pIOHandler
+    );
+  void ReadBinaryScene( IOStream * stream, aiScene* pScene );
+  void ReadBinaryNode( IOStream * stream, aiNode** mRootNode );
+  void ReadBinaryMesh( IOStream * stream, aiMesh* mesh );
+  void ReadBinaryBone( IOStream * stream, aiBone* bone );
+  void ReadBinaryMaterial(IOStream * stream, aiMaterial* mat);
+  void ReadBinaryMaterialProperty(IOStream * stream, aiMaterialProperty* prop);
+  void ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd);
+  void ReadBinaryAnim( IOStream * stream, aiAnimation* anim );
+  void ReadBinaryTexture(IOStream * stream, aiTexture* tex);
+  void ReadBinaryLight( IOStream * stream, aiLight* l );
+  void ReadBinaryCamera( IOStream * stream, aiCamera* cam );
+};
+
+} // end of namespace Assimp
+
+#endif // !! ASSIMP_BUILD_NO_ASSBIN_IMPORTER
+
+#endif // AI_ASSBINIMPORTER_H_INC

+ 363 - 318
assimplib.mod/assimp/code/Assimp.cpp

@@ -3,12 +3,12 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -25,16 +25,16 @@ conditions are met:
   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 
+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 
+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 
+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 
+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.
 ---------------------------------------------------------------------------
 */
@@ -42,49 +42,61 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *  @brief Implementation of the Plain-C API
  */
 
-#include "AssimpPCH.h"
-#include "../include/assimp/cimport.h"
+#include <assimp/cimport.h>
+#include <assimp/LogStream.hpp>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/Importer.hpp>
+#include <assimp/importerdesc.h>
+#include <assimp/scene.h>
 
 #include "GenericProperty.h"
 #include "CInterfaceIOWrapper.h"
 #include "Importer.h"
+#include "Exceptional.h"
+#include "ScenePrivate.h"
+#include "BaseImporter.h"
+#include <list>
 
 // ------------------------------------------------------------------------------------------------
 #ifndef ASSIMP_BUILD_SINGLETHREADED
-#	include <boost/thread/thread.hpp>
-#	include <boost/thread/mutex.hpp>
+#   include <boost/thread/thread.hpp>
+#   include <boost/thread/mutex.hpp>
 #endif
 // ------------------------------------------------------------------------------------------------
 using namespace Assimp;
 
 namespace Assimp
 {
-	// underlying structure for aiPropertyStore
-	typedef BatchLoader::PropertyMap PropertyMap;
+    // underlying structure for aiPropertyStore
+    typedef BatchLoader::PropertyMap PropertyMap;
 
-	/** Stores the LogStream objects for all active C log streams */
-	struct mpred {
-		bool operator  () (const aiLogStream& s0, const aiLogStream& s1) const  {
-			return s0.callback<s1.callback&&s0.user<s1.user;
-		}
-	};
-	typedef std::map<aiLogStream, Assimp::LogStream*, mpred> LogStreamMap;
+    /** Stores the LogStream objects for all active C log streams */
+    struct mpred {
+        bool operator  () (const aiLogStream& s0, const aiLogStream& s1) const  {
+            return s0.callback<s1.callback&&s0.user<s1.user;
+        }
+    };
+    typedef std::map<aiLogStream, Assimp::LogStream*, mpred> LogStreamMap;
 
-	/** Stores the LogStream objects allocated by #aiGetPredefinedLogStream */
-	typedef std::list<Assimp::LogStream*> PredefLogStreamMap;
+    /** Stores the LogStream objects allocated by #aiGetPredefinedLogStream */
+    typedef std::list<Assimp::LogStream*> PredefLogStreamMap;
 
-	/** Local storage of all active log streams */
-	static LogStreamMap gActiveLogStreams;
+    /** Local storage of all active log streams */
+    static LogStreamMap gActiveLogStreams;
 
-	/** Local storage of LogStreams allocated by #aiGetPredefinedLogStream */
-	static PredefLogStreamMap gPredefinedStreams;
+    /** Local storage of LogStreams allocated by #aiGetPredefinedLogStream */
+    static PredefLogStreamMap gPredefinedStreams;
 
-	/** Error message of the last failed import process */
-	static std::string gLastErrorString;
+    /** Error message of the last failed import process */
+    static std::string gLastErrorString;
 
-	/** Verbose logging active or not? */
-	static aiBool gVerboseLogging = false;
-}
+    /** Verbose logging active or not? */
+    static aiBool gVerboseLogging = false;
+
+    /** will return all registered importers. */
+    void GetImporterInstanceList(std::vector< BaseImporter* >& out);
+
+} // namespace assimp
 
 
 #ifndef ASSIMP_BUILD_SINGLETHREADED
@@ -98,512 +110,545 @@ static boost::mutex gLogStreamMutex;
 class LogToCallbackRedirector : public LogStream
 {
 public:
-	LogToCallbackRedirector(const aiLogStream& s) 
-		: stream (s)	{
-			ai_assert(NULL != s.callback);
-	}
+    explicit LogToCallbackRedirector(const aiLogStream& s)
+        : stream (s)    {
+            ai_assert(NULL != s.callback);
+    }
 
-	~LogToCallbackRedirector()	{
+    ~LogToCallbackRedirector()  {
 #ifndef ASSIMP_BUILD_SINGLETHREADED
-		boost::mutex::scoped_lock lock(gLogStreamMutex);
+        boost::mutex::scoped_lock lock(gLogStreamMutex);
 #endif
-		// (HACK) Check whether the 'stream.user' pointer points to a
-		// custom LogStream allocated by #aiGetPredefinedLogStream.
-		// In this case, we need to delete it, too. Of course, this 
-		// might cause strange problems, but the chance is quite low.
+        // (HACK) Check whether the 'stream.user' pointer points to a
+        // custom LogStream allocated by #aiGetPredefinedLogStream.
+        // In this case, we need to delete it, too. Of course, this
+        // might cause strange problems, but the chance is quite low.
 
-		PredefLogStreamMap::iterator it = std::find(gPredefinedStreams.begin(), 
-			gPredefinedStreams.end(), (Assimp::LogStream*)stream.user);
+        PredefLogStreamMap::iterator it = std::find(gPredefinedStreams.begin(),
+            gPredefinedStreams.end(), (Assimp::LogStream*)stream.user);
 
-		if (it != gPredefinedStreams.end()) {
-			delete *it;
-			gPredefinedStreams.erase(it);
-		}
-	}
+        if (it != gPredefinedStreams.end()) {
+            delete *it;
+            gPredefinedStreams.erase(it);
+        }
+    }
 
-	/** @copydoc LogStream::write */
-	void write(const char* message)	{
-		stream.callback(message,stream.user);
-	}
+    /** @copydoc LogStream::write */
+    void write(const char* message) {
+        stream.callback(message,stream.user);
+    }
 
 private:
-	aiLogStream stream;
+    aiLogStream stream;
 };
 
 // ------------------------------------------------------------------------------------------------
 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");
+    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");
 
-	assert(false);
+    assert(false);
 }
 
 // ------------------------------------------------------------------------------------------------
-// Reads the given file and returns its content. 
+// Reads the given file and returns its content.
 const aiScene* aiImportFile( const char* pFile, unsigned int pFlags)
 {
-	return aiImportFileEx(pFile,pFlags,NULL);
+    return aiImportFileEx(pFile,pFlags,NULL);
 }
 
 // ------------------------------------------------------------------------------------------------
 const aiScene* aiImportFileEx( const char* pFile, unsigned int pFlags,  aiFileIO* pFS)
 {
-	return aiImportFileExWithProperties(pFile, pFlags, pFS, NULL);
+    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);
+    ai_assert(NULL != pFile);
 
-	const aiScene* scene = NULL;
-	ASSIMP_BEGIN_EXCEPTION_REGION();
+    const aiScene* scene = NULL;
+    ASSIMP_BEGIN_EXCEPTION_REGION();
 
-	// create an Importer for this file
-	Assimp::Importer* imp = new Assimp::Importer();
+    // create an Importer for this file
+    Assimp::Importer* imp = new Assimp::Importer();
 
-	// copy properties
-	if(props) {
-		const PropertyMap* pp = reinterpret_cast<const PropertyMap*>(props);
-		ImporterPimpl* pimpl = imp->Pimpl();
-		pimpl->mIntProperties = pp->ints;
-		pimpl->mFloatProperties = pp->floats;
-		pimpl->mStringProperties = pp->strings;
-		pimpl->mMatrixProperties = pp->matrices;
-	}
-	// setup a custom IO system if necessary
-	if (pFS)	{
-		imp->SetIOHandler( new CIOSystemWrapper (pFS) );
-	}
+    // copy properties
+    if(props) {
+        const PropertyMap* pp = reinterpret_cast<const PropertyMap*>(props);
+        ImporterPimpl* pimpl = imp->Pimpl();
+        pimpl->mIntProperties = pp->ints;
+        pimpl->mFloatProperties = pp->floats;
+        pimpl->mStringProperties = pp->strings;
+        pimpl->mMatrixProperties = pp->matrices;
+    }
+    // setup a custom IO system if necessary
+    if (pFS)    {
+        imp->SetIOHandler( new CIOSystemWrapper (pFS) );
+    }
 
-	// and have it read the file
-	scene = imp->ReadFile( pFile, pFlags);
+    // and have it read the file
+    scene = imp->ReadFile( pFile, pFlags);
 
-	// if succeeded, store the importer in the scene and keep it alive
-	if( scene)	{
-		ScenePrivateData* priv = const_cast<ScenePrivateData*>( ScenePriv(scene) );
-		priv->mOrigImporter = imp;
-	} 
-	else	{
-		// if failed, extract error code and destroy the import
-		gLastErrorString = imp->GetErrorString();
-		delete imp;
-	}
+    // if succeeded, store the importer in the scene and keep it alive
+    if( scene)  {
+        ScenePrivateData* priv = const_cast<ScenePrivateData*>( ScenePriv(scene) );
+        priv->mOrigImporter = imp;
+    }
+    else    {
+        // if failed, extract error code and destroy the import
+        gLastErrorString = imp->GetErrorString();
+        delete imp;
+    }
 
-	// return imported data. If the import failed the pointer is NULL anyways
-	ASSIMP_END_EXCEPTION_REGION(const aiScene*);
-	return scene;
+    // return imported data. If the import failed the pointer is NULL anyways
+    ASSIMP_END_EXCEPTION_REGION(const aiScene*);
+    return scene;
 }
 
 // ------------------------------------------------------------------------------------------------
-const aiScene* aiImportFileFromMemory( 
-	const char* pBuffer,
-	unsigned int pLength,
-	unsigned int pFlags,
-	const char* pHint)
+const aiScene* aiImportFileFromMemory(
+    const char* pBuffer,
+    unsigned int pLength,
+    unsigned int pFlags,
+    const char* pHint)
 {
-	return aiImportFileFromMemoryWithProperties(pBuffer, pLength, pFlags, pHint, NULL);
+    return aiImportFileFromMemoryWithProperties(pBuffer, pLength, pFlags, pHint, NULL);
 }
 
 // ------------------------------------------------------------------------------------------------
-const aiScene* aiImportFileFromMemoryWithProperties( 
-	const char* pBuffer,
-	unsigned int pLength,
-	unsigned int pFlags,
-	const char* pHint,
-	const aiPropertyStore* props)
+const aiScene* aiImportFileFromMemoryWithProperties(
+    const char* pBuffer,
+    unsigned int pLength,
+    unsigned int pFlags,
+    const char* pHint,
+    const aiPropertyStore* props)
 {
-	ai_assert(NULL != pBuffer && 0 != pLength);
+    ai_assert(NULL != pBuffer && 0 != pLength);
 
-	const aiScene* scene = NULL;
-	ASSIMP_BEGIN_EXCEPTION_REGION();
+    const aiScene* scene = NULL;
+    ASSIMP_BEGIN_EXCEPTION_REGION();
 
-	// create an Importer for this file
-	Assimp::Importer* imp = new Assimp::Importer();
+    // create an Importer for this file
+    Assimp::Importer* imp = new Assimp::Importer();
 
-	// copy properties
-	if(props) {
-		const PropertyMap* pp = reinterpret_cast<const PropertyMap*>(props);
-		ImporterPimpl* pimpl = imp->Pimpl();
-		pimpl->mIntProperties = pp->ints;
-		pimpl->mFloatProperties = pp->floats;
-		pimpl->mStringProperties = pp->strings;
-		pimpl->mMatrixProperties = pp->matrices;
-	}
+    // copy properties
+    if(props) {
+        const PropertyMap* pp = reinterpret_cast<const PropertyMap*>(props);
+        ImporterPimpl* pimpl = imp->Pimpl();
+        pimpl->mIntProperties = pp->ints;
+        pimpl->mFloatProperties = pp->floats;
+        pimpl->mStringProperties = pp->strings;
+        pimpl->mMatrixProperties = pp->matrices;
+    }
 
-	// and have it read the file from the memory buffer
-	scene = imp->ReadFileFromMemory( pBuffer, pLength, pFlags,pHint);
+    // and have it read the file from the memory buffer
+    scene = imp->ReadFileFromMemory( pBuffer, pLength, pFlags,pHint);
 
-	// if succeeded, store the importer in the scene and keep it alive
-	if( scene)	{
-		 ScenePrivateData* priv = const_cast<ScenePrivateData*>( ScenePriv(scene) );
-		 priv->mOrigImporter = imp;
-	} 
-	else	{
-		// if failed, extract error code and destroy the import
-		gLastErrorString = imp->GetErrorString();
-		delete imp;
-	}
-	// return imported data. If the import failed the pointer is NULL anyways
-	ASSIMP_END_EXCEPTION_REGION(const aiScene*);
-	return scene;
+    // if succeeded, store the importer in the scene and keep it alive
+    if( scene)  {
+         ScenePrivateData* priv = const_cast<ScenePrivateData*>( ScenePriv(scene) );
+         priv->mOrigImporter = imp;
+    }
+    else    {
+        // if failed, extract error code and destroy the import
+        gLastErrorString = imp->GetErrorString();
+        delete imp;
+    }
+    // return imported data. If the import failed the pointer is NULL anyways
+    ASSIMP_END_EXCEPTION_REGION(const aiScene*);
+    return scene;
 }
 
-// ------------------------------------------------------------------------------------------------
-// Releases all resources associated with the given import process. 
+// ------------------------------------------------------------------------------------------------
+// Releases all resources associated with the given import process.
 void aiReleaseImport( const aiScene* pScene)
 {
-	if (!pScene) {
-		return;
-	}
-
-	ASSIMP_BEGIN_EXCEPTION_REGION();
-	
-	// find the importer associated with this data
-	const ScenePrivateData* priv = ScenePriv(pScene);
-	if( !priv || !priv->mOrigImporter)	{
-		delete pScene;
-	}
-	else {
-		// deleting the Importer also deletes the scene
-		// Note: the reason that this is not written as 'delete priv->mOrigImporter'
-		// is a suspected bug in gcc 4.4+ (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52339)
-		Importer* importer = priv->mOrigImporter;
-		delete importer;
-	}
-	
-	ASSIMP_END_EXCEPTION_REGION(void);
+    if (!pScene) {
+        return;
+    }
+
+    ASSIMP_BEGIN_EXCEPTION_REGION();
+
+    // find the importer associated with this data
+    const ScenePrivateData* priv = ScenePriv(pScene);
+    if( !priv || !priv->mOrigImporter)  {
+        delete pScene;
+    }
+    else {
+        // deleting the Importer also deletes the scene
+        // Note: the reason that this is not written as 'delete priv->mOrigImporter'
+        // is a suspected bug in gcc 4.4+ (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52339)
+        Importer* importer = priv->mOrigImporter;
+        delete importer;
+    }
+
+    ASSIMP_END_EXCEPTION_REGION(void);
 }
 
 // ------------------------------------------------------------------------------------------------
 ASSIMP_API const aiScene* aiApplyPostProcessing(const aiScene* pScene,
-	unsigned int pFlags)
+    unsigned int pFlags)
 {
-	const aiScene* sc = NULL;
-	
+    const aiScene* sc = NULL;
+
 
-	ASSIMP_BEGIN_EXCEPTION_REGION();
+    ASSIMP_BEGIN_EXCEPTION_REGION();
 
-	// find the importer associated with this data
-	const ScenePrivateData* priv = ScenePriv(pScene);
-	if( !priv || !priv->mOrigImporter)	{
-		ReportSceneNotFoundError();
-		return NULL;
-	}
+    // find the importer associated with this data
+    const ScenePrivateData* priv = ScenePriv(pScene);
+    if( !priv || !priv->mOrigImporter)  {
+        ReportSceneNotFoundError();
+        return NULL;
+    }
 
-	sc = priv->mOrigImporter->ApplyPostProcessing(pFlags);
+    sc = priv->mOrigImporter->ApplyPostProcessing(pFlags);
 
-	if (!sc) {
-		aiReleaseImport(pScene);
-		return NULL;
-	}
+    if (!sc) {
+        aiReleaseImport(pScene);
+        return NULL;
+    }
 
-	ASSIMP_END_EXCEPTION_REGION(const aiScene*);
-	return sc;
+    ASSIMP_END_EXCEPTION_REGION(const aiScene*);
+    return sc;
 }
 
 // ------------------------------------------------------------------------------------------------
 void CallbackToLogRedirector (const char* msg, char* dt)
 {
-	ai_assert(NULL != msg && NULL != dt);
-	LogStream* s = (LogStream*)dt;
+    ai_assert(NULL != msg && NULL != dt);
+    LogStream* s = (LogStream*)dt;
 
-	s->write(msg);
+    s->write(msg);
 }
 
 // ------------------------------------------------------------------------------------------------
 ASSIMP_API aiLogStream aiGetPredefinedLogStream(aiDefaultLogStream pStream,const char* file)
 {
-	aiLogStream sout;
+    aiLogStream sout;
 
-	ASSIMP_BEGIN_EXCEPTION_REGION();
-	LogStream* stream = LogStream::createDefaultStream(pStream,file);
-	if (!stream) {
-		sout.callback = NULL;
-		sout.user = NULL;
-	}
-	else {
-		sout.callback = &CallbackToLogRedirector;
-		sout.user = (char*)stream;
-	}
-	gPredefinedStreams.push_back(stream);
-	ASSIMP_END_EXCEPTION_REGION(aiLogStream);
-	return sout;
+    ASSIMP_BEGIN_EXCEPTION_REGION();
+    LogStream* stream = LogStream::createDefaultStream(pStream,file);
+    if (!stream) {
+        sout.callback = NULL;
+        sout.user = NULL;
+    }
+    else {
+        sout.callback = &CallbackToLogRedirector;
+        sout.user = (char*)stream;
+    }
+    gPredefinedStreams.push_back(stream);
+    ASSIMP_END_EXCEPTION_REGION(aiLogStream);
+    return sout;
 }
 
 // ------------------------------------------------------------------------------------------------
 ASSIMP_API void aiAttachLogStream( const aiLogStream* stream )
 {
-	ASSIMP_BEGIN_EXCEPTION_REGION();
+    ASSIMP_BEGIN_EXCEPTION_REGION();
 
 #ifndef ASSIMP_BUILD_SINGLETHREADED
-	boost::mutex::scoped_lock lock(gLogStreamMutex);
+    boost::mutex::scoped_lock lock(gLogStreamMutex);
 #endif
 
-	LogStream* lg = new LogToCallbackRedirector(*stream);
-	gActiveLogStreams[*stream] = lg;
+    LogStream* lg = new LogToCallbackRedirector(*stream);
+    gActiveLogStreams[*stream] = lg;
 
-	if (DefaultLogger::isNullLogger()) {
-		DefaultLogger::create(NULL,(gVerboseLogging == AI_TRUE ? Logger::VERBOSE : Logger::NORMAL));
-	}
-	DefaultLogger::get()->attachStream(lg);
-	ASSIMP_END_EXCEPTION_REGION(void);
+    if (DefaultLogger::isNullLogger()) {
+        DefaultLogger::create(NULL,(gVerboseLogging == AI_TRUE ? Logger::VERBOSE : Logger::NORMAL));
+    }
+    DefaultLogger::get()->attachStream(lg);
+    ASSIMP_END_EXCEPTION_REGION(void);
 }
 
 // ------------------------------------------------------------------------------------------------
 ASSIMP_API aiReturn aiDetachLogStream( const aiLogStream* stream)
 {
-	ASSIMP_BEGIN_EXCEPTION_REGION();
+    ASSIMP_BEGIN_EXCEPTION_REGION();
 
 #ifndef ASSIMP_BUILD_SINGLETHREADED
-	boost::mutex::scoped_lock lock(gLogStreamMutex);
+    boost::mutex::scoped_lock lock(gLogStreamMutex);
 #endif
-	// find the logstream associated with this data
-	LogStreamMap::iterator it = gActiveLogStreams.find( *stream);
-	// it should be there... else the user is playing fools with us
-	if( it == gActiveLogStreams.end())	{
-		return AI_FAILURE;
-	}
-	DefaultLogger::get()->detatchStream( it->second );
-	delete it->second;
+    // find the logstream associated with this data
+    LogStreamMap::iterator it = gActiveLogStreams.find( *stream);
+    // it should be there... else the user is playing fools with us
+    if( it == gActiveLogStreams.end())  {
+        return AI_FAILURE;
+    }
+    DefaultLogger::get()->detatchStream( it->second );
+    delete it->second;
 
-	gActiveLogStreams.erase( it);
+    gActiveLogStreams.erase( it);
 
-	if (gActiveLogStreams.empty()) {
-		DefaultLogger::kill();
-	}
-	ASSIMP_END_EXCEPTION_REGION(aiReturn);
-	return AI_SUCCESS;
+    if (gActiveLogStreams.empty()) {
+        DefaultLogger::kill();
+    }
+    ASSIMP_END_EXCEPTION_REGION(aiReturn);
+    return AI_SUCCESS;
 }
 
 // ------------------------------------------------------------------------------------------------
 ASSIMP_API void aiDetachAllLogStreams(void)
 {
-	ASSIMP_BEGIN_EXCEPTION_REGION();
+    ASSIMP_BEGIN_EXCEPTION_REGION();
 #ifndef ASSIMP_BUILD_SINGLETHREADED
-	boost::mutex::scoped_lock lock(gLogStreamMutex);
+    boost::mutex::scoped_lock lock(gLogStreamMutex);
 #endif
-	for (LogStreamMap::iterator it = gActiveLogStreams.begin(); it != gActiveLogStreams.end(); ++it) {
-		DefaultLogger::get()->detatchStream( it->second );
-		delete it->second;
-	}
-	gActiveLogStreams.clear();
-	DefaultLogger::kill();
-	ASSIMP_END_EXCEPTION_REGION(void);
+    for (LogStreamMap::iterator it = gActiveLogStreams.begin(); it != gActiveLogStreams.end(); ++it) {
+        DefaultLogger::get()->detatchStream( it->second );
+        delete it->second;
+    }
+    gActiveLogStreams.clear();
+    DefaultLogger::kill();
+    ASSIMP_END_EXCEPTION_REGION(void);
 }
 
 // ------------------------------------------------------------------------------------------------
 ASSIMP_API void aiEnableVerboseLogging(aiBool d)
 {
-	if (!DefaultLogger::isNullLogger()) {
-		DefaultLogger::get()->setLogSeverity((d == AI_TRUE ? Logger::VERBOSE : Logger::NORMAL));
-	}
-	gVerboseLogging = d;
+    if (!DefaultLogger::isNullLogger()) {
+        DefaultLogger::get()->setLogSeverity((d == AI_TRUE ? Logger::VERBOSE : Logger::NORMAL));
+    }
+    gVerboseLogging = d;
 }
 
 // ------------------------------------------------------------------------------------------------
-// Returns the error text of the last failed import process. 
+// Returns the error text of the last failed import process.
 const char* aiGetErrorString()
 {
-	return gLastErrorString.c_str();
+    return gLastErrorString.c_str();
+}
+
+// -----------------------------------------------------------------------------------------------
+// Return the description of a importer given its index
+const aiImporterDesc* aiGetImportFormatDescription( size_t pIndex)
+{
+    return Importer().GetImporterInfo(pIndex);
 }
 
+// -----------------------------------------------------------------------------------------------
+// Return the number of importers
+size_t aiGetImportFormatCount(void)
+{
+    return Importer().GetImporterCount();
+}
+
+
 // ------------------------------------------------------------------------------------------------
-// Returns the error text of the last failed import process. 
+// Returns the error text of the last failed import process.
 aiBool aiIsExtensionSupported(const char* szExtension)
 {
-	ai_assert(NULL != szExtension);
-	aiBool candoit=AI_FALSE;
-	ASSIMP_BEGIN_EXCEPTION_REGION();
+    ai_assert(NULL != szExtension);
+    aiBool candoit=AI_FALSE;
+    ASSIMP_BEGIN_EXCEPTION_REGION();
 
-	// FIXME: no need to create a temporary Importer instance just for that .. 
-	Assimp::Importer tmp;
-	candoit = tmp.IsExtensionSupported(std::string(szExtension)) ? AI_TRUE : AI_FALSE;
+    // FIXME: no need to create a temporary Importer instance just for that ..
+    Assimp::Importer tmp;
+    candoit = tmp.IsExtensionSupported(std::string(szExtension)) ? AI_TRUE : AI_FALSE;
 
-	ASSIMP_END_EXCEPTION_REGION(aiBool);
-	return candoit;
+    ASSIMP_END_EXCEPTION_REGION(aiBool);
+    return candoit;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Get a list of all file extensions supported by ASSIMP
 void aiGetExtensionList(aiString* szOut)
 {
-	ai_assert(NULL != szOut);
-	ASSIMP_BEGIN_EXCEPTION_REGION();
+    ai_assert(NULL != szOut);
+    ASSIMP_BEGIN_EXCEPTION_REGION();
 
-	// FIXME: no need to create a temporary Importer instance just for that .. 
-	Assimp::Importer tmp;
-	tmp.GetExtensionList(*szOut);
+    // FIXME: no need to create a temporary Importer instance just for that ..
+    Assimp::Importer tmp;
+    tmp.GetExtensionList(*szOut);
 
-	ASSIMP_END_EXCEPTION_REGION(void);
+    ASSIMP_END_EXCEPTION_REGION(void);
 }
 
 // ------------------------------------------------------------------------------------------------
 // Get the memory requirements for a particular import.
 void aiGetMemoryRequirements(const C_STRUCT aiScene* pIn,
-	C_STRUCT aiMemoryInfo* in)
+    C_STRUCT aiMemoryInfo* in)
 {
-	ASSIMP_BEGIN_EXCEPTION_REGION();
+    ASSIMP_BEGIN_EXCEPTION_REGION();
 
-	// find the importer associated with this data
-	const ScenePrivateData* priv = ScenePriv(pIn);
-	if( !priv || !priv->mOrigImporter)	{
-		ReportSceneNotFoundError();
-		return;
-	}
+    // find the importer associated with this data
+    const ScenePrivateData* priv = ScenePriv(pIn);
+    if( !priv || !priv->mOrigImporter)  {
+        ReportSceneNotFoundError();
+        return;
+    }
 
-	return priv->mOrigImporter->GetMemoryRequirements(*in);
-	ASSIMP_END_EXCEPTION_REGION(void);
+    return priv->mOrigImporter->GetMemoryRequirements(*in);
+    ASSIMP_END_EXCEPTION_REGION(void);
 }
 
 // ------------------------------------------------------------------------------------------------
 ASSIMP_API aiPropertyStore* aiCreatePropertyStore(void)
 {
-	return reinterpret_cast<aiPropertyStore*>( new PropertyMap() );
+    return reinterpret_cast<aiPropertyStore*>( new PropertyMap() );
 }
 
 
 // ------------------------------------------------------------------------------------------------
 ASSIMP_API void aiReleasePropertyStore(aiPropertyStore* p)
 {
-	delete reinterpret_cast<PropertyMap*>(p);
+    delete reinterpret_cast<PropertyMap*>(p);
 }
 
 // ------------------------------------------------------------------------------------------------
 // Importer::SetPropertyInteger
 ASSIMP_API void aiSetImportPropertyInteger(aiPropertyStore* p, const char* szName, int value)
 {
-	ASSIMP_BEGIN_EXCEPTION_REGION();
-	PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
-	SetGenericProperty<int>(pp->ints,szName,value,NULL);
-	ASSIMP_END_EXCEPTION_REGION(void);
+    ASSIMP_BEGIN_EXCEPTION_REGION();
+    PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
+    SetGenericProperty<int>(pp->ints,szName,value);
+    ASSIMP_END_EXCEPTION_REGION(void);
 }
 
 // ------------------------------------------------------------------------------------------------
 // Importer::SetPropertyFloat
 ASSIMP_API void aiSetImportPropertyFloat(aiPropertyStore* p, const char* szName, float value)
 {
-	ASSIMP_BEGIN_EXCEPTION_REGION();
-	PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
-	SetGenericProperty<float>(pp->floats,szName,value,NULL);
-	ASSIMP_END_EXCEPTION_REGION(void);
+    ASSIMP_BEGIN_EXCEPTION_REGION();
+    PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
+    SetGenericProperty<float>(pp->floats,szName,value);
+    ASSIMP_END_EXCEPTION_REGION(void);
 }
 
 // ------------------------------------------------------------------------------------------------
 // Importer::SetPropertyString
 ASSIMP_API void aiSetImportPropertyString(aiPropertyStore* p, const char* szName,
-	const C_STRUCT aiString* st)
+    const C_STRUCT aiString* st)
 {
-	if (!st) {
-		return;
-	}
-	ASSIMP_BEGIN_EXCEPTION_REGION();
-	PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
-	SetGenericProperty<std::string>(pp->strings,szName,std::string(st->C_Str()),NULL);
-	ASSIMP_END_EXCEPTION_REGION(void);
+    if (!st) {
+        return;
+    }
+    ASSIMP_BEGIN_EXCEPTION_REGION();
+    PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
+    SetGenericProperty<std::string>(pp->strings,szName,std::string(st->C_Str()));
+    ASSIMP_END_EXCEPTION_REGION(void);
 }
 
 // ------------------------------------------------------------------------------------------------
 // Importer::SetPropertyMatrix
 ASSIMP_API void aiSetImportPropertyMatrix(aiPropertyStore* p, const char* szName,
-	const C_STRUCT aiMatrix4x4* mat)
+    const C_STRUCT aiMatrix4x4* mat)
 {
-	if (!mat) {
-		return;
-	}
-	ASSIMP_BEGIN_EXCEPTION_REGION();
-	PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
-	SetGenericProperty<aiMatrix4x4>(pp->matrices,szName,*mat,NULL);
-	ASSIMP_END_EXCEPTION_REGION(void);
+    if (!mat) {
+        return;
+    }
+    ASSIMP_BEGIN_EXCEPTION_REGION();
+    PropertyMap* pp = reinterpret_cast<PropertyMap*>(p);
+    SetGenericProperty<aiMatrix4x4>(pp->matrices,szName,*mat);
+    ASSIMP_END_EXCEPTION_REGION(void);
 }
 
 // ------------------------------------------------------------------------------------------------
 // Rotation matrix to quaternion
 ASSIMP_API void aiCreateQuaternionFromMatrix(aiQuaternion* quat,const aiMatrix3x3* mat)
 {
-	ai_assert(NULL != quat && NULL != mat);
-	*quat = aiQuaternion(*mat);
+    ai_assert(NULL != quat && NULL != mat);
+    *quat = aiQuaternion(*mat);
 }
 
 // ------------------------------------------------------------------------------------------------
 // Matrix decomposition
 ASSIMP_API void aiDecomposeMatrix(const aiMatrix4x4* mat,aiVector3D* scaling,
-	aiQuaternion* rotation,
-	aiVector3D* position)
+    aiQuaternion* rotation,
+    aiVector3D* position)
 {
-	ai_assert(NULL != rotation && NULL != position && NULL != scaling && NULL != mat);
-	mat->Decompose(*scaling,*rotation,*position);
+    ai_assert(NULL != rotation && NULL != position && NULL != scaling && NULL != mat);
+    mat->Decompose(*scaling,*rotation,*position);
 }
 
 // ------------------------------------------------------------------------------------------------
 // Matrix transpose
 ASSIMP_API void aiTransposeMatrix3(aiMatrix3x3* mat)
 {
-	ai_assert(NULL != mat);
-	mat->Transpose();
+    ai_assert(NULL != mat);
+    mat->Transpose();
 }
 
 // ------------------------------------------------------------------------------------------------
 ASSIMP_API void aiTransposeMatrix4(aiMatrix4x4* mat)
 {
-	ai_assert(NULL != mat);
-	mat->Transpose();
+    ai_assert(NULL != mat);
+    mat->Transpose();
 }
 
 // ------------------------------------------------------------------------------------------------
 // Vector transformation
-ASSIMP_API void aiTransformVecByMatrix3(aiVector3D* vec, 
-	const aiMatrix3x3* mat)
+ASSIMP_API void aiTransformVecByMatrix3(aiVector3D* vec,
+    const aiMatrix3x3* mat)
 {
-	ai_assert(NULL != mat && NULL != vec);
-	*vec *= (*mat);
+    ai_assert(NULL != mat && NULL != vec);
+    *vec *= (*mat);
 }
 
 // ------------------------------------------------------------------------------------------------
-ASSIMP_API void aiTransformVecByMatrix4(aiVector3D* vec, 
-	const aiMatrix4x4* mat)
+ASSIMP_API void aiTransformVecByMatrix4(aiVector3D* vec,
+    const aiMatrix4x4* mat)
 {
-	ai_assert(NULL != mat && NULL != vec);
-	*vec *= (*mat);
+    ai_assert(NULL != mat && NULL != vec);
+    *vec *= (*mat);
 }
 
 // ------------------------------------------------------------------------------------------------
 // Matrix multiplication
 ASSIMP_API void aiMultiplyMatrix4(
-	aiMatrix4x4* dst, 
-	const aiMatrix4x4* src)
+    aiMatrix4x4* dst,
+    const aiMatrix4x4* src)
 {
-	ai_assert(NULL != dst && NULL != src);
-	*dst = (*dst) * (*src);
+    ai_assert(NULL != dst && NULL != src);
+    *dst = (*dst) * (*src);
 }
 
 // ------------------------------------------------------------------------------------------------
 ASSIMP_API void aiMultiplyMatrix3(
-	aiMatrix3x3* dst, 
-	const aiMatrix3x3* src)
+    aiMatrix3x3* dst,
+    const aiMatrix3x3* src)
 {
-	ai_assert(NULL != dst && NULL != src);
-	*dst = (*dst) * (*src);
+    ai_assert(NULL != dst && NULL != src);
+    *dst = (*dst) * (*src);
 }
 
 // ------------------------------------------------------------------------------------------------
 // Matrix identity
 ASSIMP_API void aiIdentityMatrix3(
-	aiMatrix3x3* mat)
+    aiMatrix3x3* mat)
 {
-	ai_assert(NULL != mat);
-	*mat = aiMatrix3x3();
+    ai_assert(NULL != mat);
+    *mat = aiMatrix3x3();
 }
 
 // ------------------------------------------------------------------------------------------------
 ASSIMP_API void aiIdentityMatrix4(
-	aiMatrix4x4* mat)
+    aiMatrix4x4* mat)
 {
-	ai_assert(NULL != mat);
-	*mat = aiMatrix4x4();
+    ai_assert(NULL != mat);
+    *mat = aiMatrix4x4();
 }
 
+// ------------------------------------------------------------------------------------------------
+ASSIMP_API C_STRUCT const aiImporterDesc* aiGetImporterDesc( const char *extension ) {
+    if( NULL == extension ) {
+        return NULL;
+    }
+    const aiImporterDesc *desc( NULL );
+    std::vector< BaseImporter* > out;
+    GetImporterInstanceList( out );
+    for( size_t i = 0; i < out.size(); ++i ) {
+        if( 0 == strncmp( out[ i ]->GetInfo()->mFileExtensions, extension, strlen( extension ) ) ) {
+            desc = out[ i ]->GetInfo();
+            break;
+        }
+    }
+
+    return desc;
+}
 
+// ------------------------------------------------------------------------------------------------

+ 40 - 38
assimplib.mod/assimp/code/AssimpCExport.cpp

@@ -3,12 +3,12 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -25,16 +25,16 @@ conditions are met:
   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 
+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 
+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 
+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 
+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.
 ---------------------------------------------------------------------------
 */
@@ -43,85 +43,87 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 Assimp C export interface. See Exporter.cpp for some notes.
 */
 
-#include "AssimpPCH.h"
-
 #ifndef ASSIMP_BUILD_NO_EXPORT
-#include "CInterfaceIOWrapper.h" 
+#include "CInterfaceIOWrapper.h"
 #include "SceneCombiner.h"
+#include "ScenePrivate.h"
+#include "../include/assimp/Exporter.hpp"
 
 using namespace Assimp;
 
 // ------------------------------------------------------------------------------------------------
 ASSIMP_API size_t aiGetExportFormatCount(void)
 {
-	return Exporter().GetExportFormatCount();
+    return Exporter().GetExportFormatCount();
 }
 
 
 // ------------------------------------------------------------------------------------------------
 ASSIMP_API const aiExportFormatDesc* aiGetExportFormatDescription( size_t pIndex)
 {
-	return Exporter().GetExportFormatDescription(pIndex);
+    // Note: this is valid as the index always pertains to a builtin exporter,
+    // for which the returned structure is guaranteed to be of static storage duration.
+    return Exporter().GetExportFormatDescription(pIndex);
 }
 
 
 // ------------------------------------------------------------------------------------------------
 ASSIMP_API void aiCopyScene(const aiScene* pIn, aiScene** pOut)
 {
-	if (!pOut || !pIn) {
-		return;
-	}
+    if (!pOut || !pIn) {
+        return;
+    }
 
-	SceneCombiner::CopyScene(pOut,pIn,true);
-	ScenePriv(*pOut)->mIsCopy = true;
+    SceneCombiner::CopyScene(pOut,pIn,true);
+    ScenePriv(*pOut)->mIsCopy = true;
 }
 
 
 // ------------------------------------------------------------------------------------------------
 ASSIMP_API void aiFreeScene(const C_STRUCT aiScene* pIn)
 {
-	// note: aiReleaseImport() is also able to delete scene copies, but in addition
-	// it also handles scenes with import metadata.
-	delete pIn;
+    // note: aiReleaseImport() is also able to delete scene copies, but in addition
+    // it also handles scenes with import metadata.
+    delete pIn;
 }
 
 
 // ------------------------------------------------------------------------------------------------
 ASSIMP_API aiReturn aiExportScene( const aiScene* pScene, const char* pFormatId, const char* pFileName, unsigned int pPreprocessing )
 {
-	return ::aiExportSceneEx(pScene,pFormatId,pFileName,NULL,pPreprocessing);
+    return ::aiExportSceneEx(pScene,pFormatId,pFileName,NULL,pPreprocessing);
 }
 
 
 // ------------------------------------------------------------------------------------------------
 ASSIMP_API aiReturn aiExportSceneEx( const aiScene* pScene, const char* pFormatId, const char* pFileName, aiFileIO* pIO, unsigned int pPreprocessing )
 {
-	Exporter exp;
+    Exporter exp;
 
-	if (pIO) {
-		exp.SetIOHandler(new CIOSystemWrapper(pIO));
-	}
-	return exp.Export(pScene,pFormatId,pFileName,pPreprocessing);
+    if (pIO) {
+        exp.SetIOHandler(new CIOSystemWrapper(pIO));
+    }
+    return exp.Export(pScene,pFormatId,pFileName,pPreprocessing);
 }
 
 
 // ------------------------------------------------------------------------------------------------
 ASSIMP_API const C_STRUCT aiExportDataBlob* aiExportSceneToBlob( const aiScene* pScene, const char* pFormatId, unsigned int pPreprocessing  )
 {
-	Exporter exp;
-	if (!exp.ExportToBlob(pScene,pFormatId,pPreprocessing)) {
-		return NULL;
-	}
-	const aiExportDataBlob* blob = exp.GetOrphanedBlob();
-	ai_assert(blob);
-
-	return blob;
+    Exporter exp;
+    if (!exp.ExportToBlob(pScene,pFormatId,pPreprocessing)) {
+        return NULL;
+    }
+    const aiExportDataBlob* blob = exp.GetOrphanedBlob();
+    ai_assert(blob);
+
+    return blob;
 }
 
 // ------------------------------------------------------------------------------------------------
 ASSIMP_API C_STRUCT void aiReleaseExportBlob( const aiExportDataBlob* pData )
 {
-	delete pData;
+    delete pData;
 }
 
 #endif // !ASSIMP_BUILD_NO_EXPORT

+ 0 - 135
assimplib.mod/assimp/code/AssimpPCH.cpp

@@ -1,135 +0,0 @@
-
-// Actually just a dummy, used by the compiler to build the precompiled header.
-
-#include "AssimpPCH.h"
-#include "./../include/assimp/version.h"
-
-static const unsigned int MajorVersion = 3;
-static const unsigned int MinorVersion = 1;
-
-// --------------------------------------------------------------------------------
-// Legal information string - dont't remove this.
-static const char* LEGAL_INFORMATION =
-
-"Open Asset Import Library (Assimp).\n"
-"A free C/C++ library to import various 3D file formats into applications\n\n"
-
-"(c) 2008-2010, assimp team\n"
-"License under the terms and conditions of the 3-clause BSD license\n"
-"http://assimp.sourceforge.net\n"
-;
-
-// ------------------------------------------------------------------------------------------------
-// Get legal string
-ASSIMP_API const char*  aiGetLegalString  ()	{
-	return LEGAL_INFORMATION;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Get Assimp minor version
-ASSIMP_API unsigned int aiGetVersionMinor ()	{
-    return MinorVersion;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Get Assimp major version
-ASSIMP_API unsigned int aiGetVersionMajor ()	{
-    return MajorVersion;
-}
-
-// ------------------------------------------------------------------------------------------------
-// Get flags used for compilation
-ASSIMP_API unsigned int aiGetCompileFlags ()	{
-
-	unsigned int flags = 0;
-
-#ifdef ASSIMP_BUILD_BOOST_WORKAROUND
-	flags |= ASSIMP_CFLAGS_NOBOOST;
-#endif
-#ifdef ASSIMP_BUILD_SINGLETHREADED
-	flags |= ASSIMP_CFLAGS_SINGLETHREADED;
-#endif
-#ifdef ASSIMP_BUILD_DEBUG
-	flags |= ASSIMP_CFLAGS_DEBUG;
-#endif
-#ifdef ASSIMP_BUILD_DLL_EXPORT
-	flags |= ASSIMP_CFLAGS_SHARED;
-#endif
-#ifdef _STLPORT_VERSION
-	flags |= ASSIMP_CFLAGS_STLPORT;
-#endif
-
-	return flags;
-}
-
-// include current build revision, which is even updated from time to time -- :-)
-#include "revision.h"
-
-// ------------------------------------------------------------------------------------------------
-ASSIMP_API unsigned int aiGetVersionRevision ()
-{
-    return GitVersion;
-}
-
-// ------------------------------------------------------------------------------------------------
-ASSIMP_API aiScene::aiScene()
-	: mFlags(0)
-	, mRootNode(NULL)
-	, mNumMeshes(0)
-	, mMeshes(NULL)
-	, mNumMaterials(0)
-	, mMaterials(NULL)
-	, mNumAnimations(0)
-	, mAnimations(NULL)
-	, mNumTextures(0)
-	, mTextures(NULL)
-	, mNumLights(0)
-	, mLights(NULL)
-	, mNumCameras(0)
-	, mCameras(NULL)
-	, mPrivate(new Assimp::ScenePrivateData())
-	{
-	}
-
-// ------------------------------------------------------------------------------------------------
-ASSIMP_API aiScene::~aiScene()
-{
-	// delete all sub-objects recursively
-	delete mRootNode;
-
-	// To make sure we won't crash if the data is invalid it's
-	// much better to check whether both mNumXXX and mXXX are
-	// valid instead of relying on just one of them.
-	if (mNumMeshes && mMeshes) 
-		for( unsigned int a = 0; a < mNumMeshes; a++)
-			delete mMeshes[a];
-	delete [] mMeshes;
-
-	if (mNumMaterials && mMaterials) 
-		for( unsigned int a = 0; a < mNumMaterials; a++)
-			delete mMaterials[a];
-	delete [] mMaterials;
-
-	if (mNumAnimations && mAnimations) 
-		for( unsigned int a = 0; a < mNumAnimations; a++)
-			delete mAnimations[a];
-	delete [] mAnimations;
-
-	if (mNumTextures && mTextures) 
-		for( unsigned int a = 0; a < mNumTextures; a++)
-			delete mTextures[a];
-	delete [] mTextures;
-
-	if (mNumLights && mLights) 
-		for( unsigned int a = 0; a < mNumLights; a++)
-			delete mLights[a];
-	delete [] mLights;
-
-	if (mNumCameras && mCameras) 
-		for( unsigned int a = 0; a < mNumCameras; a++)
-			delete mCameras[a];
-	delete [] mCameras;
-
-	delete static_cast<Assimp::ScenePrivateData*>( mPrivate );
-}
-

+ 0 - 162
assimplib.mod/assimp/code/AssimpPCH.h

@@ -1,162 +0,0 @@
-/*
----------------------------------------------------------------------------
-Open Asset Import Library (assimp)
----------------------------------------------------------------------------
-
-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.
----------------------------------------------------------------------------
-*/
-
-/** @file AssimpPCH.h
- *  PCH master include. Every unit in Assimp has to include it.
- */
-
-#ifndef ASSIMP_PCH_INCLUDED
-#define ASSIMP_PCH_INCLUDED
-#define ASSIMP_INTERNAL_BUILD
-
-// ----------------------------------------------------------------------------------------
-/* General compile config taken from defs.h. It is important that the user compiles
- * using exactly the same settings in defs.h. Settings in AssimpPCH.h may differ,
- * they won't affect the public API.
- */
-#include "../include/assimp/defs.h"
-
-// Include our stdint.h replacement header for MSVC, take the global header for gcc/mingw
-#if defined( _MSC_VER) && (_MSC_VER < 1600)
-#	include "../include/assimp/Compiler/pstdint.h"
-#else
-#	include <stdint.h>
-#endif
-
-/* Undefine the min/max macros defined by some platform headers (namely Windows.h) to 
- * avoid obvious conflicts with std::min() and std::max(). 
- */
-#undef min
-#undef max
-
-/* Concatenate two tokens after evaluating them
- */
-#define _AI_CONCAT(a,b)  a ## b
-#define  AI_CONCAT(a,b)  _AI_CONCAT(a,b)
-
-/* Helper macro to set a pointer to NULL in debug builds
- */
-#if (defined ASSIMP_BUILD_DEBUG)
-#	define AI_DEBUG_INVALIDATE_PTR(x) x = NULL;
-#else
-#	define AI_DEBUG_INVALIDATE_PTR(x)
-#endif
-
-/* Beginning with MSVC8 some C string manipulation functions are mapped to their _safe_
- * counterparts (e.g. _itoa_s). This avoids a lot of trouble with deprecation warnings.
- */
-#if _MSC_VER >= 1400 && !(defined _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES)
-#	define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES 1
-#endif
-
-/* size_t to unsigned int, possible loss of data. The compiler is right with his warning
- * but this loss of data won't be a problem for us. So shut up, little boy.
- */
-#ifdef _MSC_VER
-#	pragma warning (disable : 4267)
-#endif
-
-// ----------------------------------------------------------------------------------------
-/* Actually that's not required for MSVC. It is included somewhere in the deeper parts of
- * the MSVC STL but it's necessary for proper build with STLport.
- */
-#include <ctype.h>
-
-// Runtime/STL headers
-#include <vector>
-#include <list>
-#include <map>
-#include <set>
-#include <string>
-#include <sstream>
-#include <iomanip>
-#include <cassert>
-#include <stack>
-#include <queue>
-#include <iostream>
-#include <algorithm>
-#include <numeric>
-#include <new>
-#include <cstdio>
-#include <limits.h>
-#include <memory>
-
-// Boost headers
-#include <boost/pointer_cast.hpp>
-#include <boost/scoped_ptr.hpp>
-#include <boost/scoped_array.hpp>
-#include <boost/shared_ptr.hpp>
-#include <boost/shared_array.hpp>
-#include <boost/make_shared.hpp>
-#include <boost/format.hpp>
-#include <boost/foreach.hpp>
-#include <boost/static_assert.hpp>
-#include <boost/lexical_cast.hpp>
-
-// Public ASSIMP headers
-#include "../include/assimp/DefaultLogger.hpp"
-#include "../include/assimp/IOStream.hpp"
-#include "../include/assimp/IOSystem.hpp"
-#include "../include/assimp/scene.h"
-#include "../include/assimp/importerdesc.h"
-#include "../include/assimp/postprocess.h"
-#include "../include/assimp/Importer.hpp"
-#include "../include/assimp/Exporter.hpp"
-
-// Internal utility headers
-#include "BaseImporter.h"
-#include "StringComparison.h"
-#include "StreamReader.h"
-#include "qnan.h"
-#include "ScenePrivate.h" 
-
-
-// We need those constants, workaround for any platforms where nobody defined them yet
-#if (!defined SIZE_MAX)
-#	define SIZE_MAX (~((size_t)0))
-#endif
-
-#if (!defined UINT_MAX)
-#	define UINT_MAX (~((unsigned int)0))
-#endif
-
-
-#endif // !! ASSIMP_PCH_INCLUDED

+ 641 - 0
assimplib.mod/assimp/code/AssxmlExporter.cpp

@@ -0,0 +1,641 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2015, 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  AssxmlExporter.cpp
+ *  ASSXML exporter main code
+ */
+#include <stdarg.h>
+#include "./../include/assimp/version.h"
+#include "ProcessHelper.h"
+#include "../include/assimp/IOStream.hpp"
+#include "../include/assimp/IOSystem.hpp"
+#include "../include/assimp/Exporter.hpp"
+
+#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
+#   include <zlib.h>
+#else
+#   include "../contrib/zlib/zlib.h"
+#endif
+
+#include <time.h>
+#include <stdio.h>
+
+#ifndef ASSIMP_BUILD_NO_EXPORT
+#ifndef ASSIMP_BUILD_NO_ASSXML_EXPORTER
+
+using namespace Assimp;
+
+namespace Assimp    {
+
+namespace AssxmlExport  {
+
+int ioprintf( IOStream * io, const char * format, ... )
+{
+    char sz[4096];
+    va_list va;
+    va_start( va, format );
+    int nSize = vsnprintf( sz, 4096, format, va );
+  ai_assert( nSize < 4096 );
+    va_end( va );
+
+    io->Write( sz, sizeof(char), nSize );
+
+    return nSize;
+}
+
+// -----------------------------------------------------------------------------------
+// Convert a name to standard XML format
+void ConvertName(aiString& out, const aiString& in)
+{
+    out.length = 0;
+    for (unsigned int i = 0; i < in.length; ++i)  {
+        switch (in.data[i]) {
+            case '<':
+                out.Append("&lt;");break;
+            case '>':
+                out.Append("&gt;");break;
+            case '&':
+                out.Append("&amp;");break;
+            case '\"':
+                out.Append("&quot;");break;
+            case '\'':
+                out.Append("&apos;");break;
+            default:
+                out.data[out.length++] = in.data[i];
+        }
+    }
+    out.data[out.length] = 0;
+}
+
+// -----------------------------------------------------------------------------------
+// Write a single node as text dump
+void WriteNode(const aiNode* node, IOStream * io, unsigned int depth)
+{
+    char prefix[512];
+    for (unsigned int i = 0; i < depth;++i)
+        prefix[i] = '\t';
+    prefix[depth] = '\0';
+
+    const aiMatrix4x4& m = node->mTransformation;
+
+    aiString name;
+    ConvertName(name,node->mName);
+    ioprintf(io,"%s<Node name=\"%s\"> \n"
+        "%s\t<Matrix4> \n"
+        "%s\t\t%0 6f %0 6f %0 6f %0 6f\n"
+        "%s\t\t%0 6f %0 6f %0 6f %0 6f\n"
+        "%s\t\t%0 6f %0 6f %0 6f %0 6f\n"
+        "%s\t\t%0 6f %0 6f %0 6f %0 6f\n"
+        "%s\t</Matrix4> \n",
+        prefix,name.data,prefix,
+        prefix,m.a1,m.a2,m.a3,m.a4,
+        prefix,m.b1,m.b2,m.b3,m.b4,
+        prefix,m.c1,m.c2,m.c3,m.c4,
+        prefix,m.d1,m.d2,m.d3,m.d4,prefix);
+
+    if (node->mNumMeshes) {
+        ioprintf(io, "%s\t<MeshRefs num=\"%i\">\n%s\t",
+            prefix,node->mNumMeshes,prefix);
+
+        for (unsigned int i = 0; i < node->mNumMeshes;++i) {
+            ioprintf(io,"%i ",node->mMeshes[i]);
+        }
+        ioprintf(io,"\n%s\t</MeshRefs>\n",prefix);
+    }
+
+    if (node->mNumChildren) {
+        ioprintf(io,"%s\t<NodeList num=\"%i\">\n",
+            prefix,node->mNumChildren);
+
+        for (unsigned int i = 0; i < node->mNumChildren;++i) {
+            WriteNode(node->mChildren[i],io,depth+2);
+        }
+        ioprintf(io,"%s\t</NodeList>\n",prefix);
+    }
+    ioprintf(io,"%s</Node>\n",prefix);
+}
+
+
+// -----------------------------------------------------------------------------------
+// Some chuncks of text will need to be encoded for XML
+// http://stackoverflow.com/questions/5665231/most-efficient-way-to-escape-xml-html-in-c-string#5665377
+static std::string encodeXML(const std::string& data) {
+        std::string buffer;
+        buffer.reserve(data.size());
+        for(size_t pos = 0; pos != data.size(); ++pos) {
+                switch(data[pos]) {
+                        case '&':  buffer.append("&amp;");              break;
+                        case '\"': buffer.append("&quot;");             break;
+                        case '\'': buffer.append("&apos;");             break;
+                        case '<':  buffer.append("&lt;");                   break;
+                        case '>':  buffer.append("&gt;");                   break;
+                        default:   buffer.append(&data[pos], 1);    break;
+                }
+        }
+        return buffer;
+}
+
+
+
+// -----------------------------------------------------------------------------------
+// Write a text model dump
+void WriteDump(const aiScene* scene, IOStream* io, bool shortened)
+{
+    time_t tt = ::time(NULL);
+    tm* p     = ::gmtime(&tt);
+
+    aiString name;
+
+    // write header
+    ioprintf(io,
+        "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
+        "<ASSIMP format_id=\"1\">\n\n"
+
+        "<!-- XML Model dump produced by assimp dump\n"
+        "  Library version: %i.%i.%i\n"
+        "  %s\n"
+        "-->"
+        " \n\n"
+        "<Scene flags=\"%i\" postprocessing=\"%i\">\n",
+
+        aiGetVersionMajor(),aiGetVersionMinor(),aiGetVersionRevision(),asctime(p),
+        scene->mFlags,
+        0 /*globalImporter->GetEffectivePostProcessing()*/);
+
+    // write the node graph
+    WriteNode(scene->mRootNode, io, 0);
+
+#if 0
+        // write cameras
+    for (unsigned int i = 0; i < scene->mNumCameras;++i) {
+        aiCamera* cam  = scene->mCameras[i];
+        ConvertName(name,cam->mName);
+
+        // camera header
+        ioprintf(io,"\t<Camera parent=\"%s\">\n"
+            "\t\t<Vector3 name=\"up\"        > %0 8f %0 8f %0 8f </Vector3>\n"
+            "\t\t<Vector3 name=\"lookat\"    > %0 8f %0 8f %0 8f </Vector3>\n"
+            "\t\t<Vector3 name=\"pos\"       > %0 8f %0 8f %0 8f </Vector3>\n"
+            "\t\t<Float   name=\"fov\"       > %f </Float>\n"
+            "\t\t<Float   name=\"aspect\"    > %f </Float>\n"
+            "\t\t<Float   name=\"near_clip\" > %f </Float>\n"
+            "\t\t<Float   name=\"far_clip\"  > %f </Float>\n"
+            "\t</Camera>\n",
+            name.data,
+            cam->mUp.x,cam->mUp.y,cam->mUp.z,
+            cam->mLookAt.x,cam->mLookAt.y,cam->mLookAt.z,
+            cam->mPosition.x,cam->mPosition.y,cam->mPosition.z,
+            cam->mHorizontalFOV,cam->mAspect,cam->mClipPlaneNear,cam->mClipPlaneFar,i);
+    }
+
+    // write lights
+    for (unsigned int i = 0; i < scene->mNumLights;++i) {
+        aiLight* l  = scene->mLights[i];
+        ConvertName(name,l->mName);
+
+        // light header
+        ioprintf(io,"\t<Light parent=\"%s\"> type=\"%s\"\n"
+            "\t\t<Vector3 name=\"diffuse\"   > %0 8f %0 8f %0 8f </Vector3>\n"
+            "\t\t<Vector3 name=\"specular\"  > %0 8f %0 8f %0 8f </Vector3>\n"
+            "\t\t<Vector3 name=\"ambient\"   > %0 8f %0 8f %0 8f </Vector3>\n",
+            name.data,
+            (l->mType == aiLightSource_DIRECTIONAL ? "directional" :
+            (l->mType == aiLightSource_POINT ? "point" : "spot" )),
+            l->mColorDiffuse.r, l->mColorDiffuse.g, l->mColorDiffuse.b,
+            l->mColorSpecular.r,l->mColorSpecular.g,l->mColorSpecular.b,
+            l->mColorAmbient.r, l->mColorAmbient.g, l->mColorAmbient.b);
+
+        if (l->mType != aiLightSource_DIRECTIONAL) {
+            ioprintf(io,
+                "\t\t<Vector3 name=\"pos\"       > %0 8f %0 8f %0 8f </Vector3>\n"
+                "\t\t<Float   name=\"atten_cst\" > %f </Float>\n"
+                "\t\t<Float   name=\"atten_lin\" > %f </Float>\n"
+                "\t\t<Float   name=\"atten_sqr\" > %f </Float>\n",
+                l->mPosition.x,l->mPosition.y,l->mPosition.z,
+                l->mAttenuationConstant,l->mAttenuationLinear,l->mAttenuationQuadratic);
+        }
+
+        if (l->mType != aiLightSource_POINT) {
+            ioprintf(io,
+                "\t\t<Vector3 name=\"lookat\"    > %0 8f %0 8f %0 8f </Vector3>\n",
+                l->mDirection.x,l->mDirection.y,l->mDirection.z);
+        }
+
+        if (l->mType == aiLightSource_SPOT) {
+            ioprintf(io,
+                "\t\t<Float   name=\"cone_out\" > %f </Float>\n"
+                "\t\t<Float   name=\"cone_inn\" > %f </Float>\n",
+                l->mAngleOuterCone,l->mAngleInnerCone);
+        }
+        ioprintf(io,"\t</Light>\n");
+    }
+#endif
+
+    // write textures
+    if (scene->mNumTextures) {
+        ioprintf(io,"<TextureList num=\"%i\">\n",scene->mNumTextures);
+        for (unsigned int i = 0; i < scene->mNumTextures;++i) {
+            aiTexture* tex  = scene->mTextures[i];
+            bool compressed = (tex->mHeight == 0);
+
+            // mesh header
+            ioprintf(io,"\t<Texture width=\"%i\" height=\"%i\" compressed=\"%s\"> \n",
+                (compressed ? -1 : tex->mWidth),(compressed ? -1 : tex->mHeight),
+                (compressed ? "true" : "false"));
+
+            if (compressed) {
+                ioprintf(io,"\t\t<Data length=\"%i\"> \n",tex->mWidth);
+
+                if (!shortened) {
+                    for (unsigned int n = 0; n < tex->mWidth;++n) {
+                        ioprintf(io,"\t\t\t%2x",reinterpret_cast<uint8_t*>(tex->pcData)[n]);
+                        if (n && !(n % 50)) {
+                            ioprintf(io,"\n");
+                        }
+                    }
+                }
+            }
+            else if (!shortened){
+                ioprintf(io,"\t\t<Data length=\"%i\"> \n",tex->mWidth*tex->mHeight*4);
+
+                // const unsigned int width = (unsigned int)log10((double)std::max(tex->mHeight,tex->mWidth))+1;
+                for (unsigned int y = 0; y < tex->mHeight;++y) {
+                    for (unsigned int x = 0; x < tex->mWidth;++x) {
+                        aiTexel* tx = tex->pcData + y*tex->mWidth+x;
+                        unsigned int r = tx->r,g=tx->g,b=tx->b,a=tx->a;
+                        ioprintf(io,"\t\t\t%2x %2x %2x %2x",r,g,b,a);
+
+                        // group by four for readibility
+                        if (0 == (x+y*tex->mWidth) % 4)
+                            ioprintf(io,"\n");
+                    }
+                }
+            }
+            ioprintf(io,"\t\t</Data>\n\t</Texture>\n");
+        }
+        ioprintf(io,"</TextureList>\n");
+    }
+
+    // write materials
+    if (scene->mNumMaterials) {
+        ioprintf(io,"<MaterialList num=\"%i\">\n",scene->mNumMaterials);
+        for (unsigned int i = 0; i< scene->mNumMaterials; ++i) {
+            const aiMaterial* mat = scene->mMaterials[i];
+
+            ioprintf(io,"\t<Material>\n");
+            ioprintf(io,"\t\t<MatPropertyList  num=\"%i\">\n",mat->mNumProperties);
+            for (unsigned int n = 0; n < mat->mNumProperties;++n) {
+
+                const aiMaterialProperty* prop = mat->mProperties[n];
+                const char* sz = "";
+                if (prop->mType == aiPTI_Float) {
+                    sz = "float";
+                }
+                else if (prop->mType == aiPTI_Integer) {
+                    sz = "integer";
+                }
+                else if (prop->mType == aiPTI_String) {
+                    sz = "string";
+                }
+                else if (prop->mType == aiPTI_Buffer) {
+                    sz = "binary_buffer";
+                }
+
+                ioprintf(io,"\t\t\t<MatProperty key=\"%s\" \n\t\t\ttype=\"%s\" tex_usage=\"%s\" tex_index=\"%i\"",
+                    prop->mKey.data, sz,
+                    ::TextureTypeToString((aiTextureType)prop->mSemantic),prop->mIndex);
+
+                if (prop->mType == aiPTI_Float) {
+                    ioprintf(io," size=\"%i\">\n\t\t\t\t",
+                        static_cast<int>(prop->mDataLength/sizeof(float)));
+
+                    for (unsigned int p = 0; p < prop->mDataLength/sizeof(float);++p) {
+                        ioprintf(io,"%f ",*((float*)(prop->mData+p*sizeof(float))));
+                    }
+                }
+                else if (prop->mType == aiPTI_Integer) {
+                    ioprintf(io," size=\"%i\">\n\t\t\t\t",
+                        static_cast<int>(prop->mDataLength/sizeof(int)));
+
+                    for (unsigned int p = 0; p < prop->mDataLength/sizeof(int);++p) {
+                        ioprintf(io,"%i ",*((int*)(prop->mData+p*sizeof(int))));
+                    }
+                }
+                else if (prop->mType == aiPTI_Buffer) {
+                    ioprintf(io," size=\"%i\">\n\t\t\t\t",
+                        static_cast<int>(prop->mDataLength));
+
+                    for (unsigned int p = 0; p < prop->mDataLength;++p) {
+                        ioprintf(io,"%2x ",prop->mData[p]);
+                        if (p && 0 == p%30) {
+                            ioprintf(io,"\n\t\t\t\t");
+                        }
+                    }
+                }
+                else if (prop->mType == aiPTI_String) {
+                    ioprintf(io,">\n\t\t\t\t\"%s\"",encodeXML(prop->mData+4).c_str() /* skip length */);
+                }
+                ioprintf(io,"\n\t\t\t</MatProperty>\n");
+            }
+            ioprintf(io,"\t\t</MatPropertyList>\n");
+            ioprintf(io,"\t</Material>\n");
+        }
+        ioprintf(io,"</MaterialList>\n");
+    }
+
+    // write animations
+    if (scene->mNumAnimations) {
+        ioprintf(io,"<AnimationList num=\"%i\">\n",scene->mNumAnimations);
+        for (unsigned int i = 0; i < scene->mNumAnimations;++i) {
+            aiAnimation* anim = scene->mAnimations[i];
+
+            // anim header
+            ConvertName(name,anim->mName);
+            ioprintf(io,"\t<Animation name=\"%s\" duration=\"%e\" tick_cnt=\"%e\">\n",
+                name.data, anim->mDuration, anim->mTicksPerSecond);
+
+            // write bone animation channels
+            if (anim->mNumChannels) {
+                ioprintf(io,"\t\t<NodeAnimList num=\"%i\">\n",anim->mNumChannels);
+                for (unsigned int n = 0; n < anim->mNumChannels;++n) {
+                    aiNodeAnim* nd = anim->mChannels[n];
+
+                    // node anim header
+                    ConvertName(name,nd->mNodeName);
+                    ioprintf(io,"\t\t\t<NodeAnim node=\"%s\">\n",name.data);
+
+                    if (!shortened) {
+                        // write position keys
+                        if (nd->mNumPositionKeys) {
+                            ioprintf(io,"\t\t\t\t<PositionKeyList num=\"%i\">\n",nd->mNumPositionKeys);
+                            for (unsigned int a = 0; a < nd->mNumPositionKeys;++a) {
+                                aiVectorKey* vc = nd->mPositionKeys+a;
+                                ioprintf(io,"\t\t\t\t\t<PositionKey time=\"%e\">\n"
+                                    "\t\t\t\t\t\t%0 8f %0 8f %0 8f\n\t\t\t\t\t</PositionKey>\n",
+                                    vc->mTime,vc->mValue.x,vc->mValue.y,vc->mValue.z);
+                            }
+                            ioprintf(io,"\t\t\t\t</PositionKeyList>\n");
+                        }
+
+                        // write scaling keys
+                        if (nd->mNumScalingKeys) {
+                            ioprintf(io,"\t\t\t\t<ScalingKeyList num=\"%i\">\n",nd->mNumScalingKeys);
+                            for (unsigned int a = 0; a < nd->mNumScalingKeys;++a) {
+                                aiVectorKey* vc = nd->mScalingKeys+a;
+                                ioprintf(io,"\t\t\t\t\t<ScalingKey time=\"%e\">\n"
+                                    "\t\t\t\t\t\t%0 8f %0 8f %0 8f\n\t\t\t\t\t</ScalingKey>\n",
+                                    vc->mTime,vc->mValue.x,vc->mValue.y,vc->mValue.z);
+                            }
+                            ioprintf(io,"\t\t\t\t</ScalingKeyList>\n");
+                        }
+
+                        // write rotation keys
+                        if (nd->mNumRotationKeys) {
+                            ioprintf(io,"\t\t\t\t<RotationKeyList num=\"%i\">\n",nd->mNumRotationKeys);
+                            for (unsigned int a = 0; a < nd->mNumRotationKeys;++a) {
+                                aiQuatKey* vc = nd->mRotationKeys+a;
+                                ioprintf(io,"\t\t\t\t\t<RotationKey time=\"%e\">\n"
+                                    "\t\t\t\t\t\t%0 8f %0 8f %0 8f %0 8f\n\t\t\t\t\t</RotationKey>\n",
+                                    vc->mTime,vc->mValue.x,vc->mValue.y,vc->mValue.z,vc->mValue.w);
+                            }
+                            ioprintf(io,"\t\t\t\t</RotationKeyList>\n");
+                        }
+                    }
+                    ioprintf(io,"\t\t\t</NodeAnim>\n");
+                }
+                ioprintf(io,"\t\t</NodeAnimList>\n");
+            }
+            ioprintf(io,"\t</Animation>\n");
+        }
+        ioprintf(io,"</AnimationList>\n");
+    }
+
+    // write meshes
+    if (scene->mNumMeshes) {
+        ioprintf(io,"<MeshList num=\"%i\">\n",scene->mNumMeshes);
+        for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
+            aiMesh* mesh = scene->mMeshes[i];
+            // const unsigned int width = (unsigned int)log10((double)mesh->mNumVertices)+1;
+
+            // mesh header
+            ioprintf(io,"\t<Mesh types=\"%s %s %s %s\" material_index=\"%i\">\n",
+                (mesh->mPrimitiveTypes & aiPrimitiveType_POINT    ? "points"    : ""),
+                (mesh->mPrimitiveTypes & aiPrimitiveType_LINE     ? "lines"     : ""),
+                (mesh->mPrimitiveTypes & aiPrimitiveType_TRIANGLE ? "triangles" : ""),
+                (mesh->mPrimitiveTypes & aiPrimitiveType_POLYGON  ? "polygons"  : ""),
+                mesh->mMaterialIndex);
+
+            // bones
+            if (mesh->mNumBones) {
+                ioprintf(io,"\t\t<BoneList num=\"%i\">\n",mesh->mNumBones);
+
+                for (unsigned int n = 0; n < mesh->mNumBones;++n) {
+                    aiBone* bone = mesh->mBones[n];
+
+                    ConvertName(name,bone->mName);
+                    // bone header
+                    ioprintf(io,"\t\t\t<Bone name=\"%s\">\n"
+                        "\t\t\t\t<Matrix4> \n"
+                        "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n"
+                        "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n"
+                        "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n"
+                        "\t\t\t\t\t%0 6f %0 6f %0 6f %0 6f\n"
+                        "\t\t\t\t</Matrix4> \n",
+                        name.data,
+                        bone->mOffsetMatrix.a1,bone->mOffsetMatrix.a2,bone->mOffsetMatrix.a3,bone->mOffsetMatrix.a4,
+                        bone->mOffsetMatrix.b1,bone->mOffsetMatrix.b2,bone->mOffsetMatrix.b3,bone->mOffsetMatrix.b4,
+                        bone->mOffsetMatrix.c1,bone->mOffsetMatrix.c2,bone->mOffsetMatrix.c3,bone->mOffsetMatrix.c4,
+                        bone->mOffsetMatrix.d1,bone->mOffsetMatrix.d2,bone->mOffsetMatrix.d3,bone->mOffsetMatrix.d4);
+
+                    if (!shortened && bone->mNumWeights) {
+                        ioprintf(io,"\t\t\t\t<WeightList num=\"%i\">\n",bone->mNumWeights);
+
+                        // bone weights
+                        for (unsigned int a = 0; a < bone->mNumWeights;++a) {
+                            aiVertexWeight* wght = bone->mWeights+a;
+
+                            ioprintf(io,"\t\t\t\t\t<Weight index=\"%i\">\n\t\t\t\t\t\t%f\n\t\t\t\t\t</Weight>\n",
+                                wght->mVertexId,wght->mWeight);
+                        }
+                        ioprintf(io,"\t\t\t\t</WeightList>\n");
+                    }
+                    ioprintf(io,"\t\t\t</Bone>\n");
+                }
+                ioprintf(io,"\t\t</BoneList>\n");
+            }
+
+            // faces
+            if (!shortened && mesh->mNumFaces) {
+                ioprintf(io,"\t\t<FaceList num=\"%i\">\n",mesh->mNumFaces);
+                for (unsigned int n = 0; n < mesh->mNumFaces; ++n) {
+                    aiFace& f = mesh->mFaces[n];
+                    ioprintf(io,"\t\t\t<Face num=\"%i\">\n"
+                        "\t\t\t\t",f.mNumIndices);
+
+                    for (unsigned int j = 0; j < f.mNumIndices;++j)
+                        ioprintf(io,"%i ",f.mIndices[j]);
+
+                    ioprintf(io,"\n\t\t\t</Face>\n");
+                }
+                ioprintf(io,"\t\t</FaceList>\n");
+            }
+
+            // vertex positions
+            if (mesh->HasPositions()) {
+                ioprintf(io,"\t\t<Positions num=\"%i\" set=\"0\" num_components=\"3\"> \n",mesh->mNumVertices);
+                if (!shortened) {
+                    for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
+                        ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n",
+                            mesh->mVertices[n].x,
+                            mesh->mVertices[n].y,
+                            mesh->mVertices[n].z);
+                    }
+                }
+                ioprintf(io,"\t\t</Positions>\n");
+            }
+
+            // vertex normals
+            if (mesh->HasNormals()) {
+                ioprintf(io,"\t\t<Normals num=\"%i\" set=\"0\" num_components=\"3\"> \n",mesh->mNumVertices);
+                if (!shortened) {
+                    for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
+                        ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n",
+                            mesh->mNormals[n].x,
+                            mesh->mNormals[n].y,
+                            mesh->mNormals[n].z);
+                    }
+                }
+                else {
+                }
+                ioprintf(io,"\t\t</Normals>\n");
+            }
+
+            // vertex tangents and bitangents
+            if (mesh->HasTangentsAndBitangents()) {
+                ioprintf(io,"\t\t<Tangents num=\"%i\" set=\"0\" num_components=\"3\"> \n",mesh->mNumVertices);
+                if (!shortened) {
+                    for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
+                        ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n",
+                            mesh->mTangents[n].x,
+                            mesh->mTangents[n].y,
+                            mesh->mTangents[n].z);
+                    }
+                }
+                ioprintf(io,"\t\t</Tangents>\n");
+
+                ioprintf(io,"\t\t<Bitangents num=\"%i\" set=\"0\" num_components=\"3\"> \n",mesh->mNumVertices);
+                if (!shortened) {
+                    for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
+                        ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n",
+                            mesh->mBitangents[n].x,
+                            mesh->mBitangents[n].y,
+                            mesh->mBitangents[n].z);
+                    }
+                }
+                ioprintf(io,"\t\t</Bitangents>\n");
+            }
+
+            // texture coordinates
+            for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) {
+                if (!mesh->mTextureCoords[a])
+                    break;
+
+                ioprintf(io,"\t\t<TextureCoords num=\"%i\" set=\"%i\" num_components=\"%i\"> \n",mesh->mNumVertices,
+                    a,mesh->mNumUVComponents[a]);
+
+                if (!shortened) {
+                    if (mesh->mNumUVComponents[a] == 3) {
+                        for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
+                            ioprintf(io,"\t\t%0 8f %0 8f %0 8f\n",
+                                mesh->mTextureCoords[a][n].x,
+                                mesh->mTextureCoords[a][n].y,
+                                mesh->mTextureCoords[a][n].z);
+                        }
+                    }
+                    else {
+                        for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
+                            ioprintf(io,"\t\t%0 8f %0 8f\n",
+                                mesh->mTextureCoords[a][n].x,
+                                mesh->mTextureCoords[a][n].y);
+                        }
+                    }
+                }
+                ioprintf(io,"\t\t</TextureCoords>\n");
+            }
+
+            // vertex colors
+            for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a) {
+                if (!mesh->mColors[a])
+                    break;
+                ioprintf(io,"\t\t<Colors num=\"%i\" set=\"%i\" num_components=\"4\"> \n",mesh->mNumVertices,a);
+                if (!shortened) {
+                    for (unsigned int n = 0; n < mesh->mNumVertices; ++n) {
+                        ioprintf(io,"\t\t%0 8f %0 8f %0 8f %0 8f\n",
+                            mesh->mColors[a][n].r,
+                            mesh->mColors[a][n].g,
+                            mesh->mColors[a][n].b,
+                            mesh->mColors[a][n].a);
+                    }
+                }
+                ioprintf(io,"\t\t</Colors>\n");
+            }
+            ioprintf(io,"\t</Mesh>\n");
+        }
+        ioprintf(io,"</MeshList>\n");
+    }
+    ioprintf(io,"</Scene>\n</ASSIMP>");
+}
+
+} // end of namespace AssxmlExport
+
+void ExportSceneAssxml(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
+{
+    IOStream * out = pIOSystem->Open( pFile, "wt" );
+    if (!out) return;
+
+    bool shortened = false;
+    AssxmlExport::WriteDump( pScene, out, shortened );
+
+    pIOSystem->Close( out );
+}
+
+} // end of namespace Assimp
+
+#endif // ASSIMP_BUILD_NO_ASSXML_EXPORTER
+#endif // ASSIMP_BUILD_NO_EXPORT

+ 49 - 0
assimplib.mod/assimp/code/AssxmlExporter.h

@@ -0,0 +1,49 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2015, 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 AssxmlExporter.h
+ * ASSXML Exporter Main Header
+ */
+#ifndef AI_ASSXMLEXPORTER_H_INC
+#define AI_ASSXMLEXPORTER_H_INC
+
+// nothing really needed here - reserved for future use like properties
+
+#endif

+ 483 - 475
assimplib.mod/assimp/code/B3DImporter.cpp

@@ -3,7 +3,7 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, assimp team
 
 All rights reserved.
 
@@ -43,28 +43,34 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *  @brief Implementation of the b3d importer class
  */
 
-#include "AssimpPCH.h"
+
 #ifndef ASSIMP_BUILD_NO_B3D_IMPORTER
 
 // internal headers
 #include "B3DImporter.h"
 #include "TextureTransform.h"
 #include "ConvertToLHProcess.h"
+#include <boost/scoped_ptr.hpp>
+#include "../include/assimp/IOSystem.hpp"
+#include "../include/assimp/anim.h"
+#include "../include/assimp/scene.h"
+#include "../include/assimp/DefaultLogger.hpp"
+
 
 using namespace Assimp;
 using namespace std;
 
 static const aiImporterDesc desc = {
-	"BlitzBasic 3D Importer",
-	"",
-	"",
-	"http://www.blitzbasic.com/",
-	aiImporterFlags_SupportBinaryFlavour,
-	0,
-	0,
-	0,
-	0,
-	"b3d" 
+    "BlitzBasic 3D Importer",
+    "",
+    "",
+    "http://www.blitzbasic.com/",
+    aiImporterFlags_SupportBinaryFlavour,
+    0,
+    0,
+    0,
+    0,
+    "b3d" 
 };
 
 // (fixme, Aramis) quick workaround to get rid of all those signed to unsigned warnings
@@ -77,611 +83,613 @@ static const aiImporterDesc desc = {
 // ------------------------------------------------------------------------------------------------
 bool B3DImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const{
 
-	size_t pos=pFile.find_last_of( '.' );
-	if( pos==string::npos ) return false;
+    size_t pos=pFile.find_last_of( '.' );
+    if( pos==string::npos ) return false;
 
-	string ext=pFile.substr( pos+1 );
-	if( ext.size()!=3 ) return false;
+    string ext=pFile.substr( pos+1 );
+    if( ext.size()!=3 ) return false;
 
-	return (ext[0]=='b' || ext[0]=='B') && (ext[1]=='3') && (ext[2]=='d' || ext[2]=='D');
+    return (ext[0]=='b' || ext[0]=='B') && (ext[1]=='3') && (ext[2]=='d' || ext[2]=='D');
 }
 
 // ------------------------------------------------------------------------------------------------
 // Loader meta information
 const aiImporterDesc* B3DImporter::GetInfo () const
 {
-	return &desc;
+    return &desc;
 }
 
 #ifdef DEBUG_B3D
-	extern "C"{ void _stdcall AllocConsole(); }
+    extern "C"{ void _stdcall AllocConsole(); }
 #endif
 // ------------------------------------------------------------------------------------------------
 void B3DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler){
 
 #ifdef DEBUG_B3D
-	AllocConsole();
-	freopen( "conin$","r",stdin );
-	freopen( "conout$","w",stdout );
-	freopen( "conout$","w",stderr );
-	cout<<"Hello world from the B3DImporter!"<<endl;
+    AllocConsole();
+    freopen( "conin$","r",stdin );
+    freopen( "conout$","w",stdout );
+    freopen( "conout$","w",stderr );
+    cout<<"Hello world from the B3DImporter!"<<endl;
 #endif
 
-	boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
+    boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
 
-	// Check whether we can read from the file
-	if( file.get() == NULL)
-		throw DeadlyImportError( "Failed to open B3D file " + pFile + ".");
+    // Check whether we can read from the file
+    if( file.get() == NULL)
+        throw DeadlyImportError( "Failed to open B3D file " + pFile + ".");
 
-	// check whether the .b3d file is large enough to contain
-	// at least one chunk.
-	size_t fileSize = file->FileSize();
-	if( fileSize<8 ) throw DeadlyImportError( "B3D File is too small.");
+    // check whether the .b3d file is large enough to contain
+    // at least one chunk.
+    size_t fileSize = file->FileSize();
+    if( fileSize<8 ) throw DeadlyImportError( "B3D File is too small.");
 
-	_pos=0;
-	_buf.resize( fileSize );
-	file->Read( &_buf[0],1,fileSize );
-	_stack.clear();
+    _pos=0;
+    _buf.resize( fileSize );
+    file->Read( &_buf[0],1,fileSize );
+    _stack.clear();
 
-	ReadBB3D( pScene );
+    ReadBB3D( pScene );
 }
 
 // ------------------------------------------------------------------------------------------------
-void B3DImporter::Oops(){
-	throw DeadlyImportError( "B3D Importer - INTERNAL ERROR" );
+AI_WONT_RETURN void B3DImporter::Oops(){
+    throw DeadlyImportError( "B3D Importer - INTERNAL ERROR" );
 }
 
 // ------------------------------------------------------------------------------------------------
-void B3DImporter::Fail( string str ){
+AI_WONT_RETURN void B3DImporter::Fail( string str ){
 #ifdef DEBUG_B3D
-	cout<<"Error in B3D file data: "<<str<<endl;
+    cout<<"Error in B3D file data: "<<str<<endl;
 #endif
-	throw DeadlyImportError( "B3D Importer - error in B3D file data: "+str );
+    throw DeadlyImportError( "B3D Importer - error in B3D file data: "+str );
 }
 
 // ------------------------------------------------------------------------------------------------
 int B3DImporter::ReadByte(){
-	if( _pos<_buf.size() ) return _buf[_pos++];
-	Fail( "EOF" );
-	return 0;
+    if( _pos<_buf.size() ) return _buf[_pos++];
+    Fail( "EOF" );
+    return 0;
 }
 
 // ------------------------------------------------------------------------------------------------
 int B3DImporter::ReadInt(){
-	if( _pos+4<=_buf.size() ){
-		int n=*(int*)&_buf[_pos];
-		_pos+=4;
-		return n;
-	}
-	Fail( "EOF" );
-	return 0;
+    if( _pos+4<=_buf.size() ){
+        int n=*(int*)&_buf[_pos];
+        _pos+=4;
+        return n;
+    }
+    Fail( "EOF" );
+    return 0;
 }
 
 // ------------------------------------------------------------------------------------------------
 float B3DImporter::ReadFloat(){
-	if( _pos+4<=_buf.size() ){
-		float n=*(float*)&_buf[_pos];
-		_pos+=4;
-		return n;
-	}
-	Fail( "EOF" );
-	return 0.0f;
+    if( _pos+4<=_buf.size() ){
+        float n=*(float*)&_buf[_pos];
+        _pos+=4;
+        return n;
+    }
+    Fail( "EOF" );
+    return 0.0f;
 }
 
 // ------------------------------------------------------------------------------------------------
 aiVector2D B3DImporter::ReadVec2(){
-	float x=ReadFloat();
-	float y=ReadFloat();
-	return aiVector2D( x,y );
+    float x=ReadFloat();
+    float y=ReadFloat();
+    return aiVector2D( x,y );
 }
 
 // ------------------------------------------------------------------------------------------------
 aiVector3D B3DImporter::ReadVec3(){
-	float x=ReadFloat();
-	float y=ReadFloat();
-	float z=ReadFloat();
-	return aiVector3D( x,y,z );
+    float x=ReadFloat();
+    float y=ReadFloat();
+    float z=ReadFloat();
+    return aiVector3D( x,y,z );
 }
 
 // ------------------------------------------------------------------------------------------------
 aiQuaternion B3DImporter::ReadQuat(){
-	// (aramis_acg) Fix to adapt the loader to changed quat orientation
-	float w=-ReadFloat();
-	float x=ReadFloat();
-	float y=ReadFloat();
-	float z=ReadFloat();
-	return aiQuaternion( w,x,y,z );
+    // (aramis_acg) Fix to adapt the loader to changed quat orientation
+    float w=-ReadFloat();
+    float x=ReadFloat();
+    float y=ReadFloat();
+    float z=ReadFloat();
+    return aiQuaternion( w,x,y,z );
 }
 
 // ------------------------------------------------------------------------------------------------
 string B3DImporter::ReadString(){
-	string str;
-	while( _pos<_buf.size() ){
-		char c=(char)ReadByte();
-		if( !c ) return str;
-		str+=c;
-	}
-	Fail( "EOF" );
-	return string();
+    string str;
+    while( _pos<_buf.size() ){
+        char c=(char)ReadByte();
+        if( !c ) return str;
+        str+=c;
+    }
+    Fail( "EOF" );
+    return string();
 }
 
 // ------------------------------------------------------------------------------------------------
 string B3DImporter::ReadChunk(){
-	string tag;
-	for( int i=0;i<4;++i ){
-		tag+=char( ReadByte() );
-	}
+    string tag;
+    for( int i=0;i<4;++i ){
+        tag+=char( ReadByte() );
+    }
 #ifdef DEBUG_B3D
 //	cout<<"ReadChunk:"<<tag<<endl;
 #endif
-	unsigned sz=(unsigned)ReadInt();
-	_stack.push_back( _pos+sz );
-	return tag;
+    unsigned sz=(unsigned)ReadInt();
+    _stack.push_back( _pos+sz );
+    return tag;
 }
 
 // ------------------------------------------------------------------------------------------------
 void B3DImporter::ExitChunk(){
-	_pos=_stack.back();
-	_stack.pop_back();
+    _pos=_stack.back();
+    _stack.pop_back();
 }
 
 // ------------------------------------------------------------------------------------------------
 unsigned B3DImporter::ChunkSize(){
-	return _stack.back()-_pos;
+    return _stack.back()-_pos;
 }
 // ------------------------------------------------------------------------------------------------
 
 template<class T>
 T *B3DImporter::to_array( const vector<T> &v ){
-	if( !v.size() ) return 0;
-	T *p=new T[v.size()];
-	for( size_t i=0;i<v.size();++i ){
-		p[i]=v[i];
-	}
-	return p;
+    if( v.empty() ) {
+        return 0;
+    }
+    T *p=new T[ v.size() ];
+    for( size_t i=0;i<v.size();++i ){
+        p[i]=v[i];
+    }
+    return p;
 }
 
 // ------------------------------------------------------------------------------------------------
 void B3DImporter::ReadTEXS(){
-	while( ChunkSize() ){
-		string name=ReadString();
-		/*int flags=*/ReadInt();
-		/*int blend=*/ReadInt();
-		/*aiVector2D pos=*/ReadVec2();
-		/*aiVector2D scale=*/ReadVec2();
-		/*float rot=*/ReadFloat();
-
-		_textures.push_back( name );
-	}
+    while( ChunkSize() ){
+        string name=ReadString();
+        /*int flags=*/ReadInt();
+        /*int blend=*/ReadInt();
+        /*aiVector2D pos=*/ReadVec2();
+        /*aiVector2D scale=*/ReadVec2();
+        /*float rot=*/ReadFloat();
+
+        _textures.push_back( name );
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 void B3DImporter::ReadBRUS(){
-	int n_texs=ReadInt();
-	if( n_texs<0 || n_texs>8 ){
-		Fail( "Bad texture count" );
-	}
-	while( ChunkSize() ){
-		string name=ReadString();
-		aiVector3D color=ReadVec3();
-		float alpha=ReadFloat();
-		float shiny=ReadFloat();
-		/*int blend=**/ReadInt();
-		int fx=ReadInt();
-
-		aiMaterial *mat=new aiMaterial;
-		_materials.push_back( mat );
-		
-		// Name
-		aiString ainame( name );
-		mat->AddProperty( &ainame,AI_MATKEY_NAME );
-		
-		// Diffuse color 
-		mat->AddProperty( &color,1,AI_MATKEY_COLOR_DIFFUSE );
-
-		// Opacity
-		mat->AddProperty( &alpha,1,AI_MATKEY_OPACITY );
-
-		// Specular color
-		aiColor3D speccolor( shiny,shiny,shiny );
-		mat->AddProperty( &speccolor,1,AI_MATKEY_COLOR_SPECULAR );
-		
-		// Specular power
-		float specpow=shiny*128;
-		mat->AddProperty( &specpow,1,AI_MATKEY_SHININESS );
-		
-		// Double sided
-		if( fx & 0x10 ){
-			int i=1; 
-			mat->AddProperty( &i,1,AI_MATKEY_TWOSIDED );
-		} 		
-
-		//Textures
-		for( int i=0;i<n_texs;++i ){
-			int texid=ReadInt();
-			if( texid<-1 || (texid>=0 && texid>=static_cast<int>(_textures.size())) ){
-				Fail( "Bad texture id" );
-			}
-			if( i==0 && texid>=0 ){
-				aiString texname( _textures[texid] );
-				mat->AddProperty( &texname,AI_MATKEY_TEXTURE_DIFFUSE(0) );
-			}
-		}
-	}
+    int n_texs=ReadInt();
+    if( n_texs<0 || n_texs>8 ){
+        Fail( "Bad texture count" );
+    }
+    while( ChunkSize() ){
+        string name=ReadString();
+        aiVector3D color=ReadVec3();
+        float alpha=ReadFloat();
+        float shiny=ReadFloat();
+        /*int blend=**/ReadInt();
+        int fx=ReadInt();
+
+        aiMaterial *mat=new aiMaterial;
+        _materials.push_back( mat );
+        
+        // Name
+        aiString ainame( name );
+        mat->AddProperty( &ainame,AI_MATKEY_NAME );
+        
+        // Diffuse color 
+        mat->AddProperty( &color,1,AI_MATKEY_COLOR_DIFFUSE );
+
+        // Opacity
+        mat->AddProperty( &alpha,1,AI_MATKEY_OPACITY );
+
+        // Specular color
+        aiColor3D speccolor( shiny,shiny,shiny );
+        mat->AddProperty( &speccolor,1,AI_MATKEY_COLOR_SPECULAR );
+        
+        // Specular power
+        float specpow=shiny*128;
+        mat->AddProperty( &specpow,1,AI_MATKEY_SHININESS );
+        
+        // Double sided
+        if( fx & 0x10 ){
+            int i=1; 
+            mat->AddProperty( &i,1,AI_MATKEY_TWOSIDED );
+        } 		
+
+        //Textures
+        for( int i=0;i<n_texs;++i ){
+            int texid=ReadInt();
+            if( texid<-1 || (texid>=0 && texid>=static_cast<int>(_textures.size())) ){
+                Fail( "Bad texture id" );
+            }
+            if( i==0 && texid>=0 ){
+                aiString texname( _textures[texid] );
+                mat->AddProperty( &texname,AI_MATKEY_TEXTURE_DIFFUSE(0) );
+            }
+        }
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 void B3DImporter::ReadVRTS(){
-	_vflags=ReadInt();
-	_tcsets=ReadInt();
-	_tcsize=ReadInt();
-	if( _tcsets<0 || _tcsets>4 || _tcsize<0 || _tcsize>4 ){
-		Fail( "Bad texcoord data" );
-	}
+    _vflags=ReadInt();
+    _tcsets=ReadInt();
+    _tcsize=ReadInt();
+    if( _tcsets<0 || _tcsets>4 || _tcsize<0 || _tcsize>4 ){
+        Fail( "Bad texcoord data" );
+    }
 
-	int sz=12+(_vflags&1?12:0)+(_vflags&2?16:0)+(_tcsets*_tcsize*4);
-	int n_verts=ChunkSize()/sz;
+    int sz=12+(_vflags&1?12:0)+(_vflags&2?16:0)+(_tcsets*_tcsize*4);
+    int n_verts=ChunkSize()/sz;
 
-	int v0=_vertices.size();
-	_vertices.resize( v0+n_verts );
+    int v0=_vertices.size();
+    _vertices.resize( v0+n_verts );
 
-	for( int i=0;i<n_verts;++i ){
-		Vertex &v=_vertices[v0+i];
+    for( int i=0;i<n_verts;++i ){
+        Vertex &v=_vertices[v0+i];
 
-		memset( v.bones,0,sizeof(v.bones) );
-		memset( v.weights,0,sizeof(v.weights) );
+        memset( v.bones,0,sizeof(v.bones) );
+        memset( v.weights,0,sizeof(v.weights) );
 
-		v.vertex=ReadVec3();
+        v.vertex=ReadVec3();
 
-		if( _vflags & 1 ) v.normal=ReadVec3();
+        if( _vflags & 1 ) v.normal=ReadVec3();
 
-		if( _vflags & 2 ) ReadQuat();	//skip v 4bytes...
+        if( _vflags & 2 ) ReadQuat();	//skip v 4bytes...
 
-		for( int i=0;i<_tcsets;++i ){
-			float t[4]={0,0,0,0};
-			for( int j=0;j<_tcsize;++j ){
-				t[j]=ReadFloat();
-			}
-			t[1]=1-t[1];
-			if( !i ) v.texcoords=aiVector3D( t[0],t[1],t[2] );
-		}
-	}
+        for( int i=0;i<_tcsets;++i ){
+            float t[4]={0,0,0,0};
+            for( int j=0;j<_tcsize;++j ){
+                t[j]=ReadFloat();
+            }
+            t[1]=1-t[1];
+            if( !i ) v.texcoords=aiVector3D( t[0],t[1],t[2] );
+        }
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 void B3DImporter::ReadTRIS( int v0 ){
-	int matid=ReadInt();
-	if( matid==-1 ){
-		matid=0;
-	}else if( matid<0 || matid>=(int)_materials.size() ){
+    int matid=ReadInt();
+    if( matid==-1 ){
+        matid=0;
+    }else if( matid<0 || matid>=(int)_materials.size() ){
 #ifdef DEBUG_B3D
-		cout<<"material id="<<matid<<endl;
+        cout<<"material id="<<matid<<endl;
 #endif
-		Fail( "Bad material id" );
-	}
+        Fail( "Bad material id" );
+    }
 
-	aiMesh *mesh=new aiMesh;
-	_meshes.push_back( mesh );
+    aiMesh *mesh=new aiMesh;
+    _meshes.push_back( mesh );
 
-	mesh->mMaterialIndex=matid;
-	mesh->mNumFaces=0;
-	mesh->mPrimitiveTypes=aiPrimitiveType_TRIANGLE;
+    mesh->mMaterialIndex=matid;
+    mesh->mNumFaces=0;
+    mesh->mPrimitiveTypes=aiPrimitiveType_TRIANGLE;
 
-	int n_tris=ChunkSize()/12;
-	aiFace *face=mesh->mFaces=new aiFace[n_tris];
+    int n_tris=ChunkSize()/12;
+    aiFace *face=mesh->mFaces=new aiFace[n_tris];
 
-	for( int i=0;i<n_tris;++i ){
-		int i0=ReadInt()+v0;
-		int i1=ReadInt()+v0;
-		int i2=ReadInt()+v0;
-		if( i0<0 || i0>=(int)_vertices.size() || i1<0 || i1>=(int)_vertices.size() || i2<0 || i2>=(int)_vertices.size() ){
+    for( int i=0;i<n_tris;++i ){
+        int i0=ReadInt()+v0;
+        int i1=ReadInt()+v0;
+        int i2=ReadInt()+v0;
+        if( i0<0 || i0>=(int)_vertices.size() || i1<0 || i1>=(int)_vertices.size() || i2<0 || i2>=(int)_vertices.size() ){
 #ifdef DEBUG_B3D
-			cout<<"Bad triangle index: i0="<<i0<<", i1="<<i1<<", i2="<<i2<<endl;
+            cout<<"Bad triangle index: i0="<<i0<<", i1="<<i1<<", i2="<<i2<<endl;
 #endif
-			Fail( "Bad triangle index" );
-			continue;
-		}
-		face->mNumIndices=3;
-		face->mIndices=new unsigned[3];
-		face->mIndices[0]=i0;
-		face->mIndices[1]=i1;
-		face->mIndices[2]=i2;
-		++mesh->mNumFaces;
-		++face;
-	}
+            Fail( "Bad triangle index" );
+            continue;
+        }
+        face->mNumIndices=3;
+        face->mIndices=new unsigned[3];
+        face->mIndices[0]=i0;
+        face->mIndices[1]=i1;
+        face->mIndices[2]=i2;
+        ++mesh->mNumFaces;
+        ++face;
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 void B3DImporter::ReadMESH(){
-	/*int matid=*/ReadInt();
-
-	int v0=_vertices.size();
-
-	while( ChunkSize() ){
-		string t=ReadChunk();
-		if( t=="VRTS" ){
-			ReadVRTS();
-		}else if( t=="TRIS" ){
-			ReadTRIS( v0 );
-		}
-		ExitChunk();
-	}
+    /*int matid=*/ReadInt();
+
+    int v0=_vertices.size();
+
+    while( ChunkSize() ){
+        string t=ReadChunk();
+        if( t=="VRTS" ){
+            ReadVRTS();
+        }else if( t=="TRIS" ){
+            ReadTRIS( v0 );
+        }
+        ExitChunk();
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 void B3DImporter::ReadBONE( int id ){
-	while( ChunkSize() ){
-		int vertex=ReadInt();
-		float weight=ReadFloat();
-		if( vertex<0 || vertex>=(int)_vertices.size() ){
-			Fail( "Bad vertex index" );
-		}
-
-		Vertex &v=_vertices[vertex];
-		int i;
-		for( i=0;i<4;++i ){
-			if( !v.weights[i] ){
-				v.bones[i]=id;
-				v.weights[i]=weight;
-				break;
-			}
-		}
+    while( ChunkSize() ){
+        int vertex=ReadInt();
+        float weight=ReadFloat();
+        if( vertex<0 || vertex>=(int)_vertices.size() ){
+            Fail( "Bad vertex index" );
+        }
+
+        Vertex &v=_vertices[vertex];
+        int i;
+        for( i=0;i<4;++i ){
+            if( !v.weights[i] ){
+                v.bones[i]=id;
+                v.weights[i]=weight;
+                break;
+            }
+        }
 #ifdef DEBUG_B3D
-		if( i==4 ){
-			cout<<"Too many bone weights"<<endl;
-		}
+        if( i==4 ){
+            cout<<"Too many bone weights"<<endl;
+        }
 #endif
-	}
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 void B3DImporter::ReadKEYS( aiNodeAnim *nodeAnim ){
-	vector<aiVectorKey> trans,scale;
-	vector<aiQuatKey> rot;
-	int flags=ReadInt();
-	while( ChunkSize() ){
-		int frame=ReadInt();
-		if( flags & 1 ){
-			trans.push_back( aiVectorKey( frame,ReadVec3() ) );
-		}
-		if( flags & 2 ){
-			scale.push_back( aiVectorKey( frame,ReadVec3() ) );
-		}
-		if( flags & 4 ){
-			rot.push_back( aiQuatKey( frame,ReadQuat() ) );
-		}
-	}
-
-	if( flags & 1 ){
-		nodeAnim->mNumPositionKeys=trans.size();
-		nodeAnim->mPositionKeys=to_array( trans );
-	}
-
-	if( flags & 2 ){
-		nodeAnim->mNumScalingKeys=scale.size();
-		nodeAnim->mScalingKeys=to_array( scale );
-	}
-
-	if( flags & 4 ){
-		nodeAnim->mNumRotationKeys=rot.size();
-		nodeAnim->mRotationKeys=to_array( rot );
-	}
+    vector<aiVectorKey> trans,scale;
+    vector<aiQuatKey> rot;
+    int flags=ReadInt();
+    while( ChunkSize() ){
+        int frame=ReadInt();
+        if( flags & 1 ){
+            trans.push_back( aiVectorKey( frame,ReadVec3() ) );
+        }
+        if( flags & 2 ){
+            scale.push_back( aiVectorKey( frame,ReadVec3() ) );
+        }
+        if( flags & 4 ){
+            rot.push_back( aiQuatKey( frame,ReadQuat() ) );
+        }
+    }
+
+    if( flags & 1 ){
+        nodeAnim->mNumPositionKeys=trans.size();
+        nodeAnim->mPositionKeys=to_array( trans );
+    }
+
+    if( flags & 2 ){
+        nodeAnim->mNumScalingKeys=scale.size();
+        nodeAnim->mScalingKeys=to_array( scale );
+    }
+
+    if( flags & 4 ){
+        nodeAnim->mNumRotationKeys=rot.size();
+        nodeAnim->mRotationKeys=to_array( rot );
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 void B3DImporter::ReadANIM(){
-	/*int flags=*/ReadInt();
-	int frames=ReadInt();
-	float fps=ReadFloat();
+    /*int flags=*/ReadInt();
+    int frames=ReadInt();
+    float fps=ReadFloat();
 
-	aiAnimation *anim=new aiAnimation;
-	_animations.push_back( anim );
+    aiAnimation *anim=new aiAnimation;
+    _animations.push_back( anim );
 
-	anim->mDuration=frames;
-	anim->mTicksPerSecond=fps;
+    anim->mDuration=frames;
+    anim->mTicksPerSecond=fps;
 }
 
 // ------------------------------------------------------------------------------------------------
 aiNode *B3DImporter::ReadNODE( aiNode *parent ){
 
-	string name=ReadString();
-	aiVector3D t=ReadVec3();
-	aiVector3D s=ReadVec3();
-	aiQuaternion r=ReadQuat();
-
-	aiMatrix4x4 trans,scale,rot;
-
-	aiMatrix4x4::Translation( t,trans );
-	aiMatrix4x4::Scaling( s,scale );
-	rot=aiMatrix4x4( r.GetMatrix() );
-
-	aiMatrix4x4 tform=trans * rot * scale;
-
-	int nodeid=_nodes.size();
-
-	aiNode *node=new aiNode( name );
-	_nodes.push_back( node );
-
-	node->mParent=parent;
-	node->mTransformation=tform;
-
-	aiNodeAnim *nodeAnim=0;
-	vector<unsigned> meshes;
-	vector<aiNode*> children;
-
-	while( ChunkSize() ){
-		string t=ReadChunk();
-		if( t=="MESH" ){
-			int n=_meshes.size();
-			ReadMESH();
-			for( int i=n;i<(int)_meshes.size();++i ){
-				meshes.push_back( i );
-			}
-		}else if( t=="BONE" ){
-			ReadBONE( nodeid );
-		}else if( t=="ANIM" ){
-			ReadANIM();
-		}else if( t=="KEYS" ){
-			if( !nodeAnim ){
-				nodeAnim=new aiNodeAnim;
-				_nodeAnims.push_back( nodeAnim );
-				nodeAnim->mNodeName=node->mName;
-			}
-			ReadKEYS( nodeAnim );
-		}else if( t=="NODE" ){
-			aiNode *child=ReadNODE( node );
-			children.push_back( child );
-		}
-		ExitChunk();
-	}
-
-	node->mNumMeshes=meshes.size();
-	node->mMeshes=to_array( meshes );
-
-	node->mNumChildren=children.size();
-	node->mChildren=to_array( children );
-
-	return node;
+    string name=ReadString();
+    aiVector3D t=ReadVec3();
+    aiVector3D s=ReadVec3();
+    aiQuaternion r=ReadQuat();
+
+    aiMatrix4x4 trans,scale,rot;
+
+    aiMatrix4x4::Translation( t,trans );
+    aiMatrix4x4::Scaling( s,scale );
+    rot=aiMatrix4x4( r.GetMatrix() );
+
+    aiMatrix4x4 tform=trans * rot * scale;
+
+    int nodeid=_nodes.size();
+
+    aiNode *node=new aiNode( name );
+    _nodes.push_back( node );
+
+    node->mParent=parent;
+    node->mTransformation=tform;
+
+    aiNodeAnim *nodeAnim=0;
+    vector<unsigned> meshes;
+    vector<aiNode*> children;
+
+    while( ChunkSize() ){
+        string t=ReadChunk();
+        if( t=="MESH" ){
+            int n=_meshes.size();
+            ReadMESH();
+            for( int i=n;i<(int)_meshes.size();++i ){
+                meshes.push_back( i );
+            }
+        }else if( t=="BONE" ){
+            ReadBONE( nodeid );
+        }else if( t=="ANIM" ){
+            ReadANIM();
+        }else if( t=="KEYS" ){
+            if( !nodeAnim ){
+                nodeAnim=new aiNodeAnim;
+                _nodeAnims.push_back( nodeAnim );
+                nodeAnim->mNodeName=node->mName;
+            }
+            ReadKEYS( nodeAnim );
+        }else if( t=="NODE" ){
+            aiNode *child=ReadNODE( node );
+            children.push_back( child );
+        }
+        ExitChunk();
+    }
+
+    node->mNumMeshes=meshes.size();
+    node->mMeshes=to_array( meshes );
+
+    node->mNumChildren=children.size();
+    node->mChildren=to_array( children );
+
+    return node;
 }
 
 // ------------------------------------------------------------------------------------------------
 void B3DImporter::ReadBB3D( aiScene *scene ){
 
-	_textures.clear();
-	_materials.size();
-
-	_vertices.clear();
-	_meshes.clear();
-
-	_nodes.clear();
-	_nodeAnims.clear();
-	_animations.clear();
-
-	string t=ReadChunk();
-	if( t=="BB3D" ){
-		int version=ReadInt();
-		
-		if (!DefaultLogger::isNullLogger()) {
-			char dmp[128];
-			sprintf(dmp,"B3D file format version: %i",version);
-			DefaultLogger::get()->info(dmp);
-		}
-
-		while( ChunkSize() ){
-			string t=ReadChunk();
-			if( t=="TEXS" ){
-				ReadTEXS();
-			}else if( t=="BRUS" ){
-				ReadBRUS();
-			}else if( t=="NODE" ){
-				ReadNODE( 0 );
-			}
-			ExitChunk();
-		}
-	}
-	ExitChunk();
-
-	if( !_nodes.size() ) Fail( "No nodes" );
-
-	if( !_meshes.size() ) Fail( "No meshes" );
-
-	//Fix nodes/meshes/bones
-	for(size_t i=0;i<_nodes.size();++i ){
-		aiNode *node=_nodes[i];
-
-		for( size_t j=0;j<node->mNumMeshes;++j ){
-			aiMesh *mesh=_meshes[node->mMeshes[j]];
-
-			int n_tris=mesh->mNumFaces;
-			int n_verts=mesh->mNumVertices=n_tris * 3;
-
-			aiVector3D *mv=mesh->mVertices=new aiVector3D[ n_verts ],*mn=0,*mc=0;
-			if( _vflags & 1 ) mn=mesh->mNormals=new aiVector3D[ n_verts ];
-			if( _tcsets ) mc=mesh->mTextureCoords[0]=new aiVector3D[ n_verts ];
-
-			aiFace *face=mesh->mFaces;
-
-			vector< vector<aiVertexWeight> > vweights( _nodes.size() );
-
-			for( int i=0;i<n_verts;i+=3 ){
-				for( int j=0;j<3;++j ){
-					Vertex &v=_vertices[face->mIndices[j]];
-
-					*mv++=v.vertex;
-					if( mn ) *mn++=v.normal;
-					if( mc ) *mc++=v.texcoords;
-
-					face->mIndices[j]=i+j;
-
-					for( int k=0;k<4;++k ){
-						if( !v.weights[k] ) break;
-
-						int bone=v.bones[k];
-						float weight=v.weights[k];
-
-						vweights[bone].push_back( aiVertexWeight(i+j,weight) );
-					}
-				}
-				++face;
-			}
-
-			vector<aiBone*> bones;
-			for(size_t i=0;i<vweights.size();++i ){
-				vector<aiVertexWeight> &weights=vweights[i];
-				if( !weights.size() ) continue;
-
-				aiBone *bone=new aiBone;
-				bones.push_back( bone );
-
-				aiNode *bnode=_nodes[i];
-
-				bone->mName=bnode->mName;
-				bone->mNumWeights=weights.size();
-				bone->mWeights=to_array( weights );
-
-				aiMatrix4x4 mat=bnode->mTransformation;
-				while( bnode->mParent ){
-					bnode=bnode->mParent;
-					mat=bnode->mTransformation * mat;
-				}
-				bone->mOffsetMatrix=mat.Inverse();
-			}
-			mesh->mNumBones=bones.size();
-			mesh->mBones=to_array( bones );
-		}
-	}
-
-	//nodes
-	scene->mRootNode=_nodes[0];
-
-	//material
-	if( !_materials.size() ){
-		_materials.push_back( new aiMaterial );
-	}
-	scene->mNumMaterials=_materials.size();
-	scene->mMaterials=to_array( _materials );
-	
-	//meshes
-	scene->mNumMeshes=_meshes.size();
-	scene->mMeshes=to_array( _meshes );
-
-	//animations
-	if( _animations.size()==1 && _nodeAnims.size() ){
-
-		aiAnimation *anim=_animations.back();
-		anim->mNumChannels=_nodeAnims.size();
-		anim->mChannels=to_array( _nodeAnims );
-
-		scene->mNumAnimations=_animations.size();
-		scene->mAnimations=to_array( _animations );
-	}
+    _textures.clear();
+    _materials.clear();
+
+    _vertices.clear();
+    _meshes.clear();
+
+    _nodes.clear();
+    _nodeAnims.clear();
+    _animations.clear();
+
+    string t=ReadChunk();
+    if( t=="BB3D" ){
+        int version=ReadInt();
+        
+        if (!DefaultLogger::isNullLogger()) {
+            char dmp[128];
+            sprintf(dmp,"B3D file format version: %i",version);
+            DefaultLogger::get()->info(dmp);
+        }
+
+        while( ChunkSize() ){
+            string t=ReadChunk();
+            if( t=="TEXS" ){
+                ReadTEXS();
+            }else if( t=="BRUS" ){
+                ReadBRUS();
+            }else if( t=="NODE" ){
+                ReadNODE( 0 );
+            }
+            ExitChunk();
+        }
+    }
+    ExitChunk();
+
+    if( !_nodes.size() ) Fail( "No nodes" );
+
+    if( !_meshes.size() ) Fail( "No meshes" );
+
+    //Fix nodes/meshes/bones
+    for(size_t i=0;i<_nodes.size();++i ){
+        aiNode *node=_nodes[i];
+
+        for( size_t j=0;j<node->mNumMeshes;++j ){
+            aiMesh *mesh=_meshes[node->mMeshes[j]];
+
+            int n_tris=mesh->mNumFaces;
+            int n_verts=mesh->mNumVertices=n_tris * 3;
+
+            aiVector3D *mv=mesh->mVertices=new aiVector3D[ n_verts ],*mn=0,*mc=0;
+            if( _vflags & 1 ) mn=mesh->mNormals=new aiVector3D[ n_verts ];
+            if( _tcsets ) mc=mesh->mTextureCoords[0]=new aiVector3D[ n_verts ];
+
+            aiFace *face=mesh->mFaces;
+
+            vector< vector<aiVertexWeight> > vweights( _nodes.size() );
+
+            for( int i=0;i<n_verts;i+=3 ){
+                for( int j=0;j<3;++j ){
+                    Vertex &v=_vertices[face->mIndices[j]];
+
+                    *mv++=v.vertex;
+                    if( mn ) *mn++=v.normal;
+                    if( mc ) *mc++=v.texcoords;
+
+                    face->mIndices[j]=i+j;
+
+                    for( int k=0;k<4;++k ){
+                        if( !v.weights[k] ) break;
+
+                        int bone=v.bones[k];
+                        float weight=v.weights[k];
+
+                        vweights[bone].push_back( aiVertexWeight(i+j,weight) );
+                    }
+                }
+                ++face;
+            }
+
+            vector<aiBone*> bones;
+            for(size_t i=0;i<vweights.size();++i ){
+                vector<aiVertexWeight> &weights=vweights[i];
+                if( !weights.size() ) continue;
+
+                aiBone *bone=new aiBone;
+                bones.push_back( bone );
+
+                aiNode *bnode=_nodes[i];
+
+                bone->mName=bnode->mName;
+                bone->mNumWeights=weights.size();
+                bone->mWeights=to_array( weights );
+
+                aiMatrix4x4 mat=bnode->mTransformation;
+                while( bnode->mParent ){
+                    bnode=bnode->mParent;
+                    mat=bnode->mTransformation * mat;
+                }
+                bone->mOffsetMatrix=mat.Inverse();
+            }
+            mesh->mNumBones=bones.size();
+            mesh->mBones=to_array( bones );
+        }
+    }
+
+    //nodes
+    scene->mRootNode=_nodes[0];
+
+    //material
+    if( !_materials.size() ){
+        _materials.push_back( new aiMaterial );
+    }
+    scene->mNumMaterials=_materials.size();
+    scene->mMaterials=to_array( _materials );
+    
+    //meshes
+    scene->mNumMeshes=_meshes.size();
+    scene->mMeshes=to_array( _meshes );
+
+    //animations
+    if( _animations.size()==1 && _nodeAnims.size() ){
+
+        aiAnimation *anim=_animations.back();
+        anim->mNumChannels=_nodeAnims.size();
+        anim->mChannels=to_array( _nodeAnims );
+
+        scene->mNumAnimations=_animations.size();
+        scene->mAnimations=to_array( _animations );
+    }
 
-	// convert to RH
-	MakeLeftHandedProcess makeleft;
-	makeleft.Execute( scene );
+    // convert to RH
+    MakeLeftHandedProcess makeleft;
+    makeleft.Execute( scene );
 
-	FlipWindingOrderProcess flip;
-	flip.Execute( scene );
+    FlipWindingOrderProcess flip;
+    flip.Execute( scene );
 }
 
 #endif // !! ASSIMP_BUILD_NO_B3D_IMPORTER

+ 72 - 68
assimplib.mod/assimp/code/B3DImporter.h

@@ -1,13 +1,12 @@
-
 /*
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -24,16 +23,16 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -47,78 +46,83 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "../include/assimp/types.h"
 #include "../include/assimp/mesh.h"
 #include "../include/assimp/material.h"
+#include "BaseImporter.h"
 
 #include <string>
 #include <vector>
 
+struct aiNodeAnim;
+struct aiNode;
+struct aiAnimation;
+
 namespace Assimp{
 
 class B3DImporter : public BaseImporter{
 public:
 
-	virtual bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
+    virtual bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
 
 protected:
 
-	virtual const aiImporterDesc* GetInfo () const;
-	virtual void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
+    virtual const aiImporterDesc* GetInfo () const;
+    virtual void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
 
 private:
 
-	int ReadByte();
-	int ReadInt();
-	float ReadFloat();
-	aiVector2D ReadVec2();
-	aiVector3D ReadVec3();
-	aiQuaternion ReadQuat();
-	std::string ReadString();
-	std::string ReadChunk();
-	void ExitChunk();
-	unsigned ChunkSize();
-
-	template<class T>
-	T *to_array( const std::vector<T> &v );
-
-	struct Vertex{
-		aiVector3D vertex;
-		aiVector3D normal;
-		aiVector3D texcoords;
-		unsigned char bones[4];
-		float weights[4];
-	};
-
-	void Oops();
-	void Fail( std::string str );
-
-	void ReadTEXS();
-	void ReadBRUS();
-
-	void ReadVRTS();
-	void ReadTRIS( int v0 );
-	void ReadMESH();
-	void ReadBONE( int id );
-	void ReadKEYS( aiNodeAnim *nodeAnim );
-	void ReadANIM();
-
-	aiNode *ReadNODE( aiNode *parent );
-
-	void ReadBB3D( aiScene *scene );
-
-	unsigned _pos;
-//	unsigned _size;
-	std::vector<unsigned char> _buf;
-	std::vector<unsigned> _stack;
-	
-	std::vector<std::string> _textures;
-	std::vector<aiMaterial*> _materials;
-
-	int _vflags,_tcsets,_tcsize;
-	std::vector<Vertex> _vertices;
-
-	std::vector<aiNode*> _nodes;
-	std::vector<aiMesh*> _meshes;
-	std::vector<aiNodeAnim*> _nodeAnims;
-	std::vector<aiAnimation*> _animations;
+    int ReadByte();
+    int ReadInt();
+    float ReadFloat();
+    aiVector2D ReadVec2();
+    aiVector3D ReadVec3();
+    aiQuaternion ReadQuat();
+    std::string ReadString();
+    std::string ReadChunk();
+    void ExitChunk();
+    unsigned ChunkSize();
+
+    template<class T>
+    T *to_array( const std::vector<T> &v );
+
+    struct Vertex{
+        aiVector3D vertex;
+        aiVector3D normal;
+        aiVector3D texcoords;
+        unsigned char bones[4];
+        float weights[4];
+    };
+
+    AI_WONT_RETURN void Oops() AI_WONT_RETURN_SUFFIX;
+    AI_WONT_RETURN void Fail( std::string str ) AI_WONT_RETURN_SUFFIX;
+
+    void ReadTEXS();
+    void ReadBRUS();
+
+    void ReadVRTS();
+    void ReadTRIS( int v0 );
+    void ReadMESH();
+    void ReadBONE( int id );
+    void ReadKEYS( aiNodeAnim *nodeAnim );
+    void ReadANIM();
+
+    aiNode *ReadNODE( aiNode *parent );
+
+    void ReadBB3D( aiScene *scene );
+
+    unsigned _pos;
+//  unsigned _size;
+    std::vector<unsigned char> _buf;
+    std::vector<unsigned> _stack;
+
+    std::vector<std::string> _textures;
+    std::vector<aiMaterial*> _materials;
+
+    int _vflags,_tcsets,_tcsize;
+    std::vector<Vertex> _vertices;
+
+    std::vector<aiNode*> _nodes;
+    std::vector<aiMesh*> _meshes;
+    std::vector<aiNodeAnim*> _nodeAnims;
+    std::vector<aiAnimation*> _animations;
 };
 
 }

+ 393 - 385
assimplib.mod/assimp/code/BVHLoader.cpp

@@ -4,12 +4,12 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -26,46 +26,54 @@ 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 
+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 
+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 
+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 
+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 "AssimpPCH.h"
+
 #ifndef ASSIMP_BUILD_NO_BVH_IMPORTER
 
 #include "BVHLoader.h"
 #include "fast_atof.h"
 #include "SkeletonMeshBuilder.h"
+#include "../include/assimp/Importer.hpp"
+#include <boost/scoped_ptr.hpp>
+#include <boost/format.hpp>
+#include "../include/assimp/IOSystem.hpp"
+#include "../include/assimp/scene.h"
 
 using namespace Assimp;
 
 static const aiImporterDesc desc = {
-	"BVH Importer (MoCap)",
-	"",
-	"",
-	"",
-	aiImporterFlags_SupportTextFlavour,
-	0,
-	0,
-	0,
-	0,
-	"bvh"
+    "BVH Importer (MoCap)",
+    "",
+    "",
+    "",
+    aiImporterFlags_SupportTextFlavour,
+    0,
+    0,
+    0,
+    0,
+    "bvh"
 };
 
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 BVHLoader::BVHLoader()
-: noSkeletonMesh()
+    : mLine(),
+    mAnimTickDuration(),
+    mAnimNumFrames(),
+    noSkeletonMesh()
 {}
 
 // ------------------------------------------------------------------------------------------------
@@ -74,461 +82,461 @@ BVHLoader::~BVHLoader()
 {}
 
 // ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file. 
+// Returns whether the class can handle the format of the given file.
 bool BVHLoader::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool cs) const
 {
-	// check file extension 
-	const std::string extension = GetExtension(pFile);
-	
-	if( extension == "bvh")
-		return true;
-
-	if ((!extension.length() || cs) && pIOHandler) {
-		const char* tokens[] = {"HIERARCHY"};
-		return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
-	}
-	return false;
+    // check file extension
+    const std::string extension = GetExtension(pFile);
+
+    if( extension == "bvh")
+        return true;
+
+    if ((!extension.length() || cs) && pIOHandler) {
+        const char* tokens[] = {"HIERARCHY"};
+        return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
+    }
+    return false;
 }
 
 // ------------------------------------------------------------------------------------------------
 void BVHLoader::SetupProperties(const Importer* pImp)
 {
-	noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
+    noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Loader meta information
 const aiImporterDesc* BVHLoader::GetInfo () const
 {
-	return &desc;
+    return &desc;
 }
 
 // ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure. 
+// Imports the given file into the given scene structure.
 void BVHLoader::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
 {
-	mFileName = pFile;
+    mFileName = pFile;
 
-	// read file into memory
-	boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
-	if( file.get() == NULL)
-		throw DeadlyImportError( "Failed to open file " + pFile + ".");
+    // read file into memory
+    boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
+    if( file.get() == NULL)
+        throw DeadlyImportError( "Failed to open file " + pFile + ".");
 
-	size_t fileSize = file->FileSize();
-	if( fileSize == 0)
-		throw DeadlyImportError( "File is too small.");
+    size_t fileSize = file->FileSize();
+    if( fileSize == 0)
+        throw DeadlyImportError( "File is too small.");
 
-	mBuffer.resize( fileSize);
-	file->Read( &mBuffer.front(), 1, fileSize);
+    mBuffer.resize( fileSize);
+    file->Read( &mBuffer.front(), 1, fileSize);
 
-	// start reading
-	mReader = mBuffer.begin();
-	mLine = 1;
-	ReadStructure( pScene);
+    // start reading
+    mReader = mBuffer.begin();
+    mLine = 1;
+    ReadStructure( pScene);
 
-	if (!noSkeletonMesh) {
-		// build a dummy mesh for the skeleton so that we see something at least
-		SkeletonMeshBuilder meshBuilder( pScene);
-	}
+    if (!noSkeletonMesh) {
+        // build a dummy mesh for the skeleton so that we see something at least
+        SkeletonMeshBuilder meshBuilder( pScene);
+    }
 
-	// construct an animation from all the motion data we read
-	CreateAnimation( pScene);
+    // construct an animation from all the motion data we read
+    CreateAnimation( pScene);
 }
 
 // ------------------------------------------------------------------------------------------------
 // Reads the file
 void BVHLoader::ReadStructure( aiScene* pScene)
 {
-	// first comes hierarchy
-	std::string header = GetNextToken();
-	if( header != "HIERARCHY")
-		ThrowException( "Expected header string \"HIERARCHY\".");
-	ReadHierarchy( pScene);
-
-	// then comes the motion data
-	std::string motion = GetNextToken();
-	if( motion != "MOTION")
-		ThrowException( "Expected beginning of motion data \"MOTION\".");
-	ReadMotion( pScene);
+    // first comes hierarchy
+    std::string header = GetNextToken();
+    if( header != "HIERARCHY")
+        ThrowException( "Expected header string \"HIERARCHY\".");
+    ReadHierarchy( pScene);
+
+    // then comes the motion data
+    std::string motion = GetNextToken();
+    if( motion != "MOTION")
+        ThrowException( "Expected beginning of motion data \"MOTION\".");
+    ReadMotion( pScene);
 }
 
 // ------------------------------------------------------------------------------------------------
 // Reads the hierarchy
 void BVHLoader::ReadHierarchy( aiScene* pScene)
 {
-	std::string root = GetNextToken();
-	if( root != "ROOT")
-		ThrowException( "Expected root node \"ROOT\".");
+    std::string root = GetNextToken();
+    if( root != "ROOT")
+        ThrowException( "Expected root node \"ROOT\".");
 
-	// Go read the hierarchy from here
-	pScene->mRootNode = ReadNode();
+    // Go read the hierarchy from here
+    pScene->mRootNode = ReadNode();
 }
 
 // ------------------------------------------------------------------------------------------------
 // Reads a node and recursively its childs and returns the created node;
 aiNode* BVHLoader::ReadNode()
 {
-	// first token is name
-	std::string nodeName = GetNextToken();
-	if( nodeName.empty() || nodeName == "{")
-		ThrowException( boost::str( boost::format( "Expected node name, but found \"%s\".") % nodeName));
-
-	// then an opening brace should follow
-	std::string openBrace = GetNextToken();
-	if( openBrace != "{")
-		ThrowException( boost::str( boost::format( "Expected opening brace \"{\", but found \"%s\".") % openBrace));
-
-	// Create a node
-	aiNode* node = new aiNode( nodeName);
-	std::vector<aiNode*> childNodes;
-
-	// and create an bone entry for it
-	mNodes.push_back( Node( node));
-	Node& internNode = mNodes.back();
-
-	// now read the node's contents
-	while( 1)
-	{
-		std::string token = GetNextToken();
-
-		// node offset to parent node
-		if( token == "OFFSET")
-			ReadNodeOffset( node);
-		else if( token == "CHANNELS")
-			ReadNodeChannels( internNode);
-		else if( token == "JOINT")
-		{
-			// child node follows
-			aiNode* child = ReadNode();
-			child->mParent = node;
-			childNodes.push_back( child);
-		} 
-		else if( token == "End")
-		{
-			// The real symbol is "End Site". Second part comes in a separate token
-			std::string siteToken = GetNextToken();
-			if( siteToken != "Site")
-				ThrowException( boost::str( boost::format( "Expected \"End Site\" keyword, but found \"%s %s\".") % token % siteToken));
-
-			aiNode* child = ReadEndSite( nodeName);
-			child->mParent = node;
-			childNodes.push_back( child);
-		} 
-		else if( token == "}")
-		{
-			// we're done with that part of the hierarchy
-			break;
-		} else
-		{
-			// everything else is a parse error
-			ThrowException( boost::str( boost::format( "Unknown keyword \"%s\".") % token));
-		}
-	}
-
-	// add the child nodes if there are any
-	if( childNodes.size() > 0)
-	{
-		node->mNumChildren = childNodes.size();
-		node->mChildren = new aiNode*[node->mNumChildren];
-		std::copy( childNodes.begin(), childNodes.end(), node->mChildren);
-	}
-
-	// and return the sub-hierarchy we built here
-	return node;
+    // first token is name
+    std::string nodeName = GetNextToken();
+    if( nodeName.empty() || nodeName == "{")
+        ThrowException( boost::str( boost::format( "Expected node name, but found \"%s\".") % nodeName));
+
+    // then an opening brace should follow
+    std::string openBrace = GetNextToken();
+    if( openBrace != "{")
+        ThrowException( boost::str( boost::format( "Expected opening brace \"{\", but found \"%s\".") % openBrace));
+
+    // Create a node
+    aiNode* node = new aiNode( nodeName);
+    std::vector<aiNode*> childNodes;
+
+    // and create an bone entry for it
+    mNodes.push_back( Node( node));
+    Node& internNode = mNodes.back();
+
+    // now read the node's contents
+    while( 1)
+    {
+        std::string token = GetNextToken();
+
+        // node offset to parent node
+        if( token == "OFFSET")
+            ReadNodeOffset( node);
+        else if( token == "CHANNELS")
+            ReadNodeChannels( internNode);
+        else if( token == "JOINT")
+        {
+            // child node follows
+            aiNode* child = ReadNode();
+            child->mParent = node;
+            childNodes.push_back( child);
+        }
+        else if( token == "End")
+        {
+            // The real symbol is "End Site". Second part comes in a separate token
+            std::string siteToken = GetNextToken();
+            if( siteToken != "Site")
+                ThrowException( boost::str( boost::format( "Expected \"End Site\" keyword, but found \"%s %s\".") % token % siteToken));
+
+            aiNode* child = ReadEndSite( nodeName);
+            child->mParent = node;
+            childNodes.push_back( child);
+        }
+        else if( token == "}")
+        {
+            // we're done with that part of the hierarchy
+            break;
+        } else
+        {
+            // everything else is a parse error
+            ThrowException( boost::str( boost::format( "Unknown keyword \"%s\".") % token));
+        }
+    }
+
+    // add the child nodes if there are any
+    if( childNodes.size() > 0)
+    {
+        node->mNumChildren = childNodes.size();
+        node->mChildren = new aiNode*[node->mNumChildren];
+        std::copy( childNodes.begin(), childNodes.end(), node->mChildren);
+    }
+
+    // and return the sub-hierarchy we built here
+    return node;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Reads an end node and returns the created node.
 aiNode* BVHLoader::ReadEndSite( const std::string& pParentName)
 {
-	// check opening brace
-	std::string openBrace = GetNextToken();
-	if( openBrace != "{")
-		ThrowException( boost::str( boost::format( "Expected opening brace \"{\", but found \"%s\".") % openBrace));
-
-	// Create a node
-	aiNode* node = new aiNode( "EndSite_" + pParentName);
-
-	// now read the node's contents. Only possible entry is "OFFSET"
-	while( 1)
-	{
-		std::string token = GetNextToken();
-
-		// end node's offset
-		if( token == "OFFSET")
-		{
-			ReadNodeOffset( node);
-		} 
-		else if( token == "}")
-		{
-			// we're done with the end node
-			break;
-		} else
-		{
-			// everything else is a parse error
-			ThrowException( boost::str( boost::format( "Unknown keyword \"%s\".") % token));
-		}
-	}
-
-	// and return the sub-hierarchy we built here
-	return node;
+    // check opening brace
+    std::string openBrace = GetNextToken();
+    if( openBrace != "{")
+        ThrowException( boost::str( boost::format( "Expected opening brace \"{\", but found \"%s\".") % openBrace));
+
+    // Create a node
+    aiNode* node = new aiNode( "EndSite_" + pParentName);
+
+    // now read the node's contents. Only possible entry is "OFFSET"
+    while( 1)
+    {
+        std::string token = GetNextToken();
+
+        // end node's offset
+        if( token == "OFFSET")
+        {
+            ReadNodeOffset( node);
+        }
+        else if( token == "}")
+        {
+            // we're done with the end node
+            break;
+        } else
+        {
+            // everything else is a parse error
+            ThrowException( boost::str( boost::format( "Unknown keyword \"%s\".") % token));
+        }
+    }
+
+    // and return the sub-hierarchy we built here
+    return node;
 }
 // ------------------------------------------------------------------------------------------------
 // Reads a node offset for the given node
 void BVHLoader::ReadNodeOffset( aiNode* pNode)
 {
-	// Offset consists of three floats to read
-	aiVector3D offset;
-	offset.x = GetNextTokenAsFloat();
-	offset.y = GetNextTokenAsFloat();
-	offset.z = GetNextTokenAsFloat();
-
-	// build a transformation matrix from it
-	pNode->mTransformation = aiMatrix4x4( 1.0f, 0.0f, 0.0f, offset.x, 0.0f, 1.0f, 0.0f, offset.y,
-		0.0f, 0.0f, 1.0f, offset.z, 0.0f, 0.0f, 0.0f, 1.0f);
+    // Offset consists of three floats to read
+    aiVector3D offset;
+    offset.x = GetNextTokenAsFloat();
+    offset.y = GetNextTokenAsFloat();
+    offset.z = GetNextTokenAsFloat();
+
+    // build a transformation matrix from it
+    pNode->mTransformation = aiMatrix4x4( 1.0f, 0.0f, 0.0f, offset.x, 0.0f, 1.0f, 0.0f, offset.y,
+        0.0f, 0.0f, 1.0f, offset.z, 0.0f, 0.0f, 0.0f, 1.0f);
 }
 
 // ------------------------------------------------------------------------------------------------
 // Reads the animation channels for the given node
 void BVHLoader::ReadNodeChannels( BVHLoader::Node& pNode)
 {
-	// number of channels. Use the float reader because we're lazy
-	float numChannelsFloat = GetNextTokenAsFloat();
-	unsigned int numChannels = (unsigned int) numChannelsFloat;
-
-	for( unsigned int a = 0; a < numChannels; a++)
-	{
-		std::string channelToken = GetNextToken();
-
-		if( channelToken == "Xposition")
-			pNode.mChannels.push_back( Channel_PositionX);
-		else if( channelToken == "Yposition")
-			pNode.mChannels.push_back( Channel_PositionY);
-		else if( channelToken == "Zposition")
-			pNode.mChannels.push_back( Channel_PositionZ);
-		else if( channelToken == "Xrotation")
-			pNode.mChannels.push_back( Channel_RotationX);
-		else if( channelToken == "Yrotation")
-			pNode.mChannels.push_back( Channel_RotationY);
-		else if( channelToken == "Zrotation")
-			pNode.mChannels.push_back( Channel_RotationZ);
-		else
-			ThrowException( boost::str( boost::format( "Invalid channel specifier \"%s\".") % channelToken));
-	}
+    // number of channels. Use the float reader because we're lazy
+    float numChannelsFloat = GetNextTokenAsFloat();
+    unsigned int numChannels = (unsigned int) numChannelsFloat;
+
+    for( unsigned int a = 0; a < numChannels; a++)
+    {
+        std::string channelToken = GetNextToken();
+
+        if( channelToken == "Xposition")
+            pNode.mChannels.push_back( Channel_PositionX);
+        else if( channelToken == "Yposition")
+            pNode.mChannels.push_back( Channel_PositionY);
+        else if( channelToken == "Zposition")
+            pNode.mChannels.push_back( Channel_PositionZ);
+        else if( channelToken == "Xrotation")
+            pNode.mChannels.push_back( Channel_RotationX);
+        else if( channelToken == "Yrotation")
+            pNode.mChannels.push_back( Channel_RotationY);
+        else if( channelToken == "Zrotation")
+            pNode.mChannels.push_back( Channel_RotationZ);
+        else
+            ThrowException( boost::str( boost::format( "Invalid channel specifier \"%s\".") % channelToken));
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 // Reads the motion data
 void BVHLoader::ReadMotion( aiScene* /*pScene*/)
 {
-	// Read number of frames
-	std::string tokenFrames = GetNextToken();
-	if( tokenFrames != "Frames:")
-		ThrowException( boost::str( boost::format( "Expected frame count \"Frames:\", but found \"%s\".") % tokenFrames));
-
-	float numFramesFloat = GetNextTokenAsFloat();
-	mAnimNumFrames = (unsigned int) numFramesFloat;
-
-	// Read frame duration
-	std::string tokenDuration1 = GetNextToken();
-	std::string tokenDuration2 = GetNextToken();
-	if( tokenDuration1 != "Frame" || tokenDuration2 != "Time:")
-		ThrowException( boost::str( boost::format( "Expected frame duration \"Frame Time:\", but found \"%s %s\".") % tokenDuration1 % tokenDuration2));
-
-	mAnimTickDuration = GetNextTokenAsFloat();
-
-	// resize value vectors for each node
-	for( std::vector<Node>::iterator it = mNodes.begin(); it != mNodes.end(); ++it)
-		it->mChannelValues.reserve( it->mChannels.size() * mAnimNumFrames);
-
-	// now read all the data and store it in the corresponding node's value vector
-	for( unsigned int frame = 0; frame < mAnimNumFrames; ++frame)
-	{
-		// on each line read the values for all nodes
-		for( std::vector<Node>::iterator it = mNodes.begin(); it != mNodes.end(); ++it)
-		{
-			// get as many values as the node has channels
-			for( unsigned int c = 0; c < it->mChannels.size(); ++c)
-				it->mChannelValues.push_back( GetNextTokenAsFloat());
-		}
-
-		// after one frame worth of values for all nodes there should be a newline, but we better don't rely on it
-	}
+    // Read number of frames
+    std::string tokenFrames = GetNextToken();
+    if( tokenFrames != "Frames:")
+        ThrowException( boost::str( boost::format( "Expected frame count \"Frames:\", but found \"%s\".") % tokenFrames));
+
+    float numFramesFloat = GetNextTokenAsFloat();
+    mAnimNumFrames = (unsigned int) numFramesFloat;
+
+    // Read frame duration
+    std::string tokenDuration1 = GetNextToken();
+    std::string tokenDuration2 = GetNextToken();
+    if( tokenDuration1 != "Frame" || tokenDuration2 != "Time:")
+        ThrowException( boost::str( boost::format( "Expected frame duration \"Frame Time:\", but found \"%s %s\".") % tokenDuration1 % tokenDuration2));
+
+    mAnimTickDuration = GetNextTokenAsFloat();
+
+    // resize value vectors for each node
+    for( std::vector<Node>::iterator it = mNodes.begin(); it != mNodes.end(); ++it)
+        it->mChannelValues.reserve( it->mChannels.size() * mAnimNumFrames);
+
+    // now read all the data and store it in the corresponding node's value vector
+    for( unsigned int frame = 0; frame < mAnimNumFrames; ++frame)
+    {
+        // on each line read the values for all nodes
+        for( std::vector<Node>::iterator it = mNodes.begin(); it != mNodes.end(); ++it)
+        {
+            // get as many values as the node has channels
+            for( unsigned int c = 0; c < it->mChannels.size(); ++c)
+                it->mChannelValues.push_back( GetNextTokenAsFloat());
+        }
+
+        // after one frame worth of values for all nodes there should be a newline, but we better don't rely on it
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 // Retrieves the next token
 std::string BVHLoader::GetNextToken()
 {
-	// skip any preceeding whitespace
-	while( mReader != mBuffer.end())
-	{
-		if( !isspace( *mReader))
-			break;
-
-		// count lines
-		if( *mReader == '\n')
-			mLine++;
-
-		++mReader;
-	}
-
-	// collect all chars till the next whitespace. BVH is easy in respect to that.
-	std::string token;
-	while( mReader != mBuffer.end())
-	{
-		if( isspace( *mReader))
-			break;
-
-		token.push_back( *mReader);
-		++mReader;
-
-		// little extra logic to make sure braces are counted correctly
-		if( token == "{" || token == "}")
-			break;
-	}
-
-	// empty token means end of file, which is just fine
-	return token;
+    // skip any preceeding whitespace
+    while( mReader != mBuffer.end())
+    {
+        if( !isspace( *mReader))
+            break;
+
+        // count lines
+        if( *mReader == '\n')
+            mLine++;
+
+        ++mReader;
+    }
+
+    // collect all chars till the next whitespace. BVH is easy in respect to that.
+    std::string token;
+    while( mReader != mBuffer.end())
+    {
+        if( isspace( *mReader))
+            break;
+
+        token.push_back( *mReader);
+        ++mReader;
+
+        // little extra logic to make sure braces are counted correctly
+        if( token == "{" || token == "}")
+            break;
+    }
+
+    // empty token means end of file, which is just fine
+    return token;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Reads the next token as a float
 float BVHLoader::GetNextTokenAsFloat()
 {
-	std::string token = GetNextToken();
-	if( token.empty())
-		ThrowException( "Unexpected end of file while trying to read a float");
+    std::string token = GetNextToken();
+    if( token.empty())
+        ThrowException( "Unexpected end of file while trying to read a float");
 
-	// check if the float is valid by testing if the atof() function consumed every char of the token
-	const char* ctoken = token.c_str();
-	float result = 0.0f;
-	ctoken = fast_atoreal_move<float>( ctoken, result);
+    // check if the float is valid by testing if the atof() function consumed every char of the token
+    const char* ctoken = token.c_str();
+    float result = 0.0f;
+    ctoken = fast_atoreal_move<float>( ctoken, result);
 
-	if( ctoken != token.c_str() + token.length())
-		ThrowException( boost::str( boost::format( "Expected a floating point number, but found \"%s\".") % token));
+    if( ctoken != token.c_str() + token.length())
+        ThrowException( boost::str( boost::format( "Expected a floating point number, but found \"%s\".") % token));
 
-	return result;
+    return result;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Aborts the file reading with an exception
-void BVHLoader::ThrowException( const std::string& pError)
+AI_WONT_RETURN void BVHLoader::ThrowException( const std::string& pError)
 {
-	throw DeadlyImportError( boost::str( boost::format( "%s:%d - %s") % mFileName % mLine % pError));
+    throw DeadlyImportError( boost::str( boost::format( "%s:%d - %s") % mFileName % mLine % pError));
 }
 
 // ------------------------------------------------------------------------------------------------
 // Constructs an animation for the motion data and stores it in the given scene
 void BVHLoader::CreateAnimation( aiScene* pScene)
 {
-	// create the animation
-	pScene->mNumAnimations = 1;
-	pScene->mAnimations = new aiAnimation*[1];
-	aiAnimation* anim = new aiAnimation;
-	pScene->mAnimations[0] = anim;
-
-	// put down the basic parameters
-	anim->mName.Set( "Motion");
-	anim->mTicksPerSecond = 1.0 / double( mAnimTickDuration);
-	anim->mDuration = double( mAnimNumFrames - 1);
-
-	// now generate the tracks for all nodes
-	anim->mNumChannels = mNodes.size();
-	anim->mChannels = new aiNodeAnim*[anim->mNumChannels];
-
-	// FIX: set the array elements to NULL to ensure proper deletion if an exception is thrown
-	for (unsigned int i = 0; i < anim->mNumChannels;++i)
-		anim->mChannels[i] = NULL;
-
-	for( unsigned int a = 0; a < anim->mNumChannels; a++)
-	{
-		const Node& node = mNodes[a];
-		const std::string nodeName = std::string( node.mNode->mName.data );
-		aiNodeAnim* nodeAnim = new aiNodeAnim;
-		anim->mChannels[a] = nodeAnim;
-		nodeAnim->mNodeName.Set( nodeName);
-
-		// translational part, if given
-		if( node.mChannels.size() == 6)
-		{
-			nodeAnim->mNumPositionKeys = mAnimNumFrames;
-			nodeAnim->mPositionKeys = new aiVectorKey[mAnimNumFrames];
-			aiVectorKey* poskey = nodeAnim->mPositionKeys;
-			for( unsigned int fr = 0; fr < mAnimNumFrames; ++fr)
-			{
-				poskey->mTime = double( fr);
-
-				// Now compute all translations in the right order
-				for( unsigned int channel = 0; channel < 3; ++channel)
-				{
-					switch( node.mChannels[channel])
-					{	
-					case Channel_PositionX: poskey->mValue.x = node.mChannelValues[fr * node.mChannels.size() + channel]; break;
-					case Channel_PositionY: poskey->mValue.y = node.mChannelValues[fr * node.mChannels.size() + channel]; break;
-					case Channel_PositionZ: poskey->mValue.z = node.mChannelValues[fr * node.mChannels.size() + channel]; break;
-					default: throw DeadlyImportError( "Unexpected animation channel setup at node " + nodeName );
-					}
-				}
-				++poskey;
-			}
-		} else
-		{
-			// if no translation part is given, put a default sequence
-			aiVector3D nodePos( node.mNode->mTransformation.a4, node.mNode->mTransformation.b4, node.mNode->mTransformation.c4);
-			nodeAnim->mNumPositionKeys = 1;
-			nodeAnim->mPositionKeys = new aiVectorKey[1];
-			nodeAnim->mPositionKeys[0].mTime = 0.0;
-			nodeAnim->mPositionKeys[0].mValue = nodePos;
-		}
-
-		// rotation part. Always present. First find value offsets
-		{
-			unsigned int rotOffset  = 0;
-			if( node.mChannels.size() == 6)
-			{
-				// Offset all further calculations
-				rotOffset = 3;
-			} 
-
-			// Then create the number of rotation keys
-			nodeAnim->mNumRotationKeys = mAnimNumFrames;
-			nodeAnim->mRotationKeys = new aiQuatKey[mAnimNumFrames];
-			aiQuatKey* rotkey = nodeAnim->mRotationKeys;
-			for( unsigned int fr = 0; fr < mAnimNumFrames; ++fr)
-			{
-				aiMatrix4x4 temp;
-				aiMatrix3x3 rotMatrix;
-
-				for( unsigned int channel = 0; channel < 3; ++channel)
-				{
-					// translate ZXY euler angels into a quaternion
-					const float angle = node.mChannelValues[fr * node.mChannels.size() + rotOffset + channel] * float( AI_MATH_PI) / 180.0f;
-
-					// Compute rotation transformations in the right order
-					switch (node.mChannels[rotOffset+channel]) 
-					{
-					case Channel_RotationX: aiMatrix4x4::RotationX( angle, temp); rotMatrix *= aiMatrix3x3( temp); break;
-					case Channel_RotationY: aiMatrix4x4::RotationY( angle, temp); rotMatrix *= aiMatrix3x3( temp);	break;
-					case Channel_RotationZ: aiMatrix4x4::RotationZ( angle, temp); rotMatrix *= aiMatrix3x3( temp); break;
-					default: throw DeadlyImportError( "Unexpected animation channel setup at node " + nodeName );
-					}
-				}
-
-				rotkey->mTime = double( fr);
-				rotkey->mValue = aiQuaternion( rotMatrix);
-				++rotkey;
-			}
-		}
-
-		// scaling part. Always just a default track
-		{
-			nodeAnim->mNumScalingKeys = 1;
-			nodeAnim->mScalingKeys = new aiVectorKey[1];
-			nodeAnim->mScalingKeys[0].mTime = 0.0;
-			nodeAnim->mScalingKeys[0].mValue.Set( 1.0f, 1.0f, 1.0f);
-		}
-	}
+    // create the animation
+    pScene->mNumAnimations = 1;
+    pScene->mAnimations = new aiAnimation*[1];
+    aiAnimation* anim = new aiAnimation;
+    pScene->mAnimations[0] = anim;
+
+    // put down the basic parameters
+    anim->mName.Set( "Motion");
+    anim->mTicksPerSecond = 1.0 / double( mAnimTickDuration);
+    anim->mDuration = double( mAnimNumFrames - 1);
+
+    // now generate the tracks for all nodes
+    anim->mNumChannels = mNodes.size();
+    anim->mChannels = new aiNodeAnim*[anim->mNumChannels];
+
+    // FIX: set the array elements to NULL to ensure proper deletion if an exception is thrown
+    for (unsigned int i = 0; i < anim->mNumChannels;++i)
+        anim->mChannels[i] = NULL;
+
+    for( unsigned int a = 0; a < anim->mNumChannels; a++)
+    {
+        const Node& node = mNodes[a];
+        const std::string nodeName = std::string( node.mNode->mName.data );
+        aiNodeAnim* nodeAnim = new aiNodeAnim;
+        anim->mChannels[a] = nodeAnim;
+        nodeAnim->mNodeName.Set( nodeName);
+
+        // translational part, if given
+        if( node.mChannels.size() == 6)
+        {
+            nodeAnim->mNumPositionKeys = mAnimNumFrames;
+            nodeAnim->mPositionKeys = new aiVectorKey[mAnimNumFrames];
+            aiVectorKey* poskey = nodeAnim->mPositionKeys;
+            for( unsigned int fr = 0; fr < mAnimNumFrames; ++fr)
+            {
+                poskey->mTime = double( fr);
+
+                // Now compute all translations in the right order
+                for( unsigned int channel = 0; channel < 3; ++channel)
+                {
+                    switch( node.mChannels[channel])
+                    {
+                    case Channel_PositionX: poskey->mValue.x = node.mChannelValues[fr * node.mChannels.size() + channel]; break;
+                    case Channel_PositionY: poskey->mValue.y = node.mChannelValues[fr * node.mChannels.size() + channel]; break;
+                    case Channel_PositionZ: poskey->mValue.z = node.mChannelValues[fr * node.mChannels.size() + channel]; break;
+                    default: throw DeadlyImportError( "Unexpected animation channel setup at node " + nodeName );
+                    }
+                }
+                ++poskey;
+            }
+        } else
+        {
+            // if no translation part is given, put a default sequence
+            aiVector3D nodePos( node.mNode->mTransformation.a4, node.mNode->mTransformation.b4, node.mNode->mTransformation.c4);
+            nodeAnim->mNumPositionKeys = 1;
+            nodeAnim->mPositionKeys = new aiVectorKey[1];
+            nodeAnim->mPositionKeys[0].mTime = 0.0;
+            nodeAnim->mPositionKeys[0].mValue = nodePos;
+        }
+
+        // rotation part. Always present. First find value offsets
+        {
+            unsigned int rotOffset  = 0;
+            if( node.mChannels.size() == 6)
+            {
+                // Offset all further calculations
+                rotOffset = 3;
+            }
+
+            // Then create the number of rotation keys
+            nodeAnim->mNumRotationKeys = mAnimNumFrames;
+            nodeAnim->mRotationKeys = new aiQuatKey[mAnimNumFrames];
+            aiQuatKey* rotkey = nodeAnim->mRotationKeys;
+            for( unsigned int fr = 0; fr < mAnimNumFrames; ++fr)
+            {
+                aiMatrix4x4 temp;
+                aiMatrix3x3 rotMatrix;
+
+                for( unsigned int channel = 0; channel < 3; ++channel)
+                {
+                    // translate ZXY euler angels into a quaternion
+                    const float angle = node.mChannelValues[fr * node.mChannels.size() + rotOffset + channel] * float( AI_MATH_PI) / 180.0f;
+
+                    // Compute rotation transformations in the right order
+                    switch (node.mChannels[rotOffset+channel])
+                    {
+                    case Channel_RotationX: aiMatrix4x4::RotationX( angle, temp); rotMatrix *= aiMatrix3x3( temp); break;
+                    case Channel_RotationY: aiMatrix4x4::RotationY( angle, temp); rotMatrix *= aiMatrix3x3( temp);  break;
+                    case Channel_RotationZ: aiMatrix4x4::RotationZ( angle, temp); rotMatrix *= aiMatrix3x3( temp); break;
+                    default: throw DeadlyImportError( "Unexpected animation channel setup at node " + nodeName );
+                    }
+                }
+
+                rotkey->mTime = double( fr);
+                rotkey->mValue = aiQuaternion( rotMatrix);
+                ++rotkey;
+            }
+        }
+
+        // scaling part. Always just a default track
+        {
+            nodeAnim->mNumScalingKeys = 1;
+            nodeAnim->mScalingKeys = new aiVectorKey[1];
+            nodeAnim->mScalingKeys[0].mTime = 0.0;
+            nodeAnim->mScalingKeys[0].mValue.Set( 1.0f, 1.0f, 1.0f);
+        }
+    }
 }
 
 #endif // !! ASSIMP_BUILD_NO_BVH_IMPORTER

+ 83 - 81
assimplib.mod/assimp/code/BVHLoader.h

@@ -4,11 +4,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -25,16 +25,16 @@ 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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -49,11 +49,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include "BaseImporter.h"
 
+struct aiNode;
+
 namespace Assimp
 {
 
 // --------------------------------------------------------------------------------
-/** Loader class to read Motion Capturing data from a .bvh file. 
+/** Loader class to read Motion Capturing data from a .bvh file.
  *
  * This format only contains a hierarchy of joints and a series of keyframes for
  * the hierarchy. It contains no actual mesh data, but we generate a dummy mesh
@@ -62,106 +64,106 @@ namespace Assimp
 class BVHLoader : public BaseImporter
 {
 
-	/** Possible animation channels for which the motion data holds the values */
-	enum ChannelType
-	{
-		Channel_PositionX,
-		Channel_PositionY,
-		Channel_PositionZ,
-		Channel_RotationX,
-		Channel_RotationY,
-		Channel_RotationZ
-	};
-
-	/** Collected list of node. Will be bones of the dummy mesh some day, addressed by their array index */
-	struct Node
-	{
-		const aiNode* mNode;
-		std::vector<ChannelType> mChannels;
-		std::vector<float> mChannelValues; // motion data values for that node. Of size NumChannels * NumFrames
-
-		Node() { }
-		Node( const aiNode* pNode) : mNode( pNode) { }
-	};
+    /** Possible animation channels for which the motion data holds the values */
+    enum ChannelType
+    {
+        Channel_PositionX,
+        Channel_PositionY,
+        Channel_PositionZ,
+        Channel_RotationX,
+        Channel_RotationY,
+        Channel_RotationZ
+    };
+
+    /** Collected list of node. Will be bones of the dummy mesh some day, addressed by their array index */
+    struct Node
+    {
+        const aiNode* mNode;
+        std::vector<ChannelType> mChannels;
+        std::vector<float> mChannelValues; // motion data values for that node. Of size NumChannels * NumFrames
+
+        Node() { }
+        explicit Node( const aiNode* pNode) : mNode( pNode) { }
+    };
 
 public:
 
-	BVHLoader();
-	~BVHLoader();
+    BVHLoader();
+    ~BVHLoader();
 
 public:
-	/** Returns whether the class can handle the format of the given file. 
-	 * See BaseImporter::CanRead() for details.	*/
-	bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool cs) const;
+    /** Returns whether the class can handle the format of the given file.
+     * See BaseImporter::CanRead() for details. */
+    bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool cs) const;
 
-	void SetupProperties(const Importer* pImp);
-	const aiImporterDesc* GetInfo () const;
+    void SetupProperties(const Importer* pImp);
+    const aiImporterDesc* GetInfo () const;
 
 protected:
 
 
-	/** Imports the given file into the given scene structure. 
-	 * See BaseImporter::InternReadFile() for details
-	 */
-	void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
+    /** Imports the given file into the given scene structure.
+     * See BaseImporter::InternReadFile() for details
+     */
+    void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
 
 protected:
-	/** Reads the file */
-	void ReadStructure( aiScene* pScene);
+    /** Reads the file */
+    void ReadStructure( aiScene* pScene);
 
-	/** Reads the hierarchy */
-	void ReadHierarchy( aiScene* pScene);
+    /** Reads the hierarchy */
+    void ReadHierarchy( aiScene* pScene);
 
-	/** Reads a node and recursively its childs and returns the created node. */
-	aiNode* ReadNode();
+    /** Reads a node and recursively its childs and returns the created node. */
+    aiNode* ReadNode();
 
-	/** Reads an end node and returns the created node. */
-	aiNode* ReadEndSite( const std::string& pParentName);
+    /** Reads an end node and returns the created node. */
+    aiNode* ReadEndSite( const std::string& pParentName);
 
-	/** Reads a node offset for the given node */
-	void ReadNodeOffset( aiNode* pNode);
+    /** Reads a node offset for the given node */
+    void ReadNodeOffset( aiNode* pNode);
 
-	/** Reads the animation channels into the given node */
-	void ReadNodeChannels( BVHLoader::Node& pNode);
+    /** Reads the animation channels into the given node */
+    void ReadNodeChannels( BVHLoader::Node& pNode);
 
-	/** Reads the motion data */
-	void ReadMotion( aiScene* pScene);
+    /** Reads the motion data */
+    void ReadMotion( aiScene* pScene);
 
-	/** Retrieves the next token */
-	std::string GetNextToken();
+    /** Retrieves the next token */
+    std::string GetNextToken();
 
-	/** Reads the next token as a float */
-	float GetNextTokenAsFloat();
+    /** Reads the next token as a float */
+    float GetNextTokenAsFloat();
 
-	/** Aborts the file reading with an exception */
-	void ThrowException( const std::string& pError);
+    /** Aborts the file reading with an exception */
+    AI_WONT_RETURN void ThrowException( const std::string& pError) AI_WONT_RETURN_SUFFIX;
 
-	/** Constructs an animation for the motion data and stores it in the given scene */
-	void CreateAnimation( aiScene* pScene);
+    /** Constructs an animation for the motion data and stores it in the given scene */
+    void CreateAnimation( aiScene* pScene);
 
 protected:
-	/** Filename, for a verbose error message */
-	std::string mFileName;
+    /** Filename, for a verbose error message */
+    std::string mFileName;
 
-	/** Buffer to hold the loaded file */
-	std::vector<char> mBuffer;
+    /** Buffer to hold the loaded file */
+    std::vector<char> mBuffer;
 
-	/** Next char to read from the buffer */
-	std::vector<char>::const_iterator mReader;
+    /** Next char to read from the buffer */
+    std::vector<char>::const_iterator mReader;
 
-	/** Current line, for error messages */
-	unsigned int mLine;
+    /** Current line, for error messages */
+    unsigned int mLine;
 
-	/** Collected list of nodes. Will be bones of the dummy mesh some day, addressed by their array index.
-	* Also contain the motion data for the node's channels
-	*/
-	std::vector<Node> mNodes;
+    /** Collected list of nodes. Will be bones of the dummy mesh some day, addressed by their array index.
+    * Also contain the motion data for the node's channels
+    */
+    std::vector<Node> mNodes;
 
-	/** basic Animation parameters */
-	float mAnimTickDuration;
-	unsigned int mAnimNumFrames;
+    /** basic Animation parameters */
+    float mAnimTickDuration;
+    unsigned int mAnimNumFrames;
 
-	bool noSkeletonMesh;
+    bool noSkeletonMesh;
 };
 
 } // end of namespace Assimp

+ 434 - 419
assimplib.mod/assimp/code/BaseImporter.cpp

@@ -3,12 +3,12 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -25,264 +25,281 @@ conditions are met:
   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 
+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 
+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 
+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 
+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  BaseImporter.cpp
- *  @brief Implementation of BaseImporter 
+ *  @brief Implementation of BaseImporter
  */
 
-#include "AssimpPCH.h"
 #include "BaseImporter.h"
 #include "FileSystemFilter.h"
-
 #include "Importer.h"
+#include "ByteSwapper.h"
+#include "../include/assimp/scene.h"
+#include "../include/assimp/Importer.hpp"
+#include "../include/assimp/postprocess.h"
+#include <ios>
+#include <list>
+#include <boost/scoped_ptr.hpp>
+#include <boost/scoped_array.hpp>
+#include <sstream>
+#include <cctype>
+
 
 using namespace Assimp;
 
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 BaseImporter::BaseImporter()
-: progress()
+: m_progress()
 {
-	// nothing to do here
+    // nothing to do here
 }
 
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 BaseImporter::~BaseImporter()
 {
-	// nothing to do here
+    // nothing to do here
 }
 
 // ------------------------------------------------------------------------------------------------
 // Imports the given file and returns the imported data.
 aiScene* BaseImporter::ReadFile(const Importer* pImp, const std::string& pFile, IOSystem* pIOHandler)
 {
-	progress = pImp->GetProgressHandler();
-	ai_assert(progress);
+    m_progress = pImp->GetProgressHandler();
+    ai_assert(m_progress);
 
-	// Gather configuration properties for this run
-	SetupProperties( pImp );
+    // Gather configuration properties for this run
+    SetupProperties( pImp );
 
-	// Construct a file system filter to improve our success ratio at reading external files
-	FileSystemFilter filter(pFile,pIOHandler);
+    // Construct a file system filter to improve our success ratio at reading external files
+    FileSystemFilter filter(pFile,pIOHandler);
 
-	// create a scene object to hold the data
-	ScopeGuard<aiScene> sc(new aiScene());
+    // create a scene object to hold the data
+    ScopeGuard<aiScene> sc(new aiScene());
 
-	// dispatch importing
-	try
-	{
-		InternReadFile( pFile, sc, &filter);
+    // dispatch importing
+    try
+    {
+        InternReadFile( pFile, sc, &filter);
 
-	} catch( const std::exception& err )	{
-		// extract error description
-		mErrorText = err.what();
-		DefaultLogger::get()->error(mErrorText);
-		return NULL;
-	}
+    } catch( const std::exception& err )    {
+        // extract error description
+        m_ErrorText = err.what();
+        DefaultLogger::get()->error(m_ErrorText);
+        return NULL;
+    }
 
-	// return what we gathered from the import. 
-	sc.dismiss();
-	return sc;
+    // return what we gathered from the import.
+    sc.dismiss();
+    return sc;
 }
 
 // ------------------------------------------------------------------------------------------------
 void BaseImporter::SetupProperties(const Importer* /*pImp*/)
 {
-	// the default implementation does nothing
+    // the default implementation does nothing
 }
 
 // ------------------------------------------------------------------------------------------------
 void BaseImporter::GetExtensionList(std::set<std::string>& extensions)
 {
-	const aiImporterDesc* desc = GetInfo();
-	ai_assert(desc != NULL);
-
-	const char* ext = desc->mFileExtensions;
-	ai_assert(ext != NULL);
-
-	const char* last = ext;
-	do {
-		if (!*ext || *ext == ' ') {
-			extensions.insert(std::string(last,ext-last));
-			ai_assert(ext-last > 0);
-			last = ext;
-			while(*last == ' ') {
-				++last;
-			}
-		}
-	}
-	while(*ext++);
+    const aiImporterDesc* desc = GetInfo();
+    ai_assert(desc != NULL);
+
+    const char* ext = desc->mFileExtensions;
+    ai_assert(ext != NULL);
+
+    const char* last = ext;
+    do {
+        if (!*ext || *ext == ' ') {
+            extensions.insert(std::string(last,ext-last));
+            ai_assert(ext-last > 0);
+            last = ext;
+            while(*last == ' ') {
+                ++last;
+            }
+        }
+    }
+    while(*ext++);
 }
 
 // ------------------------------------------------------------------------------------------------
 /*static*/ bool BaseImporter::SearchFileHeaderForToken(IOSystem* pIOHandler,
-	const std::string&	pFile,
-	const char**		tokens, 
-	unsigned int		numTokens,
-	unsigned int		searchBytes /* = 200 */,
-	bool				tokensSol /* false */)
+    const std::string&  pFile,
+    const char**        tokens,
+    unsigned int        numTokens,
+    unsigned int        searchBytes /* = 200 */,
+    bool                tokensSol /* false */)
 {
-	ai_assert(NULL != tokens && 0 != numTokens && 0 != searchBytes);
-	if (!pIOHandler)
-		return false;
-
-	boost::scoped_ptr<IOStream> pStream (pIOHandler->Open(pFile));
-	if (pStream.get() )	{
-		// read 200 characters from the file
-		boost::scoped_array<char> _buffer (new char[searchBytes+1 /* for the '\0' */]);
-		char* buffer = _buffer.get();
-
-		const unsigned int read = pStream->Read(buffer,1,searchBytes);
-		if (!read)
-			return false;
-
-		for (unsigned int i = 0; i < read;++i)
-			buffer[i] = ::tolower(buffer[i]);
-
-		// It is not a proper handling of unicode files here ...
-		// ehm ... but it works in most cases.
-		char* cur = buffer,*cur2 = buffer,*end = &buffer[read];
-		while (cur != end)	{
-			if (*cur)
-				*cur2++ = *cur;
-			++cur;
-		}
-		*cur2 = '\0';
-
-		for (unsigned int i = 0; i < numTokens;++i)	{
-			ai_assert(NULL != tokens[i]);
-
-
-			const char* r = strstr(buffer,tokens[i]);
-			if (!r) 
-				continue;
-			// We got a match, either we don't care where it is, or it happens to
-			// be in the beginning of the file / line
-			if (!tokensSol || r == buffer || r[-1] == '\r' || r[-1] == '\n') {
-				DefaultLogger::get()->debug(std::string("Found positive match for header keyword: ") + tokens[i]);
-				return true;
-			}
-		}
-	}
-	return false;
+    ai_assert(NULL != tokens && 0 != numTokens && 0 != searchBytes);
+    if (!pIOHandler)
+        return false;
+
+    boost::scoped_ptr<IOStream> pStream (pIOHandler->Open(pFile));
+    if (pStream.get() ) {
+        // read 200 characters from the file
+        boost::scoped_array<char> _buffer (new char[searchBytes+1 /* for the '\0' */]);
+        char* buffer = _buffer.get();
+        if( NULL == buffer ) {
+            return false;
+        }
+
+        const size_t read = pStream->Read(buffer,1,searchBytes);
+        if( !read ) {
+            return false;
+        }
+
+        for( size_t i = 0; i < read; ++i ) {
+            buffer[ i ] = ::tolower( buffer[ i ] );
+        }
+
+        // It is not a proper handling of unicode files here ...
+        // ehm ... but it works in most cases.
+        char* cur = buffer,*cur2 = buffer,*end = &buffer[read];
+        while (cur != end)  {
+            if( *cur ) {
+                *cur2++ = *cur;
+            }
+            ++cur;
+        }
+        *cur2 = '\0';
+
+        for (unsigned int i = 0; i < numTokens;++i) {
+            ai_assert(NULL != tokens[i]);
+
+
+            const char* r = strstr(buffer,tokens[i]);
+            if( !r ) {
+                continue;
+            }
+            // We got a match, either we don't care where it is, or it happens to
+            // be in the beginning of the file / line
+            if (!tokensSol || r == buffer || r[-1] == '\r' || r[-1] == '\n') {
+                DefaultLogger::get()->debug(std::string("Found positive match for header keyword: ") + tokens[i]);
+                return true;
+            }
+        }
+    }
+
+    return false;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Simple check for file extension
-/*static*/ bool BaseImporter::SimpleExtensionCheck (const std::string& pFile, 
-	const char* ext0,
-	const char* ext1,
-	const char* ext2)
+/*static*/ bool BaseImporter::SimpleExtensionCheck (const std::string& pFile,
+    const char* ext0,
+    const char* ext1,
+    const char* ext2)
 {
-	std::string::size_type pos = pFile.find_last_of('.');
+    std::string::size_type pos = pFile.find_last_of('.');
 
-	// no file extension - can't read
-	if( pos == std::string::npos)
-		return false;
-	
-	const char* ext_real = & pFile[ pos+1 ];
-	if( !ASSIMP_stricmp(ext_real,ext0) )
-		return true;
+    // no file extension - can't read
+    if( pos == std::string::npos)
+        return false;
 
-	// check for other, optional, file extensions
-	if (ext1 && !ASSIMP_stricmp(ext_real,ext1))
-		return true;
+    const char* ext_real = & pFile[ pos+1 ];
+    if( !ASSIMP_stricmp(ext_real,ext0) )
+        return true;
 
-	if (ext2 && !ASSIMP_stricmp(ext_real,ext2))
-		return true;
+    // check for other, optional, file extensions
+    if (ext1 && !ASSIMP_stricmp(ext_real,ext1))
+        return true;
 
-	return false;
+    if (ext2 && !ASSIMP_stricmp(ext_real,ext2))
+        return true;
+
+    return false;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Get file extension from path
 /*static*/ std::string BaseImporter::GetExtension (const std::string& pFile)
 {
-	std::string::size_type pos = pFile.find_last_of('.');
+    std::string::size_type pos = pFile.find_last_of('.');
 
-	// no file extension at all
-	if( pos == std::string::npos)
-		return "";
+    // no file extension at all
+    if( pos == std::string::npos)
+        return "";
 
-	std::string ret = pFile.substr(pos+1);
-	std::transform(ret.begin(),ret.end(),ret.begin(),::tolower); // thanks to Andy Maloney for the hint
-	return ret;
+    std::string ret = pFile.substr(pos+1);
+    std::transform(ret.begin(),ret.end(),ret.begin(),::tolower); // thanks to Andy Maloney for the hint
+    return ret;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Check for magic bytes at the beginning of the file.
-/* static */ bool BaseImporter::CheckMagicToken(IOSystem* pIOHandler, const std::string& pFile, 
-	const void* _magic, unsigned int num, unsigned int offset, unsigned int size)
+/* static */ bool BaseImporter::CheckMagicToken(IOSystem* pIOHandler, const std::string& pFile,
+    const void* _magic, unsigned int num, unsigned int offset, unsigned int size)
 {
-	ai_assert(size <= 16 && _magic);
-
-	if (!pIOHandler) {
-		return false;
-	}
-	union {
-		const char* magic;
-		const uint16_t* magic_u16;
-		const uint32_t* magic_u32;
-	};
-	magic = reinterpret_cast<const char*>(_magic);
-	boost::scoped_ptr<IOStream> pStream (pIOHandler->Open(pFile));
-	if (pStream.get() )	{
-
-		// skip to offset
-		pStream->Seek(offset,aiOrigin_SET);
-
-		// read 'size' characters from the file
-		union {
-			char data[16];
-			uint16_t data_u16[8];
-			uint32_t data_u32[4];
-		};
-		if(size != pStream->Read(data,1,size)) {
-			return false;
-		}
-
-		for (unsigned int i = 0; i < num; ++i) {
-			// also check against big endian versions of tokens with size 2,4
-			// that's just for convinience, the chance that we cause conflicts
-			// is quite low and it can save some lines and prevent nasty bugs
-			if (2 == size) {
-				uint16_t rev = *magic_u16; 
-				ByteSwap::Swap(&rev);
-				if (data_u16[0] == *magic_u16 || data_u16[0] == rev) {
-					return true;
-				}
-			}
-			else if (4 == size) {
-				uint32_t rev = *magic_u32;
-				ByteSwap::Swap(&rev);
-				if (data_u32[0] == *magic_u32 || data_u32[0] == rev) {
-					return true;
-				}
-			}
-			else {
-				// any length ... just compare
-				if(!memcmp(magic,data,size)) {
-					return true;
-				}
-			}
-			magic += size;
-		}
-	}
-	return false;
+    ai_assert(size <= 16 && _magic);
+
+    if (!pIOHandler) {
+        return false;
+    }
+    union {
+        const char* magic;
+        const uint16_t* magic_u16;
+        const uint32_t* magic_u32;
+    };
+    magic = reinterpret_cast<const char*>(_magic);
+    boost::scoped_ptr<IOStream> pStream (pIOHandler->Open(pFile));
+    if (pStream.get() ) {
+
+        // skip to offset
+        pStream->Seek(offset,aiOrigin_SET);
+
+        // read 'size' characters from the file
+        union {
+            char data[16];
+            uint16_t data_u16[8];
+            uint32_t data_u32[4];
+        };
+        if(size != pStream->Read(data,1,size)) {
+            return false;
+        }
+
+        for (unsigned int i = 0; i < num; ++i) {
+            // also check against big endian versions of tokens with size 2,4
+            // that's just for convenience, the chance that we cause conflicts
+            // is quite low and it can save some lines and prevent nasty bugs
+            if (2 == size) {
+                uint16_t rev = *magic_u16;
+                ByteSwap::Swap(&rev);
+                if (data_u16[0] == *magic_u16 || data_u16[0] == rev) {
+                    return true;
+                }
+            }
+            else if (4 == size) {
+                uint32_t rev = *magic_u32;
+                ByteSwap::Swap(&rev);
+                if (data_u32[0] == *magic_u32 || data_u32[0] == rev) {
+                    return true;
+                }
+            }
+            else {
+                // any length ... just compare
+                if(!memcmp(magic,data,size)) {
+                    return true;
+                }
+            }
+            magic += size;
+        }
+    }
+    return false;
 }
 
 #include "../contrib/ConvertUTF/ConvertUTF.h"
@@ -290,309 +307,307 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions)
 // ------------------------------------------------------------------------------------------------
 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");
-	}
+    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");
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 // Convert to UTF8 data
 void BaseImporter::ConvertToUTF8(std::vector<char>& data)
 {
-	ConversionResult result;
-	if(data.size() < 8) {
-		throw DeadlyImportError("File is too small");
-	}
-
-	// UTF 8 with BOM
-	if((uint8_t)data[0] == 0xEF && (uint8_t)data[1] == 0xBB && (uint8_t)data[2] == 0xBF) {
-		DefaultLogger::get()->debug("Found UTF-8 BOM ...");
-
-		std::copy(data.begin()+3,data.end(),data.begin());
-		data.resize(data.size()-3);
-		return;
-	}
-
-	// UTF 32 BE with BOM
-	if(*((uint32_t*)&data.front()) == 0xFFFE0000) {
-	
-		// swap the endianess ..
-		for(uint32_t* p = (uint32_t*)&data.front(), *end = (uint32_t*)&data.back(); p <= end; ++p) {
-			AI_SWAP4P(p);
-		}
-	}
-	
-	// UTF 32 LE with BOM
-	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);
-		return;
-	}
-
-	// UTF 16 BE with BOM
-	if(*((uint16_t*)&data.front()) == 0xFFFE) {
-	
-		// swap the endianess ..
-		for(uint16_t* p = (uint16_t*)&data.front(), *end = (uint16_t*)&data.back(); p <= end; ++p) {
-			ByteSwap::Swap2(p);
-		}
-	}
-	
-	// UTF 16 LE with BOM
-	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);
-		return;
-	}
+    ConversionResult result;
+    if(data.size() < 8) {
+        throw DeadlyImportError("File is too small");
+    }
+
+    // UTF 8 with BOM
+    if((uint8_t)data[0] == 0xEF && (uint8_t)data[1] == 0xBB && (uint8_t)data[2] == 0xBF) {
+        DefaultLogger::get()->debug("Found UTF-8 BOM ...");
+
+        std::copy(data.begin()+3,data.end(),data.begin());
+        data.resize(data.size()-3);
+        return;
+    }
+
+    // UTF 32 BE with BOM
+    if(*((uint32_t*)&data.front()) == 0xFFFE0000) {
+
+        // swap the endianess ..
+        for(uint32_t* p = (uint32_t*)&data.front(), *end = (uint32_t*)&data.back(); p <= end; ++p) {
+            AI_SWAP4P(p);
+        }
+    }
+
+    // UTF 32 LE with BOM
+    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);
+        return;
+    }
+
+    // UTF 16 BE with BOM
+    if(*((uint16_t*)&data.front()) == 0xFFFE) {
+
+        // swap the endianess ..
+        for(uint16_t* p = (uint16_t*)&data.front(), *end = (uint16_t*)&data.back(); p <= end; ++p) {
+            ByteSwap::Swap2(p);
+        }
+    }
+
+    // UTF 16 LE with BOM
+    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);
+        return;
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 // Convert to UTF8 data to ISO-8859-1
 void BaseImporter::ConvertUTF8toISO8859_1(std::string& data)
 {
-	unsigned int size = data.size();
-	unsigned int i = 0, j = 0;
+    size_t size = data.size();
+    size_t i = 0, j = 0;
 
-	while(i < size) {
-		if((unsigned char) data[i] < 0x80) {
-			data[j] = data[i];
-		} else if(i < size - 1) {
-			if((unsigned char) data[i] == 0xC2) {
-				data[j] = data[++i];
-			} else if((unsigned char) data[i] == 0xC3) {
-				data[j] = ((unsigned char) data[++i] + 0x40);
-			} else {
-				std::stringstream stream;
+    while(i < size) {
+        if ((unsigned char) data[i] < (size_t) 0x80) {
+            data[j] = data[i];
+        } else if(i < size - 1) {
+            if((unsigned char) data[i] == 0xC2) {
+                data[j] = data[++i];
+            } else if((unsigned char) data[i] == 0xC3) {
+                data[j] = ((unsigned char) data[++i] + 0x40);
+            } else {
+                std::stringstream stream;
 
-				stream << "UTF8 code " << std::hex << data[i] << data[i + 1] << " can not be converted into ISA-8859-1.";
+                stream << "UTF8 code " << std::hex << data[i] << data[i + 1] << " can not be converted into ISA-8859-1.";
 
-				DefaultLogger::get()->error(stream.str());
+                DefaultLogger::get()->error(stream.str());
 
-				data[j++] = data[i++];
-				data[j] = data[i];
-			}
-		} else {
-			DefaultLogger::get()->error("UTF8 code but only one character remaining");
+                data[j++] = data[i++];
+                data[j] = data[i];
+            }
+        } else {
+            DefaultLogger::get()->error("UTF8 code but only one character remaining");
 
-			data[j] = data[i];
-		}
+            data[j] = data[i];
+        }
 
-		i++; j++;
-	}
+        i++; j++;
+    }
 
-	data.resize(j);
+    data.resize(j);
 }
 
 // ------------------------------------------------------------------------------------------------
 void BaseImporter::TextFileToBuffer(IOStream* stream,
-	std::vector<char>& data)
+    std::vector<char>& data)
 {
-	ai_assert(NULL != stream);
+    ai_assert(NULL != stream);
 
-	const size_t fileSize = stream->FileSize();
-	if(!fileSize) {
-		throw DeadlyImportError("File is empty");
-	}
+    const size_t fileSize = stream->FileSize();
+    if(!fileSize) {
+        throw DeadlyImportError("File is empty");
+    }
 
-	data.reserve(fileSize+1); 
-	data.resize(fileSize); 
-	if(fileSize != stream->Read( &data[0], 1, fileSize)) {
-		throw DeadlyImportError("File read error");
-	}
+    data.reserve(fileSize+1);
+    data.resize(fileSize);
+    if(fileSize != stream->Read( &data[0], 1, fileSize)) {
+        throw DeadlyImportError("File read error");
+    }
 
-	ConvertToUTF8(data);
+    ConvertToUTF8(data);
 
-	// append a binary zero to simplify string parsing
-	data.push_back(0);
+    // append a binary zero to simplify string parsing
+    data.push_back(0);
 }
 
 // ------------------------------------------------------------------------------------------------
 namespace Assimp
 {
-	// Represents an import request
-	struct LoadRequest
-	{
-		LoadRequest(const std::string& _file, unsigned int _flags,const BatchLoader::PropertyMap* _map, unsigned int _id)
-			: file(_file), flags(_flags), refCnt(1),scene(NULL), loaded(false), id(_id)
-		{
-			if (_map)
-				map = *_map;
-		}
-
-		const std::string file;
-		unsigned int flags;
-		unsigned int refCnt;
-		aiScene* scene;
-		bool loaded;
-		BatchLoader::PropertyMap map;
-		unsigned int id;
-
-		bool operator== (const std::string& f) {
-			return file == f;
-		}
-	};
+    // Represents an import request
+    struct LoadRequest
+    {
+        LoadRequest(const std::string& _file, unsigned int _flags,const BatchLoader::PropertyMap* _map, unsigned int _id)
+            : file(_file), flags(_flags), refCnt(1),scene(NULL), loaded(false), id(_id)
+        {
+            if (_map)
+                map = *_map;
+        }
+
+        const std::string file;
+        unsigned int flags;
+        unsigned int refCnt;
+        aiScene* scene;
+        bool loaded;
+        BatchLoader::PropertyMap map;
+        unsigned int id;
+
+        bool operator== (const std::string& f) {
+            return file == f;
+        }
+    };
 }
 
 // ------------------------------------------------------------------------------------------------
 // BatchLoader::pimpl data structure
 struct Assimp::BatchData
 {
-	BatchData()
-		:	next_id(0xffff)
-	{}
+    BatchData()
+        : pIOSystem()
+        , pImporter()
+        , next_id(0xffff)
+    {}
 
-	// IO system to be used for all imports
-	IOSystem* pIOSystem;
+    // IO system to be used for all imports
+    IOSystem* pIOSystem;
 
-	// Importer used to load all meshes
-	Importer* pImporter;
+    // Importer used to load all meshes
+    Importer* pImporter;
 
-	// List of all imports
-	std::list<LoadRequest> requests;
+    // List of all imports
+    std::list<LoadRequest> requests;
 
-	// Base path
-	std::string pathBase;
+    // Base path
+    std::string pathBase;
 
-	// Id for next item
-	unsigned int next_id;
+    // Id for next item
+    unsigned int next_id;
 };
 
 // ------------------------------------------------------------------------------------------------
 BatchLoader::BatchLoader(IOSystem* pIO)
 {
-	ai_assert(NULL != pIO);
+    ai_assert(NULL != pIO);
 
-	data = new BatchData();
-	data->pIOSystem = pIO;
+    data = new BatchData();
+    data->pIOSystem = pIO;
 
-	data->pImporter = new Importer();
-	data->pImporter->SetIOHandler(data->pIOSystem);
+    data->pImporter = new Importer();
+    data->pImporter->SetIOHandler(data->pIOSystem);
 }
 
 // ------------------------------------------------------------------------------------------------
 BatchLoader::~BatchLoader()
 {
-	// delete all scenes wthat have not been polled by the user
-	for (std::list<LoadRequest>::iterator it = data->requests.begin();it != data->requests.end(); ++it)	{
-
-		delete (*it).scene;
-	}
-	data->pImporter->SetIOHandler(NULL); /* get pointer back into our posession */
-	delete data->pImporter;
-	delete data;
+    // delete all scenes wthat have not been polled by the user
+    for (std::list<LoadRequest>::iterator it = data->requests.begin();it != data->requests.end(); ++it) {
+
+        delete (*it).scene;
+    }
+    data->pImporter->SetIOHandler(NULL); /* get pointer back into our posession */
+    delete data->pImporter;
+    delete data;
 }
 
 
 // ------------------------------------------------------------------------------------------------
-unsigned int BatchLoader::AddLoadRequest	(const std::string& file,
-	unsigned int steps /*= 0*/, const PropertyMap* map /*= NULL*/)
+unsigned int BatchLoader::AddLoadRequest    (const std::string& file,
+    unsigned int steps /*= 0*/, const PropertyMap* map /*= NULL*/)
 {
-	ai_assert(!file.empty());
-	
-	// check whether we have this loading request already
-	std::list<LoadRequest>::iterator it;
-	for (it = data->requests.begin();it != data->requests.end(); ++it)	{
-
-		// Call IOSystem's path comparison function here
-		if (data->pIOSystem->ComparePaths((*it).file,file))	{
-
-			if (map) {
-				if (!((*it).map == *map))
-					continue;
-			}
-			else if (!(*it).map.empty())
-				continue;
-
-			(*it).refCnt++;
-			return (*it).id;
-		}
-	}
-
-	// no, we don't have it. So add it to the queue ...
-	data->requests.push_back(LoadRequest(file,steps,map,data->next_id));
-	return data->next_id++;
+    ai_assert(!file.empty());
+
+    // check whether we have this loading request already
+    std::list<LoadRequest>::iterator it;
+    for (it = data->requests.begin();it != data->requests.end(); ++it)  {
+
+        // Call IOSystem's path comparison function here
+        if (data->pIOSystem->ComparePaths((*it).file,file)) {
+
+            if (map) {
+                if (!((*it).map == *map))
+                    continue;
+            }
+            else if (!(*it).map.empty())
+                continue;
+
+            (*it).refCnt++;
+            return (*it).id;
+        }
+    }
+
+    // no, we don't have it. So add it to the queue ...
+    data->requests.push_back(LoadRequest(file,steps,map,data->next_id));
+    return data->next_id++;
 }
 
 // ------------------------------------------------------------------------------------------------
-aiScene* BatchLoader::GetImport		(unsigned int which)
+aiScene* BatchLoader::GetImport     (unsigned int which)
 {
-	for (std::list<LoadRequest>::iterator it = data->requests.begin();it != data->requests.end(); ++it)	{
-
-		if ((*it).id == which && (*it).loaded)	{
-
-			aiScene* sc = (*it).scene;
-			if (!(--(*it).refCnt))	{
-				data->requests.erase(it);
-			}
-			return sc;
-		}
-	}
-	return NULL;
+    for (std::list<LoadRequest>::iterator it = data->requests.begin();it != data->requests.end(); ++it) {
+
+        if ((*it).id == which && (*it).loaded)  {
+
+            aiScene* sc = (*it).scene;
+            if (!(--(*it).refCnt))  {
+                data->requests.erase(it);
+            }
+            return sc;
+        }
+    }
+    return NULL;
 }
 
 // ------------------------------------------------------------------------------------------------
 void BatchLoader::LoadAll()
 {
-	// no threaded implementation for the moment
-	for (std::list<LoadRequest>::iterator it = data->requests.begin();it != data->requests.end(); ++it)	{
-		// force validation in debug builds
-		unsigned int pp = (*it).flags;
+    // no threaded implementation for the moment
+    for (std::list<LoadRequest>::iterator it = data->requests.begin();it != data->requests.end(); ++it) {
+        // force validation in debug builds
+        unsigned int pp = (*it).flags;
 #ifdef ASSIMP_BUILD_DEBUG
-		pp |= aiProcess_ValidateDataStructure;
+        pp |= aiProcess_ValidateDataStructure;
 #endif
-		// setup config properties if necessary
-		ImporterPimpl* pimpl = data->pImporter->Pimpl();
-		pimpl->mFloatProperties  = (*it).map.floats;
-		pimpl->mIntProperties    = (*it).map.ints;
-		pimpl->mStringProperties = (*it).map.strings;
-		pimpl->mMatrixProperties = (*it).map.matrices;
-
-		if (!DefaultLogger::isNullLogger())
-		{
-			DefaultLogger::get()->info("%%% BEGIN EXTERNAL FILE %%%");
-			DefaultLogger::get()->info("File: " + (*it).file);
-		}
-		data->pImporter->ReadFile((*it).file,pp);
-		(*it).scene = data->pImporter->GetOrphanedScene();
-		(*it).loaded = true;
-
-		DefaultLogger::get()->info("%%% END EXTERNAL FILE %%%");
-	}
+        // setup config properties if necessary
+        ImporterPimpl* pimpl = data->pImporter->Pimpl();
+        pimpl->mFloatProperties  = (*it).map.floats;
+        pimpl->mIntProperties    = (*it).map.ints;
+        pimpl->mStringProperties = (*it).map.strings;
+        pimpl->mMatrixProperties = (*it).map.matrices;
+
+        if (!DefaultLogger::isNullLogger())
+        {
+            DefaultLogger::get()->info("%%% BEGIN EXTERNAL FILE %%%");
+            DefaultLogger::get()->info("File: " + (*it).file);
+        }
+        data->pImporter->ReadFile((*it).file,pp);
+        (*it).scene = data->pImporter->GetOrphanedScene();
+        (*it).loaded = true;
+
+        DefaultLogger::get()->info("%%% END EXTERNAL FILE %%%");
+    }
 }
-
-
-
-

+ 284 - 277
assimplib.mod/assimp/code/BaseImporter.h

@@ -2,11 +2,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -23,16 +23,16 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -47,318 +47,325 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <string>
 #include <map>
 #include <vector>
-#include "./../include/assimp/types.h"
+#include <set>
+#include "../include/assimp/types.h"
+#include "../include/assimp/ProgressHandler.hpp"
 
 struct aiScene;
 
-namespace Assimp	{
+namespace Assimp    {
 
-class IOSystem;
 class Importer;
-class BaseImporter;
+class IOSystem;
 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]))
+    (string[1] << 16) + (string[2] << 8) + string[3]))
 
 // ---------------------------------------------------------------------------
 template <typename T>
 struct ScopeGuard
 {
-	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;
-	}
+    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:
-	T* obj;
-	bool mdismiss;
+    // 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 
+/** FOR IMPORTER PLUGINS ONLY: The BaseImporter defines a common interface
  *  for all importer worker classes.
  *
- * The interface defines two functions: CanRead() is used to check if the 
- * importer can handle the format of the given file. If an implementation of 
- * this function returns true, the importer then calls ReadFile() which 
- * imports the given file. ReadFile is not overridable, it just calls 
+ * The interface defines two functions: CanRead() is used to check if the
+ * importer can handle the format of the given file. If an implementation of
+ * this function returns true, the importer then calls ReadFile() which
+ * imports the given file. ReadFile is not overridable, it just calls
  * InternReadFile() and catches any ImportErrorException that might occur.
  */
 class ASSIMP_API BaseImporter
 {
-	friend class Importer;
+    friend class Importer;
 
 public:
 
-	/** Constructor to be privately used by #Importer */
-	BaseImporter();
+    /** Constructor to be privately used by #Importer */
+    BaseImporter();
 
-	/** Destructor, private as well */
-	virtual ~BaseImporter();
+    /** Destructor, private as well */
+    virtual ~BaseImporter();
 
 public:
-	// -------------------------------------------------------------------
-	/** Returns whether the class can handle the format of the given file.
-	 *
-	 * The implementation should be as quick as possible. A check for
-	 * the file extension is enough. If no suitable loader is found with
-	 * this strategy, CanRead() is called again, the 'checkSig' parameter
-	 * set to true this time. Now the implementation is expected to
-	 * perform a full check of the file structure, possibly searching the
-	 * first bytes of the file for magic identifiers or keywords.
-	 *
-	 * @param pFile Path and file name of the file to be examined.
-	 * @param pIOHandler The IO handler to use for accessing any file.
-	 * @param checkSig Set to true if this method is called a second time.
-	 *   This time, the implementation may take more time to examine the
-	 *   contents of the file to be loaded for magic bytes, keywords, etc
-	 *   to be able to load files with unknown/not existent file extensions.
-	 * @return true if the class can read this file, false if not.
-	 */
-	virtual bool CanRead( 
-		const std::string& pFile, 
-		IOSystem* pIOHandler, 
-		bool checkSig
-		) const = 0;
-
-	// -------------------------------------------------------------------
-	/** Imports the given file and returns the imported data.
-	 * If the import succeeds, ownership of the data is transferred to 
-	 * the caller. If the import fails, NULL is returned. The function
-	 * takes care that any partially constructed data is destroyed
-	 * beforehand.
-	 *
-	 * @param pImp #Importer object hosting this loader.
-	 * @param pFile Path of the file to be imported. 
-	 * @param pIOHandler IO-Handler used to open this and possible other files.
-	 * @return The imported data or NULL if failed. If it failed a 
-	 * human-readable error description can be retrieved by calling 
-	 * GetErrorText()
-	 *
-	 * @note This function is not intended to be overridden. Implement 
-	 * InternReadFile() to do the import. If an exception is thrown somewhere 
-	 * in InternReadFile(), this function will catch it and transform it into
-	 *  a suitable response to the caller.
-	 */
-	aiScene* ReadFile(
-		const Importer* pImp, 
-		const std::string& pFile, 
-		IOSystem* pIOHandler
-		);
-
-	// -------------------------------------------------------------------
-	/** Returns the error description of the last error that occured. 
-	 * @return A description of the last error that occured. An empty
-	 * string if there was no error.
-	 */
-	const std::string& GetErrorText() const {
-		return mErrorText;
-	}
-
-	// -------------------------------------------------------------------
-	/** Called prior to ReadFile().
-	 * The function is a request to the importer to update its configuration
-	 * basing on the Importer's configuration property list.
-	 * @param pImp Importer instance
-	 */
-	virtual void SetupProperties(
-		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
-	 *  #GetInfo and insert all file extensions into the given set.
-	 *  @param extension set to collect file extensions in*/
-	void GetExtensionList(std::set<std::string>& extensions);
+    // -------------------------------------------------------------------
+    /** Returns whether the class can handle the format of the given file.
+     *
+     * The implementation should be as quick as possible. A check for
+     * the file extension is enough. If no suitable loader is found with
+     * this strategy, CanRead() is called again, the 'checkSig' parameter
+     * set to true this time. Now the implementation is expected to
+     * perform a full check of the file structure, possibly searching the
+     * first bytes of the file for magic identifiers or keywords.
+     *
+     * @param pFile Path and file name of the file to be examined.
+     * @param pIOHandler The IO handler to use for accessing any file.
+     * @param checkSig Set to true if this method is called a second time.
+     *   This time, the implementation may take more time to examine the
+     *   contents of the file to be loaded for magic bytes, keywords, etc
+     *   to be able to load files with unknown/not existent file extensions.
+     * @return true if the class can read this file, false if not.
+     */
+    virtual bool CanRead(
+        const std::string& pFile,
+        IOSystem* pIOHandler,
+        bool checkSig
+        ) const = 0;
+
+    // -------------------------------------------------------------------
+    /** Imports the given file and returns the imported data.
+     * If the import succeeds, ownership of the data is transferred to
+     * the caller. If the import fails, NULL is returned. The function
+     * takes care that any partially constructed data is destroyed
+     * beforehand.
+     *
+     * @param pImp #Importer object hosting this loader.
+     * @param pFile Path of the file to be imported.
+     * @param pIOHandler IO-Handler used to open this and possible other files.
+     * @return The imported data or NULL if failed. If it failed a
+     * human-readable error description can be retrieved by calling
+     * GetErrorText()
+     *
+     * @note This function is not intended to be overridden. Implement
+     * InternReadFile() to do the import. If an exception is thrown somewhere
+     * in InternReadFile(), this function will catch it and transform it into
+     *  a suitable response to the caller.
+     */
+    aiScene* ReadFile(
+        const Importer* pImp,
+        const std::string& pFile,
+        IOSystem* pIOHandler
+        );
+
+    // -------------------------------------------------------------------
+    /** Returns the error description of the last error that occured.
+     * @return A description of the last error that occured. An empty
+     * string if there was no error.
+     */
+    const std::string& GetErrorText() const {
+        return m_ErrorText;
+    }
+
+    // -------------------------------------------------------------------
+    /** Called prior to ReadFile().
+     * The function is a request to the importer to update its configuration
+     * basing on the Importer's configuration property list.
+     * @param pImp Importer instance
+     */
+    virtual void SetupProperties(
+        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
+     *  #GetInfo and insert all file extensions into the given set.
+     *  @param extension set to collect file extensions in*/
+    void GetExtensionList(std::set<std::string>& extensions);
 
 protected:
 
-	// -------------------------------------------------------------------
-	/** Imports the given file into the given scene structure. The 
-	 * function is expected to throw an ImportErrorException if there is 
-	 * an error. If it terminates normally, the data in aiScene is 
-	 * expected to be correct. Override this function to implement the 
-	 * actual importing.
-	 * <br>
-	 *  The output scene must meet the following requirements:<br>
-	 * <ul>
-	 * <li>At least a root node must be there, even if its only purpose
-	 *     is to reference one mesh.</li>
-	 * <li>aiMesh::mPrimitiveTypes may be 0. The types of primitives
-	 *   in the mesh are determined automatically in this case.</li>
-	 * <li>the vertex data is stored in a pseudo-indexed "verbose" format.
-	 *   In fact this means that every vertex that is referenced by
-	 *   a face is unique. Or the other way round: a vertex index may
-	 *   not occur twice in a single aiMesh.</li>
-	 * <li>aiAnimation::mDuration may be -1. Assimp determines the length
-	 *   of the animation automatically in this case as the length of
-	 *   the longest animation channel.</li>
-	 * <li>aiMesh::mBitangents may be NULL if tangents and normals are
-	 *   given. In this case bitangents are computed as the cross product
-	 *   between normal and tangent.</li>
-	 * <li>There needn't be a material. If none is there a default material
-	 *   is generated. However, it is recommended practice for loaders
-	 *   to generate a default material for yourself that matches the
-	 *   default material setting for the file format better than Assimp's
-	 *   generic default material. Note that default materials *should*
-	 *   be named AI_DEFAULT_MATERIAL_NAME if they're just color-shaded
-	 *   or AI_DEFAULT_TEXTURED_MATERIAL_NAME if they define a (dummy) 
-	 *   texture. </li>
-	 * </ul>
-	 * If the AI_SCENE_FLAGS_INCOMPLETE-Flag is <b>not</b> set:<ul>
-	 * <li> at least one mesh must be there</li>
-	 * <li> there may be no meshes with 0 vertices or faces</li>
-	 * </ul>
-	 * This won't be checked (except by the validation step): Assimp will
-	 * crash if one of the conditions is not met!
-	 *
-	 * @param pFile Path of the file to be imported.
-	 * @param pScene The scene object to hold the imported data.
-	 * NULL is not a valid parameter.
-	 * @param pIOHandler The IO handler to use for any file access.
-	 * NULL is not a valid parameter. */
-	virtual void InternReadFile( 
-		const std::string& pFile, 
-		aiScene* pScene, 
-		IOSystem* pIOHandler
-		) = 0;
+    // -------------------------------------------------------------------
+    /** Imports the given file into the given scene structure. The
+     * function is expected to throw an ImportErrorException if there is
+     * an error. If it terminates normally, the data in aiScene is
+     * expected to be correct. Override this function to implement the
+     * actual importing.
+     * <br>
+     *  The output scene must meet the following requirements:<br>
+     * <ul>
+     * <li>At least a root node must be there, even if its only purpose
+     *     is to reference one mesh.</li>
+     * <li>aiMesh::mPrimitiveTypes may be 0. The types of primitives
+     *   in the mesh are determined automatically in this case.</li>
+     * <li>the vertex data is stored in a pseudo-indexed "verbose" format.
+     *   In fact this means that every vertex that is referenced by
+     *   a face is unique. Or the other way round: a vertex index may
+     *   not occur twice in a single aiMesh.</li>
+     * <li>aiAnimation::mDuration may be -1. Assimp determines the length
+     *   of the animation automatically in this case as the length of
+     *   the longest animation channel.</li>
+     * <li>aiMesh::mBitangents may be NULL if tangents and normals are
+     *   given. In this case bitangents are computed as the cross product
+     *   between normal and tangent.</li>
+     * <li>There needn't be a material. If none is there a default material
+     *   is generated. However, it is recommended practice for loaders
+     *   to generate a default material for yourself that matches the
+     *   default material setting for the file format better than Assimp's
+     *   generic default material. Note that default materials *should*
+     *   be named AI_DEFAULT_MATERIAL_NAME if they're just color-shaded
+     *   or AI_DEFAULT_TEXTURED_MATERIAL_NAME if they define a (dummy)
+     *   texture. </li>
+     * </ul>
+     * If the AI_SCENE_FLAGS_INCOMPLETE-Flag is <b>not</b> set:<ul>
+     * <li> at least one mesh must be there</li>
+     * <li> there may be no meshes with 0 vertices or faces</li>
+     * </ul>
+     * This won't be checked (except by the validation step): Assimp will
+     * crash if one of the conditions is not met!
+     *
+     * @param pFile Path of the file to be imported.
+     * @param pScene The scene object to hold the imported data.
+     * NULL is not a valid parameter.
+     * @param pIOHandler The IO handler to use for any file access.
+     * NULL is not a valid parameter. */
+    virtual void InternReadFile(
+        const std::string& pFile,
+        aiScene* pScene,
+        IOSystem* pIOHandler
+        ) = 0;
 
 public: // static utilities
 
-	// -------------------------------------------------------------------
-	/** A utility for CanRead().
-	 *
-	 *  The function searches the header of a file for a specific token
-	 *  and returns true if this token is found. This works for text
-	 *  files only. There is a rudimentary handling of UNICODE files.
-	 *  The comparison is case independent.
-	 *
-	 *  @param pIOSystem IO System to work with
-	 *  @param file File name of the file
-	 *  @param tokens List of tokens to search for
-	 *  @param numTokens Size of the token array
-	 *  @param searchBytes Number of bytes to be searched for the tokens.
-	 */
-	static bool SearchFileHeaderForToken(
-		IOSystem* pIOSystem, 
-		const std::string&	file,
-		const char** tokens, 
-		unsigned int numTokens,
-		unsigned int searchBytes = 200,
-		bool tokensSol = false);
-
-	// -------------------------------------------------------------------
-	/** @brief Check whether a file has a specific file extension
-	 *  @param pFile Input file
-	 *  @param ext0 Extension to check for. Lowercase characters only, no dot!
-	 *  @param ext1 Optional second extension
-	 *  @param ext2 Optional third extension
-	 *  @note Case-insensitive
-	 */
-	static bool SimpleExtensionCheck (
-		const std::string& pFile, 
-		const char* ext0,
-		const char* ext1 = NULL,
-		const char* ext2 = NULL);
-
-	// -------------------------------------------------------------------
-	/** @brief Extract file extension from a string
-	 *  @param pFile Input file
-	 *  @return Extension without trailing dot, all lowercase
-	 */
-	static std::string GetExtension (
-		const std::string& pFile);
-
-	// -------------------------------------------------------------------
-	/** @brief Check whether a file starts with one or more magic tokens
-	 *  @param pFile Input file
-	 *  @param pIOHandler IO system to be used
-	 *  @param magic n magic tokens
-	 *  @params num Size of magic
-	 *  @param offset Offset from file start where tokens are located
-	 *  @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
-	 *  byte-swapped variant of all tokens (big endian). Only for
-	 *  tokens of size 2,4.
-	 */
-	static bool CheckMagicToken(
-		IOSystem* pIOHandler, 
-		const std::string& pFile, 
-		const void* magic,
-		unsigned int num,
-		unsigned int offset = 0,
-		unsigned int size   = 4);
-
-	// -------------------------------------------------------------------
-	/** An utility for all text file loaders. It converts a file to our
-	 *   UTF8 character set. Errors are reported, but ignored.
-	 *
-	 *  @param data File buffer to be converted to UTF8 data. The buffer 
-	 *  is resized as appropriate. */
-	static void ConvertToUTF8(
-		std::vector<char>& data);
-
-	// -------------------------------------------------------------------
-	/** An utility for all text file loaders. It converts a file from our
-	 *   UTF8 character set back to ISO-8859-1. Errors are reported, but ignored.
-	 *
-	 *  @param data File buffer to be converted from UTF8 to ISO-8859-1. The buffer
-	 *  is resized as appropriate. */
-	static void ConvertUTF8toISO8859_1(
-		std::string& data);
-
-	// -------------------------------------------------------------------
-	/** Utility for text file loaders which copies the contents of the
-	 *  file into a memory buffer and converts it to our UTF8
-	 *  representation.
-	 *  @param stream Stream to read from. 
-	 *  @param data Output buffer to be resized and filled with the
-	 *   converted text file data. The buffer is terminated with
-	 *   a binary 0. */
-	static void TextFileToBuffer(
-		IOStream* stream,
-		std::vector<char>& data);
+    // -------------------------------------------------------------------
+    /** A utility for CanRead().
+     *
+     *  The function searches the header of a file for a specific token
+     *  and returns true if this token is found. This works for text
+     *  files only. There is a rudimentary handling of UNICODE files.
+     *  The comparison is case independent.
+     *
+     *  @param pIOSystem IO System to work with
+     *  @param file File name of the file
+     *  @param tokens List of tokens to search for
+     *  @param numTokens Size of the token array
+     *  @param searchBytes Number of bytes to be searched for the tokens.
+     */
+    static bool SearchFileHeaderForToken(
+        IOSystem* pIOSystem,
+        const std::string&  file,
+        const char** tokens,
+        unsigned int numTokens,
+        unsigned int searchBytes = 200,
+        bool tokensSol = false);
+
+    // -------------------------------------------------------------------
+    /** @brief Check whether a file has a specific file extension
+     *  @param pFile Input file
+     *  @param ext0 Extension to check for. Lowercase characters only, no dot!
+     *  @param ext1 Optional second extension
+     *  @param ext2 Optional third extension
+     *  @note Case-insensitive
+     */
+    static bool SimpleExtensionCheck (
+        const std::string& pFile,
+        const char* ext0,
+        const char* ext1 = NULL,
+        const char* ext2 = NULL);
+
+    // -------------------------------------------------------------------
+    /** @brief Extract file extension from a string
+     *  @param pFile Input file
+     *  @return Extension without trailing dot, all lowercase
+     */
+    static std::string GetExtension (
+        const std::string& pFile);
+
+    // -------------------------------------------------------------------
+    /** @brief Check whether a file starts with one or more magic tokens
+     *  @param pFile Input file
+     *  @param pIOHandler IO system to be used
+     *  @param magic n magic tokens
+     *  @params num Size of magic
+     *  @param offset Offset from file start where tokens are located
+     *  @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
+     *  byte-swapped variant of all tokens (big endian). Only for
+     *  tokens of size 2,4.
+     */
+    static bool CheckMagicToken(
+        IOSystem* pIOHandler,
+        const std::string& pFile,
+        const void* magic,
+        unsigned int num,
+        unsigned int offset = 0,
+        unsigned int size   = 4);
+
+    // -------------------------------------------------------------------
+    /** An utility for all text file loaders. It converts a file to our
+     *   UTF8 character set. Errors are reported, but ignored.
+     *
+     *  @param data File buffer to be converted to UTF8 data. The buffer
+     *  is resized as appropriate. */
+    static void ConvertToUTF8(
+        std::vector<char>& data);
+
+    // -------------------------------------------------------------------
+    /** An utility for all text file loaders. It converts a file from our
+     *   UTF8 character set back to ISO-8859-1. Errors are reported, but ignored.
+     *
+     *  @param data File buffer to be converted from UTF8 to ISO-8859-1. The buffer
+     *  is resized as appropriate. */
+    static void ConvertUTF8toISO8859_1(
+        std::string& data);
+
+    // -------------------------------------------------------------------
+    /** Utility for text file loaders which copies the contents of the
+     *  file into a memory buffer and converts it to our UTF8
+     *  representation.
+     *  @param stream Stream to read from.
+     *  @param data Output buffer to be resized and filled with the
+     *   converted text file data. The buffer is terminated with
+     *   a binary 0. */
+    static void TextFileToBuffer(
+        IOStream* stream,
+        std::vector<char>& data);
 
 protected:
 
-	/** Error description in case there was one. */
-	std::string mErrorText;
+    /** Error description in case there was one. */
+    std::string m_ErrorText;
 
-	/** Currently set progress handler */
-	ProgressHandler* progress;
+    /** Currently set progress handler */
+    ProgressHandler* m_progress;
 };
 
 

+ 31 - 31
assimplib.mod/assimp/code/BaseProcess.cpp

@@ -3,12 +3,12 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -25,26 +25,26 @@ conditions are met:
   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 
+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 
+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 
+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 
+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 Implementation of BaseProcess */
 
-#include "AssimpPCH.h"
 #include "BaseImporter.h"
 #include "BaseProcess.h"
-
+#include "../include/assimp/DefaultLogger.hpp"
+#include "../include/assimp/scene.h"
 #include "Importer.h"
 
 using namespace Assimp;
@@ -61,45 +61,45 @@ BaseProcess::BaseProcess()
 // Destructor, private as well
 BaseProcess::~BaseProcess()
 {
-	// nothing to do here
+    // nothing to do here
 }
 
 // ------------------------------------------------------------------------------------------------
 void BaseProcess::ExecuteOnScene( Importer* pImp)
 {
-	ai_assert(NULL != pImp && NULL != pImp->Pimpl()->mScene);
+    ai_assert(NULL != pImp && NULL != pImp->Pimpl()->mScene);
 
-	progress = pImp->GetProgressHandler();
-	ai_assert(progress);
+    progress = pImp->GetProgressHandler();
+    ai_assert(progress);
 
-	SetupProperties( pImp );
+    SetupProperties( pImp );
 
-	// catch exceptions thrown inside the PostProcess-Step
-	try
-	{
-		Execute(pImp->Pimpl()->mScene);
+    // catch exceptions thrown inside the PostProcess-Step
+    try
+    {
+        Execute(pImp->Pimpl()->mScene);
 
-	} catch( const std::exception& err )	{
+    } catch( const std::exception& err )    {
 
-		// extract error description
-		pImp->Pimpl()->mErrorString = err.what();
-		DefaultLogger::get()->error(pImp->Pimpl()->mErrorString);
+        // extract error description
+        pImp->Pimpl()->mErrorString = err.what();
+        DefaultLogger::get()->error(pImp->Pimpl()->mErrorString);
 
-		// and kill the partially imported data
-		delete pImp->Pimpl()->mScene;
-		pImp->Pimpl()->mScene = NULL;
-	}
+        // and kill the partially imported data
+        delete pImp->Pimpl()->mScene;
+        pImp->Pimpl()->mScene = NULL;
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 void BaseProcess::SetupProperties(const Importer* /*pImp*/)
 {
-	// the default implementation does nothing
+    // the default implementation does nothing
 }
 
 // ------------------------------------------------------------------------------------------------
 bool BaseProcess::RequireVerboseFormat() const
 {
-	return true;
+    return true;
 }
 

+ 189 - 189
assimplib.mod/assimp/code/BaseProcess.h

@@ -2,11 +2,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -23,16 +23,16 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -49,7 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 struct aiScene;
 
-namespace Assimp	{
+namespace Assimp    {
 
 class Importer;
 
@@ -64,121 +64,121 @@ class SharedPostProcessInfo
 {
 public:
 
-	struct Base
-	{
-		virtual ~Base()
-		{}
-	};
-
-	//! Represents data that is allocated on the heap, thus needs to be deleted
-	template <typename T>
-	struct THeapData : public Base
-	{
-		THeapData(T* in)
-			: data (in)
-		{}
-
-		~THeapData()
-		{
-			delete data;
-		}
-		T* data;
-	};
-
-	//! Represents static, by-value data not allocated on the heap
-	template <typename T>
-	struct TStaticData : public Base
-	{
-		TStaticData(T in)
-			: data (in)
-		{}
-
-		~TStaticData()
-		{}
-
-		T data;
-	};
-
-	// some typedefs for cleaner code
-	typedef unsigned int KeyType;
-	typedef std::map<KeyType, Base*>  PropertyMap;
+    struct Base
+    {
+        virtual ~Base()
+        {}
+    };
+
+    //! Represents data that is allocated on the heap, thus needs to be deleted
+    template <typename T>
+    struct THeapData : public Base
+    {
+        explicit THeapData(T* in)
+            : data (in)
+        {}
+
+        ~THeapData()
+        {
+            delete data;
+        }
+        T* data;
+    };
+
+    //! Represents static, by-value data not allocated on the heap
+    template <typename T>
+    struct TStaticData : public Base
+    {
+        explicit TStaticData(T in)
+            : data (in)
+        {}
+
+        ~TStaticData()
+        {}
+
+        T data;
+    };
+
+    // some typedefs for cleaner code
+    typedef unsigned int KeyType;
+    typedef std::map<KeyType, Base*>  PropertyMap;
 
 public:
 
-	//! Destructor
-	~SharedPostProcessInfo()	
-	{
-		Clean();
-	}
-
-	//! Remove all stored properties from the table
-	void Clean()
-	{
-		// invoke the virtual destructor for all stored properties
-		for (PropertyMap::iterator it = pmap.begin(), end = pmap.end();
-			 it != end; ++it)
-		{
-			delete (*it).second;
-		}
-		pmap.clear();
-	}
-
-	//! Add a heap property to the list
-	template <typename T>
-	void AddProperty( const char* name, T* in ){
-		AddProperty(name,(Base*)new THeapData<T>(in));
-	}
-
-	//! Add a static by-value property to the list
-	template <typename T>
-	void AddProperty( const char* name, T in ){
-		AddProperty(name,(Base*)new TStaticData<T>(in));
-	}
-
-
-	//! Get a heap property
-	template <typename T>
-	bool GetProperty( const char* name, T*& out ) const
-	{
-		THeapData<T>* t = (THeapData<T>*)GetPropertyInternal(name);
-		if(!t)
-		{
-			out = NULL;
-			return false;
-		}
-		out = t->data;
-		return true;
-	}
-
-	//! Get a static, by-value property
-	template <typename T>
-	bool GetProperty( const char* name, T& out ) const
-	{
-		TStaticData<T>* t = (TStaticData<T>*)GetPropertyInternal(name);
-		if(!t)return false;
-		out = t->data;
-		return true;
-	}
-
-	//! Remove a property of a specific type
-	void RemoveProperty( const char* name)	{
-		SetGenericPropertyPtr<Base>(pmap,name,NULL);
-	}
+    //! Destructor
+    ~SharedPostProcessInfo()
+    {
+        Clean();
+    }
+
+    //! Remove all stored properties from the table
+    void Clean()
+    {
+        // invoke the virtual destructor for all stored properties
+        for (PropertyMap::iterator it = pmap.begin(), end = pmap.end();
+             it != end; ++it)
+        {
+            delete (*it).second;
+        }
+        pmap.clear();
+    }
+
+    //! Add a heap property to the list
+    template <typename T>
+    void AddProperty( const char* name, T* in ){
+        AddProperty(name,(Base*)new THeapData<T>(in));
+    }
+
+    //! Add a static by-value property to the list
+    template <typename T>
+    void AddProperty( const char* name, T in ){
+        AddProperty(name,(Base*)new TStaticData<T>(in));
+    }
+
+
+    //! Get a heap property
+    template <typename T>
+    bool GetProperty( const char* name, T*& out ) const
+    {
+        THeapData<T>* t = (THeapData<T>*)GetPropertyInternal(name);
+        if(!t)
+        {
+            out = NULL;
+            return false;
+        }
+        out = t->data;
+        return true;
+    }
+
+    //! Get a static, by-value property
+    template <typename T>
+    bool GetProperty( const char* name, T& out ) const
+    {
+        TStaticData<T>* t = (TStaticData<T>*)GetPropertyInternal(name);
+        if(!t)return false;
+        out = t->data;
+        return true;
+    }
+
+    //! Remove a property of a specific type
+    void RemoveProperty( const char* name)  {
+        SetGenericPropertyPtr<Base>(pmap,name,NULL);
+    }
 
 private:
 
-	void AddProperty( const char* name, Base* data)	{
-		SetGenericPropertyPtr<Base>(pmap,name,data);
-	}
+    void AddProperty( const char* name, Base* data) {
+        SetGenericPropertyPtr<Base>(pmap,name,data);
+    }
 
-	Base* GetPropertyInternal( const char* name) const	{
-		return GetGenericProperty<Base*>(pmap,name,NULL);
-	}
+    Base* GetPropertyInternal( const char* name) const  {
+        return GetGenericProperty<Base*>(pmap,name,NULL);
+    }
 
 private:
 
-	//! Map of all stored properties
-	PropertyMap pmap;
+    //! Map of all stored properties
+    PropertyMap pmap;
 };
 
 #if 0
@@ -188,12 +188,12 @@ private:
  *
  *  For future use.
  */
- struct PPDependencyTable 
+ struct PPDependencyTable
  {
-	 unsigned int execute_me_before_these;
-	 unsigned int execute_me_after_these;
-	 unsigned int only_if_these_are_not_specified;
-	 unsigned int mutually_exclusive_with;
+     unsigned int execute_me_before_these;
+     unsigned int execute_me_after_these;
+     unsigned int only_if_these_are_not_specified;
+     unsigned int mutually_exclusive_with;
  };
 
 #endif
@@ -204,88 +204,88 @@ private:
 // ---------------------------------------------------------------------------
 /** The BaseProcess defines a common interface for all post processing steps.
  * A post processing step is run after a successful import if the caller
- * specified the corresponding flag when calling ReadFile(). 
- * Enum #aiPostProcessSteps defines which flags are available. 
- * After a successful import the Importer iterates over its internal array 
- * of processes and calls IsActive() on each process to evaluate if the step 
- * should be executed. If the function returns true, the class' Execute() 
+ * specified the corresponding flag when calling ReadFile().
+ * Enum #aiPostProcessSteps defines which flags are available.
+ * After a successful import the Importer iterates over its internal array
+ * of processes and calls IsActive() on each process to evaluate if the step
+ * should be executed. If the function returns true, the class' Execute()
  * function is called subsequently.
  */
-class ASSIMP_API_WINONLY BaseProcess 
+class ASSIMP_API_WINONLY BaseProcess
 {
-	friend class Importer;
+    friend class Importer;
 
 public:
 
-	/** Constructor to be privately used by Importer */
-	BaseProcess();
+    /** Constructor to be privately used by Importer */
+    BaseProcess();
 
-	/** Destructor, private as well */
-	virtual ~BaseProcess();
+    /** Destructor, private as well */
+    virtual ~BaseProcess();
 
 public:
 
-	// -------------------------------------------------------------------
-	/** Returns whether the processing step is present in the given flag.
-	 * @param pFlags The processing flags the importer was called with. A
-	 *   bitwise combination of #aiPostProcessSteps.
-	 * @return true if the process is present in this flag fields, 
-	 *   false if not.
-	*/
-	virtual bool IsActive( unsigned int pFlags) const = 0;
-
-	// -------------------------------------------------------------------
-	/** Check whether this step expects its input vertex data to be 
-	 *  in verbose format. */
-	virtual bool RequireVerboseFormat() const;
-
-	// -------------------------------------------------------------------
-	/** Executes the post processing step on the given imported data.
-	* The function deletes the scene if the postprocess step fails (
-	* the object pointer will be set to NULL).
-	* @param pImp Importer instance (pImp->mScene must be valid)
-	*/
-	void ExecuteOnScene( Importer* pImp);
-
-	// -------------------------------------------------------------------
-	/** Called prior to ExecuteOnScene().
-	* The function is a request to the process to update its configuration
-	* basing on the Importer's configuration property list.
-	*/
-	virtual void SetupProperties(const Importer* pImp);
-
-	// -------------------------------------------------------------------
-	/** Executes the post processing step on the given imported data.
-	* A process should throw an ImportErrorException* if it fails.
-	* This method must be implemented by deriving classes.
-	* @param pScene The imported data to work at.
-	*/
-	virtual void Execute( aiScene* pScene) = 0;
-
-
-	// -------------------------------------------------------------------
-	/** Assign a new SharedPostProcessInfo to the step. This object
-	 *  allows multiple postprocess steps to share data.
-	 * @param sh May be NULL
-	*/
-	inline void SetSharedData(SharedPostProcessInfo* sh)	{
-		shared = sh;
-	}
-
-	// -------------------------------------------------------------------
-	/** Get the shared data that is assigned to the step.
-	*/
-	inline SharedPostProcessInfo* GetSharedData()	{
-		return shared;
-	}
+    // -------------------------------------------------------------------
+    /** Returns whether the processing step is present in the given flag.
+     * @param pFlags The processing flags the importer was called with. A
+     *   bitwise combination of #aiPostProcessSteps.
+     * @return true if the process is present in this flag fields,
+     *   false if not.
+    */
+    virtual bool IsActive( unsigned int pFlags) const = 0;
+
+    // -------------------------------------------------------------------
+    /** Check whether this step expects its input vertex data to be
+     *  in verbose format. */
+    virtual bool RequireVerboseFormat() const;
+
+    // -------------------------------------------------------------------
+    /** Executes the post processing step on the given imported data.
+    * The function deletes the scene if the postprocess step fails (
+    * the object pointer will be set to NULL).
+    * @param pImp Importer instance (pImp->mScene must be valid)
+    */
+    void ExecuteOnScene( Importer* pImp);
+
+    // -------------------------------------------------------------------
+    /** Called prior to ExecuteOnScene().
+    * The function is a request to the process to update its configuration
+    * basing on the Importer's configuration property list.
+    */
+    virtual void SetupProperties(const Importer* pImp);
+
+    // -------------------------------------------------------------------
+    /** Executes the post processing step on the given imported data.
+    * A process should throw an ImportErrorException* if it fails.
+    * This method must be implemented by deriving classes.
+    * @param pScene The imported data to work at.
+    */
+    virtual void Execute( aiScene* pScene) = 0;
+
+
+    // -------------------------------------------------------------------
+    /** Assign a new SharedPostProcessInfo to the step. This object
+     *  allows multiple postprocess steps to share data.
+     * @param sh May be NULL
+    */
+    inline void SetSharedData(SharedPostProcessInfo* sh)    {
+        shared = sh;
+    }
+
+    // -------------------------------------------------------------------
+    /** Get the shared data that is assigned to the step.
+    */
+    inline SharedPostProcessInfo* GetSharedData()   {
+        return shared;
+    }
 
 protected:
 
-	/** See the doc of #SharedPostProcessInfo for more details */
-	SharedPostProcessInfo* shared;
+    /** See the doc of #SharedPostProcessInfo for more details */
+    SharedPostProcessInfo* shared;
 
-	/** Currently active progress handler */
-	ProgressHandler* progress;
+    /** Currently active progress handler */
+    ProgressHandler* progress;
 };
 
 

+ 94 - 92
assimplib.mod/assimp/code/Bitmap.cpp

@@ -3,7 +3,7 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, assimp team
 
 All rights reserved.
 
@@ -45,101 +45,103 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  * Used for file formats which embed their textures into the model file.
  */
 
-#include "AssimpPCH.h"
 
 #include "Bitmap.h"
+#include "../include/assimp/texture.h"
+#include "../include/assimp/IOStream.hpp"
+#include "ByteSwapper.h"
 
 namespace Assimp {
 
-	void Bitmap::Save(aiTexture* texture, IOStream* file) {
-		if(file != NULL) {
-			Header header;
-			DIB dib;
-
-			dib.size = DIB::dib_size;
-			dib.width = texture->mWidth;
-			dib.height = texture->mHeight;
-			dib.planes = 1;
-			dib.bits_per_pixel = 8 * mBytesPerPixel;
-			dib.compression = 0;
-			dib.image_size = (((dib.width * mBytesPerPixel) + 3) & 0x0000FFFC) * dib.height;
-			dib.x_resolution = 0;
-			dib.y_resolution = 0;
-			dib.nb_colors = 0;
-			dib.nb_important_colors = 0;
-
-			header.type = 0x4D42; // 'BM'
-			header.offset = Header::header_size + DIB::dib_size;
-			header.size = header.offset + dib.image_size;
-			header.reserved1 = 0;
-			header.reserved2 = 0;
-
-			WriteHeader(header, file);
-			WriteDIB(dib, file);
-			WriteData(texture, file);
-		}
-	}
-
-	template<typename T>
-	inline std::size_t Copy(uint8_t* data, T& field) {
-		std::memcpy(data, &AI_BE(field), sizeof(field)); return sizeof(field);
-	}
-
-	void Bitmap::WriteHeader(Header& header, IOStream* file) {
-		uint8_t data[Header::header_size];
-
-		std::size_t offset = 0;
-
-		offset += Copy(&data[offset], header.type);
-		offset += Copy(&data[offset], header.size);
-		offset += Copy(&data[offset], header.reserved1);
-		offset += Copy(&data[offset], header.reserved2);
-		offset += Copy(&data[offset], header.offset);
-
-		file->Write(data, Header::header_size, 1);
-	}
-
-	void Bitmap::WriteDIB(DIB& dib, IOStream* file) {
-		uint8_t data[DIB::dib_size];
-
-		std::size_t offset = 0;
-
-		offset += Copy(&data[offset], dib.size);
-		offset += Copy(&data[offset], dib.width);
-		offset += Copy(&data[offset], dib.height);
-		offset += Copy(&data[offset], dib.planes);
-		offset += Copy(&data[offset], dib.bits_per_pixel);
-		offset += Copy(&data[offset], dib.compression);
-		offset += Copy(&data[offset], dib.image_size);
-		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);
-
-		file->Write(data, DIB::dib_size, 1);
-	}
-
-	void Bitmap::WriteData(aiTexture* texture, IOStream* file) {
-		static const std::size_t padding_offset = 4;
-		static const uint8_t padding_data[padding_offset] = {0x0, 0x0, 0x0, 0x0};
-
-		unsigned int padding = (padding_offset - ((mBytesPerPixel * texture->mWidth) % padding_offset)) % padding_offset;
-		uint8_t pixel[mBytesPerPixel];
-
-		for(std::size_t i = 0; i < texture->mHeight; ++i) {
-			for(std::size_t j = 0; j < texture->mWidth; ++j) {
-				const aiTexel& texel = texture->pcData[(texture->mHeight - i - 1) * texture->mWidth + j]; // Bitmap files are stored in bottom-up format
-
-				pixel[0] = texel.r;
-				pixel[1] = texel.g;
-				pixel[2] = texel.b;
-				pixel[3] = texel.a;
-
-				file->Write(pixel, mBytesPerPixel, 1);
-			}
-
-			file->Write(padding_data, padding, 1);
-		}
-	}
+    void Bitmap::Save(aiTexture* texture, IOStream* file) {
+        if(file != NULL) {
+            Header header;
+            DIB dib;
+
+            dib.size = DIB::dib_size;
+            dib.width = texture->mWidth;
+            dib.height = texture->mHeight;
+            dib.planes = 1;
+            dib.bits_per_pixel = 8 * mBytesPerPixel;
+            dib.compression = 0;
+            dib.image_size = (((dib.width * mBytesPerPixel) + 3) & 0x0000FFFC) * dib.height;
+            dib.x_resolution = 0;
+            dib.y_resolution = 0;
+            dib.nb_colors = 0;
+            dib.nb_important_colors = 0;
+
+            header.type = 0x4D42; // 'BM'
+            header.offset = Header::header_size + DIB::dib_size;
+            header.size = header.offset + dib.image_size;
+            header.reserved1 = 0;
+            header.reserved2 = 0;
+
+            WriteHeader(header, file);
+            WriteDIB(dib, file);
+            WriteData(texture, file);
+        }
+    }
+
+    template<typename T>
+    inline std::size_t Copy(uint8_t* data, T& field) {
+        std::memcpy(data, &AI_BE(field), sizeof(field)); return sizeof(field);
+    }
+
+    void Bitmap::WriteHeader(Header& header, IOStream* file) {
+        uint8_t data[Header::header_size];
+
+        std::size_t offset = 0;
+
+        offset += Copy(&data[offset], header.type);
+        offset += Copy(&data[offset], header.size);
+        offset += Copy(&data[offset], header.reserved1);
+        offset += Copy(&data[offset], header.reserved2);
+        offset += Copy(&data[offset], header.offset);
+
+        file->Write(data, Header::header_size, 1);
+    }
+
+    void Bitmap::WriteDIB(DIB& dib, IOStream* file) {
+        uint8_t data[DIB::dib_size];
+
+        std::size_t offset = 0;
+
+        offset += Copy(&data[offset], dib.size);
+        offset += Copy(&data[offset], dib.width);
+        offset += Copy(&data[offset], dib.height);
+        offset += Copy(&data[offset], dib.planes);
+        offset += Copy(&data[offset], dib.bits_per_pixel);
+        offset += Copy(&data[offset], dib.compression);
+        offset += Copy(&data[offset], dib.image_size);
+        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);
+
+        file->Write(data, DIB::dib_size, 1);
+    }
+
+    void Bitmap::WriteData(aiTexture* texture, IOStream* file) {
+        static const std::size_t padding_offset = 4;
+        static const uint8_t padding_data[padding_offset] = {0x0, 0x0, 0x0, 0x0};
+
+        unsigned int padding = (padding_offset - ((mBytesPerPixel * texture->mWidth) % padding_offset)) % padding_offset;
+        uint8_t pixel[mBytesPerPixel];
+
+        for(std::size_t i = 0; i < texture->mHeight; ++i) {
+            for(std::size_t j = 0; j < texture->mWidth; ++j) {
+                const aiTexel& texel = texture->pcData[(texture->mHeight - i - 1) * texture->mWidth + j]; // Bitmap files are stored in bottom-up format
+
+                pixel[0] = texel.r;
+                pixel[1] = texel.g;
+                pixel[2] = texel.b;
+                pixel[3] = texel.a;
+
+                file->Write(pixel, mBytesPerPixel, 1);
+            }
+
+            file->Write(padding_data, padding, 1);
+        }
+    }
 
 }

+ 56 - 51
assimplib.mod/assimp/code/Bitmap.h

@@ -3,7 +3,7 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, assimp team
 
 All rights reserved.
 
@@ -48,89 +48,94 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_BITMAP_H_INC
 #define AI_BITMAP_H_INC
 
+#include <stdint.h>
+#include <cstddef>
+struct aiTexture;
+
 namespace Assimp {
 
+class IOStream;
 class Bitmap {
 
-	protected:
+    protected:
 
-		struct Header {
+        struct Header {
 
-			uint16_t type;
+            uint16_t type;
 
-			uint32_t size;
+            uint32_t size;
 
-			uint16_t reserved1;
+            uint16_t reserved1;
 
-			uint16_t reserved2;
+            uint16_t reserved2;
 
-			uint32_t offset;
+            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
+            // 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 {
+        struct DIB {
 
-			uint32_t size;
+            uint32_t size;
 
-			int32_t width;
+            int32_t width;
 
-			int32_t height;
+            int32_t height;
 
-			uint16_t planes;
+            uint16_t planes;
 
-			uint16_t bits_per_pixel;
+            uint16_t bits_per_pixel;
 
-			uint32_t compression;
+            uint32_t compression;
 
-			uint32_t image_size;
+            uint32_t image_size;
 
-			int32_t x_resolution;
+            int32_t x_resolution;
 
-			int32_t y_resolution;
+            int32_t y_resolution;
 
-			uint32_t nb_colors;
+            uint32_t nb_colors;
 
-			uint32_t nb_important_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
+            // 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;
+        static const std::size_t mBytesPerPixel = 4;
 
-	public:
+    public:
 
-		static void Save(aiTexture* texture, IOStream* file);
+        static void Save(aiTexture* texture, IOStream* file);
 
-	protected:
+    protected:
 
-		static void WriteHeader(Header& header, IOStream* file);
+        static void WriteHeader(Header& header, IOStream* file);
 
-		static void WriteDIB(DIB& dib, IOStream* file);
+        static void WriteDIB(DIB& dib, IOStream* file);
 
-		static void WriteData(aiTexture* texture, IOStream* file);
+        static void WriteData(aiTexture* texture, IOStream* file);
 
 };
 

+ 95 - 69
assimplib.mod/assimp/code/BlenderBMesh.cpp

@@ -5,8 +5,8 @@ Open Asset Import Library (assimp)
 Copyright (c) 2006-2013, 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 
+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
@@ -23,16 +23,16 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -42,7 +42,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *  @brief Conversion of Blender's new BMesh stuff
  */
 
-#include "AssimpPCH.h"
 
 #ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
 
@@ -53,7 +52,7 @@ 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 std::string LogFunctions< BlenderBMeshConverter >::log_prefix = "BLEND_BMESH: ";
 }
 
 using namespace Assimp;
@@ -62,115 +61,142 @@ using namespace Assimp::Formatter;
 
 // ------------------------------------------------------------------------------------------------
 BlenderBMeshConverter::BlenderBMeshConverter( const Mesh* mesh ):
-	BMesh( mesh ),
-	triMesh( NULL )
+    BMesh( mesh ),
+    triMesh( NULL )
 {
-	AssertValidMesh( );
 }
 
 // ------------------------------------------------------------------------------------------------
 BlenderBMeshConverter::~BlenderBMeshConverter( )
 {
-	DestroyTriMesh( );
+    DestroyTriMesh( );
 }
 
 // ------------------------------------------------------------------------------------------------
 bool BlenderBMeshConverter::ContainsBMesh( ) const
 {
-	// TODO - Should probably do some additional verification here
-	return BMesh->totpoly && BMesh->totloop && BMesh->totvert;
+    // TODO - Should probably do some additional verification here
+    return BMesh->totpoly && BMesh->totloop && BMesh->totvert;
 }
 
 // ------------------------------------------------------------------------------------------------
 const Mesh* BlenderBMeshConverter::TriangulateBMesh( )
 {
-	AssertValidMesh( );
-	AssertValidSizes( );
-	PrepareTriMesh( );
+    AssertValidMesh( );
+    AssertValidSizes( );
+    PrepareTriMesh( );
 
-	for ( int i = 0; i < BMesh->totpoly; ++i )
-	{
-		const MPoly& poly = BMesh->mpoly[ i ];
-		ConvertPolyToFaces( poly );
-	}
+    for ( int i = 0; i < BMesh->totpoly; ++i )
+    {
+        const MPoly& poly = BMesh->mpoly[ i ];
+        ConvertPolyToFaces( poly );
+    }
 
-	return triMesh;
+    return triMesh;
 }
 
 // ------------------------------------------------------------------------------------------------
 void BlenderBMeshConverter::AssertValidMesh( )
 {
-	if ( !ContainsBMesh( ) )
-	{
-		ThrowException( "BlenderBMeshConverter requires a BMesh with \"polygons\" - please call BlenderBMeshConverter::ContainsBMesh to check this first" );
-	}
+    if ( !ContainsBMesh( ) )
+    {
+        ThrowException( "BlenderBMeshConverter requires a BMesh with \"polygons\" - please call BlenderBMeshConverter::ContainsBMesh to check this first" );
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 void BlenderBMeshConverter::AssertValidSizes( )
 {
-	if ( BMesh->totpoly != static_cast<int>( BMesh->mpoly.size( ) ) )
-	{
-		ThrowException( "BMesh poly array has incorrect size" );
-	}
-	if ( BMesh->totloop != static_cast<int>( BMesh->mloop.size( ) ) )
-	{
-		ThrowException( "BMesh loop array has incorrect size" );
-	}
+    if ( BMesh->totpoly != static_cast<int>( BMesh->mpoly.size( ) ) )
+    {
+        ThrowException( "BMesh poly array has incorrect size" );
+    }
+    if ( BMesh->totloop != static_cast<int>( BMesh->mloop.size( ) ) )
+    {
+        ThrowException( "BMesh loop array has incorrect size" );
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 void BlenderBMeshConverter::PrepareTriMesh( )
 {
-	if ( triMesh )
-	{
-		DestroyTriMesh( );
-	}
-
-	triMesh = new Mesh( *BMesh );
-	triMesh->totface = 0;
-	triMesh->mface.clear( );
+    if ( triMesh )
+    {
+        DestroyTriMesh( );
+    }
+
+    triMesh = new Mesh( *BMesh );
+    triMesh->totface = 0;
+    triMesh->mface.clear( );
 }
 
 // ------------------------------------------------------------------------------------------------
 void BlenderBMeshConverter::DestroyTriMesh( )
 {
-	delete triMesh;
-	triMesh = NULL;
+    delete triMesh;
+    triMesh = NULL;
 }
 
 // ------------------------------------------------------------------------------------------------
 void BlenderBMeshConverter::ConvertPolyToFaces( const MPoly& poly )
 {
-	const MLoop* polyLoop = &BMesh->mloop[ poly.loopstart ];
-	if ( poly.totloop == 3 || poly.totloop == 4 )
-	{
-		AddFace( polyLoop[ 0 ].v, polyLoop[ 1 ].v, polyLoop[ 2 ].v, poly.totloop == 4 ? polyLoop[ 3 ].v : 0 );
-	}
-	else if ( poly.totloop > 4 )
-	{
+    const MLoop* polyLoop = &BMesh->mloop[ poly.loopstart ];
+
+    if ( poly.totloop == 3 || poly.totloop == 4 )
+    {
+        AddFace( polyLoop[ 0 ].v, polyLoop[ 1 ].v, polyLoop[ 2 ].v, poly.totloop == 4 ? polyLoop[ 3 ].v : 0 );
+
+        // UVs are optional, so only convert when present.
+        if ( BMesh->mloopuv.size() )
+        {
+            if ( (poly.loopstart + poly.totloop ) > static_cast<int>( BMesh->mloopuv.size() ) )
+            {
+                ThrowException( "BMesh uv loop array has incorrect size" );
+            }
+            const MLoopUV* loopUV = &BMesh->mloopuv[ poly.loopstart ];
+            AddTFace( loopUV[ 0 ].uv, loopUV[ 1 ].uv, loopUV[ 2 ].uv, poly.totloop == 4 ? loopUV[ 3 ].uv : 0 );
+        }
+    }
+    else if ( poly.totloop > 4 )
+    {
 #if ASSIMP_BLEND_WITH_GLU_TESSELLATE
-		BlenderTessellatorGL tessGL( *this );
-		tessGL.Tessellate( polyLoop, poly.totloop, triMesh->mvert );
+        BlenderTessellatorGL tessGL( *this );
+        tessGL.Tessellate( polyLoop, poly.totloop, triMesh->mvert );
 #elif ASSIMP_BLEND_WITH_POLY_2_TRI
-		BlenderTessellatorP2T tessP2T( *this );
-		tessP2T.Tessellate( polyLoop, poly.totloop, triMesh->mvert );
+        BlenderTessellatorP2T tessP2T( *this );
+        tessP2T.Tessellate( polyLoop, poly.totloop, triMesh->mvert );
 #endif
-	}
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 void BlenderBMeshConverter::AddFace( int v1, int v2, int v3, int v4 )
 {
-	MFace face;
-	face.v1 = v1;
-	face.v2 = v2;
-	face.v3 = v3;
-	face.v4 = v4;
-	// TODO - Work out how materials work
-	face.mat_nr = 0;
-	triMesh->mface.push_back( face );
-	triMesh->totface = triMesh->mface.size( );
+    MFace face;
+    face.v1 = v1;
+    face.v2 = v2;
+    face.v3 = v3;
+    face.v4 = v4;
+    // TODO - Work out how materials work
+    face.mat_nr = 0;
+    triMesh->mface.push_back( face );
+    triMesh->totface = triMesh->mface.size( );
+}
+
+// ------------------------------------------------------------------------------------------------
+void BlenderBMeshConverter::AddTFace( const float* uv1, const float *uv2, const float *uv3, const float* uv4 )
+{
+    MTFace mtface;
+    memcpy( &mtface.uv[ 0 ], uv1, sizeof(float) * 2 );
+    memcpy( &mtface.uv[ 1 ], uv2, sizeof(float) * 2 );
+    memcpy( &mtface.uv[ 2 ], uv3, sizeof(float) * 2 );
+
+    if ( uv4 )
+    {
+        memcpy( &mtface.uv[ 3 ], uv4, sizeof(float) * 2 );
+    }
+
+    triMesh->mtface.push_back( mtface );
 }
 
 #endif // ASSIMP_BUILD_NO_BLEND_IMPORTER

+ 49 - 48
assimplib.mod/assimp/code/BlenderBMesh.h

@@ -5,8 +5,8 @@ Open Asset Import Library (assimp)
 Copyright (c) 2006-2013, 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 
+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
@@ -23,16 +23,16 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -48,45 +48,46 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 namespace Assimp
 {
-	// TinyFormatter.h
-	namespace Formatter
-	{
-		template < typename T,typename TR, typename A > class basic_formatter;
-		typedef class basic_formatter< char, std::char_traits< char >, std::allocator< char > > format;
-	}
-
-	// BlenderScene.h
-	namespace Blender
-	{
-		struct Mesh;
-		struct MPoly;
-		struct MLoop;
-	}
-
-	class BlenderBMeshConverter: public LogFunctions< BlenderBMeshConverter >
-	{
-	public:
-		BlenderBMeshConverter( const Blender::Mesh* mesh );
-		~BlenderBMeshConverter( );
-
-		bool ContainsBMesh( ) const;
-
-		const Blender::Mesh* TriangulateBMesh( );
-
-	private:
-		void AssertValidMesh( );
-		void AssertValidSizes( );
-		void PrepareTriMesh( );
-		void DestroyTriMesh( );
-		void ConvertPolyToFaces( const Blender::MPoly& poly );
-		void AddFace( int v1, int v2, int v3, int v4 = 0 );
-
-		const Blender::Mesh* BMesh;
-		Blender::Mesh* triMesh;
-
-		friend class BlenderTessellatorGL;
-		friend class BlenderTessellatorP2T;
-	};
+    // TinyFormatter.h
+    namespace Formatter
+    {
+        template < typename T,typename TR, typename A > class basic_formatter;
+        typedef class basic_formatter< char, std::char_traits< char >, std::allocator< char > > format;
+    }
+
+    // BlenderScene.h
+    namespace Blender
+    {
+        struct Mesh;
+        struct MPoly;
+        struct MLoop;
+    }
+
+    class BlenderBMeshConverter: public LogFunctions< BlenderBMeshConverter >
+    {
+    public:
+        BlenderBMeshConverter( const Blender::Mesh* mesh );
+        ~BlenderBMeshConverter( );
+
+        bool ContainsBMesh( ) const;
+
+        const Blender::Mesh* TriangulateBMesh( );
+
+    private:
+        void AssertValidMesh( );
+        void AssertValidSizes( );
+        void PrepareTriMesh( );
+        void DestroyTriMesh( );
+        void ConvertPolyToFaces( const Blender::MPoly& poly );
+        void AddFace( int v1, int v2, int v3, int v4 = 0 );
+        void AddTFace( const float* uv1, const float* uv2, const float *uv3, const float* uv4 = 0 );
+
+        const Blender::Mesh* BMesh;
+        Blender::Mesh* triMesh;
+
+        friend class BlenderTessellatorGL;
+        friend class BlenderTessellatorP2T;
+    };
 
 } // end of namespace Assimp
 

+ 258 - 257
assimplib.mod/assimp/code/BlenderDNA.cpp

@@ -2,11 +2,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -23,16 +23,16 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -42,12 +42,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *  @brief Implementation of the Blender `DNA`, that is its own
  *    serialized set of data structures.
  */
-#include "AssimpPCH.h"
+
 
 #ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
 #include "BlenderDNA.h"
 #include "StreamReader.h"
 #include "fast_atof.h"
+#include <boost/foreach.hpp>
 
 using namespace Assimp;
 using namespace Assimp::Blender;
@@ -55,168 +56,168 @@ using namespace Assimp::Formatter;
 
 #define for_each BOOST_FOREACH
 bool match4(StreamReaderAny& stream, const char* string) {
-	char tmp[] = { 
-		(stream).GetI1(), 
-		(stream).GetI1(),  
-		(stream).GetI1(), 
-		(stream).GetI1()
-	};
-	return (tmp[0]==string[0] && tmp[1]==string[1] && tmp[2]==string[2] && tmp[3]==string[3]);
+    char tmp[] = {
+        (stream).GetI1(),
+        (stream).GetI1(),
+        (stream).GetI1(),
+        (stream).GetI1()
+    };
+    return (tmp[0]==string[0] && tmp[1]==string[1] && tmp[2]==string[2] && tmp[3]==string[3]);
 }
 
 struct Type {
-	size_t size;
-	std::string name;
+    size_t size;
+    std::string name;
 };
 
 // ------------------------------------------------------------------------------------------------
-void DNAParser :: Parse () 
+void DNAParser :: Parse ()
 {
-	StreamReaderAny& stream = *db.reader.get();
-	DNA& dna = db.dna;
-
-	if(!match4(stream,"SDNA")) {
-		throw DeadlyImportError("BlenderDNA: Expected SDNA chunk");
-	}
-
-	// name dictionary
-	if(!match4(stream,"NAME")) {
-		throw DeadlyImportError("BlenderDNA: Expected NAME field");
-	}
-	
-	std::vector<std::string> names (stream.GetI4());
-	for_each(std::string& s, names) {
-		while (char c = stream.GetI1()) {
-			s += c;
-		}
-	}
-
-	// type dictionary
-	for (;stream.GetCurrentPos() & 0x3; stream.GetI1());
-	if(!match4(stream,"TYPE")) {
-		throw DeadlyImportError("BlenderDNA: Expected TYPE field");
-	}
-	
-	std::vector<Type> types (stream.GetI4());
-	for_each(Type& s, types) {
-		while (char c = stream.GetI1()) {
-			s.name += c;
-		}
-	}
-
-	// type length dictionary
-	for (;stream.GetCurrentPos() & 0x3; stream.GetI1());
-	if(!match4(stream,"TLEN")) {
-		throw DeadlyImportError("BlenderDNA: Expected TLEN field");
-	}
-	
-	for_each(Type& s, types) {
-		s.size = stream.GetI2();
-	}
-
-	// structures dictionary
-	for (;stream.GetCurrentPos() & 0x3; stream.GetI1());
-	if(!match4(stream,"STRC")) {
-		throw DeadlyImportError("BlenderDNA: Expected STRC field");
-	}
-
-	size_t end = stream.GetI4(), fields = 0;
-
-	dna.structures.reserve(end);
-	for(size_t i = 0; i != end; ++i) {
-		
-		uint16_t n = stream.GetI2();
-		if (n >= types.size()) {
-			throw DeadlyImportError((format(),
-				"BlenderDNA: Invalid type index in structure name" ,n, 
-				" (there are only ", types.size(), " entries)"
-			));
-		}
-
-		// maintain separate indexes
-		dna.indices[types[n].name] = dna.structures.size();
-
-		dna.structures.push_back(Structure());
-		Structure& s = dna.structures.back();
-		s.name  = types[n].name;
-		//s.index = dna.structures.size()-1;
-
-		n = stream.GetI2();
-		s.fields.reserve(n);
-
-		size_t offset = 0;
-		for (size_t m = 0; m < n; ++m, ++fields) {
-
-			uint16_t j = stream.GetI2();
-			if (j >= types.size()) {
-				throw DeadlyImportError((format(), 
-					"BlenderDNA: Invalid type index in structure field ", j, 
-					" (there are only ", types.size(), " entries)"
-				));
-			}
-			s.fields.push_back(Field());
-			Field& f = s.fields.back();
-			f.offset = offset;
-
-			f.type = types[j].name;
-			f.size = types[j].size;
-
-			j = stream.GetI2();
-			if (j >= names.size()) {
-				throw DeadlyImportError((format(), 
-					"BlenderDNA: Invalid name index in structure field ", j, 
-					" (there are only ", names.size(), " entries)"
-				));
-			}
-
-			f.name = names[j];
-			f.flags = 0u;
-			
-			// pointers always specify the size of the pointee instead of their own.
-			// The pointer asterisk remains a property of the lookup name.
-			if (f.name[0] == '*') {
-				f.size = db.i64bit ? 8 : 4;
-				f.flags |= FieldFlag_Pointer;
-			}
-
-			// arrays, however, specify the size of a single element so we
-			// need to parse the (possibly multi-dimensional) array declaration
-			// in order to obtain the actual size of the array in the file.
-			// Also we need to alter the lookup name to include no array
-			// brackets anymore or size fixup won't work (if our size does 
-			// not match the size read from the DNA).
-			if (*f.name.rbegin() == ']') {
-				const std::string::size_type rb = f.name.find('[');
-				if (rb == std::string::npos) {
-					throw DeadlyImportError((format(), 
-						"BlenderDNA: Encountered invalid array declaration ",
-						f.name
-					));
-				}
-
-				f.flags |= FieldFlag_Array; 
-				DNA::ExtractArraySize(f.name,f.array_sizes);
-				f.name = f.name.substr(0,rb);
-
-				f.size *= f.array_sizes[0] * f.array_sizes[1];
-			}
-
-			// maintain separate indexes
-			s.indices[f.name] = s.fields.size()-1;
-			offset += f.size;
-		}
-		s.size = offset;
-	}
-
-	DefaultLogger::get()->debug((format(),"BlenderDNA: Got ",dna.structures.size(),
-		" structures with totally ",fields," fields"));
+    StreamReaderAny& stream = *db.reader.get();
+    DNA& dna = db.dna;
+
+    if(!match4(stream,"SDNA")) {
+        throw DeadlyImportError("BlenderDNA: Expected SDNA chunk");
+    }
+
+    // name dictionary
+    if(!match4(stream,"NAME")) {
+        throw DeadlyImportError("BlenderDNA: Expected NAME field");
+    }
+
+    std::vector<std::string> names (stream.GetI4());
+    for_each(std::string& s, names) {
+        while (char c = stream.GetI1()) {
+            s += c;
+        }
+    }
+
+    // type dictionary
+    for (;stream.GetCurrentPos() & 0x3; stream.GetI1());
+    if(!match4(stream,"TYPE")) {
+        throw DeadlyImportError("BlenderDNA: Expected TYPE field");
+    }
+
+    std::vector<Type> types (stream.GetI4());
+    for_each(Type& s, types) {
+        while (char c = stream.GetI1()) {
+            s.name += c;
+        }
+    }
+
+    // type length dictionary
+    for (;stream.GetCurrentPos() & 0x3; stream.GetI1());
+    if(!match4(stream,"TLEN")) {
+        throw DeadlyImportError("BlenderDNA: Expected TLEN field");
+    }
+
+    for_each(Type& s, types) {
+        s.size = stream.GetI2();
+    }
+
+    // structures dictionary
+    for (;stream.GetCurrentPos() & 0x3; stream.GetI1());
+    if(!match4(stream,"STRC")) {
+        throw DeadlyImportError("BlenderDNA: Expected STRC field");
+    }
+
+    size_t end = stream.GetI4(), fields = 0;
+
+    dna.structures.reserve(end);
+    for(size_t i = 0; i != end; ++i) {
+
+        uint16_t n = stream.GetI2();
+        if (n >= types.size()) {
+            throw DeadlyImportError((format(),
+                "BlenderDNA: Invalid type index in structure name" ,n,
+                " (there are only ", types.size(), " entries)"
+            ));
+        }
+
+        // maintain separate indexes
+        dna.indices[types[n].name] = dna.structures.size();
+
+        dna.structures.push_back(Structure());
+        Structure& s = dna.structures.back();
+        s.name  = types[n].name;
+        //s.index = dna.structures.size()-1;
+
+        n = stream.GetI2();
+        s.fields.reserve(n);
+
+        size_t offset = 0;
+        for (size_t m = 0; m < n; ++m, ++fields) {
+
+            uint16_t j = stream.GetI2();
+            if (j >= types.size()) {
+                throw DeadlyImportError((format(),
+                    "BlenderDNA: Invalid type index in structure field ", j,
+                    " (there are only ", types.size(), " entries)"
+                ));
+            }
+            s.fields.push_back(Field());
+            Field& f = s.fields.back();
+            f.offset = offset;
+
+            f.type = types[j].name;
+            f.size = types[j].size;
+
+            j = stream.GetI2();
+            if (j >= names.size()) {
+                throw DeadlyImportError((format(),
+                    "BlenderDNA: Invalid name index in structure field ", j,
+                    " (there are only ", names.size(), " entries)"
+                ));
+            }
+
+            f.name = names[j];
+            f.flags = 0u;
+
+            // pointers always specify the size of the pointee instead of their own.
+            // The pointer asterisk remains a property of the lookup name.
+            if (f.name[0] == '*') {
+                f.size = db.i64bit ? 8 : 4;
+                f.flags |= FieldFlag_Pointer;
+            }
+
+            // arrays, however, specify the size of a single element so we
+            // need to parse the (possibly multi-dimensional) array declaration
+            // in order to obtain the actual size of the array in the file.
+            // Also we need to alter the lookup name to include no array
+            // brackets anymore or size fixup won't work (if our size does
+            // not match the size read from the DNA).
+            if (*f.name.rbegin() == ']') {
+                const std::string::size_type rb = f.name.find('[');
+                if (rb == std::string::npos) {
+                    throw DeadlyImportError((format(),
+                        "BlenderDNA: Encountered invalid array declaration ",
+                        f.name
+                    ));
+                }
+
+                f.flags |= FieldFlag_Array;
+                DNA::ExtractArraySize(f.name,f.array_sizes);
+                f.name = f.name.substr(0,rb);
+
+                f.size *= f.array_sizes[0] * f.array_sizes[1];
+            }
+
+            // maintain separate indexes
+            s.indices[f.name] = s.fields.size()-1;
+            offset += f.size;
+        }
+        s.size = offset;
+    }
+
+    DefaultLogger::get()->debug((format(),"BlenderDNA: Got ",dna.structures.size(),
+        " structures with totally ",fields," fields"));
 
 #ifdef ASSIMP_BUILD_BLENDER_DEBUG
-	dna.DumpToFile();
+    dna.DumpToFile();
 #endif
 
-	dna.AddPrimitiveStructures();
-	dna.RegisterConverters();
+    dna.AddPrimitiveStructures();
+    dna.RegisterConverters();
 }
 
 
@@ -226,144 +227,144 @@ void DNAParser :: Parse ()
 // ------------------------------------------------------------------------------------------------
 void DNA :: DumpToFile()
 {
-	// we dont't bother using the VFS here for this is only for debugging.
-	// (and all your bases are belong to us).
-
-	std::ofstream f("dna.txt");
-	if (f.fail()) {
-		DefaultLogger::get()->error("Could not dump dna to dna.txt");
-		return;
-	}
-	f << "Field format: type name offset size" << "\n";
-	f << "Structure format: name size" << "\n";
-
-	for_each(const Structure& s, structures) {
-		f << s.name << " " << s.size << "\n\n";
-		for_each(const Field& ff, s.fields) {
-			f << "\t" << ff.type << " " << ff.name << " " << ff.offset << " " << ff.size << std::endl;
-		}
-		f << std::endl;
-	}
-	DefaultLogger::get()->info("BlenderDNA: Dumped dna to dna.txt");
+    // we dont't bother using the VFS here for this is only for debugging.
+    // (and all your bases are belong to us).
+
+    std::ofstream f("dna.txt");
+    if (f.fail()) {
+        DefaultLogger::get()->error("Could not dump dna to dna.txt");
+        return;
+    }
+    f << "Field format: type name offset size" << "\n";
+    f << "Structure format: name size" << "\n";
+
+    for_each(const Structure& s, structures) {
+        f << s.name << " " << s.size << "\n\n";
+        for_each(const Field& ff, s.fields) {
+            f << "\t" << ff.type << " " << ff.name << " " << ff.offset << " " << ff.size << std::endl;
+        }
+        f << std::endl;
+    }
+    DefaultLogger::get()->info("BlenderDNA: Dumped dna to dna.txt");
 }
 #endif
 
 // ------------------------------------------------------------------------------------------------
 /*static*/ void  DNA :: ExtractArraySize(
-	const std::string& out, 
-	size_t array_sizes[2]
+    const std::string& out,
+    size_t array_sizes[2]
 )
 {
-	array_sizes[0] = array_sizes[1] = 1;
-	std::string::size_type pos = out.find('[');
-	if (pos++ == std::string::npos) {
-		return;
-	}
-	array_sizes[0] = strtoul10(&out[pos]);
-
-	pos = out.find('[',pos);
-	if (pos++ == std::string::npos) {
-		return;
-	}
-	array_sizes[1] = strtoul10(&out[pos]);
+    array_sizes[0] = array_sizes[1] = 1;
+    std::string::size_type pos = out.find('[');
+    if (pos++ == std::string::npos) {
+        return;
+    }
+    array_sizes[0] = strtoul10(&out[pos]);
+
+    pos = out.find('[',pos);
+    if (pos++ == std::string::npos) {
+        return;
+    }
+    array_sizes[1] = strtoul10(&out[pos]);
 }
 
 // ------------------------------------------------------------------------------------------------
 boost::shared_ptr< ElemBase > DNA :: ConvertBlobToStructure(
-	const Structure& structure,
-	const FileDatabase& db
-) const 
+    const Structure& structure,
+    const FileDatabase& db
+) const
 {
-	std::map<std::string, FactoryPair >::const_iterator it = converters.find(structure.name);
-	if (it == converters.end()) {
-		return boost::shared_ptr< ElemBase >();
-	}
-
-	boost::shared_ptr< ElemBase > ret = (structure.*((*it).second.first))();
-	(structure.*((*it).second.second))(ret,db);
-	
-	return ret;
+    std::map<std::string, FactoryPair >::const_iterator it = converters.find(structure.name);
+    if (it == converters.end()) {
+        return boost::shared_ptr< ElemBase >();
+    }
+
+    boost::shared_ptr< ElemBase > ret = (structure.*((*it).second.first))();
+    (structure.*((*it).second.second))(ret,db);
+
+    return ret;
 }
 
 // ------------------------------------------------------------------------------------------------
 DNA::FactoryPair DNA :: GetBlobToStructureConverter(
-	const Structure& structure,
-	const FileDatabase& /*db*/
-) const 
+    const Structure& structure,
+    const FileDatabase& /*db*/
+) const
 {
-	std::map<std::string,  FactoryPair>::const_iterator it = converters.find(structure.name);
-	return it == converters.end() ? FactoryPair() : (*it).second;
+    std::map<std::string,  FactoryPair>::const_iterator it = converters.find(structure.name);
+    return it == converters.end() ? FactoryPair() : (*it).second;
 }
 
 // basing on http://www.blender.org/development/architecture/notes-on-sdna/
 // ------------------------------------------------------------------------------------------------
 void DNA :: AddPrimitiveStructures()
 {
-	// NOTE: these are just dummies. Their presence enforces
-	// Structure::Convert<target_type> to be called on these
-	// empty structures. These converters are special 
-	// overloads which scan the name of the structure and
-	// perform the required data type conversion if one
-	// of these special names is found in the structure
-	// in question.
+    // NOTE: these are just dummies. Their presence enforces
+    // Structure::Convert<target_type> to be called on these
+    // empty structures. These converters are special
+    // overloads which scan the name of the structure and
+    // perform the required data type conversion if one
+    // of these special names is found in the structure
+    // in question.
 
-	indices["int"] = structures.size();
-	structures.push_back( Structure() );
-	structures.back().name = "int";
-	structures.back().size = 4;
+    indices["int"] = structures.size();
+    structures.push_back( Structure() );
+    structures.back().name = "int";
+    structures.back().size = 4;
 
-	indices["short"] = structures.size();
-	structures.push_back( Structure() );
-	structures.back().name = "short";
-	structures.back().size = 2;
+    indices["short"] = structures.size();
+    structures.push_back( Structure() );
+    structures.back().name = "short";
+    structures.back().size = 2;
 
 
-	indices["char"] = structures.size();
-	structures.push_back( Structure() );
-	structures.back().name = "char";
-	structures.back().size = 1;
+    indices["char"] = structures.size();
+    structures.push_back( Structure() );
+    structures.back().name = "char";
+    structures.back().size = 1;
 
 
-	indices["float"] = structures.size();
-	structures.push_back( Structure() );
-	structures.back().name = "float";
-	structures.back().size = 4;
+    indices["float"] = structures.size();
+    structures.push_back( Structure() );
+    structures.back().name = "float";
+    structures.back().size = 4;
 
 
-	indices["double"] = structures.size();
-	structures.push_back( Structure() );
-	structures.back().name = "double";
-	structures.back().size = 8;
+    indices["double"] = structures.size();
+    structures.push_back( Structure() );
+    structures.back().name = "double";
+    structures.back().size = 8;
 
-	// no long, seemingly.
+    // no long, seemingly.
 }
 
 // ------------------------------------------------------------------------------------------------
 void SectionParser :: Next()
 {
-	stream.SetCurrentPos(current.start + current.size);
+    stream.SetCurrentPos(current.start + current.size);
 
-	const char tmp[] = {
-		stream.GetI1(),
-		stream.GetI1(),
-		stream.GetI1(),
-		stream.GetI1()
-	};
-	current.id = std::string(tmp,tmp[3]?4:tmp[2]?3:tmp[1]?2:1);
+    const char tmp[] = {
+        stream.GetI1(),
+        stream.GetI1(),
+        stream.GetI1(),
+        stream.GetI1()
+    };
+    current.id = std::string(tmp,tmp[3]?4:tmp[2]?3:tmp[1]?2:1);
 
-	current.size = stream.GetI4();
-	current.address.val = ptr64 ? stream.GetU8() : stream.GetU4();
+    current.size = stream.GetI4();
+    current.address.val = ptr64 ? stream.GetU8() : stream.GetU4();
 
-	current.dna_index = stream.GetI4();
-	current.num = stream.GetI4();
+    current.dna_index = stream.GetI4();
+    current.num = stream.GetI4();
 
-	current.start = stream.GetCurrentPos();
-	if (stream.GetRemainingSizeToLimit() < current.size) {
-		throw DeadlyImportError("BLEND: invalid size of file block");
-	}
+    current.start = stream.GetCurrentPos();
+    if (stream.GetRemainingSizeToLimit() < current.size) {
+        throw DeadlyImportError("BLEND: invalid size of file block");
+    }
 
 #ifdef ASSIMP_BUILD_BLENDER_DEBUG
-	DefaultLogger::get()->debug(current.id);
+    DefaultLogger::get()->debug(current.id);
 #endif
 }
 

+ 469 - 464
assimplib.mod/assimp/code/BlenderDNA.h

@@ -2,11 +2,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -23,23 +23,23 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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  BlenderDNA.h
- *  @brief Blender `DNA` (file format specification embedded in 
+ *  @brief Blender `DNA` (file format specification embedded in
  *    blend file itself) loader.
  */
 #ifndef INCLUDED_AI_BLEND_DNA_H
@@ -47,24 +47,29 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include "BaseImporter.h"
 #include "TinyFormatter.h"
+#include "StreamReader.h"
+#include "../include/assimp/DefaultLogger.hpp"
+#include <stdint.h>
+#include <boost/shared_ptr.hpp>
+
 
 // enable verbose log output. really verbose, so be careful.
 #ifdef ASSIMP_BUILD_DEBUG
-#	define ASSIMP_BUILD_BLENDER_DEBUG
+#   define ASSIMP_BUILD_BLENDER_DEBUG
 #endif
 
 // #define ASSIMP_BUILD_BLENDER_NO_STATS
 
-namespace Assimp	{
-	template <bool,bool> class StreamReader;
-	typedef StreamReader<true,true> StreamReaderAny;
+namespace Assimp    {
+    template <bool,bool> class StreamReader;
+    typedef StreamReader<true,true> StreamReaderAny;
 
-	namespace Blender {
-		class  FileDatabase;
-		struct FileBlockHead;
+    namespace Blender {
+        class  FileDatabase;
+        struct FileBlockHead;
 
-		template <template <typename> class TOUT>
-		class ObjectCache;
+        template <template <typename> class TOUT>
+        class ObjectCache;
 
 // -------------------------------------------------------------------------------
 /** Exception class used by the blender loader to selectively catch exceptions
@@ -75,40 +80,40 @@ namespace Assimp	{
 // -------------------------------------------------------------------------------
 struct Error : DeadlyImportError
 {
-	Error (const std::string& s)
-		: DeadlyImportError(s)
-	{}
+    Error (const std::string& s)
+        : DeadlyImportError(s)
+    {}
 };
 
 // -------------------------------------------------------------------------------
 /** The only purpose of this structure is to feed a virtual dtor into its
  *  descendents. It serves as base class for all data structure fields. */
 // -------------------------------------------------------------------------------
-struct ElemBase 
+struct ElemBase
 {
-	virtual ~ElemBase() {}
-
-	/** Type name of the element. The type 
-	 * string points is the `c_str` of the `name` attribute of the 
-	 * corresponding `Structure`, that is, it is only valid as long 
-	 * as the DNA is not modified. The dna_type is only set if the
-	 * data type is not static, i.e. a boost::shared_ptr<ElemBase>
-	 * in the scene description would have its type resolved 
-	 * at runtime, so this member is always set. */
-	const char* dna_type;
+    virtual ~ElemBase() {}
+
+    /** Type name of the element. The type
+     * string points is the `c_str` of the `name` attribute of the
+     * corresponding `Structure`, that is, it is only valid as long
+     * as the DNA is not modified. The dna_type is only set if the
+     * data type is not static, i.e. a boost::shared_ptr<ElemBase>
+     * in the scene description would have its type resolved
+     * at runtime, so this member is always set. */
+    const char* dna_type;
 };
 
 
 // -------------------------------------------------------------------------------
 /** Represents a generic pointer to a memory location, which can be either 32
  *  or 64 bits. These pointers are loaded from the BLEND file and finally
- *  fixed to point to the real, converted representation of the objects 
+ *  fixed to point to the real, converted representation of the objects
  *  they used to point to.*/
 // -------------------------------------------------------------------------------
 struct Pointer
 {
-	Pointer() : val() {}
-	uint64_t val;
+    Pointer() : val() {}
+    uint64_t val;
 };
 
 // -------------------------------------------------------------------------------
@@ -116,13 +121,13 @@ struct Pointer
 // -------------------------------------------------------------------------------
 struct FileOffset
 {
-	FileOffset() : val() {}
-	uint64_t val;
+    FileOffset() : val() {}
+    uint64_t val;
 };
 
 // -------------------------------------------------------------------------------
 /** Dummy derivate of std::vector to be able to use it in templates simultaenously
- *  with boost::shared_ptr, which takes only one template argument 
+ *  with boost::shared_ptr, which takes only one template argument
  *  while std::vector takes three. Also we need to provide some special member
  *  functions of shared_ptr */
 // -------------------------------------------------------------------------------
@@ -130,44 +135,44 @@ template <typename T>
 class vector : public std::vector<T>
 {
 public:
-	using std::vector<T>::resize;
-	using std::vector<T>::empty;
+    using std::vector<T>::resize;
+    using std::vector<T>::empty;
 
-	void reset() {
-		resize(0);
-	}
+    void reset() {
+        resize(0);
+    }
 
-	operator bool () const {
-		return !empty();
-	}
+    operator bool () const {
+        return !empty();
+    }
 };
 
 // -------------------------------------------------------------------------------
 /** Mixed flags for use in #Field */
 // -------------------------------------------------------------------------------
-enum FieldFlags 
+enum FieldFlags
 {
-	FieldFlag_Pointer = 0x1,
-	FieldFlag_Array   = 0x2
+    FieldFlag_Pointer = 0x1,
+    FieldFlag_Array   = 0x2
 };
 
 // -------------------------------------------------------------------------------
 /** Represents a single member of a data structure in a BLEND file */
 // -------------------------------------------------------------------------------
-struct Field 
-{	
-	std::string name;
-	std::string type;
+struct Field
+{
+    std::string name;
+    std::string type;
 
-	size_t size;
-	size_t offset;
+    size_t size;
+    size_t offset;
 
-	/** Size of each array dimension. For flat arrays,
-	 *  the second dimension is set to 1. */
-	size_t array_sizes[2];
+    /** Size of each array dimension. For flat arrays,
+     *  the second dimension is set to 1. */
+    size_t array_sizes[2];
 
-	/** Any of the #FieldFlags enumerated values */
-	unsigned int flags;
+    /** Any of the #FieldFlags enumerated values */
+    unsigned int flags;
 };
 
 // -------------------------------------------------------------------------------
@@ -175,18 +180,18 @@ struct Field
  *  mission critical so we need them, while others can silently be default
  *  initialized and no animations are harmed. */
 // -------------------------------------------------------------------------------
-enum ErrorPolicy 
+enum ErrorPolicy
 {
-	/** Substitute default value and ignore */
-	ErrorPolicy_Igno,
-	/** Substitute default value and write to log */
-	ErrorPolicy_Warn,
-	/** Substitute a massive error message and crash the whole matrix. Its time for another zion */
-	ErrorPolicy_Fail
+    /** Substitute default value and ignore */
+    ErrorPolicy_Igno,
+    /** Substitute default value and write to log */
+    ErrorPolicy_Warn,
+    /** Substitute a massive error message and crash the whole matrix. Its time for another zion */
+    ErrorPolicy_Fail
 };
 
 #ifdef ASSIMP_BUILD_BLENDER_DEBUG
-#	define ErrorPolicy_Igno ErrorPolicy_Warn
+#   define ErrorPolicy_Igno ErrorPolicy_Warn
 #endif
 
 // -------------------------------------------------------------------------------
@@ -197,395 +202,395 @@ enum ErrorPolicy
  *  binary `blob` read from the file to such a structure instance with
  *  meaningful contents. */
 // -------------------------------------------------------------------------------
-class Structure 
+class Structure
 {
-	template <template <typename> class> friend class ObjectCache;
+    template <template <typename> class> friend class ObjectCache;
 
 public:
 
-	Structure()
-		:	cache_idx(-1)
-	{}
+    Structure()
+        :   cache_idx(-1)
+    {}
 
 public:
 
-	// publicly accessible members
-	std::string name;
-	vector< Field > fields;
-	std::map<std::string, size_t> indices;
+    // publicly accessible members
+    std::string name;
+    vector< Field > fields;
+    std::map<std::string, size_t> indices;
 
-	size_t size;
+    size_t size;
 
 public:
 
-	// --------------------------------------------------------
-	/** Access a field of the structure by its canonical name. The pointer version
-	 *  returns NULL on failure while the reference version raises an import error. */
-	inline const Field& operator [] (const std::string& ss) const;
-	inline const Field* Get (const std::string& ss) const;
+    // --------------------------------------------------------
+    /** Access a field of the structure by its canonical name. The pointer version
+     *  returns NULL on failure while the reference version raises an import error. */
+    inline const Field& operator [] (const std::string& ss) const;
+    inline const Field* Get (const std::string& ss) const;
 
-	// --------------------------------------------------------
-	/** Access a field of the structure by its index */
-	inline const Field& operator [] (const size_t i) const;
+    // --------------------------------------------------------
+    /** Access a field of the structure by its index */
+    inline const Field& operator [] (const size_t i) const;
 
-	// --------------------------------------------------------
-	inline bool operator== (const Structure& other) const {
-		return name == other.name; // name is meant to be an unique identifier
-	}
+    // --------------------------------------------------------
+    inline bool operator== (const Structure& other) const {
+        return name == other.name; // name is meant to be an unique identifier
+    }
 
-	// --------------------------------------------------------
-	inline bool operator!= (const Structure& other) const {
-		return name != other.name;
-	}
+    // --------------------------------------------------------
+    inline bool operator!= (const Structure& other) const {
+        return name != other.name;
+    }
 
 public:
 
-	// --------------------------------------------------------
-	/** Try to read an instance of the structure from the stream
-	 *  and attempt to convert to `T`. This is done by
-	 *  an appropriate specialization. If none is available,
-	 *  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;
-
-
-
-	// --------------------------------------------------------
-	// generic converter
-	template <typename T>
-	void Convert(boost::shared_ptr<ElemBase> in,const FileDatabase& db) const;
-
-	// --------------------------------------------------------
-	// generic allocator
-	template <typename T> boost::shared_ptr<ElemBase> Allocate() const;
-
-
-
-	// --------------------------------------------------------
-	// field parsing for 1d arrays
-	template <int error_policy, typename T, size_t M>
-	void ReadFieldArray(T (& out)[M], const char* name, 
-		const FileDatabase& db) const;
-
-	// --------------------------------------------------------
-	// field parsing for 2d arrays
-	template <int error_policy, typename T, size_t M, size_t N>
-	void ReadFieldArray2(T (& out)[M][N], const char* name,
-		const FileDatabase& db) const;
-
-	// --------------------------------------------------------
-	// field parsing for pointer or dynamic array types 
-	// (boost::shared_ptr or boost::shared_array)
-	// The return value indicates whether the data was already cached.
-	template <int error_policy, template <typename> class TOUT, typename T>
-	bool ReadFieldPtr(TOUT<T>& out, const char* name, 
-		const FileDatabase& db,
-		bool non_recursive = false) const;
-
-	// --------------------------------------------------------
-	// field parsing for static arrays of pointer or dynamic
-	// array types (boost::shared_ptr[] or boost::shared_array[])
-	// The return value indicates whether the data was already cached.
-	template <int error_policy, template <typename> class TOUT, typename T, size_t N>
-	bool ReadFieldPtr(TOUT<T> (&out)[N], const char* name, 
-		const FileDatabase& db) const;
-
-	// --------------------------------------------------------
-	// field parsing for `normal` values
-	// The return value indicates whether the data was already cached.
-	template <int error_policy, typename T>
-	void ReadField(T& out, const char* name, 
-		const FileDatabase& db) const;
+    // --------------------------------------------------------
+    /** Try to read an instance of the structure from the stream
+     *  and attempt to convert to `T`. This is done by
+     *  an appropriate specialization. If none is available,
+     *  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;
+
+
+
+    // --------------------------------------------------------
+    // generic converter
+    template <typename T>
+    void Convert(boost::shared_ptr<ElemBase> in,const FileDatabase& db) const;
+
+    // --------------------------------------------------------
+    // generic allocator
+    template <typename T> boost::shared_ptr<ElemBase> Allocate() const;
+
+
+
+    // --------------------------------------------------------
+    // field parsing for 1d arrays
+    template <int error_policy, typename T, size_t M>
+    void ReadFieldArray(T (& out)[M], const char* name,
+        const FileDatabase& db) const;
+
+    // --------------------------------------------------------
+    // field parsing for 2d arrays
+    template <int error_policy, typename T, size_t M, size_t N>
+    void ReadFieldArray2(T (& out)[M][N], const char* name,
+        const FileDatabase& db) const;
+
+    // --------------------------------------------------------
+    // field parsing for pointer or dynamic array types
+    // (boost::shared_ptr or boost::shared_array)
+    // The return value indicates whether the data was already cached.
+    template <int error_policy, template <typename> class TOUT, typename T>
+    bool ReadFieldPtr(TOUT<T>& out, const char* name,
+        const FileDatabase& db,
+        bool non_recursive = false) const;
+
+    // --------------------------------------------------------
+    // field parsing for static arrays of pointer or dynamic
+    // array types (boost::shared_ptr[] or boost::shared_array[])
+    // The return value indicates whether the data was already cached.
+    template <int error_policy, template <typename> class TOUT, typename T, size_t N>
+    bool ReadFieldPtr(TOUT<T> (&out)[N], const char* name,
+        const FileDatabase& db) const;
+
+    // --------------------------------------------------------
+    // field parsing for `normal` values
+    // The return value indicates whether the data was already cached.
+    template <int error_policy, typename T>
+    void ReadField(T& out, const char* name,
+        const FileDatabase& db) const;
 
 private:
 
-	// --------------------------------------------------------
-	template <template <typename> class TOUT, typename T>
-	bool ResolvePointer(TOUT<T>& out, const Pointer & ptrval, 
-		const FileDatabase& db, const Field& f,
-		bool non_recursive = false) const;
+    // --------------------------------------------------------
+    template <template <typename> class TOUT, typename T>
+    bool ResolvePointer(TOUT<T>& out, const Pointer & ptrval,
+        const FileDatabase& db, const Field& f,
+        bool non_recursive = false) const;
 
-	// --------------------------------------------------------
-	template <template <typename> class TOUT, typename T>
-	bool ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval, 
-		const FileDatabase& db, const Field& f, bool) const;
+    // --------------------------------------------------------
+    template <template <typename> class TOUT, typename T>
+    bool ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval,
+        const FileDatabase& db, const Field& f, bool) const;
 
-	// --------------------------------------------------------
-	bool ResolvePointer( boost::shared_ptr< FileOffset >& out, const Pointer & ptrval, 
-		const FileDatabase& db, const Field& f, bool) const;
+    // --------------------------------------------------------
+    bool ResolvePointer( boost::shared_ptr< FileOffset >& out, const Pointer & ptrval,
+        const FileDatabase& db, const Field& f, bool) const;
 
-	// --------------------------------------------------------
-	inline const FileBlockHead* LocateFileBlockForAddress(
-		const Pointer & ptrval,
-		const FileDatabase& db) const;
+    // --------------------------------------------------------
+    inline const FileBlockHead* LocateFileBlockForAddress(
+        const Pointer & ptrval,
+        const FileDatabase& db) const;
 
 private:
 
-	// ------------------------------------------------------------------------------
-	template <typename T> T* _allocate(boost::shared_ptr<T>& out, size_t& s) const {
-		out = boost::shared_ptr<T>(new T());
-		s = 1;
-		return out.get();
-	}
-
-	template <typename T> T* _allocate(vector<T>& out, size_t& s) const {
-		out.resize(s);
-		return s ? &out.front() : NULL;
-	}
-
-	// --------------------------------------------------------
-	template <int error_policy>
-	struct _defaultInitializer {
-
-		template <typename T, unsigned int N>
-		void operator ()(T (& out)[N], const char* = NULL) {
-			for (unsigned int i = 0; i < N; ++i) {
-				out[i] = T(); 
-			}
-		}
-
-		template <typename T, unsigned int N, unsigned int M>
-		void operator ()(T (& out)[N][M], const char* = NULL) {
-			for (unsigned int i = 0; i < N; ++i) {
-				for (unsigned int j = 0; j < M; ++j) {
-					out[i][j] = T(); 
-				}
-			}
-		}
-
-		template <typename T>
-		void operator ()(T& out, const char* = NULL) {
-			out = T();
-		}
-	};
+    // ------------------------------------------------------------------------------
+    template <typename T> T* _allocate(boost::shared_ptr<T>& out, size_t& s) const {
+        out = boost::shared_ptr<T>(new T());
+        s = 1;
+        return out.get();
+    }
+
+    template <typename T> T* _allocate(vector<T>& out, size_t& s) const {
+        out.resize(s);
+        return s ? &out.front() : NULL;
+    }
+
+    // --------------------------------------------------------
+    template <int error_policy>
+    struct _defaultInitializer {
+
+        template <typename T, unsigned int N>
+        void operator ()(T (& out)[N], const char* = NULL) {
+            for (unsigned int i = 0; i < N; ++i) {
+                out[i] = T();
+            }
+        }
+
+        template <typename T, unsigned int N, unsigned int M>
+        void operator ()(T (& out)[N][M], const char* = NULL) {
+            for (unsigned int i = 0; i < N; ++i) {
+                for (unsigned int j = 0; j < M; ++j) {
+                    out[i][j] = T();
+                }
+            }
+        }
+
+        template <typename T>
+        void operator ()(T& out, const char* = NULL) {
+            out = T();
+        }
+    };
 
 private:
 
-	mutable size_t cache_idx;
+    mutable size_t cache_idx;
 };
 
 // --------------------------------------------------------
 template <>  struct Structure :: _defaultInitializer<ErrorPolicy_Warn> {
 
-	template <typename T>
-	void operator ()(T& out, const char* reason = "<add reason>") {
-		DefaultLogger::get()->warn(reason);
+    template <typename T>
+    void operator ()(T& out, const char* reason = "<add reason>") {
+        DefaultLogger::get()->warn(reason);
 
-		// ... and let the show go on
-		_defaultInitializer<0 /*ErrorPolicy_Igno*/>()(out);
-	}
+        // ... and let the show go on
+        _defaultInitializer<0 /*ErrorPolicy_Igno*/>()(out);
+    }
 };
 
 template <> struct Structure :: _defaultInitializer<ErrorPolicy_Fail> {
 
-	template <typename T>
-	void operator ()(T& /*out*/,const char* = "") {
-		// obviously, it is crucial that _DefaultInitializer is used 
-		// only from within a catch clause.
-		throw;
-	}
+    template <typename T>
+    void operator ()(T& /*out*/,const char* = "") {
+        // obviously, it is crucial that _DefaultInitializer is used
+        // only from within a catch clause.
+        throw;
+    }
 };
 
 // -------------------------------------------------------------------------------------------------------
-template <> inline bool Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::shared_ptr<ElemBase>& out, 
-	const Pointer & ptrval, 
-	const FileDatabase& db, 
-	const Field& f,
-	bool
-	) const;
+template <> inline bool Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::shared_ptr<ElemBase>& out,
+    const Pointer & ptrval,
+    const FileDatabase& db,
+    const Field& f,
+    bool
+    ) const;
 
 
 // -------------------------------------------------------------------------------
 /** Represents the full data structure information for a single BLEND file.
  *  This data is extracted from the DNA1 chunk in the file.
- *  #DNAParser does the reading and represents currently the only place where 
+ *  #DNAParser does the reading and represents currently the only place where
  *  DNA is altered.*/
 // -------------------------------------------------------------------------------
 class DNA
 {
 public:
 
-	typedef void (Structure::*ConvertProcPtr) (
-		boost::shared_ptr<ElemBase> in, 
-		const FileDatabase&
-	) const;
+    typedef void (Structure::*ConvertProcPtr) (
+        boost::shared_ptr<ElemBase> in,
+        const FileDatabase&
+    ) const;
+
+    typedef boost::shared_ptr<ElemBase> (
+        Structure::*AllocProcPtr) () const;
 
-	typedef boost::shared_ptr<ElemBase> (
-		Structure::*AllocProcPtr) () const;
-	
-	typedef std::pair< AllocProcPtr, ConvertProcPtr > FactoryPair;
+    typedef std::pair< AllocProcPtr, ConvertProcPtr > FactoryPair;
 
 public:
 
-	std::map<std::string, FactoryPair > converters;
-	vector<Structure > structures;
-	std::map<std::string, size_t> indices;
+    std::map<std::string, FactoryPair > converters;
+    vector<Structure > structures;
+    std::map<std::string, size_t> indices;
 
 public:
 
-	// --------------------------------------------------------
-	/** Access a structure by its canonical name, the pointer version returns NULL on failure 
-	  * while the reference version raises an error. */
-	inline const Structure& operator [] (const std::string& ss) const;
-	inline const Structure* Get (const std::string& ss) const;
+    // --------------------------------------------------------
+    /** Access a structure by its canonical name, the pointer version returns NULL on failure
+      * while the reference version raises an error. */
+    inline const Structure& operator [] (const std::string& ss) const;
+    inline const Structure* Get (const std::string& ss) const;
 
-	// --------------------------------------------------------
-	/** Access a structure by its index */
-	inline const Structure& operator [] (const size_t i) const;
+    // --------------------------------------------------------
+    /** Access a structure by its index */
+    inline const Structure& operator [] (const size_t i) const;
 
 public:
 
-	// --------------------------------------------------------
-	/** Add structure definitions for all the primitive types,
-	 *  i.e. integer, short, char, float */
-	void AddPrimitiveStructures();
-
-	// --------------------------------------------------------
-	/** Fill the @c converters member with converters for all 
-	 *  known data types. The implementation of this method is
-	 *  in BlenderScene.cpp and is machine-generated.
-	 *  Converters are used to quickly handle objects whose
-	 *  exact data type is a runtime-property and not yet 
-	 *  known at compile time (consier Object::data).*/
-	void RegisterConverters();
-
-
-	// --------------------------------------------------------
-	/** Take an input blob from the stream, interpret it according to 
-	 *  a its structure name and convert it to the intermediate
-	 *  representation. 
-	 *  @param structure Destination structure definition
-	 *  @param db File database.
-	 *  @return A null pointer if no appropriate converter is available.*/
-	boost::shared_ptr< ElemBase > ConvertBlobToStructure(
-		const Structure& structure,
-		const FileDatabase& db
-		) const;
-
-	// --------------------------------------------------------
-	/** Find a suitable conversion function for a given Structure.
-	 *  Such a converter function takes a blob from the input 
-	 *  stream, reads as much as it needs, and builds up a
-	 *  complete object in intermediate representation.
-	 *  @param structure Destination structure definition
-	 *  @param db File database.
-	 *  @return A null pointer in .first if no appropriate converter is available.*/
-	FactoryPair GetBlobToStructureConverter(
-		const Structure& structure,
-		const FileDatabase& db
-		) const;
+    // --------------------------------------------------------
+    /** Add structure definitions for all the primitive types,
+     *  i.e. integer, short, char, float */
+    void AddPrimitiveStructures();
+
+    // --------------------------------------------------------
+    /** Fill the @c converters member with converters for all
+     *  known data types. The implementation of this method is
+     *  in BlenderScene.cpp and is machine-generated.
+     *  Converters are used to quickly handle objects whose
+     *  exact data type is a runtime-property and not yet
+     *  known at compile time (consier Object::data).*/
+    void RegisterConverters();
+
+
+    // --------------------------------------------------------
+    /** Take an input blob from the stream, interpret it according to
+     *  a its structure name and convert it to the intermediate
+     *  representation.
+     *  @param structure Destination structure definition
+     *  @param db File database.
+     *  @return A null pointer if no appropriate converter is available.*/
+    boost::shared_ptr< ElemBase > ConvertBlobToStructure(
+        const Structure& structure,
+        const FileDatabase& db
+        ) const;
+
+    // --------------------------------------------------------
+    /** Find a suitable conversion function for a given Structure.
+     *  Such a converter function takes a blob from the input
+     *  stream, reads as much as it needs, and builds up a
+     *  complete object in intermediate representation.
+     *  @param structure Destination structure definition
+     *  @param db File database.
+     *  @return A null pointer in .first if no appropriate converter is available.*/
+    FactoryPair GetBlobToStructureConverter(
+        const Structure& structure,
+        const FileDatabase& db
+        ) const;
 
 
 #ifdef ASSIMP_BUILD_BLENDER_DEBUG
-	// --------------------------------------------------------
-	/** Dump the DNA to a text file. This is for debugging purposes. 
-	 *  The output file is `dna.txt` in the current working folder*/
-	void DumpToFile();
+    // --------------------------------------------------------
+    /** Dump the DNA to a text file. This is for debugging purposes.
+     *  The output file is `dna.txt` in the current working folder*/
+    void DumpToFile();
 #endif
 
-	// --------------------------------------------------------
-	/** Extract array dimensions from a C array declaration, such
-	 *  as `...[4][6]`. Returned string would be `...[][]`.
-	 *  @param out
-	 *  @param array_sizes Receive maximally two array dimensions,
-	 *    the second element is set to 1 if the array is flat.
-	 *    Both are set to 1 if the input is not an array.
-	 *  @throw DeadlyImportError if more than 2 dimensions are
-	 *    encountered. */
-	static void ExtractArraySize(
-		const std::string& out, 
-		size_t array_sizes[2]
-	);
+    // --------------------------------------------------------
+    /** Extract array dimensions from a C array declaration, such
+     *  as `...[4][6]`. Returned string would be `...[][]`.
+     *  @param out
+     *  @param array_sizes Receive maximally two array dimensions,
+     *    the second element is set to 1 if the array is flat.
+     *    Both are set to 1 if the input is not an array.
+     *  @throw DeadlyImportError if more than 2 dimensions are
+     *    encountered. */
+    static void ExtractArraySize(
+        const std::string& out,
+        size_t array_sizes[2]
+    );
 };
 
 // special converters for primitive types
-template <> inline void Structure :: Convert<int>		(int& dest,const FileDatabase& db) const;
-template <> inline void Structure :: Convert<short>		(short& dest,const FileDatabase& db) const;
-template <> inline void Structure :: Convert<char>		(char& dest,const FileDatabase& db) const;
-template <> inline void Structure :: Convert<float>		(float& dest,const FileDatabase& db) const;
-template <> inline void Structure :: Convert<double>	(double& dest,const FileDatabase& db) const;
-template <> inline void Structure :: Convert<Pointer>	(Pointer& dest,const FileDatabase& db) const;
+template <> inline void Structure :: Convert<int>       (int& dest,const FileDatabase& db) const;
+template <> inline void Structure :: Convert<short>     (short& dest,const FileDatabase& db) const;
+template <> inline void Structure :: Convert<char>      (char& dest,const FileDatabase& db) const;
+template <> inline void Structure :: Convert<float>     (float& dest,const FileDatabase& db) const;
+template <> inline void Structure :: Convert<double>    (double& dest,const FileDatabase& db) const;
+template <> inline void Structure :: Convert<Pointer>   (Pointer& dest,const FileDatabase& db) const;
 
 // -------------------------------------------------------------------------------
 /** Describes a master file block header. Each master file sections holds n
  *  elements of a certain SDNA structure (or otherwise unspecified data). */
 // -------------------------------------------------------------------------------
-struct FileBlockHead 
+struct FileBlockHead
 {
-	// points right after the header of the file block
-	StreamReaderAny::pos start;
+    // points right after the header of the file block
+    StreamReaderAny::pos start;
 
-	std::string id;
-	size_t size;
+    std::string id;
+    size_t size;
 
-	// original memory address of the data
-	Pointer address;
+    // original memory address of the data
+    Pointer address;
 
-	// index into DNA
-	unsigned int dna_index;
+    // index into DNA
+    unsigned int dna_index;
 
-	// number of structure instances to follow
-	size_t num;
+    // number of structure instances to follow
+    size_t num;
 
 
 
-	// file blocks are sorted by address to quickly locate specific memory addresses
-	bool operator < (const FileBlockHead& o) const {
-		return address.val < o.address.val;
-	}
+    // file blocks are sorted by address to quickly locate specific memory addresses
+    bool operator < (const FileBlockHead& o) const {
+        return address.val < o.address.val;
+    }
 
-	// for std::upper_bound
-	operator const Pointer& () const {
-		return address;
-	}
+    // for std::upper_bound
+    operator const Pointer& () const {
+        return address;
+    }
 };
 
 // for std::upper_bound
 inline bool operator< (const Pointer& a, const Pointer& b) {
-	return a.val < b.val;
+    return a.val < b.val;
 }
 
 // -------------------------------------------------------------------------------
 /** Utility to read all master file blocks in turn. */
 // -------------------------------------------------------------------------------
-class SectionParser 
+class SectionParser
 {
 public:
 
-	// --------------------------------------------------------
-	/** @param stream Inout stream, must point to the 
-	 *  first section in the file. Call Next() once
-	 *  to have it read. 
-	 *  @param ptr64 Pointer size in file is 64 bits? */
-	SectionParser(StreamReaderAny& stream,bool ptr64)
-		: stream(stream)
-		, ptr64(ptr64)
-	{
-		current.size = current.start = 0;
-	}
+    // --------------------------------------------------------
+    /** @param stream Inout stream, must point to the
+     *  first section in the file. Call Next() once
+     *  to have it read.
+     *  @param ptr64 Pointer size in file is 64 bits? */
+    SectionParser(StreamReaderAny& stream,bool ptr64)
+        : stream(stream)
+        , ptr64(ptr64)
+    {
+        current.size = current.start = 0;
+    }
 
 public:
 
-	// --------------------------------------------------------
-	const FileBlockHead& GetCurrent() const {
-		return current;
-	}
-	
+    // --------------------------------------------------------
+    const FileBlockHead& GetCurrent() const {
+        return current;
+    }
+
 
 public:
 
-	// --------------------------------------------------------
-	/** Advance to the next section. 
-	 *  @throw DeadlyImportError if the last chunk was passed. */
-	void Next();
+    // --------------------------------------------------------
+    /** Advance to the next section.
+     *  @throw DeadlyImportError if the last chunk was passed. */
+    void Next();
 
 public:
 
-	FileBlockHead current;
-	StreamReaderAny& stream;
-	bool ptr64;
+    FileBlockHead current;
+    StreamReaderAny& stream;
+    bool ptr64;
 };
 
 
@@ -597,31 +602,31 @@ class Statistics {
 
 public:
 
-	Statistics () 
-		: fields_read		()
-		, pointers_resolved	()
-		, cache_hits		()
-//		, blocks_read		()
-		, cached_objects	()
-	{}
+    Statistics ()
+        : fields_read       ()
+        , pointers_resolved ()
+        , cache_hits        ()
+//      , blocks_read       ()
+        , cached_objects    ()
+    {}
 
 public:
 
-	/** total number of fields we read */
-	unsigned int fields_read;
+    /** total number of fields we read */
+    unsigned int fields_read;
 
-	/** total number of resolved pointers */
-	unsigned int pointers_resolved;
+    /** total number of resolved pointers */
+    unsigned int pointers_resolved;
 
-	/** number of pointers resolved from the cache */
-	unsigned int cache_hits;
+    /** number of pointers resolved from the cache */
+    unsigned int cache_hits;
 
-	/** number of blocks (from  FileDatabase::entries) 
-	  we did actually read from. */
-	// unsigned int blocks_read;
+    /** number of blocks (from  FileDatabase::entries)
+      we did actually read from. */
+    // unsigned int blocks_read;
 
-	/** objects in FileData::cache */
-	unsigned int cached_objects;
+    /** objects in FileData::cache */
+    unsigned int cached_objects;
 };
 #endif
 
@@ -630,173 +635,173 @@ public:
  *  avoids circular references and avoids object duplication. */
 // -------------------------------------------------------------------------------
 template <template <typename> class TOUT>
-class ObjectCache 
+class ObjectCache
 {
 public:
 
-	typedef std::map< Pointer, TOUT<ElemBase> > StructureCache;
+    typedef std::map< Pointer, TOUT<ElemBase> > StructureCache;
 
 public:
 
-	ObjectCache(const FileDatabase& db)
-		: db(db)
-	{
-		// currently there are only ~400 structure records per blend file.
-		// we read only a small part of them and don't cache objects
-		// which we don't need, so this should suffice.
-		caches.reserve(64);
-	}
+    ObjectCache(const FileDatabase& db)
+        : db(db)
+    {
+        // currently there are only ~400 structure records per blend file.
+        // we read only a small part of them and don't cache objects
+        // which we don't need, so this should suffice.
+        caches.reserve(64);
+    }
 
 public:
 
-	// --------------------------------------------------------
-	/** Check whether a specific item is in the cache.
-	 *  @param s Data type of the item
-	 *  @param out Output pointer. Unchanged if the
-	 *   cache doens't know the item yet.
-	 *  @param ptr Item address to look for. */
-	template <typename T> void get (
-		const Structure& s, 
-		TOUT<T>& out, 
-		const Pointer& ptr) const;
-
-	// --------------------------------------------------------
-	/** Add an item to the cache after the item has 
-	 * been fully read. Do not insert anything that
-	 * may be faulty or might cause the loading
-	 * to abort. 
-	 *  @param s Data type of the item
-	 *  @param out Item to insert into the cache
-	 *  @param ptr address (cache key) of the item. */
-	template <typename T> void set 
-		(const Structure& s, 
-		const TOUT<T>& out, 
-		const Pointer& ptr);
+    // --------------------------------------------------------
+    /** Check whether a specific item is in the cache.
+     *  @param s Data type of the item
+     *  @param out Output pointer. Unchanged if the
+     *   cache doens't know the item yet.
+     *  @param ptr Item address to look for. */
+    template <typename T> void get (
+        const Structure& s,
+        TOUT<T>& out,
+        const Pointer& ptr) const;
+
+    // --------------------------------------------------------
+    /** Add an item to the cache after the item has
+     * been fully read. Do not insert anything that
+     * may be faulty or might cause the loading
+     * to abort.
+     *  @param s Data type of the item
+     *  @param out Item to insert into the cache
+     *  @param ptr address (cache key) of the item. */
+    template <typename T> void set
+        (const Structure& s,
+        const TOUT<T>& out,
+        const Pointer& ptr);
 
 private:
 
-	mutable vector<StructureCache> caches;
-	const FileDatabase& db;
+    mutable vector<StructureCache> caches;
+    const FileDatabase& db;
 };
 
 // -------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------
-template <> class ObjectCache<Blender::vector> 
+template <> class ObjectCache<Blender::vector>
 {
 public:
 
-	ObjectCache(const FileDatabase&) {}
+    ObjectCache(const FileDatabase&) {}
 
-	template <typename T> void get(const Structure&, vector<T>&, const Pointer&) {}
-	template <typename T> void set(const Structure&, const vector<T>&, const Pointer&) {}
+    template <typename T> void get(const Structure&, vector<T>&, const Pointer&) {}
+    template <typename T> void set(const Structure&, const vector<T>&, const Pointer&) {}
 };
 
 #ifdef _MSC_VER
-#	pragma warning(disable:4355)
+#   pragma warning(disable:4355)
 #endif
 
 // -------------------------------------------------------------------------------
 /** Memory representation of a full BLEND file and all its dependencies. The
  *  output aiScene is constructed from an instance of this data structure. */
 // -------------------------------------------------------------------------------
-class FileDatabase 
+class FileDatabase
 {
-	template <template <typename> class TOUT> friend class ObjectCache;
+    template <template <typename> class TOUT> friend class ObjectCache;
 
 public:
 
 
-	FileDatabase()
-		: _cacheArrays(*this)
-		, _cache(*this)
-		, next_cache_idx()
-	{} 
+    FileDatabase()
+        : _cacheArrays(*this)
+        , _cache(*this)
+        , next_cache_idx()
+    {}
 
 public:
 
-	// publicly accessible fields
-	bool i64bit;
-	bool little;
+    // publicly accessible fields
+    bool i64bit;
+    bool little;
 
-	DNA dna;
-	boost::shared_ptr< StreamReaderAny > reader;
-	vector< FileBlockHead > entries;
+    DNA dna;
+    boost::shared_ptr< StreamReaderAny > reader;
+    vector< FileBlockHead > entries;
 
 public:
 
-	Statistics& stats() const {
-		return _stats;
-	}
+    Statistics& stats() const {
+        return _stats;
+    }
 
-	// For all our templates to work on both shared_ptr's and vector's
-	// using the same code, a dummy cache for arrays is provided. Actually,
-	// arrays of objects are never cached because we can't easily 
-	// ensure their proper destruction.
-	template <typename T>
-	ObjectCache<boost::shared_ptr>& cache(boost::shared_ptr<T>& /*in*/) const {
-		return _cache;
-	}
+    // For all our templates to work on both shared_ptr's and vector's
+    // using the same code, a dummy cache for arrays is provided. Actually,
+    // arrays of objects are never cached because we can't easily
+    // ensure their proper destruction.
+    template <typename T>
+    ObjectCache<boost::shared_ptr>& cache(boost::shared_ptr<T>& /*in*/) const {
+        return _cache;
+    }
 
-	template <typename T>
-	ObjectCache<vector>& cache(vector<T>& /*in*/) const {
-		return _cacheArrays;
-	}
+    template <typename T>
+    ObjectCache<vector>& cache(vector<T>& /*in*/) const {
+        return _cacheArrays;
+    }
 
 private:
 
-	
+
 #ifndef ASSIMP_BUILD_BLENDER_NO_STATS
-	mutable Statistics _stats;
+    mutable Statistics _stats;
 #endif
 
-	mutable ObjectCache<vector> _cacheArrays;
-	mutable ObjectCache<boost::shared_ptr> _cache;
+    mutable ObjectCache<vector> _cacheArrays;
+    mutable ObjectCache<boost::shared_ptr> _cache;
 
-	mutable size_t next_cache_idx;
+    mutable size_t next_cache_idx;
 };
 
 #ifdef _MSC_VER
-#	pragma warning(default:4355)
+#   pragma warning(default:4355)
 #endif
 
 // -------------------------------------------------------------------------------
 /** Factory to extract a #DNA from the DNA1 file block in a BLEND file. */
 // -------------------------------------------------------------------------------
-class DNAParser 
+class DNAParser
 {
 
 public:
 
-	/** Bind the parser to a empty DNA and an input stream */
-	DNAParser(FileDatabase& db)
-		: db(db)
-	{}
+    /** Bind the parser to a empty DNA and an input stream */
+    DNAParser(FileDatabase& db)
+        : db(db)
+    {}
 
 public:
 
-	// --------------------------------------------------------
-	/** Locate the DNA in the file and parse it. The input
-	 *  stream is expected to point to the beginning of the DN1
-	 *  chunk at the time this method is called and is
-	 *  undefined afterwards.
-	 *  @throw DeadlyImportError if the DNA cannot be read.
-	 *  @note The position of the stream pointer is undefined
-	 *    afterwards.*/
-	void Parse ();
+    // --------------------------------------------------------
+    /** Locate the DNA in the file and parse it. The input
+     *  stream is expected to point to the beginning of the DN1
+     *  chunk at the time this method is called and is
+     *  undefined afterwards.
+     *  @throw DeadlyImportError if the DNA cannot be read.
+     *  @note The position of the stream pointer is undefined
+     *    afterwards.*/
+    void Parse ();
 
 public:
 
-	/** Obtain a reference to the extracted DNA information */
-	const Blender::DNA& GetDNA() const {
-		return db.dna;
-	}
+    /** Obtain a reference to the extracted DNA information */
+    const Blender::DNA& GetDNA() const {
+        return db.dna;
+    }
 
 private:
 
-	FileDatabase& db;
+    FileDatabase& db;
 };
 
-	} // end Blend
+    } // end Blend
 } // end Assimp
 
 #include "BlenderDNA.inl"

+ 488 - 486
assimplib.mod/assimp/code/BlenderDNA.inl

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, assimp team
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms, 
@@ -45,91 +45,93 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef INCLUDED_AI_BLEND_DNA_INL
 #define INCLUDED_AI_BLEND_DNA_INL
 
-namespace Assimp	{
-	namespace Blender {
+#include <boost/shared_ptr.hpp>
+
+namespace Assimp {
+    namespace Blender {
 
 //--------------------------------------------------------------------------------
 const Field& Structure :: operator [] (const std::string& ss) const
 {
-	std::map<std::string, size_t>::const_iterator it = indices.find(ss);
-	if (it == indices.end()) {
-		throw Error((Formatter::format(),
-			"BlendDNA: Did not find a field named `",ss,"` in structure `",name,"`"
-			));
-	}
-
-	return fields[(*it).second];
+    std::map<std::string, size_t>::const_iterator it = indices.find(ss);
+    if (it == indices.end()) {
+        throw Error((Formatter::format(),
+            "BlendDNA: Did not find a field named `",ss,"` in structure `",name,"`"
+            ));
+    }
+
+    return fields[(*it).second];
 }
 
 //--------------------------------------------------------------------------------
 const Field* Structure :: Get (const std::string& ss) const
 {
-	std::map<std::string, size_t>::const_iterator it = indices.find(ss);
-	return it == indices.end() ? NULL : &fields[(*it).second];
+    std::map<std::string, size_t>::const_iterator it = indices.find(ss);
+    return it == indices.end() ? NULL : &fields[(*it).second];
 }
 
 //--------------------------------------------------------------------------------
 const Field& Structure :: operator [] (const size_t i) const 
 {
-	if (i >= fields.size()) {
-		throw Error((Formatter::format(),
-			"BlendDNA: There is no field with index `",i,"` in structure `",name,"`"
-			));
-	}
+    if (i >= fields.size()) {
+        throw Error((Formatter::format(),
+            "BlendDNA: There is no field with index `",i,"` in structure `",name,"`"
+            ));
+    }
 
-	return fields[i];
+    return fields[i];
 }
 
 //--------------------------------------------------------------------------------
 template <typename T> boost::shared_ptr<ElemBase> Structure :: Allocate() const 
 {
-	return boost::shared_ptr<T>(new T()); 
+    return boost::shared_ptr<T>(new T()); 
 }
 
 //--------------------------------------------------------------------------------
 template <typename T> void Structure :: Convert(
-	boost::shared_ptr<ElemBase> in,
-	const FileDatabase& db) const 
+    boost::shared_ptr<ElemBase> in,
+    const FileDatabase& db) const 
 {
-	Convert<T> (*static_cast<T*> ( in.get() ),db);
+    Convert<T> (*static_cast<T*> ( in.get() ),db);
 }
 
 //--------------------------------------------------------------------------------
 template <int error_policy, typename T, size_t M>
 void Structure :: ReadFieldArray(T (& out)[M], const char* name, const FileDatabase& db) const
 {
-	const StreamReaderAny::pos old = db.reader->GetCurrentPos();
-	try {
-		const Field& f = (*this)[name];
-		const Structure& s = db.dna[f.type];
-
-		// is the input actually an array?
-		if (!(f.flags & FieldFlag_Array)) {
-			throw Error((Formatter::format(),"Field `",name,"` of structure `",
-				this->name,"` ought to be an array of size ",M
-				));
-		}
-
-		db.reader->IncPtr(f.offset);
-
-		// size conversions are always allowed, regardless of error_policy
-		unsigned int i = 0;
-		for(; i < std::min(f.array_sizes[0],M); ++i) {
-			s.Convert(out[i],db);
-		}
-		for(; i < M; ++i) {
-			_defaultInitializer<ErrorPolicy_Igno>()(out[i]);
-		}
-	}
-	catch (const Error& e) {
-		_defaultInitializer<error_policy>()(out,e.what());
-	}
-
-	// and recover the previous stream position
-	db.reader->SetCurrentPos(old);
+    const StreamReaderAny::pos old = db.reader->GetCurrentPos();
+    try {
+        const Field& f = (*this)[name];
+        const Structure& s = db.dna[f.type];
+
+        // is the input actually an array?
+        if (!(f.flags & FieldFlag_Array)) {
+            throw Error((Formatter::format(),"Field `",name,"` of structure `",
+                this->name,"` ought to be an array of size ",M
+                ));
+        }
+
+        db.reader->IncPtr(f.offset);
+
+        // size conversions are always allowed, regardless of error_policy
+        unsigned int i = 0;
+        for(; i < std::min(f.array_sizes[0],M); ++i) {
+            s.Convert(out[i],db);
+        }
+        for(; i < M; ++i) {
+            _defaultInitializer<ErrorPolicy_Igno>()(out[i]);
+        }
+    }
+    catch (const Error& e) {
+        _defaultInitializer<error_policy>()(out,e.what());
+    }
+
+    // and recover the previous stream position
+    db.reader->SetCurrentPos(old);
 
 #ifndef ASSIMP_BUILD_BLENDER_NO_STATS
-	++db.stats().fields_read;
+    ++db.stats().fields_read;
 #endif
 }
 
@@ -137,167 +139,167 @@ void Structure :: ReadFieldArray(T (& out)[M], const char* name, const FileDatab
 template <int error_policy, typename T, size_t M, size_t N>
 void Structure :: ReadFieldArray2(T (& out)[M][N], const char* name, const FileDatabase& db) const
 {
-	const StreamReaderAny::pos old = db.reader->GetCurrentPos();
-	try {
-		const Field& f = (*this)[name];
-		const Structure& s = db.dna[f.type];
-
-		// is the input actually an array?
-		if (!(f.flags & FieldFlag_Array)) {
-			throw Error((Formatter::format(),"Field `",name,"` of structure `",
-				this->name,"` ought to be an array of size ",M,"*",N
-				));
-		}
-
-		db.reader->IncPtr(f.offset);
-
-		// size conversions are always allowed, regardless of error_policy
-		unsigned int i = 0;
-		for(; i < std::min(f.array_sizes[0],M); ++i) {
-			unsigned int j = 0;
-			for(; j < std::min(f.array_sizes[1],N); ++j) {
-				s.Convert(out[i][j],db);
-			}
-			for(; j < N; ++j) {
-				_defaultInitializer<ErrorPolicy_Igno>()(out[i][j]);
-			}
-		}
-		for(; i < M; ++i) {
-			_defaultInitializer<ErrorPolicy_Igno>()(out[i]);
-		}
-	}
-	catch (const Error& e) {
-		_defaultInitializer<error_policy>()(out,e.what());
-	}
-
-	// and recover the previous stream position
-	db.reader->SetCurrentPos(old);
+    const StreamReaderAny::pos old = db.reader->GetCurrentPos();
+    try {
+        const Field& f = (*this)[name];
+        const Structure& s = db.dna[f.type];
+
+        // is the input actually an array?
+        if (!(f.flags & FieldFlag_Array)) {
+            throw Error((Formatter::format(),"Field `",name,"` of structure `",
+                this->name,"` ought to be an array of size ",M,"*",N
+                ));
+        }
+
+        db.reader->IncPtr(f.offset);
+
+        // size conversions are always allowed, regardless of error_policy
+        unsigned int i = 0;
+        for(; i < std::min(f.array_sizes[0],M); ++i) {
+            unsigned int j = 0;
+            for(; j < std::min(f.array_sizes[1],N); ++j) {
+                s.Convert(out[i][j],db);
+            }
+            for(; j < N; ++j) {
+                _defaultInitializer<ErrorPolicy_Igno>()(out[i][j]);
+            }
+        }
+        for(; i < M; ++i) {
+            _defaultInitializer<ErrorPolicy_Igno>()(out[i]);
+        }
+    }
+    catch (const Error& e) {
+        _defaultInitializer<error_policy>()(out,e.what());
+    }
+
+    // and recover the previous stream position
+    db.reader->SetCurrentPos(old);
 
 #ifndef ASSIMP_BUILD_BLENDER_NO_STATS
-	++db.stats().fields_read;
+    ++db.stats().fields_read;
 #endif
 }
 
 //--------------------------------------------------------------------------------
 template <int error_policy, template <typename> class TOUT, typename T>
 bool Structure :: ReadFieldPtr(TOUT<T>& out, const char* name, const FileDatabase& db,
-	bool non_recursive /*= false*/) const
+    bool non_recursive /*= false*/) const
 {
-	const StreamReaderAny::pos old = db.reader->GetCurrentPos();
-	Pointer ptrval;
-	const Field* f;
-	try {
-		f = &(*this)[name];
-
-		// sanity check, should never happen if the genblenddna script is right
-		if (!(f->flags & FieldFlag_Pointer)) {
-			throw Error((Formatter::format(),"Field `",name,"` of structure `",
-				this->name,"` ought to be a pointer"));
-		}
-
-		db.reader->IncPtr(f->offset);
-		Convert(ptrval,db);
-		// actually it is meaningless on which Structure the Convert is called
-		// because the `Pointer` argument triggers a special implementation.
-	}
-	catch (const Error& e) {
-		_defaultInitializer<error_policy>()(out,e.what());
-
-		out.reset();
-		return false;
-	}
-
-	// resolve the pointer and load the corresponding structure
-	const bool res = ResolvePointer(out,ptrval,db,*f, non_recursive);
-
-	if(!non_recursive) {
-		// and recover the previous stream position
-		db.reader->SetCurrentPos(old);
-	}
+    const StreamReaderAny::pos old = db.reader->GetCurrentPos();
+    Pointer ptrval;
+    const Field* f;
+    try {
+        f = &(*this)[name];
+
+        // sanity check, should never happen if the genblenddna script is right
+        if (!(f->flags & FieldFlag_Pointer)) {
+            throw Error((Formatter::format(),"Field `",name,"` of structure `",
+                this->name,"` ought to be a pointer"));
+        }
+
+        db.reader->IncPtr(f->offset);
+        Convert(ptrval,db);
+        // actually it is meaningless on which Structure the Convert is called
+        // because the `Pointer` argument triggers a special implementation.
+    }
+    catch (const Error& e) {
+        _defaultInitializer<error_policy>()(out,e.what());
+
+        out.reset();
+        return false;
+    }
+
+    // resolve the pointer and load the corresponding structure
+    const bool res = ResolvePointer(out,ptrval,db,*f, non_recursive);
+
+    if(!non_recursive) {
+        // and recover the previous stream position
+        db.reader->SetCurrentPos(old);
+    }
 
 #ifndef ASSIMP_BUILD_BLENDER_NO_STATS
-	++db.stats().fields_read;
+    ++db.stats().fields_read;
 #endif
 
-	return res;
+    return res;
 }
 
 //--------------------------------------------------------------------------------
 template <int error_policy, template <typename> class TOUT, typename T, size_t N>
 bool Structure :: ReadFieldPtr(TOUT<T> (&out)[N], const char* name, 
-	const FileDatabase& db) const
+    const FileDatabase& db) const
 {
-	// XXX see if we can reduce this to call to the 'normal' ReadFieldPtr
-	const StreamReaderAny::pos old = db.reader->GetCurrentPos();
-	Pointer ptrval[N];
-	const Field* f;
-	try {
-		f = &(*this)[name];
-
-		// sanity check, should never happen if the genblenddna script is right
-		if ((FieldFlag_Pointer|FieldFlag_Pointer) != (f->flags & (FieldFlag_Pointer|FieldFlag_Pointer))) {
-			throw Error((Formatter::format(),"Field `",name,"` of structure `",
-				this->name,"` ought to be a pointer AND an array"));
-		}
-
-		db.reader->IncPtr(f->offset);
-
-		size_t i = 0;
-		for(; i < std::min(f->array_sizes[0],N); ++i) {
-			Convert(ptrval[i],db);
-		}
-		for(; i < N; ++i) {
-			_defaultInitializer<ErrorPolicy_Igno>()(ptrval[i]);
-		}
-
-		// actually it is meaningless on which Structure the Convert is called
-		// because the `Pointer` argument triggers a special implementation.
-	}
-	catch (const Error& e) {
-		_defaultInitializer<error_policy>()(out,e.what());
-		for(size_t i = 0; i < N; ++i) {
-			out[i].reset();
-		}
-		return false;
-	}
-
-	bool res = true;
-	for(size_t i = 0; i < N; ++i) {
-		// resolve the pointer and load the corresponding structure
-		res = ResolvePointer(out[i],ptrval[i],db,*f) && res;
-	}
-
-	// and recover the previous stream position
-	db.reader->SetCurrentPos(old);
+    // XXX see if we can reduce this to call to the 'normal' ReadFieldPtr
+    const StreamReaderAny::pos old = db.reader->GetCurrentPos();
+    Pointer ptrval[N];
+    const Field* f;
+    try {
+        f = &(*this)[name];
+
+        // sanity check, should never happen if the genblenddna script is right
+        if ((FieldFlag_Pointer|FieldFlag_Pointer) != (f->flags & (FieldFlag_Pointer|FieldFlag_Pointer))) {
+            throw Error((Formatter::format(),"Field `",name,"` of structure `",
+                this->name,"` ought to be a pointer AND an array"));
+        }
+
+        db.reader->IncPtr(f->offset);
+
+        size_t i = 0;
+        for(; i < std::min(f->array_sizes[0],N); ++i) {
+            Convert(ptrval[i],db);
+        }
+        for(; i < N; ++i) {
+            _defaultInitializer<ErrorPolicy_Igno>()(ptrval[i]);
+        }
+
+        // actually it is meaningless on which Structure the Convert is called
+        // because the `Pointer` argument triggers a special implementation.
+    }
+    catch (const Error& e) {
+        _defaultInitializer<error_policy>()(out,e.what());
+        for(size_t i = 0; i < N; ++i) {
+            out[i].reset();
+        }
+        return false;
+    }
+
+    bool res = true;
+    for(size_t i = 0; i < N; ++i) {
+        // resolve the pointer and load the corresponding structure
+        res = ResolvePointer(out[i],ptrval[i],db,*f) && res;
+    }
+
+    // and recover the previous stream position
+    db.reader->SetCurrentPos(old);
 
 #ifndef ASSIMP_BUILD_BLENDER_NO_STATS
-	++db.stats().fields_read;
+    ++db.stats().fields_read;
 #endif
-	return res;
+    return res;
 }
 
 //--------------------------------------------------------------------------------
 template <int error_policy, typename T>
 void Structure :: ReadField(T& out, const char* name, const FileDatabase& db) const
 {
-	const StreamReaderAny::pos old = db.reader->GetCurrentPos();
-	try {
-		const Field& f = (*this)[name];
-		// find the structure definition pertaining to this field
-		const Structure& s = db.dna[f.type];
-
-		db.reader->IncPtr(f.offset);
-		s.Convert(out,db);
-	}
-	catch (const Error& e) {
-		_defaultInitializer<error_policy>()(out,e.what());
-	}
-
-	// and recover the previous stream position
-	db.reader->SetCurrentPos(old);
+    const StreamReaderAny::pos old = db.reader->GetCurrentPos();
+    try {
+        const Field& f = (*this)[name];
+        // find the structure definition pertaining to this field
+        const Structure& s = db.dna[f.type];
+
+        db.reader->IncPtr(f.offset);
+        s.Convert(out,db);
+    }
+    catch (const Error& e) {
+        _defaultInitializer<error_policy>()(out,e.what());
+    }
+
+    // and recover the previous stream position
+    db.reader->SetCurrentPos(old);
 
 #ifndef ASSIMP_BUILD_BLENDER_NO_STATS
-	++db.stats().fields_read;
+    ++db.stats().fields_read;
 #endif
 }
 
@@ -305,221 +307,221 @@ void Structure :: ReadField(T& out, const char* name, const FileDatabase& db) co
 //--------------------------------------------------------------------------------
 template <template <typename> class TOUT, typename T>
 bool Structure :: ResolvePointer(TOUT<T>& out, const Pointer & ptrval, const FileDatabase& db, 
-	const Field& f, 
-	bool non_recursive /*= false*/) const 
+    const Field& f, 
+    bool non_recursive /*= false*/) const 
 {
-	out.reset(); // ensure null pointers work
-	if (!ptrval.val) { 
-		return false;
-	}
-	const Structure& s = db.dna[f.type];
-	// find the file block the pointer is pointing to
-	const FileBlockHead* block = LocateFileBlockForAddress(ptrval,db);
-
-	// also determine the target type from the block header
-	// and check if it matches the type which we expect.
-	const Structure& ss = db.dna[block->dna_index];
-	if (ss != s) {
-		throw Error((Formatter::format(),"Expected target to be of type `",s.name,
-			"` but seemingly it is a `",ss.name,"` instead"
-			));
-	}
-
-	// try to retrieve the object from the cache
-	db.cache(out).get(s,out,ptrval); 
-	if (out) {
-		return true;
-	}
-
-	// seek to this location, but save the previous stream pointer.
-	const StreamReaderAny::pos pold = db.reader->GetCurrentPos();
-	db.reader->SetCurrentPos(block->start+ static_cast<size_t>((ptrval.val - block->address.val) ));
-	// FIXME: basically, this could cause problems with 64 bit pointers on 32 bit systems.
-	// I really ought to improve StreamReader to work with 64 bit indices exclusively.
-
-	// continue conversion after allocating the required storage
-	size_t num = block->size / ss.size; 
-	T* o = _allocate(out,num);
-
-	// cache the object before we convert it to avoid cyclic recursion.
-	db.cache(out).set(s,out,ptrval); 
-
-	// if the non_recursive flag is set, we don't do anything but leave
-	// the cursor at the correct position to resolve the object.
-	if (!non_recursive) {
-		for (size_t i = 0; i < num; ++i,++o) {
-			s.Convert(*o,db);
-		}
-
-		db.reader->SetCurrentPos(pold);
-	}
+    out.reset(); // ensure null pointers work
+    if (!ptrval.val) { 
+        return false;
+    }
+    const Structure& s = db.dna[f.type];
+    // find the file block the pointer is pointing to
+    const FileBlockHead* block = LocateFileBlockForAddress(ptrval,db);
+
+    // also determine the target type from the block header
+    // and check if it matches the type which we expect.
+    const Structure& ss = db.dna[block->dna_index];
+    if (ss != s) {
+        throw Error((Formatter::format(),"Expected target to be of type `",s.name,
+            "` but seemingly it is a `",ss.name,"` instead"
+            ));
+    }
+
+    // try to retrieve the object from the cache
+    db.cache(out).get(s,out,ptrval); 
+    if (out) {
+        return true;
+    }
+
+    // seek to this location, but save the previous stream pointer.
+    const StreamReaderAny::pos pold = db.reader->GetCurrentPos();
+    db.reader->SetCurrentPos(block->start+ static_cast<size_t>((ptrval.val - block->address.val) ));
+    // FIXME: basically, this could cause problems with 64 bit pointers on 32 bit systems.
+    // I really ought to improve StreamReader to work with 64 bit indices exclusively.
+
+    // continue conversion after allocating the required storage
+    size_t num = block->size / ss.size; 
+    T* o = _allocate(out,num);
+
+    // cache the object before we convert it to avoid cyclic recursion.
+    db.cache(out).set(s,out,ptrval); 
+
+    // if the non_recursive flag is set, we don't do anything but leave
+    // the cursor at the correct position to resolve the object.
+    if (!non_recursive) {
+        for (size_t i = 0; i < num; ++i,++o) {
+            s.Convert(*o,db);
+        }
+
+        db.reader->SetCurrentPos(pold);
+    }
 
 #ifndef ASSIMP_BUILD_BLENDER_NO_STATS
-	if(out) {
-		++db.stats().pointers_resolved;
-	}
+    if(out) {
+        ++db.stats().pointers_resolved;
+    }
 #endif
-	return false;
+    return false;
 }
 
 
 //--------------------------------------------------------------------------------
 inline bool Structure :: ResolvePointer( boost::shared_ptr< FileOffset >& out, const Pointer & ptrval, 
-	const FileDatabase& db, 
-	const Field&,
-	bool) const
+    const FileDatabase& db, 
+    const Field&,
+    bool) const
 {
-	// Currently used exclusively by PackedFile::data to represent
-	// a simple offset into the mapped BLEND file. 
-	out.reset();
-	if (!ptrval.val) { 
-		return false;
-	}
-
-	// find the file block the pointer is pointing to
-	const FileBlockHead* block = LocateFileBlockForAddress(ptrval,db);
-
-	out =  boost::shared_ptr< FileOffset > (new FileOffset());
-	out->val = block->start+ static_cast<size_t>((ptrval.val - block->address.val) );
-	return false;
+    // Currently used exclusively by PackedFile::data to represent
+    // a simple offset into the mapped BLEND file. 
+    out.reset();
+    if (!ptrval.val) { 
+        return false;
+    }
+
+    // find the file block the pointer is pointing to
+    const FileBlockHead* block = LocateFileBlockForAddress(ptrval,db);
+
+    out =  boost::shared_ptr< FileOffset > (new FileOffset());
+    out->val = block->start+ static_cast<size_t>((ptrval.val - block->address.val) );
+    return false;
 }
 
 //--------------------------------------------------------------------------------
 template <template <typename> class TOUT, typename T>
 bool Structure :: ResolvePointer(vector< TOUT<T> >& out, const Pointer & ptrval, 
-	const FileDatabase& db, 
-	const Field& f,
-	bool) const 
+    const FileDatabase& db, 
+    const Field& f,
+    bool) const 
 {
-	// This is a function overload, not a template specialization. According to
-	// the partial ordering rules, it should be selected by the compiler
-	// for array-of-pointer inputs, i.e. Object::mats.
-
-	out.reset();
-	if (!ptrval.val) { 
-		return false;
-	}
-
-	// find the file block the pointer is pointing to
-	const FileBlockHead* block = LocateFileBlockForAddress(ptrval,db);
-	const size_t num = block->size / (db.i64bit?8:4); 
-
-	// keep the old stream position
-	const StreamReaderAny::pos pold = db.reader->GetCurrentPos();
-	db.reader->SetCurrentPos(block->start+ static_cast<size_t>((ptrval.val - block->address.val) ));
-
-	bool res = false;
-	// allocate raw storage for the array
-	out.resize(num);
-	for (size_t i = 0; i< num; ++i) {
-		Pointer val;
-		Convert(val,db);
-
-		// and resolve the pointees
-		res = ResolvePointer(out[i],val,db,f) && res; 
-	}
-
-	db.reader->SetCurrentPos(pold);
-	return res;
+    // This is a function overload, not a template specialization. According to
+    // the partial ordering rules, it should be selected by the compiler
+    // for array-of-pointer inputs, i.e. Object::mats.
+
+    out.reset();
+    if (!ptrval.val) { 
+        return false;
+    }
+
+    // find the file block the pointer is pointing to
+    const FileBlockHead* block = LocateFileBlockForAddress(ptrval,db);
+    const size_t num = block->size / (db.i64bit?8:4); 
+
+    // keep the old stream position
+    const StreamReaderAny::pos pold = db.reader->GetCurrentPos();
+    db.reader->SetCurrentPos(block->start+ static_cast<size_t>((ptrval.val - block->address.val) ));
+
+    bool res = false;
+    // allocate raw storage for the array
+    out.resize(num);
+    for (size_t i = 0; i< num; ++i) {
+        Pointer val;
+        Convert(val,db);
+
+        // and resolve the pointees
+        res = ResolvePointer(out[i],val,db,f) && res; 
+    }
+
+    db.reader->SetCurrentPos(pold);
+    return res;
 }
 
 //--------------------------------------------------------------------------------
 template <> bool Structure :: ResolvePointer<boost::shared_ptr,ElemBase>(boost::shared_ptr<ElemBase>& out, 
-	const Pointer & ptrval, 
-	const FileDatabase& db, 
-	const Field&,
-	bool
+    const Pointer & ptrval, 
+    const FileDatabase& db, 
+    const Field&,
+    bool
 ) const 
 {
-	// Special case when the data type needs to be determined at runtime.
-	// Less secure than in the `strongly-typed` case.
-
-	out.reset();
-	if (!ptrval.val) { 
-		return false;
-	}
-
-	// find the file block the pointer is pointing to
-	const FileBlockHead* block = LocateFileBlockForAddress(ptrval,db);
-
-	// determine the target type from the block header
-	const Structure& s = db.dna[block->dna_index];
-
-	// try to retrieve the object from the cache
-	db.cache(out).get(s,out,ptrval); 
-	if (out) {
-		return true;
-	}
-
-	// seek to this location, but save the previous stream pointer.
-	const StreamReaderAny::pos pold = db.reader->GetCurrentPos();
-	db.reader->SetCurrentPos(block->start+ static_cast<size_t>((ptrval.val - block->address.val) ));
-	// FIXME: basically, this could cause problems with 64 bit pointers on 32 bit systems.
-	// I really ought to improve StreamReader to work with 64 bit indices exclusively.
-
-	// continue conversion after allocating the required storage
-	DNA::FactoryPair builders = db.dna.GetBlobToStructureConverter(s,db);
-	if (!builders.first) {
-		// this might happen if DNA::RegisterConverters hasn't been called so far
-		// or if the target type is not contained in `our` DNA.
-		out.reset();
-		DefaultLogger::get()->warn((Formatter::format(),
-			"Failed to find a converter for the `",s.name,"` structure"
-			));
-		return false;
-	}
-
-	// allocate the object hull
-	out = (s.*builders.first)();
-	
-	// cache the object immediately to prevent infinite recursion in a 
-	// circular list with a single element (i.e. a self-referencing element).
-	db.cache(out).set(s,out,ptrval);
-
-	// and do the actual conversion
-	(s.*builders.second)(out,db);
-	db.reader->SetCurrentPos(pold);
-	
-	// store a pointer to the name string of the actual type
-	// in the object itself. This allows the conversion code
-	// to perform additional type checking.
-	out->dna_type = s.name.c_str();
+    // Special case when the data type needs to be determined at runtime.
+    // Less secure than in the `strongly-typed` case.
+
+    out.reset();
+    if (!ptrval.val) { 
+        return false;
+    }
+
+    // find the file block the pointer is pointing to
+    const FileBlockHead* block = LocateFileBlockForAddress(ptrval,db);
+
+    // determine the target type from the block header
+    const Structure& s = db.dna[block->dna_index];
+
+    // try to retrieve the object from the cache
+    db.cache(out).get(s,out,ptrval); 
+    if (out) {
+        return true;
+    }
+
+    // seek to this location, but save the previous stream pointer.
+    const StreamReaderAny::pos pold = db.reader->GetCurrentPos();
+    db.reader->SetCurrentPos(block->start+ static_cast<size_t>((ptrval.val - block->address.val) ));
+    // FIXME: basically, this could cause problems with 64 bit pointers on 32 bit systems.
+    // I really ought to improve StreamReader to work with 64 bit indices exclusively.
+
+    // continue conversion after allocating the required storage
+    DNA::FactoryPair builders = db.dna.GetBlobToStructureConverter(s,db);
+    if (!builders.first) {
+        // this might happen if DNA::RegisterConverters hasn't been called so far
+        // or if the target type is not contained in `our` DNA.
+        out.reset();
+        DefaultLogger::get()->warn((Formatter::format(),
+            "Failed to find a converter for the `",s.name,"` structure"
+            ));
+        return false;
+    }
+
+    // allocate the object hull
+    out = (s.*builders.first)();
+    
+    // cache the object immediately to prevent infinite recursion in a 
+    // circular list with a single element (i.e. a self-referencing element).
+    db.cache(out).set(s,out,ptrval);
+
+    // and do the actual conversion
+    (s.*builders.second)(out,db);
+    db.reader->SetCurrentPos(pold);
+    
+    // store a pointer to the name string of the actual type
+    // in the object itself. This allows the conversion code
+    // to perform additional type checking.
+    out->dna_type = s.name.c_str();
 
 
 #ifndef ASSIMP_BUILD_BLENDER_NO_STATS
-	++db.stats().pointers_resolved;
+    ++db.stats().pointers_resolved;
 #endif
-	return false;
+    return false;
 }
 
 //--------------------------------------------------------------------------------
 const FileBlockHead* Structure :: LocateFileBlockForAddress(const Pointer & ptrval, const FileDatabase& db) const 
 {
-	// the file blocks appear in list sorted by
-	// with ascending base addresses so we can run a 
-	// binary search to locate the pointee quickly.
-
-	// NOTE: Blender seems to distinguish between side-by-side
-	// data (stored in the same data block) and far pointers,
-	// which are only used for structures starting with an ID.
-	// We don't need to make this distinction, our algorithm
-	// works regardless where the data is stored.
-	vector<FileBlockHead>::const_iterator it = std::lower_bound(db.entries.begin(),db.entries.end(),ptrval);
-	if (it == db.entries.end()) {
-		// this is crucial, pointers may not be invalid.
-		// this is either a corrupted file or an attempted attack.
-		throw DeadlyImportError((Formatter::format(),"Failure resolving pointer 0x",
-			std::hex,ptrval.val,", no file block falls into this address range"
-			));
-	}
-	if (ptrval.val >= (*it).address.val + (*it).size) {
-		throw DeadlyImportError((Formatter::format(),"Failure resolving pointer 0x",
-			std::hex,ptrval.val,", nearest file block starting at 0x",
-			(*it).address.val," ends at 0x",
-			(*it).address.val + (*it).size
-			));
-	}
-	return &*it;
+    // the file blocks appear in list sorted by
+    // with ascending base addresses so we can run a 
+    // binary search to locate the pointee quickly.
+
+    // NOTE: Blender seems to distinguish between side-by-side
+    // data (stored in the same data block) and far pointers,
+    // which are only used for structures starting with an ID.
+    // We don't need to make this distinction, our algorithm
+    // works regardless where the data is stored.
+    vector<FileBlockHead>::const_iterator it = std::lower_bound(db.entries.begin(),db.entries.end(),ptrval);
+    if (it == db.entries.end()) {
+        // this is crucial, pointers may not be invalid.
+        // this is either a corrupted file or an attempted attack.
+        throw DeadlyImportError((Formatter::format(),"Failure resolving pointer 0x",
+            std::hex,ptrval.val,", no file block falls into this address range"
+            ));
+    }
+    if (ptrval.val >= (*it).address.val + (*it).size) {
+        throw DeadlyImportError((Formatter::format(),"Failure resolving pointer 0x",
+            std::hex,ptrval.val,", nearest file block starting at 0x",
+            (*it).address.val," ends at 0x",
+            (*it).address.val + (*it).size
+            ));
+    }
+    return &*it;
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -532,199 +534,199 @@ template <> struct signless<short> {typedef unsigned short type;};
 template <> struct signless<int> {typedef unsigned int type;};
 
 template <typename T>
-struct static_cast_silent {	
-	template <typename V>
-	T operator()(V in) {
-		return static_cast<T>(in & static_cast<typename signless<T>::type>(-1));
-	}
+struct static_cast_silent { 
+    template <typename V>
+    T operator()(V in) {
+        return static_cast<T>(in & static_cast<typename signless<T>::type>(-1));
+    }
 };
 
 template <> struct static_cast_silent<float> {
-	template <typename V> float  operator()(V in) {
-		return static_cast<float> (in);
-	}
+    template <typename V> float  operator()(V in) {
+        return static_cast<float> (in);
+    }
 };
 
 template <> struct static_cast_silent<double> {
-	template <typename V> double operator()(V in) {
-		return static_cast<double>(in);
-	}
+    template <typename V> double operator()(V in) {
+        return static_cast<double>(in);
+    }
 };
 
 // ------------------------------------------------------------------------------------------------
 template <typename T> inline void ConvertDispatcher(T& out, const Structure& in,const FileDatabase& db) 
 {
-	if (in.name == "int") {
-		out = static_cast_silent<T>()(db.reader->GetU4());
-	}
-	else if (in.name == "short") {
-		out = static_cast_silent<T>()(db.reader->GetU2());
-	}
-	else if (in.name == "char") {
-		out = static_cast_silent<T>()(db.reader->GetU1());
-	}
-	else if (in.name == "float") {
-		out = static_cast<T>(db.reader->GetF4());
-	}
-	else if (in.name == "double") {
-		out = static_cast<T>(db.reader->GetF8());
-	}
-	else {
-		throw DeadlyImportError("Unknown source for conversion to primitive data type: "+in.name);
-	}
+    if (in.name == "int") {
+        out = static_cast_silent<T>()(db.reader->GetU4());
+    }
+    else if (in.name == "short") {
+        out = static_cast_silent<T>()(db.reader->GetU2());
+    }
+    else if (in.name == "char") {
+        out = static_cast_silent<T>()(db.reader->GetU1());
+    }
+    else if (in.name == "float") {
+        out = static_cast<T>(db.reader->GetF4());
+    }
+    else if (in.name == "double") {
+        out = static_cast<T>(db.reader->GetF8());
+    }
+    else {
+        throw DeadlyImportError("Unknown source for conversion to primitive data type: "+in.name);
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 template <> inline void Structure :: Convert<int>    (int& dest,const FileDatabase& db) const
 {
-	ConvertDispatcher(dest,*this,db);
+    ConvertDispatcher(dest,*this,db);
 }
 
 // ------------------------------------------------------------------------------------------------
 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);
-		//db.reader->IncPtr(-4);
-		return;
-	}
-	else if (name == "double") {
-		dest = static_cast<short>(db.reader->GetF8() * 32767.);
-		//db.reader->IncPtr(-8);
-		return;
-	}
-	ConvertDispatcher(dest,*this,db);
+    // 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);
+        //db.reader->IncPtr(-4);
+        return;
+    }
+    else if (name == "double") {
+        dest = static_cast<short>(db.reader->GetF8() * 32767.);
+        //db.reader->IncPtr(-8);
+        return;
+    }
+    ConvertDispatcher(dest,*this,db);
 }
 
 // ------------------------------------------------------------------------------------------------
 template <> inline void Structure :: Convert<char>   (char& dest,const FileDatabase& db) const
 {
-	// automatic rescaling from char to float and vice versa (seems useful for RGB colors)
-	if (name == "float") {
-		dest = static_cast<char>(db.reader->GetF4() * 255.f);
-		return;
-	}
-	else if (name == "double") {
-		dest = static_cast<char>(db.reader->GetF8() * 255.f);
-		return;
-	}
-	ConvertDispatcher(dest,*this,db);
+    // automatic rescaling from char to float and vice versa (seems useful for RGB colors)
+    if (name == "float") {
+        dest = static_cast<char>(db.reader->GetF4() * 255.f);
+        return;
+    }
+    else if (name == "double") {
+        dest = static_cast<char>(db.reader->GetF8() * 255.f);
+        return;
+    }
+    ConvertDispatcher(dest,*this,db);
 }
 
 // ------------------------------------------------------------------------------------------------
 template <> inline void Structure :: Convert<float>  (float& dest,const FileDatabase& db) const
 {
-	// automatic rescaling from char to float and vice versa (seems useful for RGB colors)
-	if (name == "char") {
-		dest = db.reader->GetI1() / 255.f;
-		return;
-	}
-	// automatic rescaling from short to float and vice versa (used by normals)
-	else if (name == "short") {
-		dest = db.reader->GetI2() / 32767.f;
-		return;
-	}
-	ConvertDispatcher(dest,*this,db);
+    // automatic rescaling from char to float and vice versa (seems useful for RGB colors)
+    if (name == "char") {
+        dest = db.reader->GetI1() / 255.f;
+        return;
+    }
+    // automatic rescaling from short to float and vice versa (used by normals)
+    else if (name == "short") {
+        dest = db.reader->GetI2() / 32767.f;
+        return;
+    }
+    ConvertDispatcher(dest,*this,db);
 }
 
 // ------------------------------------------------------------------------------------------------
 template <> inline void Structure :: Convert<double> (double& dest,const FileDatabase& db) const
 {
-	if (name == "char") {
-		dest = db.reader->GetI1() / 255.;
-		return;
-	}
-	else if (name == "short") {
-		dest = db.reader->GetI2() / 32767.;
-		return;
-	}
-	ConvertDispatcher(dest,*this,db);
+    if (name == "char") {
+        dest = db.reader->GetI1() / 255.;
+        return;
+    }
+    else if (name == "short") {
+        dest = db.reader->GetI2() / 32767.;
+        return;
+    }
+    ConvertDispatcher(dest,*this,db);
 }
 
 // ------------------------------------------------------------------------------------------------
 template <> inline void Structure :: Convert<Pointer> (Pointer& dest,const FileDatabase& db) const
 {
-	if (db.i64bit) {
-		dest.val = db.reader->GetU8();
-		//db.reader->IncPtr(-8);
-		return;
-	}
-	dest.val = db.reader->GetU4();
-	//db.reader->IncPtr(-4);
+    if (db.i64bit) {
+        dest.val = db.reader->GetU8();
+        //db.reader->IncPtr(-8);
+        return;
+    }
+    dest.val = db.reader->GetU4();
+    //db.reader->IncPtr(-4);
 }
 
 //--------------------------------------------------------------------------------
 const Structure& DNA :: operator [] (const std::string& ss) const
 {
-	std::map<std::string, size_t>::const_iterator it = indices.find(ss);
-	if (it == indices.end()) {
-		throw Error((Formatter::format(),
-			"BlendDNA: Did not find a structure named `",ss,"`"
-			));
-	}
-
-	return structures[(*it).second];
+    std::map<std::string, size_t>::const_iterator it = indices.find(ss);
+    if (it == indices.end()) {
+        throw Error((Formatter::format(),
+            "BlendDNA: Did not find a structure named `",ss,"`"
+            ));
+    }
+
+    return structures[(*it).second];
 }
 
 //--------------------------------------------------------------------------------
 const Structure* DNA :: Get (const std::string& ss) const
 {
-	std::map<std::string, size_t>::const_iterator it = indices.find(ss);
-	return it == indices.end() ? NULL : &structures[(*it).second];
+    std::map<std::string, size_t>::const_iterator it = indices.find(ss);
+    return it == indices.end() ? NULL : &structures[(*it).second];
 }
 
 //--------------------------------------------------------------------------------
 const Structure& DNA :: operator [] (const size_t i) const 
 {
-	if (i >= structures.size()) {
-		throw Error((Formatter::format(),
-			"BlendDNA: There is no structure with index `",i,"`"
-			));
-	}
+    if (i >= structures.size()) {
+        throw Error((Formatter::format(),
+            "BlendDNA: There is no structure with index `",i,"`"
+            ));
+    }
 
-	return structures[i];
+    return structures[i];
 }
 
 //--------------------------------------------------------------------------------
 template <template <typename> class TOUT> template <typename T> void ObjectCache<TOUT> :: get (
-	const Structure& s, 
-	TOUT<T>& out, 
-	const Pointer& ptr
+    const Structure& s, 
+    TOUT<T>& out, 
+    const Pointer& ptr
 ) const {
 
-	if(s.cache_idx == static_cast<size_t>(-1)) {
-		s.cache_idx = db.next_cache_idx++;
-		caches.resize(db.next_cache_idx);
-		return;
-	}
+    if(s.cache_idx == static_cast<size_t>(-1)) {
+        s.cache_idx = db.next_cache_idx++;
+        caches.resize(db.next_cache_idx);
+        return;
+    }
 
-	typename StructureCache::const_iterator it = caches[s.cache_idx].find(ptr);
-	if (it != caches[s.cache_idx].end()) {
-		out = boost::static_pointer_cast<T>( (*it).second );
+    typename StructureCache::const_iterator it = caches[s.cache_idx].find(ptr);
+    if (it != caches[s.cache_idx].end()) {
+        out = boost::static_pointer_cast<T>( (*it).second );
 
 #ifndef ASSIMP_BUILD_BLENDER_NO_STATS
-		++db.stats().cache_hits;
+        ++db.stats().cache_hits;
 #endif
-	}
-	// otherwise, out remains untouched
+    }
+    // otherwise, out remains untouched
 }
 
 
 //--------------------------------------------------------------------------------
 template <template <typename> class TOUT> template <typename T> void ObjectCache<TOUT> :: set (
-	const Structure& s, 
-	const TOUT<T>& out,
-	const Pointer& ptr
+    const Structure& s, 
+    const TOUT<T>& out,
+    const Pointer& ptr
 ) {
-	if(s.cache_idx == static_cast<size_t>(-1)) {
-		s.cache_idx = db.next_cache_idx++;
-		caches.resize(db.next_cache_idx);
-	}
-	caches[s.cache_idx][ptr] = boost::static_pointer_cast<ElemBase>( out ); 
+    if(s.cache_idx == static_cast<size_t>(-1)) {
+        s.cache_idx = db.next_cache_idx++;
+        caches.resize(db.next_cache_idx);
+    }
+    caches[s.cache_idx][ptr] = boost::static_pointer_cast<ElemBase>( out ); 
 
 #ifndef ASSIMP_BUILD_BLENDER_NO_STATS
-	++db.stats().cached_objects;
+    ++db.stats().cached_objects;
 #endif
 }
 

+ 143 - 122
assimplib.mod/assimp/code/BlenderIntermediate.h

@@ -2,11 +2,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -23,16 +23,16 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -49,132 +49,153 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "BlenderDNA.h"
 #include "BlenderScene.h"
 #include "BlenderSceneGen.h"
+#include <boost/foreach.hpp>
+#include <deque>
+#include "./../include/assimp/material.h"
+
+struct aiTexture;
 
 #define for_each(x,y) BOOST_FOREACH(x,y)
 
 namespace Assimp {
 namespace Blender {
 
-	// --------------------------------------------------------------------
-	/** Mini smart-array to avoid pulling in even more boost stuff. usable with vector and deque */
-	// --------------------------------------------------------------------
-	template <template <typename,typename> class TCLASS, typename T>
-	struct TempArray	{
-		typedef TCLASS< T*,std::allocator<T*> > mywrap;
-
-		TempArray() {
-		}
-
-		~TempArray () {
-			for_each(T* elem, arr) {
-				delete elem;
-			}
-		}
-
-		void dismiss() {
-			arr.clear();
-		}
-
-		mywrap* operator -> () {
-			return &arr;
-		}
-
-		operator mywrap& () {
-			return arr;
-		}
-
-		operator const mywrap& () const {
-			return arr;
-		}
-
-		mywrap& get () {
-			return arr;
-		}
-
-		const mywrap& get () const {
-			return arr;
-		}
-
-		T* operator[] (size_t idx) const {
-			return arr[idx];
-		}
-
-		T*& operator[] (size_t idx) {
-			return arr[idx];
-		}
-
-	private:
-		// no copy semantics
-		void operator= (const TempArray&)  {
-		}
-
-		TempArray(const TempArray& arr) {
-		}
-
-	private:
-		mywrap arr;
-	};
-	
+    // --------------------------------------------------------------------
+    /** Mini smart-array to avoid pulling in even more boost stuff. usable with vector and deque */
+    // --------------------------------------------------------------------
+    template <template <typename,typename> class TCLASS, typename T>
+    struct TempArray    {
+        typedef TCLASS< T*,std::allocator<T*> > mywrap;
+
+        TempArray() {
+        }
+
+        ~TempArray () {
+            for_each(T* elem, arr) {
+                delete elem;
+            }
+        }
+
+        void dismiss() {
+            arr.clear();
+        }
+
+        mywrap* operator -> () {
+            return &arr;
+        }
+
+        operator mywrap& () {
+            return arr;
+        }
+
+        operator const mywrap& () const {
+            return arr;
+        }
+
+        mywrap& get () {
+            return arr;
+        }
+
+        const mywrap& get () const {
+            return arr;
+        }
+
+        T* operator[] (size_t idx) const {
+            return arr[idx];
+        }
+
+        T*& operator[] (size_t idx) {
+            return arr[idx];
+        }
+
+    private:
+        // no copy semantics
+        void operator= (const TempArray&)  {
+        }
+
+        TempArray(const TempArray& arr) {
+        }
+
+    private:
+        mywrap arr;
+    };
+
 #ifdef _MSC_VER
-#	pragma warning(disable:4351)
+#   pragma warning(disable:4351)
 #endif
-	// --------------------------------------------------------------------
-	/** ConversionData acts as intermediate storage location for
-	 *  the various ConvertXXX routines in BlenderImporter.*/
-	// --------------------------------------------------------------------
-	struct ConversionData	
-	{
-		ConversionData(const FileDatabase& db)
-			: sentinel_cnt()
-			, next_texture()
-			, db(db)
-		{}
-
-		std::set<const Object*> objects;
-
-		TempArray <std::vector, aiMesh> meshes;
-		TempArray <std::vector, aiCamera> cameras;
-		TempArray <std::vector, aiLight> lights;
-		TempArray <std::vector, aiMaterial> materials;
-		TempArray <std::vector, aiTexture> textures;
-
-		// set of all materials referenced by at least one mesh in the scene
-		std::deque< boost::shared_ptr< Material > > materials_raw;
-
-		// counter to name sentinel textures inserted as substitutes for procedural textures.
-		unsigned int sentinel_cnt;
-
-		// next texture ID for each texture type, respectively
-		unsigned int next_texture[aiTextureType_UNKNOWN+1];
-
-		// original file data
-		const FileDatabase& db;
-	};
+
+    struct ObjectCompare {
+        bool operator() (const Object* left, const Object* right) const {
+            return strcmp(left->id.name, right->id.name) == -1;
+        }
+    };
+
+    // When keeping objects in sets, sort them by their name.
+    typedef std::set<const Object*, ObjectCompare> ObjectSet;
+
+    // --------------------------------------------------------------------
+    /** ConversionData acts as intermediate storage location for
+     *  the various ConvertXXX routines in BlenderImporter.*/
+    // --------------------------------------------------------------------
+    struct ConversionData
+    {
+        ConversionData(const FileDatabase& db)
+            : sentinel_cnt()
+            , next_texture()
+            , db(db)
+        {}
+
+        struct ObjectCompare {
+            bool operator() (const Object* left, const Object* right) const {
+                return strcmp(left->id.name, right->id.name) == -1;
+            }
+        };
+
+        ObjectSet objects;
+
+        TempArray <std::vector, aiMesh> meshes;
+        TempArray <std::vector, aiCamera> cameras;
+        TempArray <std::vector, aiLight> lights;
+        TempArray <std::vector, aiMaterial> materials;
+        TempArray <std::vector, aiTexture> textures;
+
+        // set of all materials referenced by at least one mesh in the scene
+        std::deque< boost::shared_ptr< Material > > materials_raw;
+
+        // counter to name sentinel textures inserted as substitutes for procedural textures.
+        unsigned int sentinel_cnt;
+
+        // next texture ID for each texture type, respectively
+        unsigned int next_texture[aiTextureType_UNKNOWN+1];
+
+        // original file data
+        const FileDatabase& db;
+    };
 #ifdef _MSC_VER
-#	pragma warning(default:4351)
+#   pragma warning(default:4351)
 #endif
 
 // ------------------------------------------------------------------------------------------------
 inline const char* GetTextureTypeDisplayString(Tex::Type t)
 {
-	switch (t)	{
-	case Tex::Type_CLOUDS		:  return  "Clouds";			
-	case Tex::Type_WOOD			:  return  "Wood";			
-	case Tex::Type_MARBLE		:  return  "Marble";			
-	case Tex::Type_MAGIC		:  return  "Magic";		
-	case Tex::Type_BLEND		:  return  "Blend";			
-	case Tex::Type_STUCCI		:  return  "Stucci";			
-	case Tex::Type_NOISE		:  return  "Noise";			
-	case Tex::Type_PLUGIN		:  return  "Plugin";			
-	case Tex::Type_MUSGRAVE		:  return  "Musgrave";		
-	case Tex::Type_VORONOI		:  return  "Voronoi";			
-	case Tex::Type_DISTNOISE	:  return  "DistortedNoise";	
-	case Tex::Type_ENVMAP		:  return  "EnvMap";	
-	case Tex::Type_IMAGE		:  return  "Image";	
-	default: 
-		break;
-	}
-	return "<Unknown>";
+    switch (t)  {
+    case Tex::Type_CLOUDS       :  return  "Clouds";
+    case Tex::Type_WOOD         :  return  "Wood";
+    case Tex::Type_MARBLE       :  return  "Marble";
+    case Tex::Type_MAGIC        :  return  "Magic";
+    case Tex::Type_BLEND        :  return  "Blend";
+    case Tex::Type_STUCCI       :  return  "Stucci";
+    case Tex::Type_NOISE        :  return  "Noise";
+    case Tex::Type_PLUGIN       :  return  "Plugin";
+    case Tex::Type_MUSGRAVE     :  return  "Musgrave";
+    case Tex::Type_VORONOI      :  return  "Voronoi";
+    case Tex::Type_DISTNOISE    :  return  "DistortedNoise";
+    case Tex::Type_ENVMAP       :  return  "EnvMap";
+    case Tex::Type_IMAGE        :  return  "Image";
+    default:
+        break;
+    }
+    return "<Unknown>";
 }
 
 } // ! Blender

+ 965 - 954
assimplib.mod/assimp/code/BlenderLoader.cpp

@@ -3,11 +3,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -24,16 +24,16 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -42,7 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 /** @file  BlenderLoader.cpp
  *  @brief Implementation of the Blender3D importer class.
  */
-#include "AssimpPCH.h"
+
 
 //#define ASSIMP_BUILD_NO_COMPRESSED_BLEND
 // Uncomment this to disable support for (gzip)compressed .BLEND files
@@ -52,21 +52,25 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "BlenderIntermediate.h"
 #include "BlenderModifier.h"
 #include "BlenderBMesh.h"
+#include "../include/assimp/scene.h"
+#include "StringComparison.h"
 
 #include "StreamReader.h"
 #include "MemoryIOWrapper.h"
+#include <cctype>
+
 
-// zlib is needed for compressed blend files 
+// zlib is needed for compressed blend files
 #ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND
-#	ifdef ASSIMP_BUILD_NO_OWN_ZLIB
-#		include <zlib.h>
-#	else
-#		include "../contrib/zlib/zlib.h"
-#	endif
+#   ifdef ASSIMP_BUILD_NO_OWN_ZLIB
+#       include <zlib.h>
+#   else
+#       include "../contrib/zlib/zlib.h"
+#   endif
 #endif
 
 namespace Assimp {
-	template<> const std::string LogFunctions<BlenderImporter>::log_prefix = "BLEND: ";
+    template<> const std::string LogFunctions<BlenderImporter>::log_prefix = "BLEND: ";
 }
 
 using namespace Assimp;
@@ -74,16 +78,16 @@ using namespace Assimp::Blender;
 using namespace Assimp::Formatter;
 
 static const aiImporterDesc blenderDesc = {
-	"Blender 3D Importer \nhttp://www.blender3d.org",
-	"",
-	"",
-	"No animation support yet",
-	aiImporterFlags_SupportBinaryFlavour,
-	0,
-	0,
-	2,
-	50,
-	"blend"
+    "Blender 3D Importer \nhttp://www.blender3d.org",
+    "",
+    "",
+    "No animation support yet",
+    aiImporterFlags_SupportBinaryFlavour,
+    0,
+    0,
+    2,
+    50,
+    "blend"
 };
 
 
@@ -94,1055 +98,1062 @@ BlenderImporter::BlenderImporter()
 {}
 
 // ------------------------------------------------------------------------------------------------
-// Destructor, private as well 
+// Destructor, private as well
 BlenderImporter::~BlenderImporter()
 {
-	delete modifier_cache;
+    delete modifier_cache;
 }
 
 // ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file. 
+// Returns whether the class can handle the format of the given file.
 bool BlenderImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
 {
-	const std::string& extension = GetExtension(pFile);
-	if (extension == "blend") {
-		return true;
-	}
-
-	else if ((!extension.length() || checkSig) && pIOHandler)	{
-		// note: this won't catch compressed files
-		const char* tokens[] = {"BLENDER"};
-		return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
-	}
-	return false;
+    const std::string& extension = GetExtension(pFile);
+    if (extension == "blend") {
+        return true;
+    }
+
+    else if ((!extension.length() || checkSig) && pIOHandler)   {
+        // note: this won't catch compressed files
+        const char* tokens[] = {"BLENDER"};
+        return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
+    }
+    return false;
 }
 
 // ------------------------------------------------------------------------------------------------
 // List all extensions handled by this loader
-void BlenderImporter::GetExtensionList(std::set<std::string>& app) 
+void BlenderImporter::GetExtensionList(std::set<std::string>& app)
 {
-	app.insert("blend");
+    app.insert("blend");
 }
 
 // ------------------------------------------------------------------------------------------------
 // Loader registry entry
 const aiImporterDesc* BlenderImporter::GetInfo () const
 {
-	return &blenderDesc;
+    return &blenderDesc;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Setup configuration properties for the loader
 void BlenderImporter::SetupProperties(const Importer* /*pImp*/)
 {
-	// nothing to be done for the moment
+    // nothing to be done for the moment
 }
 
 struct free_it
 {
-	free_it(void* free) : free(free) {}
-	~free_it() {
-		::free(this->free);
-	}
+    free_it(void* free) : free(free) {}
+    ~free_it() {
+        ::free(this->free);
+    }
 
-	void* free;
+    void* free;
 };
 
 // ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure. 
-void BlenderImporter::InternReadFile( const std::string& pFile, 
-	aiScene* pScene, IOSystem* pIOHandler)
+// Imports the given file into the given scene structure.
+void BlenderImporter::InternReadFile( const std::string& pFile,
+    aiScene* pScene, IOSystem* pIOHandler)
 {
 #ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND
-	Bytef* dest = NULL;
-	free_it free_it_really(dest);
+    Bytef* dest = NULL;
+    free_it free_it_really(dest);
 #endif
 
-	FileDatabase file; 
-	boost::shared_ptr<IOStream> stream(pIOHandler->Open(pFile,"rb"));
-	if (!stream) {
-		ThrowException("Could not open file for reading");
-	}
-
-	char magic[8] = {0};
-	stream->Read(magic,7,1);
-	if (strcmp(magic,"BLENDER")) {
-		// Check for presence of the gzip header. If yes, assume it is a
-		// compressed blend file and try uncompressing it, else fail. This is to
-		// avoid uncompressing random files which our loader might end up with.
+    FileDatabase file;
+    boost::shared_ptr<IOStream> stream(pIOHandler->Open(pFile,"rb"));
+    if (!stream) {
+        ThrowException("Could not open file for reading");
+    }
+
+    char magic[8] = {0};
+    stream->Read(magic,7,1);
+    if (strcmp(magic,"BLENDER")) {
+        // Check for presence of the gzip header. If yes, assume it is a
+        // compressed blend file and try uncompressing it, else fail. This is to
+        // avoid uncompressing random files which our loader might end up with.
 #ifdef ASSIMP_BUILD_NO_COMPRESSED_BLEND
-		ThrowException("BLENDER magic bytes are missing, is this file compressed (Assimp was built without decompression support)?");
+        ThrowException("BLENDER magic bytes are missing, is this file compressed (Assimp was built without decompression support)?");
 #else
 
-		if (magic[0] != 0x1f || static_cast<uint8_t>(magic[1]) != 0x8b) {
-			ThrowException("BLENDER magic bytes are missing, couldn't find GZIP header either");
-		}
+        if (magic[0] != 0x1f || static_cast<uint8_t>(magic[1]) != 0x8b) {
+            ThrowException("BLENDER magic bytes are missing, couldn't find GZIP header either");
+        }
 
-		LogDebug("Found no BLENDER magic word but a GZIP header, might be a compressed file");
-		if (magic[2] != 8) {
-			ThrowException("Unsupported GZIP compression method");
-		}
+        LogDebug("Found no BLENDER magic word but a GZIP header, might be a compressed file");
+        if (magic[2] != 8) {
+            ThrowException("Unsupported GZIP compression method");
+        }
 
-		// http://www.gzip.org/zlib/rfc-gzip.html#header-trailer
-		stream->Seek(0L,aiOrigin_SET);
-		boost::shared_ptr<StreamReaderLE> reader = boost::shared_ptr<StreamReaderLE>(new StreamReaderLE(stream));
+        // http://www.gzip.org/zlib/rfc-gzip.html#header-trailer
+        stream->Seek(0L,aiOrigin_SET);
+        boost::shared_ptr<StreamReaderLE> reader = boost::shared_ptr<StreamReaderLE>(new StreamReaderLE(stream));
 
-		// build a zlib stream
-		z_stream zstream;
-		zstream.opaque = Z_NULL;
-		zstream.zalloc = Z_NULL;
-		zstream.zfree  = Z_NULL;
-		zstream.data_type = Z_BINARY;
+        // build a zlib stream
+        z_stream zstream;
+        zstream.opaque = Z_NULL;
+        zstream.zalloc = Z_NULL;
+        zstream.zfree  = Z_NULL;
+        zstream.data_type = Z_BINARY;
 
-		// http://hewgill.com/journal/entries/349-how-to-decompress-gzip-stream-with-zlib
-		inflateInit2(&zstream, 16+MAX_WBITS);
+        // http://hewgill.com/journal/entries/349-how-to-decompress-gzip-stream-with-zlib
+        inflateInit2(&zstream, 16+MAX_WBITS);
 
-		zstream.next_in   = reinterpret_cast<Bytef*>( reader->GetPtr() );
-		zstream.avail_in  = reader->GetRemainingSize();
+        zstream.next_in   = reinterpret_cast<Bytef*>( reader->GetPtr() );
+        zstream.avail_in  = reader->GetRemainingSize();
 
-		size_t total = 0l;
+        size_t total = 0l;
 
-		// and decompress the data .... do 1k chunks in the hope that we won't kill the stack
+        // and decompress the data .... do 1k chunks in the hope that we won't kill the stack
 #define MYBLOCK 1024
-		Bytef block[MYBLOCK];
-		int ret;
-		do {
-			zstream.avail_out = MYBLOCK;
-			zstream.next_out = block;
-			ret = inflate(&zstream, Z_NO_FLUSH);
-
-			if (ret != Z_STREAM_END && ret != Z_OK) {
-				ThrowException("Failure decompressing this file using gzip, seemingly it is NOT a compressed .BLEND file");
-			}
-			const size_t have = MYBLOCK - zstream.avail_out;
-			total += have;
-			dest = reinterpret_cast<Bytef*>( realloc(dest,total) );
-			memcpy(dest + total - have,block,have);
-		} 
-		while (ret != Z_STREAM_END);
-
-		// terminate zlib
-		inflateEnd(&zstream);
-
-		// replace the input stream with a memory stream
-		stream.reset(new MemoryIOStream(reinterpret_cast<uint8_t*>(dest),total)); 
-
-		// .. and retry
-		stream->Read(magic,7,1);
-		if (strcmp(magic,"BLENDER")) {
-			ThrowException("Found no BLENDER magic word in decompressed GZIP file");
-		}
+        Bytef block[MYBLOCK];
+        int ret;
+        do {
+            zstream.avail_out = MYBLOCK;
+            zstream.next_out = block;
+            ret = inflate(&zstream, Z_NO_FLUSH);
+
+            if (ret != Z_STREAM_END && ret != Z_OK) {
+                ThrowException("Failure decompressing this file using gzip, seemingly it is NOT a compressed .BLEND file");
+            }
+            const size_t have = MYBLOCK - zstream.avail_out;
+            total += have;
+            dest = reinterpret_cast<Bytef*>( realloc(dest,total) );
+            memcpy(dest + total - have,block,have);
+        }
+        while (ret != Z_STREAM_END);
+
+        // terminate zlib
+        inflateEnd(&zstream);
+
+        // replace the input stream with a memory stream
+        stream.reset(new MemoryIOStream(reinterpret_cast<uint8_t*>(dest),total));
+
+        // .. and retry
+        stream->Read(magic,7,1);
+        if (strcmp(magic,"BLENDER")) {
+            ThrowException("Found no BLENDER magic word in decompressed GZIP file");
+        }
 #endif
-	}
+    }
 
-	file.i64bit = (stream->Read(magic,1,1),magic[0]=='-');
-	file.little = (stream->Read(magic,1,1),magic[0]=='v');
+    file.i64bit = (stream->Read(magic,1,1),magic[0]=='-');
+    file.little = (stream->Read(magic,1,1),magic[0]=='v');
 
-	stream->Read(magic,3,1);
-	magic[3] = '\0';
+    stream->Read(magic,3,1);
+    magic[3] = '\0';
 
-	LogInfo((format(),"Blender version is ",magic[0],".",magic+1,
-		" (64bit: ",file.i64bit?"true":"false",
-		", little endian: ",file.little?"true":"false",")"
-	));
+    LogInfo((format(),"Blender version is ",magic[0],".",magic+1,
+        " (64bit: ",file.i64bit?"true":"false",
+        ", little endian: ",file.little?"true":"false",")"
+    ));
 
-	ParseBlendFile(file,stream);
+    ParseBlendFile(file,stream);
 
-	Scene scene;
-	ExtractScene(scene,file);
+    Scene scene;
+    ExtractScene(scene,file);
 
-	ConvertBlendFile(pScene,scene,file);
+    ConvertBlendFile(pScene,scene,file);
 }
 
 // ------------------------------------------------------------------------------------------------
-void BlenderImporter::ParseBlendFile(FileDatabase& out, boost::shared_ptr<IOStream> stream) 
+void BlenderImporter::ParseBlendFile(FileDatabase& out, boost::shared_ptr<IOStream> stream)
 {
-	out.reader = boost::shared_ptr<StreamReaderAny>(new StreamReaderAny(stream,out.little));
-
-	DNAParser dna_reader(out);
-	const DNA* dna = NULL;
-
-	out.entries.reserve(128); { // even small BLEND files tend to consist of many file blocks
-		SectionParser parser(*out.reader.get(),out.i64bit);
-
-		// first parse the file in search for the DNA and insert all other sections into the database
-		while ((parser.Next(),1)) {
-			const FileBlockHead& head = parser.GetCurrent();
-
-			if (head.id == "ENDB") {
-				break; // only valid end of the file
-			}
-			else if (head.id == "DNA1") {
-				dna_reader.Parse();
-				dna = &dna_reader.GetDNA();
-				continue;
-			}
-
-			out.entries.push_back(head);
-		}
-	}
-	if (!dna) {
-		ThrowException("SDNA not found");
-	}
-
-	std::sort(out.entries.begin(),out.entries.end());
+    out.reader = boost::shared_ptr<StreamReaderAny>(new StreamReaderAny(stream,out.little));
+
+    DNAParser dna_reader(out);
+    const DNA* dna = NULL;
+
+    out.entries.reserve(128); { // even small BLEND files tend to consist of many file blocks
+        SectionParser parser(*out.reader.get(),out.i64bit);
+
+        // first parse the file in search for the DNA and insert all other sections into the database
+        while ((parser.Next(),1)) {
+            const FileBlockHead& head = parser.GetCurrent();
+
+            if (head.id == "ENDB") {
+                break; // only valid end of the file
+            }
+            else if (head.id == "DNA1") {
+                dna_reader.Parse();
+                dna = &dna_reader.GetDNA();
+                continue;
+            }
+
+            out.entries.push_back(head);
+        }
+    }
+    if (!dna) {
+        ThrowException("SDNA not found");
+    }
+
+    std::sort(out.entries.begin(),out.entries.end());
 }
 
 // ------------------------------------------------------------------------------------------------
-void BlenderImporter::ExtractScene(Scene& out, const FileDatabase& file) 
+void BlenderImporter::ExtractScene(Scene& out, const FileDatabase& file)
 {
-	const FileBlockHead* block = NULL;
-	std::map<std::string,size_t>::const_iterator it = file.dna.indices.find("Scene");
-	if (it == file.dna.indices.end()) {
-		ThrowException("There is no `Scene` structure record");
-	}
+    const FileBlockHead* block = NULL;
+    std::map<std::string,size_t>::const_iterator it = file.dna.indices.find("Scene");
+    if (it == file.dna.indices.end()) {
+        ThrowException("There is no `Scene` structure record");
+    }
 
-	const Structure& ss = file.dna.structures[(*it).second];
+    const Structure& ss = file.dna.structures[(*it).second];
 
-	// we need a scene somewhere to start with. 
-	for_each(const FileBlockHead& bl,file.entries) {
+    // we need a scene somewhere to start with.
+    for_each(const FileBlockHead& bl,file.entries) {
 
-		// Fix: using the DNA index is more reliable to locate scenes
-		//if (bl.id == "SC") {
+        // Fix: using the DNA index is more reliable to locate scenes
+        //if (bl.id == "SC") {
 
-		if (bl.dna_index == (*it).second) {
-			block = &bl;
-			break;
-		}
-	}
+        if (bl.dna_index == (*it).second) {
+            block = &bl;
+            break;
+        }
+    }
 
-	if (!block) {
-		ThrowException("There is not a single `Scene` record to load");
-	}
+    if (!block) {
+        ThrowException("There is not a single `Scene` record to load");
+    }
 
-	file.reader->SetCurrentPos(block->start);
-	ss.Convert(out,file);
+    file.reader->SetCurrentPos(block->start);
+    ss.Convert(out,file);
 
 #ifndef ASSIMP_BUILD_BLENDER_NO_STATS
-	DefaultLogger::get()->info((format(),
-		"(Stats) Fields read: "	,file.stats().fields_read,
-		", pointers resolved: "	,file.stats().pointers_resolved,  
-		", cache hits: "        ,file.stats().cache_hits,  
-		", cached objects: "	,file.stats().cached_objects
-	));
+    DefaultLogger::get()->info((format(),
+        "(Stats) Fields read: " ,file.stats().fields_read,
+        ", pointers resolved: " ,file.stats().pointers_resolved,
+        ", cache hits: "        ,file.stats().cache_hits,
+        ", cached objects: "    ,file.stats().cached_objects
+    ));
 #endif
 }
 
 // ------------------------------------------------------------------------------------------------
-void BlenderImporter::ConvertBlendFile(aiScene* out, const Scene& in,const FileDatabase& file) 
+void BlenderImporter::ConvertBlendFile(aiScene* out, const Scene& in,const FileDatabase& file)
 {
-	ConversionData conv(file);
-
-	// FIXME it must be possible to take the hierarchy directly from
-	// the file. This is terrible. Here, we're first looking for
-	// all objects which don't have parent objects at all -
-	std::deque<const Object*> no_parents;
-	for (boost::shared_ptr<Base> cur = boost::static_pointer_cast<Base> ( in.base.first ); cur; cur = cur->next) {
-		if (cur->object) {
-			if(!cur->object->parent) {
-				no_parents.push_back(cur->object.get());
-			}
-			else conv.objects.insert(cur->object.get());
-		}
-	}
-	for (boost::shared_ptr<Base> cur = in.basact; cur; cur = cur->next) {
-		if (cur->object) {
-			if(cur->object->parent) {
-				conv.objects.insert(cur->object.get());
-			}
-		}
-	}
-
-	if (no_parents.empty()) {
-		ThrowException("Expected at least one object with no parent");
-	}
-
-	aiNode* root = out->mRootNode = new aiNode("<BlenderRoot>");
-
-	root->mNumChildren = static_cast<unsigned int>(no_parents.size());
-	root->mChildren = new aiNode*[root->mNumChildren]();
-	for (unsigned int i = 0; i < root->mNumChildren; ++i) {
-		root->mChildren[i] = ConvertNode(in, no_parents[i], conv, aiMatrix4x4());	
-		root->mChildren[i]->mParent = root;
-	}
-
-	BuildMaterials(conv);
-
-	if (conv.meshes->size()) {
-		out->mMeshes = new aiMesh*[out->mNumMeshes = static_cast<unsigned int>( conv.meshes->size() )];
-		std::copy(conv.meshes->begin(),conv.meshes->end(),out->mMeshes);
-		conv.meshes.dismiss();
-	}
-
-	if (conv.lights->size()) {
-		out->mLights = new aiLight*[out->mNumLights = static_cast<unsigned int>( conv.lights->size() )];
-		std::copy(conv.lights->begin(),conv.lights->end(),out->mLights);
-		conv.lights.dismiss();
-	}
-
-	if (conv.cameras->size()) {
-		out->mCameras = new aiCamera*[out->mNumCameras = static_cast<unsigned int>( conv.cameras->size() )];
-		std::copy(conv.cameras->begin(),conv.cameras->end(),out->mCameras);
-		conv.cameras.dismiss();
-	}
-
-	if (conv.materials->size()) {
-		out->mMaterials = new aiMaterial*[out->mNumMaterials = static_cast<unsigned int>( conv.materials->size() )];
-		std::copy(conv.materials->begin(),conv.materials->end(),out->mMaterials);
-		conv.materials.dismiss();
-	}
-
-	if (conv.textures->size()) {
-		out->mTextures = new aiTexture*[out->mNumTextures = static_cast<unsigned int>( conv.textures->size() )];
-		std::copy(conv.textures->begin(),conv.textures->end(),out->mTextures);
-		conv.textures.dismiss();
-	}
-
-	// acknowledge that the scene might come out incomplete
-	// by Assimps definition of `complete`: blender scenes
-	// can consist of thousands of cameras or lights with
-	// not a single mesh between them.
-	if (!out->mNumMeshes) {
-		out->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
-	}
+    ConversionData conv(file);
+
+    // FIXME it must be possible to take the hierarchy directly from
+    // the file. This is terrible. Here, we're first looking for
+    // all objects which don't have parent objects at all -
+    std::deque<const Object*> no_parents;
+    for (boost::shared_ptr<Base> cur = boost::static_pointer_cast<Base> ( in.base.first ); cur; cur = cur->next) {
+        if (cur->object) {
+            if(!cur->object->parent) {
+                no_parents.push_back(cur->object.get());
+            }
+            else conv.objects.insert(cur->object.get());
+        }
+    }
+    for (boost::shared_ptr<Base> cur = in.basact; cur; cur = cur->next) {
+        if (cur->object) {
+            if(cur->object->parent) {
+                conv.objects.insert(cur->object.get());
+            }
+        }
+    }
+
+    if (no_parents.empty()) {
+        ThrowException("Expected at least one object with no parent");
+    }
+
+    aiNode* root = out->mRootNode = new aiNode("<BlenderRoot>");
+
+    root->mNumChildren = static_cast<unsigned int>(no_parents.size());
+    root->mChildren = new aiNode*[root->mNumChildren]();
+    for (unsigned int i = 0; i < root->mNumChildren; ++i) {
+        root->mChildren[i] = ConvertNode(in, no_parents[i], conv, aiMatrix4x4());
+        root->mChildren[i]->mParent = root;
+    }
+
+    BuildMaterials(conv);
+
+    if (conv.meshes->size()) {
+        out->mMeshes = new aiMesh*[out->mNumMeshes = static_cast<unsigned int>( conv.meshes->size() )];
+        std::copy(conv.meshes->begin(),conv.meshes->end(),out->mMeshes);
+        conv.meshes.dismiss();
+    }
+
+    if (conv.lights->size()) {
+        out->mLights = new aiLight*[out->mNumLights = static_cast<unsigned int>( conv.lights->size() )];
+        std::copy(conv.lights->begin(),conv.lights->end(),out->mLights);
+        conv.lights.dismiss();
+    }
+
+    if (conv.cameras->size()) {
+        out->mCameras = new aiCamera*[out->mNumCameras = static_cast<unsigned int>( conv.cameras->size() )];
+        std::copy(conv.cameras->begin(),conv.cameras->end(),out->mCameras);
+        conv.cameras.dismiss();
+    }
+
+    if (conv.materials->size()) {
+        out->mMaterials = new aiMaterial*[out->mNumMaterials = static_cast<unsigned int>( conv.materials->size() )];
+        std::copy(conv.materials->begin(),conv.materials->end(),out->mMaterials);
+        conv.materials.dismiss();
+    }
+
+    if (conv.textures->size()) {
+        out->mTextures = new aiTexture*[out->mNumTextures = static_cast<unsigned int>( conv.textures->size() )];
+        std::copy(conv.textures->begin(),conv.textures->end(),out->mTextures);
+        conv.textures.dismiss();
+    }
+
+    // acknowledge that the scene might come out incomplete
+    // by Assimps definition of `complete`: blender scenes
+    // can consist of thousands of cameras or lights with
+    // not a single mesh between them.
+    if (!out->mNumMeshes) {
+        out->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 void BlenderImporter::ResolveImage(aiMaterial* out, const Material* mat, const MTex* tex, const Image* img, ConversionData& conv_data)
 {
-	(void)mat; (void)tex; (void)conv_data;
-	aiString name;
-
-	// check if the file contents are bundled with the BLEND file
-	if (img->packedfile) {
-		name.data[0] = '*';
-		name.length = 1+ ASSIMP_itoa10(name.data+1,MAXLEN-1,conv_data.textures->size());
-
-		conv_data.textures->push_back(new aiTexture());
-		aiTexture* tex = conv_data.textures->back();
-
-		// usually 'img->name' will be the original file name of the embedded textures,
-		// so we can extract the file extension from it.
-		const size_t nlen = strlen( img->name );
-		const char* s = img->name+nlen, *e = s;
-
-		while (s >= img->name && *s != '.')--s;
-
-		tex->achFormatHint[0] = s+1>e ? '\0' : ::tolower( s[1] );
-		tex->achFormatHint[1] = s+2>e ? '\0' : ::tolower( s[2] );
-		tex->achFormatHint[2] = s+3>e ? '\0' : ::tolower( s[3] );
-		tex->achFormatHint[3] = '\0';
-
-		// tex->mHeight = 0;
-		tex->mWidth = img->packedfile->size;
-		uint8_t* ch = new uint8_t[tex->mWidth];
-
-		conv_data.db.reader->SetCurrentPos(static_cast<size_t>( img->packedfile->data->val));
-		conv_data.db.reader->CopyAndAdvance(ch,tex->mWidth);
-
-		tex->pcData = reinterpret_cast<aiTexel*>(ch);
-
-		LogInfo("Reading embedded texture, original file was "+std::string(img->name));
-	}
-	else {
-		name = aiString( img->name );
-	}
-
-	aiTextureType texture_type = aiTextureType_UNKNOWN;
-	MTex::MapType map_type = tex->mapto;
-
-	if (map_type & MTex::MapType_COL)
-	    texture_type = aiTextureType_DIFFUSE;
-	else if (map_type & MTex::MapType_NORM) {
-	    if (tex->tex->imaflag & Tex::ImageFlags_NORMALMAP) {
-	        texture_type = aiTextureType_NORMALS;
-	    }
-	    else {
-	        texture_type = aiTextureType_HEIGHT;
-	    }
-	    out->AddProperty(&tex->norfac,1,AI_MATKEY_BUMPSCALING);
-	}
-	else if (map_type & MTex::MapType_COLSPEC)
-		texture_type = aiTextureType_SPECULAR;
-	else if (map_type & MTex::MapType_COLMIR)
-		texture_type = aiTextureType_REFLECTION;
-	//else if (map_type & MTex::MapType_REF)
-	else if (map_type & MTex::MapType_SPEC)
-		texture_type = aiTextureType_SHININESS;
-	else if (map_type & MTex::MapType_EMIT)
-		texture_type = aiTextureType_EMISSIVE;
-	//else if (map_type & MTex::MapType_ALPHA)
-	//else if (map_type & MTex::MapType_HAR)
-	//else if (map_type & MTex::MapType_RAYMIRR)
-	//else if (map_type & MTex::MapType_TRANSLU)
-	else if (map_type & MTex::MapType_AMB)
-		texture_type = aiTextureType_AMBIENT;
-	else if (map_type & MTex::MapType_DISPLACE)
-		texture_type = aiTextureType_DISPLACEMENT;
-	//else if (map_type & MTex::MapType_WARP)
-
-	out->AddProperty(&name,AI_MATKEY_TEXTURE(texture_type,
-	    conv_data.next_texture[texture_type]++));
+    (void)mat; (void)tex; (void)conv_data;
+    aiString name;
+
+    // check if the file contents are bundled with the BLEND file
+    if (img->packedfile) {
+        name.data[0] = '*';
+        name.length = 1+ ASSIMP_itoa10(name.data+1,MAXLEN-1,conv_data.textures->size());
+
+        conv_data.textures->push_back(new aiTexture());
+        aiTexture* tex = conv_data.textures->back();
+
+        // usually 'img->name' will be the original file name of the embedded textures,
+        // so we can extract the file extension from it.
+        const size_t nlen = strlen( img->name );
+        const char* s = img->name+nlen, *e = s;
+
+        while (s >= img->name && *s != '.')--s;
+
+        tex->achFormatHint[0] = s+1>e ? '\0' : ::tolower( s[1] );
+        tex->achFormatHint[1] = s+2>e ? '\0' : ::tolower( s[2] );
+        tex->achFormatHint[2] = s+3>e ? '\0' : ::tolower( s[3] );
+        tex->achFormatHint[3] = '\0';
+
+        // tex->mHeight = 0;
+        tex->mWidth = img->packedfile->size;
+        uint8_t* ch = new uint8_t[tex->mWidth];
+
+        conv_data.db.reader->SetCurrentPos(static_cast<size_t>( img->packedfile->data->val));
+        conv_data.db.reader->CopyAndAdvance(ch,tex->mWidth);
+
+        tex->pcData = reinterpret_cast<aiTexel*>(ch);
+
+        LogInfo("Reading embedded texture, original file was "+std::string(img->name));
+    }
+    else {
+        name = aiString( img->name );
+    }
+
+    aiTextureType texture_type = aiTextureType_UNKNOWN;
+    MTex::MapType map_type = tex->mapto;
+
+    if (map_type & MTex::MapType_COL)
+        texture_type = aiTextureType_DIFFUSE;
+    else if (map_type & MTex::MapType_NORM) {
+        if (tex->tex->imaflag & Tex::ImageFlags_NORMALMAP) {
+            texture_type = aiTextureType_NORMALS;
+        }
+        else {
+            texture_type = aiTextureType_HEIGHT;
+        }
+        out->AddProperty(&tex->norfac,1,AI_MATKEY_BUMPSCALING);
+    }
+    else if (map_type & MTex::MapType_COLSPEC)
+        texture_type = aiTextureType_SPECULAR;
+    else if (map_type & MTex::MapType_COLMIR)
+        texture_type = aiTextureType_REFLECTION;
+    //else if (map_type & MTex::MapType_REF)
+    else if (map_type & MTex::MapType_SPEC)
+        texture_type = aiTextureType_SHININESS;
+    else if (map_type & MTex::MapType_EMIT)
+        texture_type = aiTextureType_EMISSIVE;
+    //else if (map_type & MTex::MapType_ALPHA)
+    //else if (map_type & MTex::MapType_HAR)
+    //else if (map_type & MTex::MapType_RAYMIRR)
+    //else if (map_type & MTex::MapType_TRANSLU)
+    else if (map_type & MTex::MapType_AMB)
+        texture_type = aiTextureType_AMBIENT;
+    else if (map_type & MTex::MapType_DISPLACE)
+        texture_type = aiTextureType_DISPLACEMENT;
+    //else if (map_type & MTex::MapType_WARP)
+
+    out->AddProperty(&name,AI_MATKEY_TEXTURE(texture_type,
+        conv_data.next_texture[texture_type]++));
 
 }
 
 // ------------------------------------------------------------------------------------------------
 void BlenderImporter::AddSentinelTexture(aiMaterial* out, const Material* mat, const MTex* tex, ConversionData& conv_data)
 {
-	(void)mat; (void)tex; (void)conv_data;
-
-	aiString name;
-	name.length = sprintf(name.data, "Procedural,num=%i,type=%s",conv_data.sentinel_cnt++,
-		GetTextureTypeDisplayString(tex->tex->type)
-	);
-	out->AddProperty(&name,AI_MATKEY_TEXTURE_DIFFUSE(
-		conv_data.next_texture[aiTextureType_DIFFUSE]++)
-	);
+    (void)mat; (void)tex; (void)conv_data;
+
+    aiString name;
+    name.length = sprintf(name.data, "Procedural,num=%i,type=%s",conv_data.sentinel_cnt++,
+        GetTextureTypeDisplayString(tex->tex->type)
+    );
+    out->AddProperty(&name,AI_MATKEY_TEXTURE_DIFFUSE(
+        conv_data.next_texture[aiTextureType_DIFFUSE]++)
+    );
 }
 
 // ------------------------------------------------------------------------------------------------
 void BlenderImporter::ResolveTexture(aiMaterial* out, const Material* mat, const MTex* tex, ConversionData& conv_data)
 {
-	const Tex* rtex = tex->tex.get();
-	if(!rtex || !rtex->type) {
-		return;
-	}
-	
-	// We can't support most of the texture types because they're mostly procedural.
-	// These are substituted by a dummy texture.
-	const char* dispnam = "";
-	switch( rtex->type ) 
-	{
-			// these are listed in blender's UI
-		case Tex::Type_CLOUDS		:  
-		case Tex::Type_WOOD			:  
-		case Tex::Type_MARBLE		:  
-		case Tex::Type_MAGIC		: 
-		case Tex::Type_BLEND		:  
-		case Tex::Type_STUCCI		: 
-		case Tex::Type_NOISE		: 
-		case Tex::Type_PLUGIN		: 
-		case Tex::Type_MUSGRAVE		:  
-		case Tex::Type_VORONOI		:  
-		case Tex::Type_DISTNOISE	:  
-		case Tex::Type_ENVMAP		:  
-
-			// these do no appear in the UI, why?
-		case Tex::Type_POINTDENSITY	:  
-		case Tex::Type_VOXELDATA	: 
-
-			LogWarn(std::string("Encountered a texture with an unsupported type: ")+dispnam);
-			AddSentinelTexture(out, mat, tex, conv_data);
-			break;
-
-		case Tex::Type_IMAGE		:
-			if (!rtex->ima) {
-				LogError("A texture claims to be an Image, but no image reference is given");
-				break;
-			}
-			ResolveImage(out, mat, tex, rtex->ima.get(),conv_data);
-			break;
-
-		default:
-			ai_assert(false);
-	};
+    const Tex* rtex = tex->tex.get();
+    if(!rtex || !rtex->type) {
+        return;
+    }
+
+    // We can't support most of the texture types because they're mostly procedural.
+    // These are substituted by a dummy texture.
+    const char* dispnam = "";
+    switch( rtex->type )
+    {
+            // these are listed in blender's UI
+        case Tex::Type_CLOUDS       :
+        case Tex::Type_WOOD         :
+        case Tex::Type_MARBLE       :
+        case Tex::Type_MAGIC        :
+        case Tex::Type_BLEND        :
+        case Tex::Type_STUCCI       :
+        case Tex::Type_NOISE        :
+        case Tex::Type_PLUGIN       :
+        case Tex::Type_MUSGRAVE     :
+        case Tex::Type_VORONOI      :
+        case Tex::Type_DISTNOISE    :
+        case Tex::Type_ENVMAP       :
+
+            // these do no appear in the UI, why?
+        case Tex::Type_POINTDENSITY :
+        case Tex::Type_VOXELDATA    :
+
+            LogWarn(std::string("Encountered a texture with an unsupported type: ")+dispnam);
+            AddSentinelTexture(out, mat, tex, conv_data);
+            break;
+
+        case Tex::Type_IMAGE        :
+            if (!rtex->ima) {
+                LogError("A texture claims to be an Image, but no image reference is given");
+                break;
+            }
+            ResolveImage(out, mat, tex, rtex->ima.get(),conv_data);
+            break;
+
+        default:
+            ai_assert(false);
+    };
 }
 
 // ------------------------------------------------------------------------------------------------
-void BlenderImporter::BuildMaterials(ConversionData& conv_data) 
+void BlenderImporter::BuildMaterials(ConversionData& conv_data)
 {
-	conv_data.materials->reserve(conv_data.materials_raw.size());
-
-	// add a default material if necessary
-	unsigned int index = static_cast<unsigned int>( -1 );
-	for_each( aiMesh* mesh, conv_data.meshes.get() ) {
-		if (mesh->mMaterialIndex == static_cast<unsigned int>( -1 )) {
-
-			if (index == static_cast<unsigned int>( -1 )) {
-
-				// ok, we need to add a dedicated default material for some poor material-less meshes
-				boost::shared_ptr<Material> p(new Material());
-				strcpy( p->id.name+2, AI_DEFAULT_MATERIAL_NAME );
-
-				p->r = p->g = p->b = 0.6f;
-				p->specr = p->specg = p->specb = 0.6f;
-				p->ambr = p->ambg = p->ambb = 0.0f;
-				p->mirr = p->mirg = p->mirb = 0.0f;
-				p->emit = 0.f;
-				p->alpha = 0.f;
-
-				// XXX add more / or add default c'tor to Material
-
-				index = static_cast<unsigned int>( conv_data.materials_raw.size() );
-				conv_data.materials_raw.push_back(p);
-
-				LogInfo("Adding default material ...");
-			}
-			mesh->mMaterialIndex = index;
-		}
-	}
-
-	for_each(boost::shared_ptr<Material> mat, conv_data.materials_raw) {
-
-		// reset per material global counters
-		for (size_t i = 0; i < sizeof(conv_data.next_texture)/sizeof(conv_data.next_texture[0]);++i) {
-			conv_data.next_texture[i] = 0 ;
-		}
-	
-		aiMaterial* mout = new aiMaterial();
-		conv_data.materials->push_back(mout);
-
-		// set material name
-		aiString name = aiString(mat->id.name+2); // skip over the name prefix 'MA'
-		mout->AddProperty(&name,AI_MATKEY_NAME);
-
-
-		// basic material colors
-		aiColor3D col(mat->r,mat->g,mat->b);
-		if (mat->r || mat->g || mat->b ) {
-			
-			// Usually, zero diffuse color means no diffuse color at all in the equation.
-			// So we omit this member to express this intent.
-			mout->AddProperty(&col,1,AI_MATKEY_COLOR_DIFFUSE);
-
-			if (mat->emit) {
-				aiColor3D emit_col(mat->emit * mat->r, mat->emit * mat->g, mat->emit * mat->b) ;
-				mout->AddProperty(&emit_col, 1, AI_MATKEY_COLOR_EMISSIVE) ;
-			}
-		}
-
-		col = aiColor3D(mat->specr,mat->specg,mat->specb);
-		mout->AddProperty(&col,1,AI_MATKEY_COLOR_SPECULAR);
-
-		// is hardness/shininess set?
-		if( mat->har ) {
-			const float har = mat->har;
-			mout->AddProperty(&har,1,AI_MATKEY_SHININESS);
-		}
-
-		col = aiColor3D(mat->ambr,mat->ambg,mat->ambb);
-		mout->AddProperty(&col,1,AI_MATKEY_COLOR_AMBIENT);
-
-		col = aiColor3D(mat->mirr,mat->mirg,mat->mirb);
-		mout->AddProperty(&col,1,AI_MATKEY_COLOR_REFLECTIVE);
-
-		for(size_t i = 0; i < sizeof(mat->mtex) / sizeof(mat->mtex[0]); ++i) {
-			if (!mat->mtex[i]) {
-				continue;
-			}
-
-			ResolveTexture(mout,mat.get(),mat->mtex[i].get(),conv_data);
-		}
-	}
+    conv_data.materials->reserve(conv_data.materials_raw.size());
+
+    // add a default material if necessary
+    unsigned int index = static_cast<unsigned int>( -1 );
+    for_each( aiMesh* mesh, conv_data.meshes.get() ) {
+        if (mesh->mMaterialIndex == static_cast<unsigned int>( -1 )) {
+
+            if (index == static_cast<unsigned int>( -1 )) {
+                // Setup a default material.
+                boost::shared_ptr<Material> p(new Material());
+                ai_assert(::strlen(AI_DEFAULT_MATERIAL_NAME) < sizeof(p->id.name)-2);
+                strcpy( p->id.name+2, AI_DEFAULT_MATERIAL_NAME );
+
+                // Note: MSVC11 does not zero-initialize Material here, although it should.
+                // Thus all relevant fields should be explicitly initialized. We cannot add
+                // a default constructor to Material since the DNA codegen does not support
+                // parsing it.
+                p->r = p->g = p->b = 0.6f;
+                p->specr = p->specg = p->specb = 0.6f;
+                p->ambr = p->ambg = p->ambb = 0.0f;
+                p->mirr = p->mirg = p->mirb = 0.0f;
+                p->emit = 0.f;
+                p->alpha = 0.f;
+                p->har = 0;
+
+                index = static_cast<unsigned int>( conv_data.materials_raw.size() );
+                conv_data.materials_raw.push_back(p);
+                LogInfo("Adding default material");
+            }
+            mesh->mMaterialIndex = index;
+        }
+    }
+
+    for_each(boost::shared_ptr<Material> mat, conv_data.materials_raw) {
+
+        // reset per material global counters
+        for (size_t i = 0; i < sizeof(conv_data.next_texture)/sizeof(conv_data.next_texture[0]);++i) {
+            conv_data.next_texture[i] = 0 ;
+        }
+
+        aiMaterial* mout = new aiMaterial();
+        conv_data.materials->push_back(mout);
+        // For any new material field handled here, the default material above must be updated with an appropriate default value.
+
+        // set material name
+        aiString name = aiString(mat->id.name+2); // skip over the name prefix 'MA'
+        mout->AddProperty(&name,AI_MATKEY_NAME);
+
+
+        // basic material colors
+        aiColor3D col(mat->r,mat->g,mat->b);
+        if (mat->r || mat->g || mat->b ) {
+
+            // Usually, zero diffuse color means no diffuse color at all in the equation.
+            // So we omit this member to express this intent.
+            mout->AddProperty(&col,1,AI_MATKEY_COLOR_DIFFUSE);
+
+            if (mat->emit) {
+                aiColor3D emit_col(mat->emit * mat->r, mat->emit * mat->g, mat->emit * mat->b) ;
+                mout->AddProperty(&emit_col, 1, AI_MATKEY_COLOR_EMISSIVE) ;
+            }
+        }
+
+        col = aiColor3D(mat->specr,mat->specg,mat->specb);
+        mout->AddProperty(&col,1,AI_MATKEY_COLOR_SPECULAR);
+
+        // is hardness/shininess set?
+        if( mat->har ) {
+            const float har = mat->har;
+            mout->AddProperty(&har,1,AI_MATKEY_SHININESS);
+        }
+
+        col = aiColor3D(mat->ambr,mat->ambg,mat->ambb);
+        mout->AddProperty(&col,1,AI_MATKEY_COLOR_AMBIENT);
+
+        col = aiColor3D(mat->mirr,mat->mirg,mat->mirb);
+        mout->AddProperty(&col,1,AI_MATKEY_COLOR_REFLECTIVE);
+
+        for(size_t i = 0; i < sizeof(mat->mtex) / sizeof(mat->mtex[0]); ++i) {
+            if (!mat->mtex[i]) {
+                continue;
+            }
+
+            ResolveTexture(mout,mat.get(),mat->mtex[i].get(),conv_data);
+        }
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 void BlenderImporter::CheckActualType(const ElemBase* dt, const char* check)
 {
-	ai_assert(dt);
-	if (strcmp(dt->dna_type,check)) {
-		ThrowException((format(),
-			"Expected object at ",std::hex,dt," to be of type `",check, 
-			"`, but it claims to be a `",dt->dna_type,"`instead"
-		));
-	}
+    ai_assert(dt);
+    if (strcmp(dt->dna_type,check)) {
+        ThrowException((format(),
+            "Expected object at ",std::hex,dt," to be of type `",check,
+            "`, but it claims to be a `",dt->dna_type,"`instead"
+        ));
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 void BlenderImporter::NotSupportedObjectType(const Object* obj, const char* type)
 {
-	LogWarn((format(), "Object `",obj->id.name,"` - type is unsupported: `",type, "`, skipping" ));
+    LogWarn((format(), "Object `",obj->id.name,"` - type is unsupported: `",type, "`, skipping" ));
 }
 
 // ------------------------------------------------------------------------------------------------
 void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, const Mesh* mesh,
-	ConversionData& conv_data, TempArray<std::vector,aiMesh>&  temp
-	) 
+    ConversionData& conv_data, TempArray<std::vector,aiMesh>&  temp
+    )
 {
-	BlenderBMeshConverter BMeshConverter( mesh );
-	if ( BMeshConverter.ContainsBMesh( ) )
-	{
-		mesh = BMeshConverter.TriangulateBMesh( );
-	}
-
-	typedef std::pair<const int,size_t> MyPair;
-	if ((!mesh->totface && !mesh->totloop) || !mesh->totvert) {
-		return;
-	}
-
-	// some sanity checks
-	if (static_cast<size_t> ( mesh->totface ) > mesh->mface.size() ){
-		ThrowException("Number of faces is larger than the corresponding array");
-	}
-
-	if (static_cast<size_t> ( mesh->totvert ) > mesh->mvert.size()) {
-		ThrowException("Number of vertices is larger than the corresponding array");
-	}
-
-	if (static_cast<size_t> ( mesh->totloop ) > mesh->mloop.size()) {
-		ThrowException("Number of vertices is larger than the corresponding array");
-	}
-
-	// collect per-submesh numbers
-	std::map<int,size_t> per_mat;
-	std::map<int,size_t> per_mat_verts;
-	for (int i = 0; i < mesh->totface; ++i) {
-
-		const MFace& mf = mesh->mface[i];
-		per_mat[ mf.mat_nr ]++;
-		per_mat_verts[ mf.mat_nr ] += mf.v4?4:3;
-	}
-
-	for (int i = 0; i < mesh->totpoly; ++i) {
-		const MPoly& mp = mesh->mpoly[i];
-		per_mat[ mp.mat_nr ]++;
-		per_mat_verts[ mp.mat_nr ] += mp.totloop;
-	}
-
-	// ... and allocate the corresponding meshes
-	const size_t old = temp->size();
-	temp->reserve(temp->size() + per_mat.size());
-
-	std::map<size_t,size_t> mat_num_to_mesh_idx;
-	for_each(MyPair& it, per_mat) {
-
-		mat_num_to_mesh_idx[it.first] = temp->size();
-		temp->push_back(new aiMesh());
-
-		aiMesh* out = temp->back();
-		out->mVertices = new aiVector3D[per_mat_verts[it.first]];
-		out->mNormals  = new aiVector3D[per_mat_verts[it.first]];
-
-		//out->mNumFaces = 0
-		//out->mNumVertices = 0
-		out->mFaces = new aiFace[it.second]();
-
-		// all submeshes created from this mesh are named equally. this allows
-		// curious users to recover the original adjacency.
-		out->mName = aiString(mesh->id.name+2);  
-			// skip over the name prefix 'ME'
-
-		// resolve the material reference and add this material to the set of
-		// output materials. The (temporary) material index is the index 
-		// of the material entry within the list of resolved materials.
-		if (mesh->mat) {
-
-			if (static_cast<size_t> ( it.first ) >= mesh->mat.size() ) {
-				ThrowException("Material index is out of range");
-			}
-
-			boost::shared_ptr<Material> mat = mesh->mat[it.first];
-			const std::deque< boost::shared_ptr<Material> >::iterator has = std::find(
-					conv_data.materials_raw.begin(),
-					conv_data.materials_raw.end(),mat
-			);
-
-			if (has != conv_data.materials_raw.end()) {
-				out->mMaterialIndex = static_cast<unsigned int>( std::distance(conv_data.materials_raw.begin(),has));
-			}
-			else {
-				out->mMaterialIndex = static_cast<unsigned int>( conv_data.materials_raw.size() );
-				conv_data.materials_raw.push_back(mat);
-			}
-		}
-		else out->mMaterialIndex = static_cast<unsigned int>( -1 );
-	}
-
-	for (int i = 0; i < mesh->totface; ++i) {
-
-		const MFace& mf = mesh->mface[i];
-
-		aiMesh* const out = temp[ mat_num_to_mesh_idx[ mf.mat_nr ] ];
-		aiFace& f = out->mFaces[out->mNumFaces++];
-
-		f.mIndices = new unsigned int[ f.mNumIndices = mf.v4?4:3 ];
-		aiVector3D* vo = out->mVertices + out->mNumVertices;
-		aiVector3D* vn = out->mNormals + out->mNumVertices;
-
-		// XXX we can't fold this easily, because we are restricted
-		// to the member names from the BLEND file (v1,v2,v3,v4) 
-		// which are assigned by the genblenddna.py script and
-		// cannot be changed without breaking the entire
-		// import process.
-
-		if (mf.v1 >= mesh->totvert) {
-			ThrowException("Vertex index v1 out of range");
-		}
-		const MVert* v = &mesh->mvert[mf.v1];
-		vo->x = v->co[0];
-		vo->y = v->co[1];
-		vo->z = v->co[2];
-		vn->x = v->no[0];
-		vn->y = v->no[1];
-		vn->z = v->no[2];
-		f.mIndices[0] = out->mNumVertices++;
-		++vo;
-		++vn;
-
-		//	if (f.mNumIndices >= 2) {
-		if (mf.v2 >= mesh->totvert) {
-			ThrowException("Vertex index v2 out of range");
-		}
-		v = &mesh->mvert[mf.v2];
-		vo->x = v->co[0];
-		vo->y = v->co[1];
-		vo->z = v->co[2];
-		vn->x = v->no[0];
-		vn->y = v->no[1];
-		vn->z = v->no[2];
-		f.mIndices[1] = out->mNumVertices++;
-		++vo;
-		++vn;
-
-		if (mf.v3 >= mesh->totvert) {
-			ThrowException("Vertex index v3 out of range");
-		}
-		//	if (f.mNumIndices >= 3) {
-		v = &mesh->mvert[mf.v3];
-		vo->x = v->co[0];
-		vo->y = v->co[1];
-		vo->z = v->co[2];
-		vn->x = v->no[0];
-		vn->y = v->no[1];
-		vn->z = v->no[2];
-		f.mIndices[2] = out->mNumVertices++;
-		++vo;
-		++vn;
-
-		if (mf.v4 >= mesh->totvert) {
-			ThrowException("Vertex index v4 out of range");
-		}
-		//	if (f.mNumIndices >= 4) {
-		if (mf.v4) {
-			v = &mesh->mvert[mf.v4];
-			vo->x = v->co[0];
-			vo->y = v->co[1];
-			vo->z = v->co[2];
-			vn->x = v->no[0];
-			vn->y = v->no[1];
-			vn->z = v->no[2];
-			f.mIndices[3] = out->mNumVertices++;
-			++vo;
-			++vn;
-
-			out->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
-		}
-		else out->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
-
-		//	}
-		//	}
-		//	}
-	}
-
-	for (int i = 0; i < mesh->totpoly; ++i) {
-		
-		const MPoly& mf = mesh->mpoly[i];
-		
-		aiMesh* const out = temp[ mat_num_to_mesh_idx[ mf.mat_nr ] ];
-		aiFace& f = out->mFaces[out->mNumFaces++];
-		
-		f.mIndices = new unsigned int[ f.mNumIndices = mf.totloop ];
-		aiVector3D* vo = out->mVertices + out->mNumVertices;
-		aiVector3D* vn = out->mNormals + out->mNumVertices;
-		
-		// XXX we can't fold this easily, because we are restricted
-		// to the member names from the BLEND file (v1,v2,v3,v4)
-		// which are assigned by the genblenddna.py script and
-		// cannot be changed without breaking the entire
-		// import process.
-		for (int j = 0;j < mf.totloop; ++j)
-		{
-			const MLoop& loop = mesh->mloop[mf.loopstart + j];
-
-			if (loop.v >= mesh->totvert) {
-				ThrowException("Vertex index out of range");
-			}
-
-			const MVert& v = mesh->mvert[loop.v];
-			
-			vo->x = v.co[0];
-			vo->y = v.co[1];
-			vo->z = v.co[2];
-			vn->x = v.no[0];
-			vn->y = v.no[1];
-			vn->z = v.no[2];
-			f.mIndices[j] = out->mNumVertices++;
-			
-			++vo;
-			++vn;
-			
-		}
-		if (mf.totloop == 3)
-		{
-			out->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
-		}
-		else
-		{
-			out->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
-		}
-	}
-	
-	// collect texture coordinates, they're stored in a separate per-face buffer
-	if (mesh->mtface || mesh->mloopuv) {
-		if (mesh->totface > static_cast<int> ( mesh->mtface.size())) {
-			ThrowException("Number of UV faces is larger than the corresponding UV face array (#1)");
-		}
-		for (std::vector<aiMesh*>::iterator it = temp->begin()+old; it != temp->end(); ++it) {
-			ai_assert((*it)->mNumVertices && (*it)->mNumFaces);
-
-			(*it)->mTextureCoords[0] = new aiVector3D[(*it)->mNumVertices];
-			(*it)->mNumFaces = (*it)->mNumVertices = 0;
-		}
-
-		for (int i = 0; i < mesh->totface; ++i) {
-			const MTFace* v = &mesh->mtface[i];
-
-			aiMesh* const out = temp[ mat_num_to_mesh_idx[ mesh->mface[i].mat_nr ] ];
-			const aiFace& f = out->mFaces[out->mNumFaces++];
-			
-			aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices];
-			for (unsigned int i = 0; i < f.mNumIndices; ++i,++vo,++out->mNumVertices) {
-				vo->x = v->uv[i][0];
-				vo->y = v->uv[i][1];
-			}
-		}
-		
-		for (int i = 0; i < mesh->totpoly; ++i) {
-			const MPoly& v = mesh->mpoly[i];
-			aiMesh* const out = temp[ mat_num_to_mesh_idx[ v.mat_nr ] ];
-			const aiFace& f = out->mFaces[out->mNumFaces++];
-			
-			aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices];
-			for (unsigned int j = 0; j < f.mNumIndices; ++j,++vo,++out->mNumVertices) {
-				const MLoopUV& uv = mesh->mloopuv[v.loopstart + j];
-				vo->x = uv.uv[0];
-				vo->y = uv.uv[1];
-			}
-			
-		}
-	}
-
-	// collect texture coordinates, old-style (marked as deprecated in current blender sources)
-	if (mesh->tface) {
-		if (mesh->totface > static_cast<int> ( mesh->tface.size())) {
-			ThrowException("Number of faces is larger than the corresponding UV face array (#2)");
-		}
-		for (std::vector<aiMesh*>::iterator it = temp->begin()+old; it != temp->end(); ++it) {
-			ai_assert((*it)->mNumVertices && (*it)->mNumFaces);
-
-			(*it)->mTextureCoords[0] = new aiVector3D[(*it)->mNumVertices];
-			(*it)->mNumFaces = (*it)->mNumVertices = 0;
-		}
-
-		for (int i = 0; i < mesh->totface; ++i) {
-			const TFace* v = &mesh->tface[i];
-
-			aiMesh* const out = temp[ mat_num_to_mesh_idx[ mesh->mface[i].mat_nr ] ];
-			const aiFace& f = out->mFaces[out->mNumFaces++];
-			
-			aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices];
-			for (unsigned int i = 0; i < f.mNumIndices; ++i,++vo,++out->mNumVertices) {
-				vo->x = v->uv[i][0];
-				vo->y = v->uv[i][1];
-			}
-		}
-	}
-
-	// collect vertex colors, stored separately as well
-	if (mesh->mcol || mesh->mloopcol) {
-		if (mesh->totface > static_cast<int> ( (mesh->mcol.size()/4)) ) {
-			ThrowException("Number of faces is larger than the corresponding color face array");
-		}
-		for (std::vector<aiMesh*>::iterator it = temp->begin()+old; it != temp->end(); ++it) {
-			ai_assert((*it)->mNumVertices && (*it)->mNumFaces);
-
-			(*it)->mColors[0] = new aiColor4D[(*it)->mNumVertices];
-			(*it)->mNumFaces = (*it)->mNumVertices = 0;
-		}
-
-		for (int i = 0; i < mesh->totface; ++i) {
-
-			aiMesh* const out = temp[ mat_num_to_mesh_idx[ mesh->mface[i].mat_nr ] ];
-			const aiFace& f = out->mFaces[out->mNumFaces++];
-			
-			aiColor4D* vo = &out->mColors[0][out->mNumVertices];
-			for (unsigned int n = 0; n < f.mNumIndices; ++n, ++vo,++out->mNumVertices) {
-				const MCol* col = &mesh->mcol[(i<<2)+n];
-
-				vo->r = col->r;
-				vo->g = col->g;
-				vo->b = col->b;
-				vo->a = col->a;
-			}
-			for (unsigned int n = f.mNumIndices; n < 4; ++n);
-		}
-		
-		for (int i = 0; i < mesh->totpoly; ++i) {
-			const MPoly& v = mesh->mpoly[i];
-			aiMesh* const out = temp[ mat_num_to_mesh_idx[ v.mat_nr ] ];
-			const aiFace& f = out->mFaces[out->mNumFaces++];
-			
-			aiColor4D* vo = &out->mColors[0][out->mNumVertices];
-			for (unsigned int j = 0; j < f.mNumIndices; ++j,++vo,++out->mNumVertices) {
-				const MLoopCol& col = mesh->mloopcol[v.loopstart + j];
-				vo->r = col.r;
-				vo->g = col.g;
-				vo->b = col.b;
-				vo->a = col.a;
-			}
-			
-		}
-
-	}
-
-	return;
+    // TODO: Resolve various problems with BMesh triangluation before re-enabling.
+    //       See issues #400, #373, #318  #315 and #132.
+#if defined(TODO_FIX_BMESH_CONVERSION)
+    BlenderBMeshConverter BMeshConverter( mesh );
+    if ( BMeshConverter.ContainsBMesh( ) )
+    {
+        mesh = BMeshConverter.TriangulateBMesh( );
+    }
+#endif
+
+    typedef std::pair<const int,size_t> MyPair;
+    if ((!mesh->totface && !mesh->totloop) || !mesh->totvert) {
+        return;
+    }
+
+    // some sanity checks
+    if (static_cast<size_t> ( mesh->totface ) > mesh->mface.size() ){
+        ThrowException("Number of faces is larger than the corresponding array");
+    }
+
+    if (static_cast<size_t> ( mesh->totvert ) > mesh->mvert.size()) {
+        ThrowException("Number of vertices is larger than the corresponding array");
+    }
+
+    if (static_cast<size_t> ( mesh->totloop ) > mesh->mloop.size()) {
+        ThrowException("Number of vertices is larger than the corresponding array");
+    }
+
+    // collect per-submesh numbers
+    std::map<int,size_t> per_mat;
+    std::map<int,size_t> per_mat_verts;
+    for (int i = 0; i < mesh->totface; ++i) {
+
+        const MFace& mf = mesh->mface[i];
+        per_mat[ mf.mat_nr ]++;
+        per_mat_verts[ mf.mat_nr ] += mf.v4?4:3;
+    }
+
+    for (int i = 0; i < mesh->totpoly; ++i) {
+        const MPoly& mp = mesh->mpoly[i];
+        per_mat[ mp.mat_nr ]++;
+        per_mat_verts[ mp.mat_nr ] += mp.totloop;
+    }
+
+    // ... and allocate the corresponding meshes
+    const size_t old = temp->size();
+    temp->reserve(temp->size() + per_mat.size());
+
+    std::map<size_t,size_t> mat_num_to_mesh_idx;
+    for_each(MyPair& it, per_mat) {
+
+        mat_num_to_mesh_idx[it.first] = temp->size();
+        temp->push_back(new aiMesh());
+
+        aiMesh* out = temp->back();
+        out->mVertices = new aiVector3D[per_mat_verts[it.first]];
+        out->mNormals  = new aiVector3D[per_mat_verts[it.first]];
+
+        //out->mNumFaces = 0
+        //out->mNumVertices = 0
+        out->mFaces = new aiFace[it.second]();
+
+        // all submeshes created from this mesh are named equally. this allows
+        // curious users to recover the original adjacency.
+        out->mName = aiString(mesh->id.name+2);
+            // skip over the name prefix 'ME'
+
+        // resolve the material reference and add this material to the set of
+        // output materials. The (temporary) material index is the index
+        // of the material entry within the list of resolved materials.
+        if (mesh->mat) {
+
+            if (static_cast<size_t> ( it.first ) >= mesh->mat.size() ) {
+                ThrowException("Material index is out of range");
+            }
+
+            boost::shared_ptr<Material> mat = mesh->mat[it.first];
+            const std::deque< boost::shared_ptr<Material> >::iterator has = std::find(
+                    conv_data.materials_raw.begin(),
+                    conv_data.materials_raw.end(),mat
+            );
+
+            if (has != conv_data.materials_raw.end()) {
+                out->mMaterialIndex = static_cast<unsigned int>( std::distance(conv_data.materials_raw.begin(),has));
+            }
+            else {
+                out->mMaterialIndex = static_cast<unsigned int>( conv_data.materials_raw.size() );
+                conv_data.materials_raw.push_back(mat);
+            }
+        }
+        else out->mMaterialIndex = static_cast<unsigned int>( -1 );
+    }
+
+    for (int i = 0; i < mesh->totface; ++i) {
+
+        const MFace& mf = mesh->mface[i];
+
+        aiMesh* const out = temp[ mat_num_to_mesh_idx[ mf.mat_nr ] ];
+        aiFace& f = out->mFaces[out->mNumFaces++];
+
+        f.mIndices = new unsigned int[ f.mNumIndices = mf.v4?4:3 ];
+        aiVector3D* vo = out->mVertices + out->mNumVertices;
+        aiVector3D* vn = out->mNormals + out->mNumVertices;
+
+        // XXX we can't fold this easily, because we are restricted
+        // to the member names from the BLEND file (v1,v2,v3,v4)
+        // which are assigned by the genblenddna.py script and
+        // cannot be changed without breaking the entire
+        // import process.
+
+        if (mf.v1 >= mesh->totvert) {
+            ThrowException("Vertex index v1 out of range");
+        }
+        const MVert* v = &mesh->mvert[mf.v1];
+        vo->x = v->co[0];
+        vo->y = v->co[1];
+        vo->z = v->co[2];
+        vn->x = v->no[0];
+        vn->y = v->no[1];
+        vn->z = v->no[2];
+        f.mIndices[0] = out->mNumVertices++;
+        ++vo;
+        ++vn;
+
+        //  if (f.mNumIndices >= 2) {
+        if (mf.v2 >= mesh->totvert) {
+            ThrowException("Vertex index v2 out of range");
+        }
+        v = &mesh->mvert[mf.v2];
+        vo->x = v->co[0];
+        vo->y = v->co[1];
+        vo->z = v->co[2];
+        vn->x = v->no[0];
+        vn->y = v->no[1];
+        vn->z = v->no[2];
+        f.mIndices[1] = out->mNumVertices++;
+        ++vo;
+        ++vn;
+
+        if (mf.v3 >= mesh->totvert) {
+            ThrowException("Vertex index v3 out of range");
+        }
+        //  if (f.mNumIndices >= 3) {
+        v = &mesh->mvert[mf.v3];
+        vo->x = v->co[0];
+        vo->y = v->co[1];
+        vo->z = v->co[2];
+        vn->x = v->no[0];
+        vn->y = v->no[1];
+        vn->z = v->no[2];
+        f.mIndices[2] = out->mNumVertices++;
+        ++vo;
+        ++vn;
+
+        if (mf.v4 >= mesh->totvert) {
+            ThrowException("Vertex index v4 out of range");
+        }
+        //  if (f.mNumIndices >= 4) {
+        if (mf.v4) {
+            v = &mesh->mvert[mf.v4];
+            vo->x = v->co[0];
+            vo->y = v->co[1];
+            vo->z = v->co[2];
+            vn->x = v->no[0];
+            vn->y = v->no[1];
+            vn->z = v->no[2];
+            f.mIndices[3] = out->mNumVertices++;
+            ++vo;
+            ++vn;
+
+            out->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
+        }
+        else out->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
+
+        //  }
+        //  }
+        //  }
+    }
+
+    for (int i = 0; i < mesh->totpoly; ++i) {
+
+        const MPoly& mf = mesh->mpoly[i];
+
+        aiMesh* const out = temp[ mat_num_to_mesh_idx[ mf.mat_nr ] ];
+        aiFace& f = out->mFaces[out->mNumFaces++];
+
+        f.mIndices = new unsigned int[ f.mNumIndices = mf.totloop ];
+        aiVector3D* vo = out->mVertices + out->mNumVertices;
+        aiVector3D* vn = out->mNormals + out->mNumVertices;
+
+        // XXX we can't fold this easily, because we are restricted
+        // to the member names from the BLEND file (v1,v2,v3,v4)
+        // which are assigned by the genblenddna.py script and
+        // cannot be changed without breaking the entire
+        // import process.
+        for (int j = 0;j < mf.totloop; ++j)
+        {
+            const MLoop& loop = mesh->mloop[mf.loopstart + j];
+
+            if (loop.v >= mesh->totvert) {
+                ThrowException("Vertex index out of range");
+            }
+
+            const MVert& v = mesh->mvert[loop.v];
+
+            vo->x = v.co[0];
+            vo->y = v.co[1];
+            vo->z = v.co[2];
+            vn->x = v.no[0];
+            vn->y = v.no[1];
+            vn->z = v.no[2];
+            f.mIndices[j] = out->mNumVertices++;
+
+            ++vo;
+            ++vn;
+
+        }
+        if (mf.totloop == 3)
+        {
+            out->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE;
+        }
+        else
+        {
+            out->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
+        }
+    }
+
+    // collect texture coordinates, they're stored in a separate per-face buffer
+    if (mesh->mtface || mesh->mloopuv) {
+        if (mesh->totface > static_cast<int> ( mesh->mtface.size())) {
+            ThrowException("Number of UV faces is larger than the corresponding UV face array (#1)");
+        }
+        for (std::vector<aiMesh*>::iterator it = temp->begin()+old; it != temp->end(); ++it) {
+            ai_assert((*it)->mNumVertices && (*it)->mNumFaces);
+
+            (*it)->mTextureCoords[0] = new aiVector3D[(*it)->mNumVertices];
+            (*it)->mNumFaces = (*it)->mNumVertices = 0;
+        }
+
+        for (int i = 0; i < mesh->totface; ++i) {
+            const MTFace* v = &mesh->mtface[i];
+
+            aiMesh* const out = temp[ mat_num_to_mesh_idx[ mesh->mface[i].mat_nr ] ];
+            const aiFace& f = out->mFaces[out->mNumFaces++];
+
+            aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices];
+            for (unsigned int i = 0; i < f.mNumIndices; ++i,++vo,++out->mNumVertices) {
+                vo->x = v->uv[i][0];
+                vo->y = v->uv[i][1];
+            }
+        }
+
+        for (int i = 0; i < mesh->totpoly; ++i) {
+            const MPoly& v = mesh->mpoly[i];
+            aiMesh* const out = temp[ mat_num_to_mesh_idx[ v.mat_nr ] ];
+            const aiFace& f = out->mFaces[out->mNumFaces++];
+
+            aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices];
+            for (unsigned int j = 0; j < f.mNumIndices; ++j,++vo,++out->mNumVertices) {
+                const MLoopUV& uv = mesh->mloopuv[v.loopstart + j];
+                vo->x = uv.uv[0];
+                vo->y = uv.uv[1];
+            }
+
+        }
+    }
+
+    // collect texture coordinates, old-style (marked as deprecated in current blender sources)
+    if (mesh->tface) {
+        if (mesh->totface > static_cast<int> ( mesh->tface.size())) {
+            ThrowException("Number of faces is larger than the corresponding UV face array (#2)");
+        }
+        for (std::vector<aiMesh*>::iterator it = temp->begin()+old; it != temp->end(); ++it) {
+            ai_assert((*it)->mNumVertices && (*it)->mNumFaces);
+
+            (*it)->mTextureCoords[0] = new aiVector3D[(*it)->mNumVertices];
+            (*it)->mNumFaces = (*it)->mNumVertices = 0;
+        }
+
+        for (int i = 0; i < mesh->totface; ++i) {
+            const TFace* v = &mesh->tface[i];
+
+            aiMesh* const out = temp[ mat_num_to_mesh_idx[ mesh->mface[i].mat_nr ] ];
+            const aiFace& f = out->mFaces[out->mNumFaces++];
+
+            aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices];
+            for (unsigned int i = 0; i < f.mNumIndices; ++i,++vo,++out->mNumVertices) {
+                vo->x = v->uv[i][0];
+                vo->y = v->uv[i][1];
+            }
+        }
+    }
+
+    // collect vertex colors, stored separately as well
+    if (mesh->mcol || mesh->mloopcol) {
+        if (mesh->totface > static_cast<int> ( (mesh->mcol.size()/4)) ) {
+            ThrowException("Number of faces is larger than the corresponding color face array");
+        }
+        for (std::vector<aiMesh*>::iterator it = temp->begin()+old; it != temp->end(); ++it) {
+            ai_assert((*it)->mNumVertices && (*it)->mNumFaces);
+
+            (*it)->mColors[0] = new aiColor4D[(*it)->mNumVertices];
+            (*it)->mNumFaces = (*it)->mNumVertices = 0;
+        }
+
+        for (int i = 0; i < mesh->totface; ++i) {
+
+            aiMesh* const out = temp[ mat_num_to_mesh_idx[ mesh->mface[i].mat_nr ] ];
+            const aiFace& f = out->mFaces[out->mNumFaces++];
+
+            aiColor4D* vo = &out->mColors[0][out->mNumVertices];
+            for (unsigned int n = 0; n < f.mNumIndices; ++n, ++vo,++out->mNumVertices) {
+                const MCol* col = &mesh->mcol[(i<<2)+n];
+
+                vo->r = col->r;
+                vo->g = col->g;
+                vo->b = col->b;
+                vo->a = col->a;
+            }
+            for (unsigned int n = f.mNumIndices; n < 4; ++n);
+        }
+
+        for (int i = 0; i < mesh->totpoly; ++i) {
+            const MPoly& v = mesh->mpoly[i];
+            aiMesh* const out = temp[ mat_num_to_mesh_idx[ v.mat_nr ] ];
+            const aiFace& f = out->mFaces[out->mNumFaces++];
+
+            aiColor4D* vo = &out->mColors[0][out->mNumVertices];
+            for (unsigned int j = 0; j < f.mNumIndices; ++j,++vo,++out->mNumVertices) {
+                const MLoopCol& col = mesh->mloopcol[v.loopstart + j];
+                vo->r = col.r;
+                vo->g = col.g;
+                vo->b = col.b;
+                vo->a = col.a;
+            }
+
+        }
+
+    }
+
+    return;
 }
 
 // ------------------------------------------------------------------------------------------------
-aiCamera* BlenderImporter::ConvertCamera(const Scene& /*in*/, const Object* obj, const Camera* camera, ConversionData& /*conv_data*/)
+aiCamera* BlenderImporter::ConvertCamera(const Scene& /*in*/, const Object* obj, const Camera* /*camera*/, ConversionData& /*conv_data*/)
 {
-	ScopeGuard<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);
-	out->mLookAt = aiVector3D(0.f, 0.f, -1.f);
-	return out.dismiss();
+    ScopeGuard<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);
+    out->mLookAt = aiVector3D(0.f, 0.f, -1.f);
+    return out.dismiss();
 }
 
 // ------------------------------------------------------------------------------------------------
-aiLight* BlenderImporter::ConvertLight(const Scene& in, const Object* obj, const Lamp* lamp, ConversionData& conv_data)
+aiLight* BlenderImporter::ConvertLight(const Scene& /*in*/, const Object* obj, const Lamp* lamp, ConversionData& /*conv_data*/)
 {
-	ScopeGuard<aiLight> out(new aiLight());
-	out->mName = obj->id.name+2;
-
-	switch (lamp->type)
-	{
-	    case Lamp::Type_Local:
-	        out->mType = aiLightSource_POINT;
-	        break;
-	    case Lamp::Type_Sun:
-	        out->mType = aiLightSource_DIRECTIONAL;
-
-	        // blender orients directional lights as facing toward -z
-	        out->mDirection = aiVector3D(0.f, 0.f, -1.f);
-	        break;
-	    default:
-	        break;
-	}
-
-	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();
+    ScopeGuard<aiLight> out(new aiLight());
+    out->mName = obj->id.name+2;
+
+    switch (lamp->type)
+    {
+        case Lamp::Type_Local:
+            out->mType = aiLightSource_POINT;
+            break;
+        case Lamp::Type_Sun:
+            out->mType = aiLightSource_DIRECTIONAL;
+
+            // blender orients directional lights as facing toward -z
+            out->mDirection = aiVector3D(0.f, 0.f, -1.f);
+            break;
+        default:
+            break;
+    }
+
+    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();
 }
 
 // ------------------------------------------------------------------------------------------------
 aiNode* BlenderImporter::ConvertNode(const Scene& in, const Object* obj, ConversionData& conv_data, const aiMatrix4x4& parentTransform)
 {
-	std::deque<const Object*> children;
-	for(std::set<const Object*>::iterator it = conv_data.objects.begin(); it != conv_data.objects.end() ;) {
-		const Object* object = *it;
-		if (object->parent == obj) {
-			children.push_back(object);
-
-			conv_data.objects.erase(it++);
-			continue;
-		}
-		++it;
-	}
-
-	ScopeGuard<aiNode> node(new aiNode(obj->id.name+2)); // skip over the name prefix 'OB'
-	if (obj->data) {
-		switch (obj->type)
-		{
-		case Object :: Type_EMPTY:
-			break; // do nothing
-
-
-			// supported object types
-		case Object :: Type_MESH: {
-			const size_t old = conv_data.meshes->size();
-
-			CheckActualType(obj->data.get(),"Mesh");
-			ConvertMesh(in,obj,static_cast<const Mesh*>(obj->data.get()),conv_data,conv_data.meshes);
-
-			if (conv_data.meshes->size() > old) {
-				node->mMeshes = new unsigned int[node->mNumMeshes = static_cast<unsigned int>(conv_data.meshes->size()-old)];
-				for (unsigned int i = 0; i < node->mNumMeshes; ++i) {
-					node->mMeshes[i] = i + old;
-				}
-			}}
-			break;
-		case Object :: Type_LAMP: {
-			CheckActualType(obj->data.get(),"Lamp");
-			aiLight* mesh = ConvertLight(in,obj,static_cast<const Lamp*>(
-				obj->data.get()),conv_data);
-
-			if (mesh) {
-				conv_data.lights->push_back(mesh);
-			}}
-			break;
-		case Object :: Type_CAMERA: {
-			CheckActualType(obj->data.get(),"Camera");
-			aiCamera* mesh = ConvertCamera(in,obj,static_cast<const Camera*>(
-				obj->data.get()),conv_data);
-
-			if (mesh) {
-				conv_data.cameras->push_back(mesh);
-			}}
-			break;
-
-
-			// unsupported object types / log, but do not break
-		case Object :: Type_CURVE:
-			NotSupportedObjectType(obj,"Curve");
-			break;
-		case Object :: Type_SURF:
-			NotSupportedObjectType(obj,"Surface");
-			break;
-		case Object :: Type_FONT:
-			NotSupportedObjectType(obj,"Font");
-			break;
-		case Object :: Type_MBALL:
-			NotSupportedObjectType(obj,"MetaBall");
-			break;
-		case Object :: Type_WAVE:
-			NotSupportedObjectType(obj,"Wave");
-			break;
-		case Object :: Type_LATTICE:
-			NotSupportedObjectType(obj,"Lattice");
-			break;
-
-			// invalid or unknown type
-		default:
-			break;
-		}
-	}
-
-	for(unsigned int x = 0; x < 4; ++x) {
-		for(unsigned int y = 0; y < 4; ++y) {
-			node->mTransformation[y][x] = obj->obmat[x][y];
-		}
-	}
-
-	aiMatrix4x4 m = parentTransform;
-	m = m.Inverse();
-
-	node->mTransformation = m*node->mTransformation;
-	
-	if (children.size()) {
-		node->mNumChildren = static_cast<unsigned int>(children.size());
-		aiNode** nd = node->mChildren = new aiNode*[node->mNumChildren]();
-		for_each (const Object* nobj,children) {
-			*nd = ConvertNode(in,nobj,conv_data,node->mTransformation * parentTransform);
-			(*nd++)->mParent = node;
-		}
-	}
-
-	// apply modifiers
-	modifier_cache->ApplyModifiers(*node,conv_data,in,*obj);
-
-	return node.dismiss();
+    std::deque<const Object*> children;
+    for(ObjectSet::iterator it = conv_data.objects.begin(); it != conv_data.objects.end() ;) {
+        const Object* object = *it;
+        if (object->parent == obj) {
+            children.push_back(object);
+
+            conv_data.objects.erase(it++);
+            continue;
+        }
+        ++it;
+    }
+
+    ScopeGuard<aiNode> node(new aiNode(obj->id.name+2)); // skip over the name prefix 'OB'
+    if (obj->data) {
+        switch (obj->type)
+        {
+        case Object :: Type_EMPTY:
+            break; // do nothing
+
+
+            // supported object types
+        case Object :: Type_MESH: {
+            const size_t old = conv_data.meshes->size();
+
+            CheckActualType(obj->data.get(),"Mesh");
+            ConvertMesh(in,obj,static_cast<const Mesh*>(obj->data.get()),conv_data,conv_data.meshes);
+
+            if (conv_data.meshes->size() > old) {
+                node->mMeshes = new unsigned int[node->mNumMeshes = static_cast<unsigned int>(conv_data.meshes->size()-old)];
+                for (unsigned int i = 0; i < node->mNumMeshes; ++i) {
+                    node->mMeshes[i] = i + old;
+                }
+            }}
+            break;
+        case Object :: Type_LAMP: {
+            CheckActualType(obj->data.get(),"Lamp");
+            aiLight* mesh = ConvertLight(in,obj,static_cast<const Lamp*>(
+                obj->data.get()),conv_data);
+
+            if (mesh) {
+                conv_data.lights->push_back(mesh);
+            }}
+            break;
+        case Object :: Type_CAMERA: {
+            CheckActualType(obj->data.get(),"Camera");
+            aiCamera* mesh = ConvertCamera(in,obj,static_cast<const Camera*>(
+                obj->data.get()),conv_data);
+
+            if (mesh) {
+                conv_data.cameras->push_back(mesh);
+            }}
+            break;
+
+
+            // unsupported object types / log, but do not break
+        case Object :: Type_CURVE:
+            NotSupportedObjectType(obj,"Curve");
+            break;
+        case Object :: Type_SURF:
+            NotSupportedObjectType(obj,"Surface");
+            break;
+        case Object :: Type_FONT:
+            NotSupportedObjectType(obj,"Font");
+            break;
+        case Object :: Type_MBALL:
+            NotSupportedObjectType(obj,"MetaBall");
+            break;
+        case Object :: Type_WAVE:
+            NotSupportedObjectType(obj,"Wave");
+            break;
+        case Object :: Type_LATTICE:
+            NotSupportedObjectType(obj,"Lattice");
+            break;
+
+            // invalid or unknown type
+        default:
+            break;
+        }
+    }
+
+    for(unsigned int x = 0; x < 4; ++x) {
+        for(unsigned int y = 0; y < 4; ++y) {
+            node->mTransformation[y][x] = obj->obmat[x][y];
+        }
+    }
+
+    aiMatrix4x4 m = parentTransform;
+    m = m.Inverse();
+
+    node->mTransformation = m*node->mTransformation;
+
+    if (children.size()) {
+        node->mNumChildren = static_cast<unsigned int>(children.size());
+        aiNode** nd = node->mChildren = new aiNode*[node->mNumChildren]();
+        for_each (const Object* nobj,children) {
+            *nd = ConvertNode(in,nobj,conv_data,node->mTransformation * parentTransform);
+            (*nd++)->mParent = node;
+        }
+    }
+
+    // apply modifiers
+    modifier_cache->ApplyModifiers(*node,conv_data,in,*obj);
+
+    return node.dismiss();
 }
 
 

+ 152 - 145
assimplib.mod/assimp/code/BlenderLoader.h

@@ -2,11 +2,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -23,16 +23,16 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -46,44 +46,51 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include "BaseImporter.h"
 #include "LogAux.h"
-
-namespace Assimp	{
-	
-	// TinyFormatter.h
-	namespace Formatter {
-		template <typename T,typename TR, typename A> class basic_formatter;
-		typedef class basic_formatter< char, std::char_traits<char>, std::allocator<char> > format;
-	}
-
-	// BlenderDNA.h
-	namespace Blender {
-		class  FileDatabase;
-		struct ElemBase;
-	}
-
-	// BlenderScene.h
-	namespace Blender {
-		struct Scene;
-		struct Object;
-		struct Mesh;
-		struct Camera;
-		struct Lamp;
-		struct MTex;
-		struct Image;
-		struct Material;
-	}
-
-	// BlenderIntermediate.h
-	namespace Blender {
-		struct ConversionData;
-		template <template <typename,typename> class TCLASS, typename T> struct TempArray;
-	}
-
-	// BlenderModifier.h
-	namespace Blender {
-		class BlenderModifierShowcase;
-		class BlenderModifier;
-	}
+#include <boost/shared_ptr.hpp>
+
+struct aiNode;
+struct aiMesh;
+struct aiLight;
+struct aiCamera;
+struct aiMaterial;
+
+namespace Assimp    {
+
+    // TinyFormatter.h
+    namespace Formatter {
+        template <typename T,typename TR, typename A> class basic_formatter;
+        typedef class basic_formatter< char, std::char_traits<char>, std::allocator<char> > format;
+    }
+
+    // BlenderDNA.h
+    namespace Blender {
+        class  FileDatabase;
+        struct ElemBase;
+    }
+
+    // BlenderScene.h
+    namespace Blender {
+        struct Scene;
+        struct Object;
+        struct Mesh;
+        struct Camera;
+        struct Lamp;
+        struct MTex;
+        struct Image;
+        struct Material;
+    }
+
+    // BlenderIntermediate.h
+    namespace Blender {
+        struct ConversionData;
+        template <template <typename,typename> class TCLASS, typename T> struct TempArray;
+    }
+
+    // BlenderModifier.h
+    namespace Blender {
+        class BlenderModifierShowcase;
+        class BlenderModifier;
+    }
 
 
 
@@ -95,127 +102,127 @@ namespace Assimp	{
 class BlenderImporter : public BaseImporter, public LogFunctions<BlenderImporter>
 {
 public:
-	BlenderImporter();
-	~BlenderImporter();
+    BlenderImporter();
+    ~BlenderImporter();
 
 
 public:
 
-	// --------------------
-	bool CanRead( const std::string& pFile, 
-		IOSystem* pIOHandler,
-		bool checkSig
-	) const;
+    // --------------------
+    bool CanRead( const std::string& pFile,
+        IOSystem* pIOHandler,
+        bool checkSig
+    ) const;
 
 protected:
 
-	// --------------------
-	const aiImporterDesc* GetInfo () const;
+    // --------------------
+    const aiImporterDesc* GetInfo () const;
 
-	// --------------------
-	void GetExtensionList(std::set<std::string>& app);
+    // --------------------
+    void GetExtensionList(std::set<std::string>& app);
 
-	// --------------------
-	void SetupProperties(const Importer* pImp);
+    // --------------------
+    void SetupProperties(const Importer* pImp);
 
-	// --------------------
-	void InternReadFile( const std::string& pFile, 
-		aiScene* pScene, 
-		IOSystem* pIOHandler
-	);
+    // --------------------
+    void InternReadFile( const std::string& pFile,
+        aiScene* pScene,
+        IOSystem* pIOHandler
+    );
 
-	// --------------------
-	void ParseBlendFile(Blender::FileDatabase& out, 
-		boost::shared_ptr<IOStream> stream
-	);
+    // --------------------
+    void ParseBlendFile(Blender::FileDatabase& out,
+        boost::shared_ptr<IOStream> stream
+    );
 
-	// --------------------
-	void ExtractScene(Blender::Scene& out, 
-		const Blender::FileDatabase& file
-	); 
+    // --------------------
+    void ExtractScene(Blender::Scene& out,
+        const Blender::FileDatabase& file
+    );
 
-	// --------------------
-	void ConvertBlendFile(aiScene* out,
-		const Blender::Scene& in,
-		const Blender::FileDatabase& file
-	);
+    // --------------------
+    void ConvertBlendFile(aiScene* out,
+        const Blender::Scene& in,
+        const Blender::FileDatabase& file
+    );
 
 private:
 
-	// --------------------
-	aiNode* ConvertNode(const Blender::Scene& in, 
-		const Blender::Object* obj, 
-		Blender::ConversionData& conv_info,
-		const aiMatrix4x4& parentTransform
-	); 
-
-	// --------------------
-	void ConvertMesh(const Blender::Scene& in, 
-		const Blender::Object* obj, 
-		const Blender::Mesh* mesh, 
-		Blender::ConversionData& conv_data,
-		Blender::TempArray<std::vector,aiMesh>& temp
-	); 
-
-	// --------------------
-	aiLight* ConvertLight(const Blender::Scene& in, 
-		const Blender::Object* obj, 
-		const Blender::Lamp* mesh, 
-		Blender::ConversionData& conv_data
-	); 
-
-	// --------------------
-	aiCamera* ConvertCamera(const Blender::Scene& in, 
-		const Blender::Object* obj, 
-		const Blender::Camera* mesh, 
-		Blender::ConversionData& conv_data
-	); 
-
-	// --------------------
-	void BuildMaterials(
-		Blender::ConversionData& conv_data
-	) ;
-
-	// --------------------
-	void ResolveTexture(
-		aiMaterial* out, 
-		const Blender::Material* mat, 
-		const Blender::MTex* tex,
-		Blender::ConversionData& conv_data
-	);
-
-	// --------------------
-	void ResolveImage(
-		aiMaterial* out, 
-		const Blender::Material* mat, 
-		const Blender::MTex* tex, 
-		const Blender::Image* img,
-		Blender::ConversionData& conv_data
-	);
-
-	void AddSentinelTexture(
-		aiMaterial* out, 
-		const Blender::Material* mat,
-		const Blender::MTex* tex, 
-		Blender::ConversionData& conv_data
-	);
+    // --------------------
+    aiNode* ConvertNode(const Blender::Scene& in,
+        const Blender::Object* obj,
+        Blender::ConversionData& conv_info,
+        const aiMatrix4x4& parentTransform
+    );
+
+    // --------------------
+    void ConvertMesh(const Blender::Scene& in,
+        const Blender::Object* obj,
+        const Blender::Mesh* mesh,
+        Blender::ConversionData& conv_data,
+        Blender::TempArray<std::vector,aiMesh>& temp
+    );
+
+    // --------------------
+    aiLight* ConvertLight(const Blender::Scene& in,
+        const Blender::Object* obj,
+        const Blender::Lamp* mesh,
+        Blender::ConversionData& conv_data
+    );
+
+    // --------------------
+    aiCamera* ConvertCamera(const Blender::Scene& in,
+        const Blender::Object* obj,
+        const Blender::Camera* mesh,
+        Blender::ConversionData& conv_data
+    );
+
+    // --------------------
+    void BuildMaterials(
+        Blender::ConversionData& conv_data
+    ) ;
+
+    // --------------------
+    void ResolveTexture(
+        aiMaterial* out,
+        const Blender::Material* mat,
+        const Blender::MTex* tex,
+        Blender::ConversionData& conv_data
+    );
+
+    // --------------------
+    void ResolveImage(
+        aiMaterial* out,
+        const Blender::Material* mat,
+        const Blender::MTex* tex,
+        const Blender::Image* img,
+        Blender::ConversionData& conv_data
+    );
+
+    void AddSentinelTexture(
+        aiMaterial* out,
+        const Blender::Material* mat,
+        const Blender::MTex* tex,
+        Blender::ConversionData& conv_data
+    );
 
 private: // static stuff, mostly logging and error reporting.
 
-	// --------------------
-	static void CheckActualType(const Blender::ElemBase* dt, 
-		const char* check
-	);
+    // --------------------
+    static void CheckActualType(const Blender::ElemBase* dt,
+        const char* check
+    );
 
-	// --------------------
-	static void NotSupportedObjectType(const Blender::Object* obj, 
-		const char* type
-	);
+    // --------------------
+    static void NotSupportedObjectType(const Blender::Object* obj,
+        const char* type
+    );
 
 
 private:
 
-	Blender::BlenderModifierShowcase* modifier_cache;
+    Blender::BlenderModifierShowcase* modifier_cache;
 
 }; // !class BlenderImporter
 

+ 222 - 218
assimplib.mod/assimp/code/BlenderModifier.cpp

@@ -2,11 +2,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -23,16 +23,16 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -41,12 +41,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 /** @file  BlenderModifier.cpp
  *  @brief Implementation of some blender modifiers (i.e subdivision, mirror).
  */
-#include "AssimpPCH.h"
+
 
 #ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
 #include "BlenderModifier.h"
 #include "SceneCombiner.h"
 #include "Subdivision.h"
+#include "../include/assimp/scene.h"
+#include <boost/scoped_ptr.hpp>
+#include <boost/scoped_array.hpp>
+#include <boost/pointer_cast.hpp>
 
 #include <functional>
 
@@ -54,120 +58,120 @@ using namespace Assimp;
 using namespace Assimp::Blender;
 
 template <typename T> BlenderModifier* god() {
-	return new T();
+    return new T();
 }
 
 // add all available modifiers here
 typedef BlenderModifier* (*fpCreateModifier)();
 static const fpCreateModifier creators[] = {
-		&god<BlenderModifier_Mirror>,
-		&god<BlenderModifier_Subdivision>,
+        &god<BlenderModifier_Mirror>,
+        &god<BlenderModifier_Subdivision>,
 
-		NULL // sentinel
+        NULL // sentinel
 };
 
 // ------------------------------------------------------------------------------------------------
 // just testing out some new macros to simplify logging
 #define ASSIMP_LOG_WARN_F(string,...)\
-	DefaultLogger::get()->warn((Formatter::format(string),__VA_ARGS__))
+    DefaultLogger::get()->warn((Formatter::format(string),__VA_ARGS__))
 
 #define ASSIMP_LOG_ERROR_F(string,...)\
-	DefaultLogger::get()->error((Formatter::format(string),__VA_ARGS__))
+    DefaultLogger::get()->error((Formatter::format(string),__VA_ARGS__))
 
 #define ASSIMP_LOG_DEBUG_F(string,...)\
-	DefaultLogger::get()->debug((Formatter::format(string),__VA_ARGS__))
+    DefaultLogger::get()->debug((Formatter::format(string),__VA_ARGS__))
 
 #define ASSIMP_LOG_INFO_F(string,...)\
-	DefaultLogger::get()->info((Formatter::format(string),__VA_ARGS__))
+    DefaultLogger::get()->info((Formatter::format(string),__VA_ARGS__))
 
 
 #define ASSIMP_LOG_WARN(string)\
-	DefaultLogger::get()->warn(string)
+    DefaultLogger::get()->warn(string)
 
 #define ASSIMP_LOG_ERROR(string)\
-	DefaultLogger::get()->error(string)
+    DefaultLogger::get()->error(string)
 
 #define ASSIMP_LOG_DEBUG(string)\
-	DefaultLogger::get()->debug(string)
+    DefaultLogger::get()->debug(string)
 
 #define ASSIMP_LOG_INFO(string)\
-	DefaultLogger::get()->info(string)
+    DefaultLogger::get()->info(string)
 
 
 // ------------------------------------------------------------------------------------------------
 struct SharedModifierData : ElemBase
 {
-	ModifierData modifier;
+    ModifierData modifier;
 };
 
 // ------------------------------------------------------------------------------------------------
-void BlenderModifierShowcase::ApplyModifiers(aiNode& out, ConversionData& conv_data, const Scene& in, const Object& orig_object ) 
+void BlenderModifierShowcase::ApplyModifiers(aiNode& out, ConversionData& conv_data, const Scene& in, const Object& orig_object )
 {
-	size_t cnt = 0u, ful = 0u;
-
-	// NOTE: this cast is potentially unsafe by design, so we need to perform type checks before
-	// we're allowed to dereference the pointers without risking to crash. We might still be
-	// invoking UB btw - we're assuming that the ModifierData member of the respective modifier
-	// structures is at offset sizeof(vftable) with no padding.
-	const SharedModifierData* cur = boost::static_pointer_cast<const SharedModifierData> ( orig_object.modifiers.first.get() );
-	for (; cur; cur =  boost::static_pointer_cast<const SharedModifierData> ( cur->modifier.next.get() ), ++ful) {
-		ai_assert(cur->dna_type);
-
-		const Structure* s = conv_data.db.dna.Get( cur->dna_type );
-		if (!s) {
-			ASSIMP_LOG_WARN_F("BlendModifier: could not resolve DNA name: ",cur->dna_type);
-			continue;
-		}
-
-		// this is a common trait of all XXXMirrorData structures in BlenderDNA
-		const Field* f = s->Get("modifier");
-		if (!f || f->offset != 0) {
-			ASSIMP_LOG_WARN("BlendModifier: expected a `modifier` member at offset 0");
-			continue;
-		}
-
-		s = conv_data.db.dna.Get( f->type );
-		if (!s || s->name != "ModifierData") {
-			ASSIMP_LOG_WARN("BlendModifier: expected a ModifierData structure as first member");
-			continue;
-		}
-
-		// now, we can be sure that we should be fine to dereference *cur* as
-		// ModifierData (with the above note).
-		const ModifierData& dat = cur->modifier;
-
-		const fpCreateModifier* curgod = creators;
-		std::vector< BlenderModifier* >::iterator curmod = cached_modifiers->begin(), endmod = cached_modifiers->end();
-
-		for (;*curgod;++curgod,++curmod) { // allocate modifiers on the fly
-			if (curmod == endmod) {
-				cached_modifiers->push_back((*curgod)());
-
-				endmod = cached_modifiers->end();
-				curmod = endmod-1;
-			}
-
-			BlenderModifier* const modifier = *curmod;
-			if(modifier->IsActive(dat)) {
-				modifier->DoIt(out,conv_data,*boost::static_pointer_cast<const ElemBase>(cur),in,orig_object);
-				cnt++;
-
-				curgod = NULL;
-				break;
-			}
-		}
-		if (curgod) {
-			ASSIMP_LOG_WARN_F("Couldn't find a handler for modifier: ",dat.name);
-		}
-	}
-
-	// Even though we managed to resolve some or all of the modifiers on this
-	// object, we still can't say whether our modifier implementations were
-	// able to fully do their job.
-	if (ful) {
-		ASSIMP_LOG_DEBUG_F("BlendModifier: found handlers for ",cnt," of ",ful," modifiers on `",orig_object.id.name,
-			"`, check log messages above for errors");
-	}
+    size_t cnt = 0u, ful = 0u;
+
+    // NOTE: this cast is potentially unsafe by design, so we need to perform type checks before
+    // we're allowed to dereference the pointers without risking to crash. We might still be
+    // invoking UB btw - we're assuming that the ModifierData member of the respective modifier
+    // structures is at offset sizeof(vftable) with no padding.
+    const SharedModifierData* cur = boost::static_pointer_cast<const SharedModifierData> ( orig_object.modifiers.first.get() );
+    for (; cur; cur =  boost::static_pointer_cast<const SharedModifierData> ( cur->modifier.next.get() ), ++ful) {
+        ai_assert(cur->dna_type);
+
+        const Structure* s = conv_data.db.dna.Get( cur->dna_type );
+        if (!s) {
+            ASSIMP_LOG_WARN_F("BlendModifier: could not resolve DNA name: ",cur->dna_type);
+            continue;
+        }
+
+        // this is a common trait of all XXXMirrorData structures in BlenderDNA
+        const Field* f = s->Get("modifier");
+        if (!f || f->offset != 0) {
+            ASSIMP_LOG_WARN("BlendModifier: expected a `modifier` member at offset 0");
+            continue;
+        }
+
+        s = conv_data.db.dna.Get( f->type );
+        if (!s || s->name != "ModifierData") {
+            ASSIMP_LOG_WARN("BlendModifier: expected a ModifierData structure as first member");
+            continue;
+        }
+
+        // now, we can be sure that we should be fine to dereference *cur* as
+        // ModifierData (with the above note).
+        const ModifierData& dat = cur->modifier;
+
+        const fpCreateModifier* curgod = creators;
+        std::vector< BlenderModifier* >::iterator curmod = cached_modifiers->begin(), endmod = cached_modifiers->end();
+
+        for (;*curgod;++curgod,++curmod) { // allocate modifiers on the fly
+            if (curmod == endmod) {
+                cached_modifiers->push_back((*curgod)());
+
+                endmod = cached_modifiers->end();
+                curmod = endmod-1;
+            }
+
+            BlenderModifier* const modifier = *curmod;
+            if(modifier->IsActive(dat)) {
+                modifier->DoIt(out,conv_data,*boost::static_pointer_cast<const ElemBase>(cur),in,orig_object);
+                cnt++;
+
+                curgod = NULL;
+                break;
+            }
+        }
+        if (curgod) {
+            ASSIMP_LOG_WARN_F("Couldn't find a handler for modifier: ",dat.name);
+        }
+    }
+
+    // Even though we managed to resolve some or all of the modifiers on this
+    // object, we still can't say whether our modifier implementations were
+    // able to fully do their job.
+    if (ful) {
+        ASSIMP_LOG_DEBUG_F("BlendModifier: found handlers for ",cnt," of ",ful," modifiers on `",orig_object.id.name,
+            "`, check log messages above for errors");
+    }
 }
 
 
@@ -175,102 +179,102 @@ void BlenderModifierShowcase::ApplyModifiers(aiNode& out, ConversionData& conv_d
 // ------------------------------------------------------------------------------------------------
 bool BlenderModifier_Mirror :: IsActive (const ModifierData& modin)
 {
-	return modin.type == ModifierData::eModifierType_Mirror;
+    return modin.type == ModifierData::eModifierType_Mirror;
 }
 
 // ------------------------------------------------------------------------------------------------
-void  BlenderModifier_Mirror :: DoIt(aiNode& out, ConversionData& conv_data,  const ElemBase& orig_modifier, 
-	const Scene& /*in*/,
-	const Object& orig_object ) 
+void  BlenderModifier_Mirror :: DoIt(aiNode& out, ConversionData& conv_data,  const ElemBase& orig_modifier,
+    const Scene& /*in*/,
+    const Object& orig_object )
 {
-	// hijacking the ABI, see the big note in BlenderModifierShowcase::ApplyModifiers()
-	const MirrorModifierData& mir = static_cast<const MirrorModifierData&>(orig_modifier);
-	ai_assert(mir.modifier.type == ModifierData::eModifierType_Mirror);
-
-	conv_data.meshes->reserve(conv_data.meshes->size() + out.mNumMeshes);
-
-	// XXX not entirely correct, mirroring on two axes results in 4 distinct objects in blender ...
-
-	// take all input meshes and clone them
-	for (unsigned int i = 0; i < out.mNumMeshes; ++i) {
-		aiMesh* mesh;
-		SceneCombiner::Copy(&mesh,conv_data.meshes[out.mMeshes[i]]);
-
-		const float xs = mir.flag & MirrorModifierData::Flags_AXIS_X ? -1.f : 1.f;
-		const float ys = mir.flag & MirrorModifierData::Flags_AXIS_Y ? -1.f : 1.f;
-		const float zs = mir.flag & MirrorModifierData::Flags_AXIS_Z ? -1.f : 1.f;
-
-		if (mir.mirror_ob) {
-			const aiVector3D center( mir.mirror_ob->obmat[3][0],mir.mirror_ob->obmat[3][1],mir.mirror_ob->obmat[3][2] );
-			for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
-				aiVector3D& v = mesh->mVertices[i];
-		
-				v.x = center.x + xs*(center.x - v.x);
-				v.y = center.y + ys*(center.y - v.y);
-				v.z = center.z + zs*(center.z - v.z);
-			}
-		}
-		else {
-			for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
-				aiVector3D& v = mesh->mVertices[i];
-				v.x *= xs;v.y *= ys;v.z *= zs;
-			}
-		}
-
-		if (mesh->mNormals) {
-			for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
-				aiVector3D& v = mesh->mNormals[i];
-				v.x *= xs;v.y *= ys;v.z *= zs;
-			}
-		}
-
-		if (mesh->mTangents) {
-			for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
-				aiVector3D& v = mesh->mTangents[i];
-				v.x *= xs;v.y *= ys;v.z *= zs;
-			}
-		}
-
-		if (mesh->mBitangents) {
-			for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
-				aiVector3D& v = mesh->mBitangents[i];
-				v.x *= xs;v.y *= ys;v.z *= zs;
-			}
-		}
-
-		const float us = mir.flag & MirrorModifierData::Flags_MIRROR_U ? -1.f : 1.f;
-		const float vs = mir.flag & MirrorModifierData::Flags_MIRROR_V ? -1.f : 1.f;
-
-		for (unsigned int n = 0; mesh->HasTextureCoords(n); ++n) {
-			for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
-				aiVector3D& v = mesh->mTextureCoords[n][i];
-				v.x *= us;v.y *= vs;
-			}
-		}
-
-		// Only reverse the winding order if an odd number of axes were mirrored.
-		if (xs * ys * zs < 0) {
-			for( unsigned int i = 0; i < mesh->mNumFaces; i++) {
-				aiFace& face = mesh->mFaces[i];
-				for( unsigned int fi = 0; fi < face.mNumIndices / 2; ++fi)
-					std::swap( face.mIndices[fi], face.mIndices[face.mNumIndices - 1 - fi]);
-			}
-		}
-
-		conv_data.meshes->push_back(mesh);
-	}
-	unsigned int* nind = new unsigned int[out.mNumMeshes*2];
-
-	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));
-
-	delete[] out.mMeshes;
-	out.mMeshes = nind;
-	out.mNumMeshes *= 2;
-
-	ASSIMP_LOG_INFO_F("BlendModifier: Applied the `Mirror` modifier to `",
-		orig_object.id.name,"`");
+    // hijacking the ABI, see the big note in BlenderModifierShowcase::ApplyModifiers()
+    const MirrorModifierData& mir = static_cast<const MirrorModifierData&>(orig_modifier);
+    ai_assert(mir.modifier.type == ModifierData::eModifierType_Mirror);
+
+    conv_data.meshes->reserve(conv_data.meshes->size() + out.mNumMeshes);
+
+    // XXX not entirely correct, mirroring on two axes results in 4 distinct objects in blender ...
+
+    // take all input meshes and clone them
+    for (unsigned int i = 0; i < out.mNumMeshes; ++i) {
+        aiMesh* mesh;
+        SceneCombiner::Copy(&mesh,conv_data.meshes[out.mMeshes[i]]);
+
+        const float xs = mir.flag & MirrorModifierData::Flags_AXIS_X ? -1.f : 1.f;
+        const float ys = mir.flag & MirrorModifierData::Flags_AXIS_Y ? -1.f : 1.f;
+        const float zs = mir.flag & MirrorModifierData::Flags_AXIS_Z ? -1.f : 1.f;
+
+        if (mir.mirror_ob) {
+            const aiVector3D center( mir.mirror_ob->obmat[3][0],mir.mirror_ob->obmat[3][1],mir.mirror_ob->obmat[3][2] );
+            for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
+                aiVector3D& v = mesh->mVertices[i];
+
+                v.x = center.x + xs*(center.x - v.x);
+                v.y = center.y + ys*(center.y - v.y);
+                v.z = center.z + zs*(center.z - v.z);
+            }
+        }
+        else {
+            for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
+                aiVector3D& v = mesh->mVertices[i];
+                v.x *= xs;v.y *= ys;v.z *= zs;
+            }
+        }
+
+        if (mesh->mNormals) {
+            for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
+                aiVector3D& v = mesh->mNormals[i];
+                v.x *= xs;v.y *= ys;v.z *= zs;
+            }
+        }
+
+        if (mesh->mTangents) {
+            for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
+                aiVector3D& v = mesh->mTangents[i];
+                v.x *= xs;v.y *= ys;v.z *= zs;
+            }
+        }
+
+        if (mesh->mBitangents) {
+            for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
+                aiVector3D& v = mesh->mBitangents[i];
+                v.x *= xs;v.y *= ys;v.z *= zs;
+            }
+        }
+
+        const float us = mir.flag & MirrorModifierData::Flags_MIRROR_U ? -1.f : 1.f;
+        const float vs = mir.flag & MirrorModifierData::Flags_MIRROR_V ? -1.f : 1.f;
+
+        for (unsigned int n = 0; mesh->HasTextureCoords(n); ++n) {
+            for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
+                aiVector3D& v = mesh->mTextureCoords[n][i];
+                v.x *= us;v.y *= vs;
+            }
+        }
+
+        // Only reverse the winding order if an odd number of axes were mirrored.
+        if (xs * ys * zs < 0) {
+            for( unsigned int i = 0; i < mesh->mNumFaces; i++) {
+                aiFace& face = mesh->mFaces[i];
+                for( unsigned int fi = 0; fi < face.mNumIndices / 2; ++fi)
+                    std::swap( face.mIndices[fi], face.mIndices[face.mNumIndices - 1 - fi]);
+            }
+        }
+
+        conv_data.meshes->push_back(mesh);
+    }
+    unsigned int* nind = new unsigned int[out.mNumMeshes*2];
+
+    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));
+
+    delete[] out.mMeshes;
+    out.mMeshes = nind;
+    out.mNumMeshes *= 2;
+
+    ASSIMP_LOG_INFO_F("BlendModifier: Applied the `Mirror` modifier to `",
+        orig_object.id.name,"`");
 }
 
 
@@ -279,46 +283,46 @@ void  BlenderModifier_Mirror :: DoIt(aiNode& out, ConversionData& conv_data,  co
 // ------------------------------------------------------------------------------------------------
 bool BlenderModifier_Subdivision :: IsActive (const ModifierData& modin)
 {
-	return modin.type == ModifierData::eModifierType_Subsurf;
+    return modin.type == ModifierData::eModifierType_Subsurf;
 }
 
 // ------------------------------------------------------------------------------------------------
-void  BlenderModifier_Subdivision :: DoIt(aiNode& out, ConversionData& conv_data,  const ElemBase& orig_modifier, 
-	const Scene& /*in*/,
-	const Object& orig_object ) 
+void  BlenderModifier_Subdivision :: DoIt(aiNode& out, ConversionData& conv_data,  const ElemBase& orig_modifier,
+    const Scene& /*in*/,
+    const Object& orig_object )
 {
-	// hijacking the ABI, see the big note in BlenderModifierShowcase::ApplyModifiers()
-	const SubsurfModifierData& mir = static_cast<const SubsurfModifierData&>(orig_modifier);
-	ai_assert(mir.modifier.type == ModifierData::eModifierType_Subsurf);
-
-	Subdivider::Algorithm algo;
-	switch (mir.subdivType) 
-	{
-	case SubsurfModifierData::TYPE_CatmullClarke:
-		algo = Subdivider::CATMULL_CLARKE;
-		break;
-
-	case SubsurfModifierData::TYPE_Simple:
-		ASSIMP_LOG_WARN("BlendModifier: The `SIMPLE` subdivision algorithm is not currently implemented, using Catmull-Clarke");
-		algo = Subdivider::CATMULL_CLARKE;
-		break;
-
-	default:
-		ASSIMP_LOG_WARN_F("BlendModifier: Unrecognized subdivision algorithm: ",mir.subdivType);
-		return;
-	};
-
-	boost::scoped_ptr<Subdivider> subd(Subdivider::Create(algo));
-	ai_assert(subd);
-
-	aiMesh** const meshes = &conv_data.meshes[conv_data.meshes->size() - out.mNumMeshes];
-	boost::scoped_array<aiMesh*> tempmeshes(new aiMesh*[out.mNumMeshes]());
-
-	subd->Subdivide(meshes,out.mNumMeshes,tempmeshes.get(),std::max( mir.renderLevels, mir.levels ),true);
-	std::copy(tempmeshes.get(),tempmeshes.get()+out.mNumMeshes,meshes);
-
-	ASSIMP_LOG_INFO_F("BlendModifier: Applied the `Subdivision` modifier to `",
-		orig_object.id.name,"`");
+    // hijacking the ABI, see the big note in BlenderModifierShowcase::ApplyModifiers()
+    const SubsurfModifierData& mir = static_cast<const SubsurfModifierData&>(orig_modifier);
+    ai_assert(mir.modifier.type == ModifierData::eModifierType_Subsurf);
+
+    Subdivider::Algorithm algo;
+    switch (mir.subdivType)
+    {
+    case SubsurfModifierData::TYPE_CatmullClarke:
+        algo = Subdivider::CATMULL_CLARKE;
+        break;
+
+    case SubsurfModifierData::TYPE_Simple:
+        ASSIMP_LOG_WARN("BlendModifier: The `SIMPLE` subdivision algorithm is not currently implemented, using Catmull-Clarke");
+        algo = Subdivider::CATMULL_CLARKE;
+        break;
+
+    default:
+        ASSIMP_LOG_WARN_F("BlendModifier: Unrecognized subdivision algorithm: ",mir.subdivType);
+        return;
+    };
+
+    boost::scoped_ptr<Subdivider> subd(Subdivider::Create(algo));
+    ai_assert(subd);
+
+    aiMesh** const meshes = &conv_data.meshes[conv_data.meshes->size() - out.mNumMeshes];
+    boost::scoped_array<aiMesh*> tempmeshes(new aiMesh*[out.mNumMeshes]());
+
+    subd->Subdivide(meshes,out.mNumMeshes,tempmeshes.get(),std::max( mir.renderLevels, mir.levels ),true);
+    std::copy(tempmeshes.get(),tempmeshes.get()+out.mNumMeshes,meshes);
+
+    ASSIMP_LOG_INFO_F("BlendModifier: Applied the `Subdivision` modifier to `",
+        orig_object.id.name,"`");
 }
 
 #endif

+ 61 - 61
assimplib.mod/assimp/code/BlenderModifier.h

@@ -2,11 +2,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -23,16 +23,16 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -47,40 +47,40 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "BlenderIntermediate.h"
 #include "TinyFormatter.h"
 namespace Assimp {
-	namespace Blender {
+    namespace Blender {
 
 // -------------------------------------------------------------------------------------------
 /** Dummy base class for all blender modifiers. Modifiers are reused between imports, so
  *  they should be stateless and not try to cache model data. */
 // -------------------------------------------------------------------------------------------
-class BlenderModifier 
+class BlenderModifier
 {
 public:
 
-	virtual ~BlenderModifier() {
-	}
+    virtual ~BlenderModifier() {
+    }
 
 public:
 
-	// --------------------
-	/** Check if *this* modifier is active, given a ModifierData& block.*/
-	virtual bool IsActive( const ModifierData& /*modin*/) {
-		return false;
-	}
-
-	// --------------------
-	/** Apply the modifier to a given output node. The original data used
-	 *  to construct the node is given as well. Not called unless IsActive()
-	 *  was called and gave positive response. */
-	virtual void DoIt(aiNode& /*out*/,
-		ConversionData& /*conv_data*/,
-		const ElemBase& orig_modifier, 
-		const Scene& /*in*/,
-		const Object& /*orig_object*/
-	) {
-		DefaultLogger::get()->warn((Formatter::format("This modifier is not supported, skipping: "),orig_modifier.dna_type));
-		return;
-	}
+    // --------------------
+    /** Check if *this* modifier is active, given a ModifierData& block.*/
+    virtual bool IsActive( const ModifierData& /*modin*/) {
+        return false;
+    }
+
+    // --------------------
+    /** Apply the modifier to a given output node. The original data used
+     *  to construct the node is given as well. Not called unless IsActive()
+     *  was called and gave positive response. */
+    virtual void DoIt(aiNode& /*out*/,
+        ConversionData& /*conv_data*/,
+        const ElemBase& orig_modifier,
+        const Scene& /*in*/,
+        const Object& /*orig_object*/
+    ) {
+        DefaultLogger::get()->warn((Formatter::format("This modifier is not supported, skipping: "),orig_modifier.dna_type));
+        return;
+    }
 };
 
 
@@ -91,17 +91,17 @@ class BlenderModifierShowcase
 {
 public:
 
-	// --------------------
-	/** Apply all requested modifiers provided we support them. */
-	void ApplyModifiers(aiNode& out,
-		ConversionData& conv_data, 
-		const Scene& in, 
-		const Object& orig_object 
-	);
+    // --------------------
+    /** Apply all requested modifiers provided we support them. */
+    void ApplyModifiers(aiNode& out,
+        ConversionData& conv_data,
+        const Scene& in,
+        const Object& orig_object
+    );
 
 private:
 
-	TempArray< std::vector,BlenderModifier > cached_modifiers;
+    TempArray< std::vector,BlenderModifier > cached_modifiers;
 };
 
 
@@ -119,16 +119,16 @@ class BlenderModifier_Mirror : public BlenderModifier
 {
 public:
 
-	// --------------------
-	virtual bool IsActive( const ModifierData& modin);
-	
-	// --------------------
-	virtual void DoIt(aiNode& out, 
-		ConversionData& conv_data,  
-		const ElemBase& orig_modifier, 
-		const Scene& in, 
-		const Object& orig_object 
-	) ;
+    // --------------------
+    virtual bool IsActive( const ModifierData& modin);
+
+    // --------------------
+    virtual void DoIt(aiNode& out,
+        ConversionData& conv_data,
+        const ElemBase& orig_modifier,
+        const Scene& in,
+        const Object& orig_object
+    ) ;
 };
 
 // -------------------------------------------------------------------------------------------
@@ -138,16 +138,16 @@ class BlenderModifier_Subdivision : public BlenderModifier
 {
 public:
 
-	// --------------------
-	virtual bool IsActive( const ModifierData& modin);
-	
-	// --------------------
-	virtual void DoIt(aiNode& out, 
-		ConversionData& conv_data,  
-		const ElemBase& orig_modifier, 
-		const Scene& in, 
-		const Object& orig_object 
-	) ;
+    // --------------------
+    virtual bool IsActive( const ModifierData& modin);
+
+    // --------------------
+    virtual void DoIt(aiNode& out,
+        ConversionData& conv_data,
+        const ElemBase& orig_modifier,
+        const Scene& in,
+        const Object& orig_object
+    ) ;
 };
 
 

+ 100 - 100
assimplib.mod/assimp/code/BlenderScene.cpp

@@ -5,8 +5,8 @@ Open Asset Import Library (ASSIMP)
 Copyright (c) 2006-2010, ASSIMP Development Team
 All rights reserved.
 
-Redistribution and use of this software in source and binary forms, 
-with or without modification, are permitted provided that the 
+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
@@ -23,16 +23,16 @@ following conditions are met:
   derived from this software without specific prior
   written permission of the ASSIMP Development Team.
 
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -41,7 +41,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 /** @file  BlenderScene.cpp
  *  @brief MACHINE GENERATED BY ./scripts/BlenderImporter/genblenddna.py
  */
-#include "AssimpPCH.h"
+
 #ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
 
 #include "BlenderDNA.h"
@@ -56,7 +56,7 @@ template <> void Structure :: Convert<Object> (
     Object& dest,
     const FileDatabase& db
     ) const
-{ 
+{
 
     ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
     ReadField<ErrorPolicy_Fail>((int&)dest.type,"type",db);
@@ -76,7 +76,7 @@ template <> void Structure :: Convert<Object> (
     ReadFieldPtr<ErrorPolicy_Fail>(dest.data,"*data",db);
     ReadField<ErrorPolicy_Igno>(dest.modifiers,"modifiers",db);
 
-	db.reader->IncPtr(size);
+    db.reader->IncPtr(size);
 }
 
 //--------------------------------------------------------------------------------
@@ -84,13 +84,13 @@ template <> void Structure :: Convert<Group> (
     Group& dest,
     const FileDatabase& db
     ) const
-{ 
+{
 
     ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
     ReadField<ErrorPolicy_Igno>(dest.layer,"layer",db);
     ReadFieldPtr<ErrorPolicy_Igno>(dest.gobject,"*gobject",db);
 
-	db.reader->IncPtr(size);
+    db.reader->IncPtr(size);
 }
 
 //--------------------------------------------------------------------------------
@@ -98,7 +98,7 @@ template <> void Structure :: Convert<MTex> (
     MTex& dest,
     const FileDatabase& db
     ) const
-{ 
+{
 
     ReadField<ErrorPolicy_Igno>((short&)dest.mapto,"mapto",db);
     ReadField<ErrorPolicy_Igno>((int&)dest.blendtype,"blendtype",db);
@@ -129,7 +129,7 @@ template <> void Structure :: Convert<MTex> (
     ReadField<ErrorPolicy_Igno>(dest.hardfac,"hardfac",db);
     ReadField<ErrorPolicy_Igno>(dest.norfac,"norfac",db);
 
-	db.reader->IncPtr(size);
+    db.reader->IncPtr(size);
 }
 
 //--------------------------------------------------------------------------------
@@ -137,7 +137,7 @@ template <> void Structure :: Convert<TFace> (
     TFace& dest,
     const FileDatabase& db
     ) const
-{ 
+{
 
     ReadFieldArray2<ErrorPolicy_Fail>(dest.uv,"uv",db);
     ReadFieldArray<ErrorPolicy_Fail>(dest.col,"col",db);
@@ -146,7 +146,7 @@ template <> void Structure :: Convert<TFace> (
     ReadField<ErrorPolicy_Igno>(dest.tile,"tile",db);
     ReadField<ErrorPolicy_Igno>(dest.unwrap,"unwrap",db);
 
-	db.reader->IncPtr(size);
+    db.reader->IncPtr(size);
 }
 
 //--------------------------------------------------------------------------------
@@ -154,7 +154,7 @@ template <> void Structure :: Convert<SubsurfModifierData> (
     SubsurfModifierData& dest,
     const FileDatabase& db
     ) const
-{ 
+{
 
     ReadField<ErrorPolicy_Fail>(dest.modifier,"modifier",db);
     ReadField<ErrorPolicy_Warn>(dest.subdivType,"subdivType",db);
@@ -162,7 +162,7 @@ template <> void Structure :: Convert<SubsurfModifierData> (
     ReadField<ErrorPolicy_Igno>(dest.renderLevels,"renderLevels",db);
     ReadField<ErrorPolicy_Igno>(dest.flags,"flags",db);
 
-	db.reader->IncPtr(size);
+    db.reader->IncPtr(size);
 }
 
 //--------------------------------------------------------------------------------
@@ -170,7 +170,7 @@ template <> void Structure :: Convert<MFace> (
     MFace& dest,
     const FileDatabase& db
     ) const
-{ 
+{
 
     ReadField<ErrorPolicy_Fail>(dest.v1,"v1",db);
     ReadField<ErrorPolicy_Fail>(dest.v2,"v2",db);
@@ -179,7 +179,7 @@ template <> void Structure :: Convert<MFace> (
     ReadField<ErrorPolicy_Fail>(dest.mat_nr,"mat_nr",db);
     ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
 
-	db.reader->IncPtr(size);
+    db.reader->IncPtr(size);
 }
 
 //--------------------------------------------------------------------------------
@@ -187,7 +187,7 @@ template <> void Structure :: Convert<Lamp> (
     Lamp& dest,
     const FileDatabase& db
     ) const
-{ 
+{
 
     ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
     ReadField<ErrorPolicy_Fail>((int&)dest.type,"type",db);
@@ -207,7 +207,7 @@ template <> void Structure :: Convert<Lamp> (
     ReadField<ErrorPolicy_Igno>((int&)dest.falloff_type,"falloff_type",db);
     ReadField<ErrorPolicy_Igno>(dest.sun_brightness,"sun_brightness",db);
 
-	db.reader->IncPtr(size);
+    db.reader->IncPtr(size);
 }
 
 //--------------------------------------------------------------------------------
@@ -215,12 +215,12 @@ template <> void Structure :: Convert<MDeformWeight> (
     MDeformWeight& dest,
     const FileDatabase& db
     ) const
-{ 
+{
 
     ReadField<ErrorPolicy_Fail>(dest.def_nr,"def_nr",db);
     ReadField<ErrorPolicy_Fail>(dest.weight,"weight",db);
 
-	db.reader->IncPtr(size);
+    db.reader->IncPtr(size);
 }
 
 //--------------------------------------------------------------------------------
@@ -228,13 +228,13 @@ template <> void Structure :: Convert<PackedFile> (
     PackedFile& dest,
     const FileDatabase& db
     ) const
-{ 
+{
 
     ReadField<ErrorPolicy_Warn>(dest.size,"size",db);
     ReadField<ErrorPolicy_Warn>(dest.seek,"seek",db);
     ReadFieldPtr<ErrorPolicy_Warn>(dest.data,"*data",db);
 
-	db.reader->IncPtr(size);
+    db.reader->IncPtr(size);
 }
 
 //--------------------------------------------------------------------------------
@@ -242,37 +242,37 @@ template <> void Structure :: Convert<Base> (
     Base& dest,
     const FileDatabase& db
     ) const
-{ 
-	// note: as per https://github.com/assimp/assimp/issues/128,
-	// reading the Object linked list recursively is prone to stack overflow.
-	// This structure converter is therefore an hand-written exception that
-	// does it iteratively.
+{
+    // note: as per https://github.com/assimp/assimp/issues/128,
+    // reading the Object linked list recursively is prone to stack overflow.
+    // This structure converter is therefore an hand-written exception that
+    // does it iteratively.
+
+    const int initial_pos = db.reader->GetCurrentPos();
 
-	const int initial_pos = db.reader->GetCurrentPos();
+    std::pair<Base*, int> todo = std::make_pair(&dest, initial_pos);
+    for ( ;; ) {
 
-	std::pair<Base*, int> todo = std::make_pair(&dest, initial_pos);
-	for ( ;; ) {
-	
-		Base& cur_dest = *todo.first;
-		db.reader->SetCurrentPos(todo.second);
+        Base& cur_dest = *todo.first;
+        db.reader->SetCurrentPos(todo.second);
 
-		// we know that this is a double-linked, circular list which we never
-		// traverse backwards, so don't bother resolving the back links.
-		cur_dest.prev = NULL;
+        // we know that this is a double-linked, circular list which we never
+        // traverse backwards, so don't bother resolving the back links.
+        cur_dest.prev = NULL;
 
-		ReadFieldPtr<ErrorPolicy_Warn>(cur_dest.object,"*object",db);
+        ReadFieldPtr<ErrorPolicy_Warn>(cur_dest.object,"*object",db);
+
+        // the return value of ReadFieldPtr indicates whether the object
+        // was already cached. In this case, we don't need to resolve
+        // it again.
+        if(!ReadFieldPtr<ErrorPolicy_Warn>(cur_dest.next,"*next",db, true) && cur_dest.next) {
+            todo = std::make_pair(&*cur_dest.next, db.reader->GetCurrentPos());
+            continue;
+        }
+        break;
+    }
 
-		// the return value of ReadFieldPtr indicates whether the object 
-		// was already cached. In this case, we don't need to resolve
-		// it again.
-		if(!ReadFieldPtr<ErrorPolicy_Warn>(cur_dest.next,"*next",db, true) && cur_dest.next) {
-			todo = std::make_pair(&*cur_dest.next, db.reader->GetCurrentPos());
-			continue;
-		}
-		break;
-	}
-	
-	db.reader->SetCurrentPos(initial_pos + size);
+    db.reader->SetCurrentPos(initial_pos + size);
 }
 
 //--------------------------------------------------------------------------------
@@ -280,7 +280,7 @@ template <> void Structure :: Convert<MTFace> (
     MTFace& dest,
     const FileDatabase& db
     ) const
-{ 
+{
 
     ReadFieldArray2<ErrorPolicy_Fail>(dest.uv,"uv",db);
     ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
@@ -288,7 +288,7 @@ template <> void Structure :: Convert<MTFace> (
     ReadField<ErrorPolicy_Igno>(dest.tile,"tile",db);
     ReadField<ErrorPolicy_Igno>(dest.unwrap,"unwrap",db);
 
-	db.reader->IncPtr(size);
+    db.reader->IncPtr(size);
 }
 
 //--------------------------------------------------------------------------------
@@ -296,7 +296,7 @@ template <> void Structure :: Convert<Material> (
     Material& dest,
     const FileDatabase& db
     ) const
-{ 
+{
 
     ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
     ReadField<ErrorPolicy_Warn>(dest.r,"r",db);
@@ -324,7 +324,7 @@ template <> void Structure :: Convert<Material> (
     ReadField<ErrorPolicy_Warn>(dest.spec_shader,"spec_shader",db);
     ReadFieldPtr<ErrorPolicy_Igno>(dest.mtex,"*mtex",db);
 
-	db.reader->IncPtr(size);
+    db.reader->IncPtr(size);
 }
 
 //--------------------------------------------------------------------------------
@@ -332,7 +332,7 @@ template <> void Structure :: Convert<MTexPoly> (
     MTexPoly& dest,
     const FileDatabase& db
     ) const
-{ 
+{
 
     {
         boost::shared_ptr<Image> tpage;
@@ -345,7 +345,7 @@ template <> void Structure :: Convert<MTexPoly> (
     ReadField<ErrorPolicy_Igno>(dest.tile,"tile",db);
     ReadField<ErrorPolicy_Igno>(dest.pad,"pad",db);
 
-	db.reader->IncPtr(size);
+    db.reader->IncPtr(size);
 }
 
 //--------------------------------------------------------------------------------
@@ -353,7 +353,7 @@ template <> void Structure :: Convert<Mesh> (
     Mesh& dest,
     const FileDatabase& db
     ) const
-{ 
+{
 
     ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
     ReadField<ErrorPolicy_Fail>(dest.totface,"totface",db);
@@ -379,7 +379,7 @@ template <> void Structure :: Convert<Mesh> (
     ReadFieldPtr<ErrorPolicy_Igno>(dest.mcol,"*mcol",db);
     ReadFieldPtr<ErrorPolicy_Fail>(dest.mat,"**mat",db);
 
-	db.reader->IncPtr(size);
+    db.reader->IncPtr(size);
 }
 
 //--------------------------------------------------------------------------------
@@ -387,12 +387,12 @@ template <> void Structure :: Convert<MDeformVert> (
     MDeformVert& dest,
     const FileDatabase& db
     ) const
-{ 
+{
 
     ReadFieldPtr<ErrorPolicy_Warn>(dest.dw,"*dw",db);
     ReadField<ErrorPolicy_Igno>(dest.totweight,"totweight",db);
 
-	db.reader->IncPtr(size);
+    db.reader->IncPtr(size);
 }
 
 //--------------------------------------------------------------------------------
@@ -400,11 +400,11 @@ template <> void Structure :: Convert<World> (
     World& dest,
     const FileDatabase& db
     ) const
-{ 
+{
 
     ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
 
-	db.reader->IncPtr(size);
+    db.reader->IncPtr(size);
 }
 
 //--------------------------------------------------------------------------------
@@ -412,14 +412,14 @@ template <> void Structure :: Convert<MLoopCol> (
     MLoopCol& dest,
     const FileDatabase& db
     ) const
-{ 
+{
 
     ReadField<ErrorPolicy_Igno>(dest.r,"r",db);
     ReadField<ErrorPolicy_Igno>(dest.g,"g",db);
     ReadField<ErrorPolicy_Igno>(dest.b,"b",db);
     ReadField<ErrorPolicy_Igno>(dest.a,"a",db);
 
-	db.reader->IncPtr(size);
+    db.reader->IncPtr(size);
 }
 
 //--------------------------------------------------------------------------------
@@ -427,7 +427,7 @@ template <> void Structure :: Convert<MVert> (
     MVert& dest,
     const FileDatabase& db
     ) const
-{ 
+{
 
     ReadFieldArray<ErrorPolicy_Fail>(dest.co,"co",db);
     ReadFieldArray<ErrorPolicy_Fail>(dest.no,"no",db);
@@ -435,7 +435,7 @@ template <> void Structure :: Convert<MVert> (
     ReadField<ErrorPolicy_Warn>(dest.mat_nr,"mat_nr",db);
     ReadField<ErrorPolicy_Igno>(dest.bweight,"bweight",db);
 
-	db.reader->IncPtr(size);
+    db.reader->IncPtr(size);
 }
 
 //--------------------------------------------------------------------------------
@@ -443,7 +443,7 @@ template <> void Structure :: Convert<MEdge> (
     MEdge& dest,
     const FileDatabase& db
     ) const
-{ 
+{
 
     ReadField<ErrorPolicy_Fail>(dest.v1,"v1",db);
     ReadField<ErrorPolicy_Fail>(dest.v2,"v2",db);
@@ -451,7 +451,7 @@ template <> void Structure :: Convert<MEdge> (
     ReadField<ErrorPolicy_Igno>(dest.bweight,"bweight",db);
     ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
 
-	db.reader->IncPtr(size);
+    db.reader->IncPtr(size);
 }
 
 //--------------------------------------------------------------------------------
@@ -459,12 +459,12 @@ template <> void Structure :: Convert<MLoopUV> (
     MLoopUV& dest,
     const FileDatabase& db
     ) const
-{ 
+{
 
     ReadFieldArray<ErrorPolicy_Igno>(dest.uv,"uv",db);
     ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
 
-	db.reader->IncPtr(size);
+    db.reader->IncPtr(size);
 }
 
 //--------------------------------------------------------------------------------
@@ -472,13 +472,13 @@ template <> void Structure :: Convert<GroupObject> (
     GroupObject& dest,
     const FileDatabase& db
     ) const
-{ 
+{
 
     ReadFieldPtr<ErrorPolicy_Fail>(dest.prev,"*prev",db);
     ReadFieldPtr<ErrorPolicy_Fail>(dest.next,"*next",db);
     ReadFieldPtr<ErrorPolicy_Igno>(dest.ob,"*ob",db);
 
-	db.reader->IncPtr(size);
+    db.reader->IncPtr(size);
 }
 
 //--------------------------------------------------------------------------------
@@ -486,12 +486,12 @@ template <> void Structure :: Convert<ListBase> (
     ListBase& dest,
     const FileDatabase& db
     ) const
-{ 
+{
 
     ReadFieldPtr<ErrorPolicy_Igno>(dest.first,"*first",db);
     ReadFieldPtr<ErrorPolicy_Igno>(dest.last,"*last",db);
 
-	db.reader->IncPtr(size);
+    db.reader->IncPtr(size);
 }
 
 //--------------------------------------------------------------------------------
@@ -499,12 +499,12 @@ template <> void Structure :: Convert<MLoop> (
     MLoop& dest,
     const FileDatabase& db
     ) const
-{ 
+{
 
     ReadField<ErrorPolicy_Igno>(dest.v,"v",db);
     ReadField<ErrorPolicy_Igno>(dest.e,"e",db);
 
-	db.reader->IncPtr(size);
+    db.reader->IncPtr(size);
 }
 
 //--------------------------------------------------------------------------------
@@ -512,7 +512,7 @@ template <> void Structure :: Convert<ModifierData> (
     ModifierData& dest,
     const FileDatabase& db
     ) const
-{ 
+{
 
     ReadFieldPtr<ErrorPolicy_Warn>(dest.next,"*next",db);
     ReadFieldPtr<ErrorPolicy_Warn>(dest.prev,"*prev",db);
@@ -520,7 +520,7 @@ template <> void Structure :: Convert<ModifierData> (
     ReadField<ErrorPolicy_Igno>(dest.mode,"mode",db);
     ReadFieldArray<ErrorPolicy_Igno>(dest.name,"name",db);
 
-	db.reader->IncPtr(size);
+    db.reader->IncPtr(size);
 }
 
 //--------------------------------------------------------------------------------
@@ -528,12 +528,12 @@ template <> void Structure :: Convert<ID> (
     ID& dest,
     const FileDatabase& db
     ) const
-{ 
+{
 
     ReadFieldArray<ErrorPolicy_Warn>(dest.name,"name",db);
     ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
 
-	db.reader->IncPtr(size);
+    db.reader->IncPtr(size);
 }
 
 //--------------------------------------------------------------------------------
@@ -541,14 +541,14 @@ template <> void Structure :: Convert<MCol> (
     MCol& dest,
     const FileDatabase& db
     ) const
-{ 
+{
 
     ReadField<ErrorPolicy_Fail>(dest.r,"r",db);
     ReadField<ErrorPolicy_Fail>(dest.g,"g",db);
     ReadField<ErrorPolicy_Fail>(dest.b,"b",db);
     ReadField<ErrorPolicy_Fail>(dest.a,"a",db);
 
-	db.reader->IncPtr(size);
+    db.reader->IncPtr(size);
 }
 
 //--------------------------------------------------------------------------------
@@ -556,14 +556,14 @@ template <> void Structure :: Convert<MPoly> (
     MPoly& dest,
     const FileDatabase& db
     ) const
-{ 
+{
 
     ReadField<ErrorPolicy_Igno>(dest.loopstart,"loopstart",db);
     ReadField<ErrorPolicy_Igno>(dest.totloop,"totloop",db);
     ReadField<ErrorPolicy_Igno>(dest.mat_nr,"mat_nr",db);
     ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
 
-	db.reader->IncPtr(size);
+    db.reader->IncPtr(size);
 }
 
 //--------------------------------------------------------------------------------
@@ -571,7 +571,7 @@ template <> void Structure :: Convert<Scene> (
     Scene& dest,
     const FileDatabase& db
     ) const
-{ 
+{
 
     ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
     ReadFieldPtr<ErrorPolicy_Warn>(dest.camera,"*camera",db);
@@ -579,7 +579,7 @@ template <> void Structure :: Convert<Scene> (
     ReadFieldPtr<ErrorPolicy_Warn>(dest.basact,"*basact",db);
     ReadField<ErrorPolicy_Igno>(dest.base,"base",db);
 
-	db.reader->IncPtr(size);
+    db.reader->IncPtr(size);
 }
 
 //--------------------------------------------------------------------------------
@@ -587,14 +587,14 @@ template <> void Structure :: Convert<Library> (
     Library& dest,
     const FileDatabase& db
     ) const
-{ 
+{
 
     ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
     ReadFieldArray<ErrorPolicy_Warn>(dest.name,"name",db);
     ReadFieldArray<ErrorPolicy_Fail>(dest.filename,"filename",db);
     ReadFieldPtr<ErrorPolicy_Warn>(dest.parent,"*parent",db);
 
-	db.reader->IncPtr(size);
+    db.reader->IncPtr(size);
 }
 
 //--------------------------------------------------------------------------------
@@ -602,12 +602,12 @@ template <> void Structure :: Convert<Tex> (
     Tex& dest,
     const FileDatabase& db
     ) const
-{ 
+{
     ReadField<ErrorPolicy_Igno>((short&)dest.imaflag,"imaflag",db);
     ReadField<ErrorPolicy_Fail>((int&)dest.type,"type",db);
     ReadFieldPtr<ErrorPolicy_Warn>(dest.ima,"*ima",db);
 
-	db.reader->IncPtr(size);
+    db.reader->IncPtr(size);
 }
 
 //--------------------------------------------------------------------------------
@@ -615,14 +615,14 @@ template <> void Structure :: Convert<Camera> (
     Camera& dest,
     const FileDatabase& db
     ) const
-{ 
+{
 
     ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
     ReadField<ErrorPolicy_Warn>((int&)dest.type,"type",db);
     ReadField<ErrorPolicy_Warn>((int&)dest.flag,"flag",db);
     ReadField<ErrorPolicy_Warn>(dest.angle,"angle",db);
 
-	db.reader->IncPtr(size);
+    db.reader->IncPtr(size);
 }
 
 //--------------------------------------------------------------------------------
@@ -630,7 +630,7 @@ template <> void Structure :: Convert<MirrorModifierData> (
     MirrorModifierData& dest,
     const FileDatabase& db
     ) const
-{ 
+{
 
     ReadField<ErrorPolicy_Fail>(dest.modifier,"modifier",db);
     ReadField<ErrorPolicy_Igno>(dest.axis,"axis",db);
@@ -638,7 +638,7 @@ template <> void Structure :: Convert<MirrorModifierData> (
     ReadField<ErrorPolicy_Igno>(dest.tolerance,"tolerance",db);
     ReadFieldPtr<ErrorPolicy_Igno>(dest.mirror_ob,"*mirror_ob",db);
 
-	db.reader->IncPtr(size);
+    db.reader->IncPtr(size);
 }
 
 //--------------------------------------------------------------------------------
@@ -646,7 +646,7 @@ template <> void Structure :: Convert<Image> (
     Image& dest,
     const FileDatabase& db
     ) const
-{ 
+{
 
     ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
     ReadFieldArray<ErrorPolicy_Warn>(dest.name,"name",db);
@@ -671,7 +671,7 @@ template <> void Structure :: Convert<Image> (
     ReadField<ErrorPolicy_Igno>(dest.gen_y,"gen_y",db);
     ReadField<ErrorPolicy_Igno>(dest.gen_type,"gen_type",db);
 
-	db.reader->IncPtr(size);
+    db.reader->IncPtr(size);
 }
 
 //--------------------------------------------------------------------------------

+ 432 - 430
assimplib.mod/assimp/code/BlenderScene.h

@@ -2,11 +2,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -23,16 +23,16 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -44,8 +44,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef INCLUDED_AI_BLEND_SCENE_H
 #define INCLUDED_AI_BLEND_SCENE_H
 
-namespace Assimp	{
-	namespace Blender {
+#include "BlenderDNA.h"
+
+namespace Assimp    {
+    namespace Blender {
 
 // Minor parts of this file are extracts from blender data structures,
 // declared in the ./source/blender/makesdna directory.
@@ -56,14 +58,14 @@ namespace Assimp	{
 // this file serves as input data to the `./scripts/genblenddna.py`
 // script. This script generates the actual binding code to read a
 // blender file with a possibly different DNA into our structures.
-// Only `struct` declarations are considered and the following 
+// Only `struct` declarations are considered and the following
 // rules must be obeyed in order for the script to work properly:
 //
 // * C++ style comments only
 //
 // * Structures may include the primitive types char, int, short,
-//   float, double. Signedness specifiers are not allowed on 
-//	 integers. Enum types are allowed, but they must have been
+//   float, double. Signedness specifiers are not allowed on
+//   integers. Enum types are allowed, but they must have been
 //   defined in this header.
 //
 // * Structures may aggregate other structures, unless not defined
@@ -101,15 +103,15 @@ struct Image;
 // -------------------------------------------------------------------------------
 struct ID : ElemBase {
 
-	char name[24] WARN; 
-	short flag;
+    char name[1024] WARN;
+    short flag;
 };
 
 // -------------------------------------------------------------------------------
 struct ListBase : ElemBase {
-    
-	boost::shared_ptr<ElemBase> first;
-	boost::shared_ptr<ElemBase> last;
+
+    boost::shared_ptr<ElemBase> first;
+    boost::shared_ptr<ElemBase> last;
 };
 
 
@@ -117,37 +119,37 @@ struct ListBase : ElemBase {
 struct PackedFile : ElemBase {
      int size WARN;
      int seek WARN;
-	 boost::shared_ptr< FileOffset > data WARN;
+     boost::shared_ptr< FileOffset > data WARN;
 };
 
 // -------------------------------------------------------------------------------
 struct GroupObject : ElemBase {
-	
-	boost::shared_ptr<GroupObject> prev,next FAIL;
-	boost::shared_ptr<Object> ob;
+
+    boost::shared_ptr<GroupObject> prev,next FAIL;
+    boost::shared_ptr<Object> ob;
 };
 
 // -------------------------------------------------------------------------------
 struct Group : ElemBase {
-	ID id FAIL;
-	int layer;
+    ID id FAIL;
+    int layer;
 
-	boost::shared_ptr<GroupObject> gobject;
+    boost::shared_ptr<GroupObject> gobject;
 };
 
 // -------------------------------------------------------------------------------
 struct World : ElemBase {
-	ID id FAIL;
-	
+    ID id FAIL;
+
 };
 
 // -------------------------------------------------------------------------------
 struct MVert : ElemBase {
-	float co[3] FAIL;
-	float no[3] FAIL;
-	char flag;
-	int mat_nr WARN;
-	int bweight;
+    float co[3] FAIL;
+    float no[3] FAIL;
+    char flag;
+    int mat_nr WARN;
+    int bweight;
 };
 
 // -------------------------------------------------------------------------------
@@ -159,68 +161,68 @@ struct MEdge : ElemBase {
 
 // -------------------------------------------------------------------------------
 struct MLoop : ElemBase {
-	int v, e;
+    int v, e;
 };
 
 // -------------------------------------------------------------------------------
 struct MLoopUV : ElemBase {
-	float uv[2];
-	int flag;
+    float uv[2];
+    int flag;
 };
 
 // -------------------------------------------------------------------------------
 // Note that red and blue are not swapped, as with MCol
 struct MLoopCol : ElemBase {
-	char r, g, b, a;
+    char r, g, b, a;
 };
 
 // -------------------------------------------------------------------------------
 struct MPoly : ElemBase {
-	int loopstart;
-	int totloop;
-	short mat_nr;
-	char flag;
+    int loopstart;
+    int totloop;
+    short mat_nr;
+    char flag;
 };
 
 // -------------------------------------------------------------------------------
 struct MTexPoly : ElemBase {
-	Image* tpage;
-	char flag, transp;
-	short mode, tile, pad;
+    Image* tpage;
+    char flag, transp;
+    short mode, tile, pad;
 };
 
 // -------------------------------------------------------------------------------
 struct MCol : ElemBase {
-	char r,g,b,a FAIL;
+    char r,g,b,a FAIL;
 };
 
 // -------------------------------------------------------------------------------
 struct MFace : ElemBase {
-	int v1,v2,v3,v4 FAIL;
-	int mat_nr FAIL;
-	char flag;
+    int v1,v2,v3,v4 FAIL;
+    int mat_nr FAIL;
+    char flag;
 };
 
 // -------------------------------------------------------------------------------
 struct TFace : ElemBase {
-	float uv[4][2] FAIL;
-	int col[4] FAIL;
-	char flag;
-	short mode;
-	short tile;
-	short unwrap;
+    float uv[4][2] FAIL;
+    int col[4] FAIL;
+    char flag;
+    short mode;
+    short tile;
+    short unwrap;
 };
 
 // -------------------------------------------------------------------------------
 struct MTFace : ElemBase {
 
-	float uv[4][2] FAIL;
-	char flag;
-	short mode;
-	short tile;
-	short unwrap;
+    float uv[4][2] FAIL;
+    char flag;
+    short mode;
+    short tile;
+    short unwrap;
 
-	// boost::shared_ptr<Image> tpage;
+    // boost::shared_ptr<Image> tpage;
 };
 
 // -------------------------------------------------------------------------------
@@ -232,185 +234,185 @@ struct MDeformWeight : ElemBase  {
 // -------------------------------------------------------------------------------
 struct MDeformVert : ElemBase  {
 
-	vector<MDeformWeight> dw WARN;
-	int totweight;
+    vector<MDeformWeight> dw WARN;
+    int totweight;
 };
 
 // -------------------------------------------------------------------------------
 struct Material : ElemBase {
-	ID id FAIL;
+    ID id FAIL;
 
-	float r,g,b WARN;
-	float specr,specg,specb WARN;
-	short har;
-	float ambr,ambg,ambb WARN;
-	float mirr,mirg,mirb;
-	float emit WARN;
-	float alpha WARN;
-	float ref;
-	float translucency;
-	float roughness;
-	float darkness;
-	float refrac;
+    float r,g,b WARN;
+    float specr,specg,specb WARN;
+    short har;
+    float ambr,ambg,ambb WARN;
+    float mirr,mirg,mirb;
+    float emit WARN;
+    float alpha WARN;
+    float ref;
+    float translucency;
+    float roughness;
+    float darkness;
+    float refrac;
 
-	boost::shared_ptr<Group> group;
+    boost::shared_ptr<Group> group;
 
-	short diff_shader WARN;
-	short spec_shader WARN;
+    short diff_shader WARN;
+    short spec_shader WARN;
 
-	boost::shared_ptr<MTex> mtex[18];
+    boost::shared_ptr<MTex> mtex[18];
 };
 
 // -------------------------------------------------------------------------------
 struct Mesh : ElemBase {
-	ID id FAIL;
+    ID id FAIL;
 
-	int totface FAIL;
-	int totedge FAIL;
-	int totvert FAIL;
-	int totloop;
-	int totpoly;
+    int totface FAIL;
+    int totedge FAIL;
+    int totvert FAIL;
+    int totloop;
+    int totpoly;
 
-	short subdiv;
-	short subdivr;
-	short subsurftype;
-	short smoothresh;
+    short subdiv;
+    short subdivr;
+    short subsurftype;
+    short smoothresh;
 
-	vector<MFace> mface FAIL;
-	vector<MTFace> mtface;
-	vector<TFace> tface;
-	vector<MVert> mvert FAIL;
-	vector<MEdge> medge WARN;
-	vector<MLoop> mloop;
-	vector<MLoopUV> mloopuv;
-	vector<MLoopCol> mloopcol;
-	vector<MPoly> mpoly;
-	vector<MTexPoly> mtpoly;
-	vector<MDeformVert> dvert;
-	vector<MCol> mcol;
+    vector<MFace> mface FAIL;
+    vector<MTFace> mtface;
+    vector<TFace> tface;
+    vector<MVert> mvert FAIL;
+    vector<MEdge> medge WARN;
+    vector<MLoop> mloop;
+    vector<MLoopUV> mloopuv;
+    vector<MLoopCol> mloopcol;
+    vector<MPoly> mpoly;
+    vector<MTexPoly> mtpoly;
+    vector<MDeformVert> dvert;
+    vector<MCol> mcol;
 
-	vector< boost::shared_ptr<Material> > mat FAIL;
+    vector< boost::shared_ptr<Material> > mat FAIL;
 };
 
 // -------------------------------------------------------------------------------
 struct Library : ElemBase {
-	ID id FAIL;
-	
-	char name[240] WARN;
-	char filename[240] FAIL;
-	boost::shared_ptr<Library> parent WARN;
+    ID id FAIL;
+
+    char name[240] WARN;
+    char filename[240] FAIL;
+    boost::shared_ptr<Library> parent WARN;
 };
 
 // -------------------------------------------------------------------------------
 struct Camera : ElemBase {
-	enum Type {
-		  Type_PERSP	=	0
-		 ,Type_ORTHO	=	1
-	};
+    enum Type {
+          Type_PERSP    =   0
+         ,Type_ORTHO    =   1
+    };
 
-	ID id FAIL;
+    ID id FAIL;
 
-	// struct AnimData *adt;  
+    // struct AnimData *adt;
 
-	Type type,flag WARN;
-	float angle WARN;
-	//float passepartalpha, angle;
-	//float clipsta, clipend;
-	//float lens, ortho_scale, drawsize;
-	//float shiftx, shifty;
+    Type type,flag WARN;
+    float angle WARN;
+    //float passepartalpha, angle;
+    //float clipsta, clipend;
+    //float lens, ortho_scale, drawsize;
+    //float shiftx, shifty;
 
-	//float YF_dofdist, YF_aperture;
-	//short YF_bkhtype, YF_bkhbias;
-	//float YF_bkhrot;
+    //float YF_dofdist, YF_aperture;
+    //short YF_bkhtype, YF_bkhbias;
+    //float YF_bkhrot;
 };
 
 
 // -------------------------------------------------------------------------------
 struct Lamp : ElemBase {
 
-	enum FalloffType {
-		 FalloffType_Constant	= 0x0
-		,FalloffType_InvLinear	= 0x1
-		,FalloffType_InvSquare	= 0x2
-		//,FalloffType_Curve	= 0x3
-		//,FalloffType_Sliders	= 0x4
-	};
-
-	enum Type {
-		 Type_Local			= 0x0
-		,Type_Sun			= 0x1
-		,Type_Spot			= 0x2
-		,Type_Hemi			= 0x3
-		,Type_Area			= 0x4
-		//,Type_YFPhoton	= 0x5
-	};
+    enum FalloffType {
+         FalloffType_Constant   = 0x0
+        ,FalloffType_InvLinear  = 0x1
+        ,FalloffType_InvSquare  = 0x2
+        //,FalloffType_Curve    = 0x3
+        //,FalloffType_Sliders  = 0x4
+    };
+
+    enum Type {
+         Type_Local         = 0x0
+        ,Type_Sun           = 0x1
+        ,Type_Spot          = 0x2
+        ,Type_Hemi          = 0x3
+        ,Type_Area          = 0x4
+        //,Type_YFPhoton    = 0x5
+    };
 
       ID id FAIL;
-      //AnimData *adt;  
-      
+      //AnimData *adt;
+
       Type type FAIL;
-	  short flags;
+      short flags;
 
       //int mode;
-      
+
       short colormodel, totex;
       float r,g,b,k WARN;
       //float shdwr, shdwg, shdwb;
-      
+
       float energy, dist, spotsize, spotblend;
       //float haint;
-         
-      float att1, att2; 
+
+      float att1, att2;
       //struct CurveMapping *curfalloff;
       FalloffType falloff_type;
-      
+
       //float clipsta, clipend, shadspotsize;
       //float bias, soft, compressthresh;
       //short bufsize, samp, buffers, filtertype;
       //char bufflag, buftype;
-      
+
       //short ray_samp, ray_sampy, ray_sampz;
       //short ray_samp_type;
       //short area_shape;
-	  //float area_size, area_sizey, area_sizez;
-	  //float adapt_thresh;
-	  //short ray_samp_method;
-
-	  //short texact, shadhalostep;
-
-	  //short sun_effect_type;
-	  //short skyblendtype;
-	  //float horizon_brightness;
-	  //float spread;
-	  float sun_brightness;
-	  //float sun_size;
-	  //float backscattered_light;
-	  //float sun_intensity;
-	  //float atm_turbidity;
-	  //float atm_inscattering_factor;
-	  //float atm_extinction_factor;
-	  //float atm_distance_factor;
-	  //float skyblendfac;
-	  //float sky_exposure;
-	  //short sky_colorspace;
-
-	  // int YF_numphotons, YF_numsearch;
-	  // short YF_phdepth, YF_useqmc, YF_bufsize, YF_pad;
-	  // float YF_causticblur, YF_ltradius;
-
-	  // float YF_glowint, YF_glowofs;
+      //float area_size, area_sizey, area_sizez;
+      //float adapt_thresh;
+      //short ray_samp_method;
+
+      //short texact, shadhalostep;
+
+      //short sun_effect_type;
+      //short skyblendtype;
+      //float horizon_brightness;
+      //float spread;
+      float sun_brightness;
+      //float sun_size;
+      //float backscattered_light;
+      //float sun_intensity;
+      //float atm_turbidity;
+      //float atm_inscattering_factor;
+      //float atm_extinction_factor;
+      //float atm_distance_factor;
+      //float skyblendfac;
+      //float sky_exposure;
+      //short sky_colorspace;
+
+      // int YF_numphotons, YF_numsearch;
+      // short YF_phdepth, YF_useqmc, YF_bufsize, YF_pad;
+      // float YF_causticblur, YF_ltradius;
+
+      // float YF_glowint, YF_glowofs;
       // short YF_glowtype, YF_pad2;
-      
-      //struct Ipo *ipo;                    
-      //struct MTex *mtex[18];              
+
+      //struct Ipo *ipo;
+      //struct MTex *mtex[18];
       // short pr_texture;
-      
+
       //struct PreviewImage *preview;
 };
 
 // -------------------------------------------------------------------------------
 struct ModifierData : ElemBase  {
-	enum ModifierType {
+    enum ModifierType {
       eModifierType_None = 0,
       eModifierType_Subsurf,
       eModifierType_Lattice,
@@ -444,314 +446,314 @@ struct ModifierData : ElemBase  {
       eModifierType_Surface,
       eModifierType_Smoke,
       eModifierType_ShapeKey
-	};
+    };
 
-	boost::shared_ptr<ElemBase> next WARN;
-	boost::shared_ptr<ElemBase> prev WARN;
+    boost::shared_ptr<ElemBase> next WARN;
+    boost::shared_ptr<ElemBase> prev WARN;
 
-	int type, mode;
-	char name[32];
+    int type, mode;
+    char name[32];
 };
 
 // -------------------------------------------------------------------------------
 struct SubsurfModifierData : ElemBase  {
 
-	enum Type {
-		
-		TYPE_CatmullClarke = 0x0,
-		TYPE_Simple = 0x1
-	};
+    enum Type {
+
+        TYPE_CatmullClarke = 0x0,
+        TYPE_Simple = 0x1
+    };
 
-	enum Flags {
-		// some omitted
-		FLAGS_SubsurfUV		=1<<3
-	};
+    enum Flags {
+        // some omitted
+        FLAGS_SubsurfUV     =1<<3
+    };
 
-	ModifierData modifier FAIL;
-	short subdivType WARN;
-	short levels FAIL;
-	short renderLevels ;
-	short flags;
+    ModifierData modifier FAIL;
+    short subdivType WARN;
+    short levels FAIL;
+    short renderLevels ;
+    short flags;
 };
 
 // -------------------------------------------------------------------------------
 struct MirrorModifierData : ElemBase {
 
-	enum Flags {
-		Flags_CLIPPING      =1<<0,
-		Flags_MIRROR_U      =1<<1,
-		Flags_MIRROR_V      =1<<2,
-		Flags_AXIS_X        =1<<3,
-		Flags_AXIS_Y        =1<<4,
-		Flags_AXIS_Z        =1<<5,
-		Flags_VGROUP        =1<<6
-	};
+    enum Flags {
+        Flags_CLIPPING      =1<<0,
+        Flags_MIRROR_U      =1<<1,
+        Flags_MIRROR_V      =1<<2,
+        Flags_AXIS_X        =1<<3,
+        Flags_AXIS_Y        =1<<4,
+        Flags_AXIS_Z        =1<<5,
+        Flags_VGROUP        =1<<6
+    };
 
-	ModifierData modifier FAIL;
+    ModifierData modifier FAIL;
 
-	short axis, flag;
-	float tolerance;
-	boost::shared_ptr<Object> mirror_ob;
+    short axis, flag;
+    float tolerance;
+    boost::shared_ptr<Object> mirror_ob;
 };
 
 // -------------------------------------------------------------------------------
 struct Object : ElemBase  {
-	ID id FAIL;
+    ID id FAIL;
+
+    enum Type {
+         Type_EMPTY     =   0
+        ,Type_MESH      =   1
+        ,Type_CURVE     =   2
+        ,Type_SURF      =   3
+        ,Type_FONT      =   4
+        ,Type_MBALL     =   5
 
-	enum Type {
-		 Type_EMPTY		=	0
-		,Type_MESH		=	1
-		,Type_CURVE		=	2
-		,Type_SURF		=   3
-		,Type_FONT		=   4
-		,Type_MBALL		=	5
+        ,Type_LAMP      =   10
+        ,Type_CAMERA    =   11
 
-		,Type_LAMP		=	10
-		,Type_CAMERA	=   11
+        ,Type_WAVE      =   21
+        ,Type_LATTICE   =   22
+    };
 
-		,Type_WAVE		=   21
-		,Type_LATTICE	=   22
-	};
+    Type type FAIL;
+    float obmat[4][4] WARN;
+    float parentinv[4][4] WARN;
+    char parsubstr[32] WARN;
 
-	Type type FAIL;
-	float obmat[4][4] WARN;
-	float parentinv[4][4] WARN;
-	char parsubstr[32] WARN;
-	
-	Object* parent WARN;
-	boost::shared_ptr<Object> track WARN;
+    Object* parent WARN;
+    boost::shared_ptr<Object> track WARN;
 
-	boost::shared_ptr<Object> proxy,proxy_from,proxy_group WARN;
-	boost::shared_ptr<Group> dup_group WARN;
-	boost::shared_ptr<ElemBase> data FAIL;
+    boost::shared_ptr<Object> proxy,proxy_from,proxy_group WARN;
+    boost::shared_ptr<Group> dup_group WARN;
+    boost::shared_ptr<ElemBase> data FAIL;
 
-	ListBase modifiers;
+    ListBase modifiers;
 };
 
 
 // -------------------------------------------------------------------------------
 struct Base : ElemBase {
-	Base* prev WARN;
-	boost::shared_ptr<Base> next WARN;
-	boost::shared_ptr<Object> object WARN;
+    Base* prev WARN;
+    boost::shared_ptr<Base> next WARN;
+    boost::shared_ptr<Object> object WARN;
 };
 
 // -------------------------------------------------------------------------------
 struct Scene : ElemBase {
-	ID id FAIL;
+    ID id FAIL;
 
-	boost::shared_ptr<Object> camera WARN;
-	boost::shared_ptr<World> world WARN;
-	boost::shared_ptr<Base> basact WARN;
+    boost::shared_ptr<Object> camera WARN;
+    boost::shared_ptr<World> world WARN;
+    boost::shared_ptr<Base> basact WARN;
 
-	ListBase base;
+    ListBase base;
 };
 
 
 // -------------------------------------------------------------------------------
 struct Image : ElemBase {
-	ID id FAIL;
+    ID id FAIL;
 
-	char name[240] WARN;               
+    char name[240] WARN;
 
-	//struct anim *anim;
+    //struct anim *anim;
 
-	short ok, flag;
-	short source, type, pad, pad1;
-	int lastframe;
+    short ok, flag;
+    short source, type, pad, pad1;
+    int lastframe;
 
-	short tpageflag, totbind;
-	short xrep, yrep;
-	short twsta, twend;
-	//unsigned int bindcode;  
-	//unsigned int *repbind; 
+    short tpageflag, totbind;
+    short xrep, yrep;
+    short twsta, twend;
+    //unsigned int bindcode;
+    //unsigned int *repbind;
 
-	boost::shared_ptr<PackedFile> packedfile;
-	//struct PreviewImage * preview;
+    boost::shared_ptr<PackedFile> packedfile;
+    //struct PreviewImage * preview;
 
-	float lastupdate;
-	int lastused;
-	short animspeed;
+    float lastupdate;
+    int lastused;
+    short animspeed;
 
-	short gen_x, gen_y, gen_type; 
+    short gen_x, gen_y, gen_type;
 };
 
 // -------------------------------------------------------------------------------
 struct Tex : ElemBase {
 
-	// actually, the only texture type we support is Type_IMAGE
-	enum Type {
-		 Type_CLOUDS		= 1
-		,Type_WOOD			= 2
-		,Type_MARBLE		= 3
-		,Type_MAGIC			= 4
-		,Type_BLEND			= 5
-		,Type_STUCCI		= 6
-		,Type_NOISE			= 7
-		,Type_IMAGE			= 8
-		,Type_PLUGIN		= 9
-		,Type_ENVMAP		= 10
-		,Type_MUSGRAVE		= 11
-		,Type_VORONOI		= 12
-		,Type_DISTNOISE		= 13
-		,Type_POINTDENSITY	= 14
-		,Type_VOXELDATA		= 15
-	};
-
-	enum ImageFlags {
-	     ImageFlags_INTERPOL    	 = 1
-	    ,ImageFlags_USEALPHA    	 = 2
-	    ,ImageFlags_MIPMAP      	 = 4
-	    ,ImageFlags_IMAROT      	 = 16
-	    ,ImageFlags_CALCALPHA   	 = 32
-	    ,ImageFlags_NORMALMAP   	 = 2048
-	    ,ImageFlags_GAUSS_MIP   	 = 4096
-	    ,ImageFlags_FILTER_MIN  	 = 8192
-	    ,ImageFlags_DERIVATIVEMAP   = 16384
-	};
-
-	ID id FAIL;
-	// AnimData *adt; 
-
-	//float noisesize, turbul;
-	//float bright, contrast, rfac, gfac, bfac;
-	//float filtersize;
-
-	//float mg_H, mg_lacunarity, mg_octaves, mg_offset, mg_gain;
-	//float dist_amount, ns_outscale;
-
-	//float vn_w1;
-	//float vn_w2;
-	//float vn_w3;
-	//float vn_w4;
-	//float vn_mexp;
-	//short vn_distm, vn_coltype;
-
-	//short noisedepth, noisetype;
-	//short noisebasis, noisebasis2;
-
-	//short flag;
-	ImageFlags imaflag;
-	Type type FAIL;
-	//short stype;
-
-	//float cropxmin, cropymin, cropxmax, cropymax;
-	//int texfilter;
-	//int afmax;  
-	//short xrepeat, yrepeat;
-	//short extend;
-
-	//short fie_ima;
-	//int len;
-	//int frames, offset, sfra;
-
-	//float checkerdist, nabla;
-	//float norfac;
-
-	//ImageUser iuser;
-
-	//bNodeTree *nodetree;
-	//Ipo *ipo;                  
-	boost::shared_ptr<Image> ima WARN;
-	//PluginTex *plugin;
-	//ColorBand *coba;
-	//EnvMap *env;
-	//PreviewImage * preview;
-	//PointDensity *pd;
-	//VoxelData *vd;
-
-	//char use_nodes;
+    // actually, the only texture type we support is Type_IMAGE
+    enum Type {
+         Type_CLOUDS        = 1
+        ,Type_WOOD          = 2
+        ,Type_MARBLE        = 3
+        ,Type_MAGIC         = 4
+        ,Type_BLEND         = 5
+        ,Type_STUCCI        = 6
+        ,Type_NOISE         = 7
+        ,Type_IMAGE         = 8
+        ,Type_PLUGIN        = 9
+        ,Type_ENVMAP        = 10
+        ,Type_MUSGRAVE      = 11
+        ,Type_VORONOI       = 12
+        ,Type_DISTNOISE     = 13
+        ,Type_POINTDENSITY  = 14
+        ,Type_VOXELDATA     = 15
+    };
+
+    enum ImageFlags {
+         ImageFlags_INTERPOL         = 1
+        ,ImageFlags_USEALPHA         = 2
+        ,ImageFlags_MIPMAP           = 4
+        ,ImageFlags_IMAROT           = 16
+        ,ImageFlags_CALCALPHA        = 32
+        ,ImageFlags_NORMALMAP        = 2048
+        ,ImageFlags_GAUSS_MIP        = 4096
+        ,ImageFlags_FILTER_MIN       = 8192
+        ,ImageFlags_DERIVATIVEMAP   = 16384
+    };
+
+    ID id FAIL;
+    // AnimData *adt;
+
+    //float noisesize, turbul;
+    //float bright, contrast, rfac, gfac, bfac;
+    //float filtersize;
+
+    //float mg_H, mg_lacunarity, mg_octaves, mg_offset, mg_gain;
+    //float dist_amount, ns_outscale;
+
+    //float vn_w1;
+    //float vn_w2;
+    //float vn_w3;
+    //float vn_w4;
+    //float vn_mexp;
+    //short vn_distm, vn_coltype;
+
+    //short noisedepth, noisetype;
+    //short noisebasis, noisebasis2;
+
+    //short flag;
+    ImageFlags imaflag;
+    Type type FAIL;
+    //short stype;
+
+    //float cropxmin, cropymin, cropxmax, cropymax;
+    //int texfilter;
+    //int afmax;
+    //short xrepeat, yrepeat;
+    //short extend;
+
+    //short fie_ima;
+    //int len;
+    //int frames, offset, sfra;
+
+    //float checkerdist, nabla;
+    //float norfac;
+
+    //ImageUser iuser;
+
+    //bNodeTree *nodetree;
+    //Ipo *ipo;
+    boost::shared_ptr<Image> ima WARN;
+    //PluginTex *plugin;
+    //ColorBand *coba;
+    //EnvMap *env;
+    //PreviewImage * preview;
+    //PointDensity *pd;
+    //VoxelData *vd;
+
+    //char use_nodes;
 };
 
 // -------------------------------------------------------------------------------
 struct MTex : ElemBase {
 
-	enum Projection {
-		 Proj_N = 0
-		,Proj_X = 1
-		,Proj_Y = 2
-		,Proj_Z = 3
-	};
-
-	enum Flag {
-		 Flag_RGBTOINT		= 0x1
-		,Flag_STENCIL		= 0x2
-		,Flag_NEGATIVE		= 0x4
-		,Flag_ALPHAMIX		= 0x8
-		,Flag_VIEWSPACE		= 0x10
-	};
-
-	enum BlendType {
-		 BlendType_BLEND			= 0
-		,BlendType_MUL				= 1
-		,BlendType_ADD				= 2
-		,BlendType_SUB				= 3
-		,BlendType_DIV				= 4
-		,BlendType_DARK				= 5
-		,BlendType_DIFF				= 6
-		,BlendType_LIGHT			= 7
-		,BlendType_SCREEN			= 8
-		,BlendType_OVERLAY			= 9
-		,BlendType_BLEND_HUE		= 10
-		,BlendType_BLEND_SAT		= 11
-		,BlendType_BLEND_VAL		= 12
-		,BlendType_BLEND_COLOR		= 13
-	};
-
-	enum MapType {
-	     MapType_COL         = 1
-	    ,MapType_NORM        = 2
-	    ,MapType_COLSPEC     = 4
-	    ,MapType_COLMIR      = 8
-	    ,MapType_REF         = 16
-	    ,MapType_SPEC        = 32
-	    ,MapType_EMIT        = 64
-	    ,MapType_ALPHA       = 128
-	    ,MapType_HAR         = 256
-	    ,MapType_RAYMIRR     = 512
-	    ,MapType_TRANSLU     = 1024
-	    ,MapType_AMB         = 2048
-	    ,MapType_DISPLACE    = 4096
-	    ,MapType_WARP        = 8192
-	};
-
-	// short texco, maptoneg;
-	MapType mapto;
-
-	BlendType blendtype;
-	boost::shared_ptr<Object> object;
-	boost::shared_ptr<Tex> tex;
-	char uvname[32];
-
-	Projection projx,projy,projz;
-	char mapping;
-	float ofs[3], size[3], rot;
-
-	int texflag;
-	short colormodel, pmapto, pmaptoneg;
-	//short normapspace, which_output;
-	//char brush_map_mode;
-	float r,g,b,k WARN;
-	//float def_var, rt;
-
-	//float colfac, varfac;
-
-	float norfac;
-	//float dispfac, warpfac;
-	float colspecfac, mirrfac, alphafac;
-	float difffac, specfac, emitfac, hardfac;
-	//float raymirrfac, translfac, ambfac;
-	//float colemitfac, colreflfac, coltransfac;
-	//float densfac, scatterfac, reflfac;
-
-	//float timefac, lengthfac, clumpfac;
-	//float kinkfac, roughfac, padensfac;
-	//float lifefac, sizefac, ivelfac, pvelfac;
-	//float shadowfac;
-	//float zenupfac, zendownfac, blendfac;
-};
-
-
-	}
+    enum Projection {
+         Proj_N = 0
+        ,Proj_X = 1
+        ,Proj_Y = 2
+        ,Proj_Z = 3
+    };
+
+    enum Flag {
+         Flag_RGBTOINT      = 0x1
+        ,Flag_STENCIL       = 0x2
+        ,Flag_NEGATIVE      = 0x4
+        ,Flag_ALPHAMIX      = 0x8
+        ,Flag_VIEWSPACE     = 0x10
+    };
+
+    enum BlendType {
+         BlendType_BLEND            = 0
+        ,BlendType_MUL              = 1
+        ,BlendType_ADD              = 2
+        ,BlendType_SUB              = 3
+        ,BlendType_DIV              = 4
+        ,BlendType_DARK             = 5
+        ,BlendType_DIFF             = 6
+        ,BlendType_LIGHT            = 7
+        ,BlendType_SCREEN           = 8
+        ,BlendType_OVERLAY          = 9
+        ,BlendType_BLEND_HUE        = 10
+        ,BlendType_BLEND_SAT        = 11
+        ,BlendType_BLEND_VAL        = 12
+        ,BlendType_BLEND_COLOR      = 13
+    };
+
+    enum MapType {
+         MapType_COL         = 1
+        ,MapType_NORM        = 2
+        ,MapType_COLSPEC     = 4
+        ,MapType_COLMIR      = 8
+        ,MapType_REF         = 16
+        ,MapType_SPEC        = 32
+        ,MapType_EMIT        = 64
+        ,MapType_ALPHA       = 128
+        ,MapType_HAR         = 256
+        ,MapType_RAYMIRR     = 512
+        ,MapType_TRANSLU     = 1024
+        ,MapType_AMB         = 2048
+        ,MapType_DISPLACE    = 4096
+        ,MapType_WARP        = 8192
+    };
+
+    // short texco, maptoneg;
+    MapType mapto;
+
+    BlendType blendtype;
+    boost::shared_ptr<Object> object;
+    boost::shared_ptr<Tex> tex;
+    char uvname[32];
+
+    Projection projx,projy,projz;
+    char mapping;
+    float ofs[3], size[3], rot;
+
+    int texflag;
+    short colormodel, pmapto, pmaptoneg;
+    //short normapspace, which_output;
+    //char brush_map_mode;
+    float r,g,b,k WARN;
+    //float def_var, rt;
+
+    //float colfac, varfac;
+
+    float norfac;
+    //float dispfac, warpfac;
+    float colspecfac, mirrfac, alphafac;
+    float difffac, specfac, emitfac, hardfac;
+    //float raymirrfac, translfac, ambfac;
+    //float colemitfac, colreflfac, coltransfac;
+    //float densfac, scatterfac, reflfac;
+
+    //float timefac, lengthfac, clumpfac;
+    //float kinkfac, roughfac, padensfac;
+    //float lifefac, sizefac, ivelfac, pvelfac;
+    //float shadowfac;
+    //float zenupfac, zendownfac, blendfac;
+};
+
+
+    }
 }
 #endif

+ 15 - 12
assimplib.mod/assimp/code/BlenderSceneGen.h

@@ -5,8 +5,8 @@ Open Asset Import Library (ASSIMP)
 Copyright (c) 2006-2010, ASSIMP Development Team
 All rights reserved.
 
-Redistribution and use of this software in source and binary forms, 
-with or without modification, are permitted provided that the 
+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
@@ -23,16 +23,16 @@ following conditions are met:
   derived from this software without specific prior
   written permission of the ASSIMP Development Team.
 
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -44,8 +44,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef INCLUDED_AI_BLEND_SCENEGEN_H
 #define INCLUDED_AI_BLEND_SCENEGEN_H
 
-namespace Assimp	{
-	namespace Blender {
+#include "BlenderDNA.h"
+#include "BlenderScene.h"
+
+namespace Assimp    {
+    namespace Blender {
 
 
 template <> void Structure :: Convert<Object> (
@@ -247,7 +250,7 @@ template <> void Structure :: Convert<Image> (
 ;
 
 
-	}
+    }
 }
 
 #endif

+ 262 - 263
assimplib.mod/assimp/code/BlenderTessellator.cpp

@@ -5,8 +5,8 @@ Open Asset Import Library (assimp)
 Copyright (c) 2006-2013, 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 
+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
@@ -23,16 +23,16 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -42,7 +42,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *  @brief A simple tessellation wrapper
  */
 
-#include "AssimpPCH.h"
 
 #ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
 
@@ -57,7 +56,7 @@ static const unsigned int BLEND_TESS_MAGIC = 0x83ed9ac3;
 
 namspace Assimp
 {
-	template< > const std::string LogFunctions< BlenderTessellatorGL >::log_prefix = "BLEND_TESS_GL: ";
+    template< > const std::string LogFunctions< BlenderTessellatorGL >::log_prefix = "BLEND_TESS_GL: ";
 }
 
 using namespace Assimp;
@@ -69,7 +68,7 @@ using namespace Assimp::Blender;
 
 // ------------------------------------------------------------------------------------------------
 BlenderTessellatorGL::BlenderTessellatorGL( BlenderBMeshConverter& converter ):
-	converter( &converter )
+    converter( &converter )
 {
 }
 
@@ -81,167 +80,167 @@ BlenderTessellatorGL::~BlenderTessellatorGL( )
 // ------------------------------------------------------------------------------------------------
 void BlenderTessellatorGL::Tessellate( const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices )
 {
-	AssertVertexCount( vertexCount );
+    AssertVertexCount( vertexCount );
 
-	std::vector< VertexGL > polyLoopGL;
-	GenerateLoopVerts( polyLoopGL, polyLoop, vertexCount, vertices );
+    std::vector< VertexGL > polyLoopGL;
+    GenerateLoopVerts( polyLoopGL, polyLoop, vertexCount, vertices );
 
-	TessDataGL tessData;
-	Tesssellate( polyLoopGL, tessData );
+    TessDataGL tessData;
+    Tesssellate( polyLoopGL, tessData );
 
-	TriangulateDrawCalls( tessData );
+    TriangulateDrawCalls( tessData );
 }
 
 // ------------------------------------------------------------------------------------------------
 void BlenderTessellatorGL::AssertVertexCount( int vertexCount )
 {
-	if ( vertexCount <= 4 )
-	{
-		ThrowException( "Expected more than 4 vertices for tessellation" );
-	}
+    if ( vertexCount <= 4 )
+    {
+        ThrowException( "Expected more than 4 vertices for tessellation" );
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 void BlenderTessellatorGL::GenerateLoopVerts( std::vector< VertexGL >& polyLoopGL, const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices )
 {
-	for ( int i = 0; i < vertexCount; ++i )
-	{
-		const MLoop& loopItem = polyLoop[ i ];
-		const MVert& vertex = vertices[ loopItem.v ];
-		polyLoopGL.push_back( VertexGL( vertex.co[ 0 ], vertex.co[ 1 ], vertex.co[ 2 ], loopItem.v, BLEND_TESS_MAGIC ) );
-	}
+    for ( int i = 0; i < vertexCount; ++i )
+    {
+        const MLoop& loopItem = polyLoop[ i ];
+        const MVert& vertex = vertices[ loopItem.v ];
+        polyLoopGL.push_back( VertexGL( vertex.co[ 0 ], vertex.co[ 1 ], vertex.co[ 2 ], loopItem.v, BLEND_TESS_MAGIC ) );
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 void BlenderTessellatorGL::Tesssellate( std::vector< VertexGL >& polyLoopGL, TessDataGL& tessData )
 {
-	GLUtesselator* tessellator = gluNewTess( );
-	gluTessCallback( tessellator, GLU_TESS_BEGIN_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateBegin ) );
-	gluTessCallback( tessellator, GLU_TESS_END_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateEnd ) );
-	gluTessCallback( tessellator, GLU_TESS_VERTEX_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateVertex ) );
-	gluTessCallback( tessellator, GLU_TESS_COMBINE_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateCombine ) );
-	gluTessCallback( tessellator, GLU_TESS_EDGE_FLAG_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateEdgeFlag ) );
-	gluTessCallback( tessellator, GLU_TESS_ERROR_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateError ) );
-	gluTessProperty( tessellator, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO );
+    GLUtesselator* tessellator = gluNewTess( );
+    gluTessCallback( tessellator, GLU_TESS_BEGIN_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateBegin ) );
+    gluTessCallback( tessellator, GLU_TESS_END_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateEnd ) );
+    gluTessCallback( tessellator, GLU_TESS_VERTEX_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateVertex ) );
+    gluTessCallback( tessellator, GLU_TESS_COMBINE_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateCombine ) );
+    gluTessCallback( tessellator, GLU_TESS_EDGE_FLAG_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateEdgeFlag ) );
+    gluTessCallback( tessellator, GLU_TESS_ERROR_DATA, reinterpret_cast< void ( CALLBACK * )( ) >( TessellateError ) );
+    gluTessProperty( tessellator, GLU_TESS_WINDING_RULE, GLU_TESS_WINDING_NONZERO );
 
-	gluTessBeginPolygon( tessellator, &tessData );
-	gluTessBeginContour( tessellator );
+    gluTessBeginPolygon( tessellator, &tessData );
+    gluTessBeginContour( tessellator );
 
-	for ( unsigned int i = 0; i < polyLoopGL.size( ); ++i )
-	{
-		gluTessVertex( tessellator, reinterpret_cast< GLdouble* >( &polyLoopGL[ i ] ), &polyLoopGL[ i ] );
-	}
+    for ( unsigned int i = 0; i < polyLoopGL.size( ); ++i )
+    {
+        gluTessVertex( tessellator, reinterpret_cast< GLdouble* >( &polyLoopGL[ i ] ), &polyLoopGL[ i ] );
+    }
 
-	gluTessEndContour( tessellator );
-	gluTessEndPolygon( tessellator );
+    gluTessEndContour( tessellator );
+    gluTessEndPolygon( tessellator );
 }
 
 // ------------------------------------------------------------------------------------------------
 void BlenderTessellatorGL::TriangulateDrawCalls( const TessDataGL& tessData )
 {
-	// NOTE - Because we are supplying a callback to GLU_TESS_EDGE_FLAG_DATA we don't technically
-	//        need support for GL_TRIANGLE_STRIP and GL_TRIANGLE_FAN but we'll keep it here in case
-	//        GLU tessellate changes or tristrips and fans are wanted.
-	//        See: http://www.opengl.org/sdk/docs/man2/xhtml/gluTessCallback.xml
-	for ( unsigned int i = 0; i < tessData.drawCalls.size( ); ++i )
-	{
-		const DrawCallGL& drawCallGL = tessData.drawCalls[ i ];
-		const VertexGL* vertices = &tessData.vertices[ drawCallGL.baseVertex ];
-		if ( drawCallGL.drawMode == GL_TRIANGLES )
-		{
-			MakeFacesFromTris( vertices, drawCallGL.vertexCount );
-		}
-		else if ( drawCallGL.drawMode == GL_TRIANGLE_STRIP )
-		{
-			MakeFacesFromTriStrip( vertices, drawCallGL.vertexCount );
-		}
-		else if ( drawCallGL.drawMode == GL_TRIANGLE_FAN )
-		{
-			MakeFacesFromTriFan( vertices, drawCallGL.vertexCount );
-		}
-	}
+    // NOTE - Because we are supplying a callback to GLU_TESS_EDGE_FLAG_DATA we don't technically
+    //        need support for GL_TRIANGLE_STRIP and GL_TRIANGLE_FAN but we'll keep it here in case
+    //        GLU tessellate changes or tristrips and fans are wanted.
+    //        See: http://www.opengl.org/sdk/docs/man2/xhtml/gluTessCallback.xml
+    for ( unsigned int i = 0; i < tessData.drawCalls.size( ); ++i )
+    {
+        const DrawCallGL& drawCallGL = tessData.drawCalls[ i ];
+        const VertexGL* vertices = &tessData.vertices[ drawCallGL.baseVertex ];
+        if ( drawCallGL.drawMode == GL_TRIANGLES )
+        {
+            MakeFacesFromTris( vertices, drawCallGL.vertexCount );
+        }
+        else if ( drawCallGL.drawMode == GL_TRIANGLE_STRIP )
+        {
+            MakeFacesFromTriStrip( vertices, drawCallGL.vertexCount );
+        }
+        else if ( drawCallGL.drawMode == GL_TRIANGLE_FAN )
+        {
+            MakeFacesFromTriFan( vertices, drawCallGL.vertexCount );
+        }
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 void BlenderTessellatorGL::MakeFacesFromTris( const VertexGL* vertices, int vertexCount )
 {
-	int triangleCount = vertexCount / 3;
-	for ( int i = 0; i < triangleCount; ++i )
-	{
-		int vertexBase = i * 3;
-		converter->AddFace( vertices[ vertexBase + 0 ].index, vertices[ vertexBase + 1 ].index, vertices[ vertexBase + 2 ].index );
-	}
+    int triangleCount = vertexCount / 3;
+    for ( int i = 0; i < triangleCount; ++i )
+    {
+        int vertexBase = i * 3;
+        converter->AddFace( vertices[ vertexBase + 0 ].index, vertices[ vertexBase + 1 ].index, vertices[ vertexBase + 2 ].index );
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 void BlenderTessellatorGL::MakeFacesFromTriStrip( const VertexGL* vertices, int vertexCount )
 {
-	int triangleCount = vertexCount - 2;
-	for ( int i = 0; i < triangleCount; ++i )
-	{
-		int vertexBase = i;
-		converter->AddFace( vertices[ vertexBase + 0 ].index, vertices[ vertexBase + 1 ].index, vertices[ vertexBase + 2 ].index );
-	}
+    int triangleCount = vertexCount - 2;
+    for ( int i = 0; i < triangleCount; ++i )
+    {
+        int vertexBase = i;
+        converter->AddFace( vertices[ vertexBase + 0 ].index, vertices[ vertexBase + 1 ].index, vertices[ vertexBase + 2 ].index );
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 void BlenderTessellatorGL::MakeFacesFromTriFan( const VertexGL* vertices, int vertexCount )
 {
-	int triangleCount = vertexCount - 2;
-	for ( int i = 0; i < triangleCount; ++i )
-	{
-		int vertexBase = i;
-		converter->AddFace( vertices[ 0 ].index, vertices[ vertexBase + 1 ].index, vertices[ vertexBase + 2 ].index );
-	}
+    int triangleCount = vertexCount - 2;
+    for ( int i = 0; i < triangleCount; ++i )
+    {
+        int vertexBase = i;
+        converter->AddFace( vertices[ 0 ].index, vertices[ vertexBase + 1 ].index, vertices[ vertexBase + 2 ].index );
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 void BlenderTessellatorGL::TessellateBegin( GLenum drawModeGL, void* userData )
 {
-	TessDataGL& tessData = *reinterpret_cast< TessDataGL* >( userData );
-	tessData.drawCalls.push_back( DrawCallGL( drawModeGL, tessData.vertices.size( ) ) );
+    TessDataGL& tessData = *reinterpret_cast< TessDataGL* >( userData );
+    tessData.drawCalls.push_back( DrawCallGL( drawModeGL, tessData.vertices.size( ) ) );
 }
 
 // ------------------------------------------------------------------------------------------------
 void BlenderTessellatorGL::TessellateEnd( void* )
 {
-	// Do nothing
+    // Do nothing
 }
 
 // ------------------------------------------------------------------------------------------------
 void BlenderTessellatorGL::TessellateVertex( const void* vtxData, void* userData )
 {
-	TessDataGL& tessData = *reinterpret_cast< TessDataGL* >( userData );
+    TessDataGL& tessData = *reinterpret_cast< TessDataGL* >( userData );
 
-	const VertexGL& vertex = *reinterpret_cast< const VertexGL* >( vtxData );
-	if ( vertex.magic != BLEND_TESS_MAGIC )
-	{
-		ThrowException( "Point returned by GLU Tessellate was probably not one of ours. This indicates we need a new way to store vertex information" );
-	}
-	tessData.vertices.push_back( vertex );
-	if ( tessData.drawCalls.size( ) == 0 )
-	{
-		ThrowException( "\"Vertex\" callback received before \"Begin\"" );
-	}
-	++( tessData.drawCalls.back( ).vertexCount );
+    const VertexGL& vertex = *reinterpret_cast< const VertexGL* >( vtxData );
+    if ( vertex.magic != BLEND_TESS_MAGIC )
+    {
+        ThrowException( "Point returned by GLU Tessellate was probably not one of ours. This indicates we need a new way to store vertex information" );
+    }
+    tessData.vertices.push_back( vertex );
+    if ( tessData.drawCalls.size( ) == 0 )
+    {
+        ThrowException( "\"Vertex\" callback received before \"Begin\"" );
+    }
+    ++( tessData.drawCalls.back( ).vertexCount );
 }
 
 // ------------------------------------------------------------------------------------------------
 void BlenderTessellatorGL::TessellateCombine( const GLdouble intersection[ 3 ], const GLdouble* [ 4 ], const GLfloat [ 4 ], GLdouble** out, void* userData )
 {
-	ThrowException( "Intersected polygon loops are not yet supported" );
+    ThrowException( "Intersected polygon loops are not yet supported" );
 }
 
 // ------------------------------------------------------------------------------------------------
 void BlenderTessellatorGL::TessellateEdgeFlag( GLboolean, void* )
 {
-	// Do nothing
+    // Do nothing
 }
 
 // ------------------------------------------------------------------------------------------------
 void BlenderTessellatorGL::TessellateError( GLenum errorCode, void* )
 {
-	ThrowException( reinterpret_cast< const char* >( gluErrorString( errorCode ) ) );
+    ThrowException( reinterpret_cast< const char* >( gluErrorString( errorCode ) ) );
 }
 
 #endif // ASSIMP_BLEND_WITH_GLU_TESSELLATE
@@ -250,7 +249,7 @@ void BlenderTessellatorGL::TessellateError( GLenum errorCode, void* )
 
 namespace Assimp
 {
-	template< > const std::string LogFunctions< BlenderTessellatorP2T >::log_prefix = "BLEND_TESS_P2T: ";
+    template< > const std::string LogFunctions< BlenderTessellatorP2T >::log_prefix = "BLEND_TESS_P2T: ";
 }
 
 using namespace Assimp;
@@ -258,7 +257,7 @@ using namespace Assimp::Blender;
 
 // ------------------------------------------------------------------------------------------------
 BlenderTessellatorP2T::BlenderTessellatorP2T( BlenderBMeshConverter& converter ):
-	converter( &converter )
+    converter( &converter )
 {
 }
 
@@ -270,178 +269,178 @@ BlenderTessellatorP2T::~BlenderTessellatorP2T( )
 // ------------------------------------------------------------------------------------------------
 void BlenderTessellatorP2T::Tessellate( const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices )
 {
-	AssertVertexCount( vertexCount );
+    AssertVertexCount( vertexCount );
 
-	// NOTE - We have to hope that points in a Blender polygon are roughly on the same plane.
-	//        There may be some triangulation artifacts if they are wildly different.
+    // NOTE - We have to hope that points in a Blender polygon are roughly on the same plane.
+    //        There may be some triangulation artifacts if they are wildly different.
 
-	std::vector< PointP2T > points;
-	Copy3DVertices( polyLoop, vertexCount, vertices, points );
+    std::vector< PointP2T > points;
+    Copy3DVertices( polyLoop, vertexCount, vertices, points );
 
-	PlaneP2T plane = FindLLSQPlane( points );
+    PlaneP2T plane = FindLLSQPlane( points );
 
-	aiMatrix4x4 transform = GeneratePointTransformMatrix( plane );
+    aiMatrix4x4 transform = GeneratePointTransformMatrix( plane );
 
-	TransformAndFlattenVectices( transform, points );
+    TransformAndFlattenVectices( transform, points );
 
-	std::vector< p2t::Point* > pointRefs;
-	ReferencePoints( points, pointRefs );
+    std::vector< p2t::Point* > pointRefs;
+    ReferencePoints( points, pointRefs );
 
-	p2t::CDT cdt( pointRefs );
+    p2t::CDT cdt( pointRefs );
 
-	cdt.Triangulate( );
-	std::vector< p2t::Triangle* > triangles = cdt.GetTriangles( );
+    cdt.Triangulate( );
+    std::vector< p2t::Triangle* > triangles = cdt.GetTriangles( );
 
-	MakeFacesFromTriangles( triangles );
+    MakeFacesFromTriangles( triangles );
 }
 
 // ------------------------------------------------------------------------------------------------
 void BlenderTessellatorP2T::AssertVertexCount( int vertexCount )
 {
-	if ( vertexCount <= 4 )
-	{
-		ThrowException( "Expected more than 4 vertices for tessellation" );
-	}
+    if ( vertexCount <= 4 )
+    {
+        ThrowException( "Expected more than 4 vertices for tessellation" );
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 void BlenderTessellatorP2T::Copy3DVertices( const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices, std::vector< PointP2T >& points ) const
 {
-	points.resize( vertexCount );
-	for ( int i = 0; i < vertexCount; ++i )
-	{
-		const MLoop& loop = polyLoop[ i ];
-		const MVert& vert = vertices[ loop.v ];
+    points.resize( vertexCount );
+    for ( int i = 0; i < vertexCount; ++i )
+    {
+        const MLoop& loop = polyLoop[ i ];
+        const MVert& vert = vertices[ loop.v ];
 
-		PointP2T& point = points[ i ];
-		point.point3D.Set( vert.co[ 0 ], vert.co[ 1 ], vert.co[ 2 ] );
-		point.index = loop.v;
-		point.magic = BLEND_TESS_MAGIC;
-	}
+        PointP2T& point = points[ i ];
+        point.point3D.Set( vert.co[ 0 ], vert.co[ 1 ], vert.co[ 2 ] );
+        point.index = loop.v;
+        point.magic = BLEND_TESS_MAGIC;
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 aiMatrix4x4 BlenderTessellatorP2T::GeneratePointTransformMatrix( const Blender::PlaneP2T& plane ) const
 {
-	aiVector3D sideA( 1.0f, 0.0f, 0.0f );
-	if ( fabs( plane.normal * sideA ) > 0.999f )
-	{
-		sideA = aiVector3D( 0.0f, 1.0f, 0.0f );
-	}
-
-	aiVector3D sideB( plane.normal ^ sideA );
-	sideB.Normalize( );
-	sideA = sideB ^ plane.normal;
-
-	aiMatrix4x4 result;
-	result.a1 = sideA.x;
-	result.a2 = sideA.y;
-	result.a3 = sideA.z;
-	result.b1 = sideB.x;
-	result.b2 = sideB.y;
-	result.b3 = sideB.z;
-	result.c1 = plane.normal.x;
-	result.c2 = plane.normal.y;
-	result.c3 = plane.normal.z;
-	result.a4 = plane.centre.x;
-	result.b4 = plane.centre.y;
-	result.c4 = plane.centre.z;
-	result.Inverse( );
-
-	return result;
+    aiVector3D sideA( 1.0f, 0.0f, 0.0f );
+    if ( std::fabs( plane.normal * sideA ) > 0.999f )
+    {
+        sideA = aiVector3D( 0.0f, 1.0f, 0.0f );
+    }
+
+    aiVector3D sideB( plane.normal ^ sideA );
+    sideB.Normalize( );
+    sideA = sideB ^ plane.normal;
+
+    aiMatrix4x4 result;
+    result.a1 = sideA.x;
+    result.a2 = sideA.y;
+    result.a3 = sideA.z;
+    result.b1 = sideB.x;
+    result.b2 = sideB.y;
+    result.b3 = sideB.z;
+    result.c1 = plane.normal.x;
+    result.c2 = plane.normal.y;
+    result.c3 = plane.normal.z;
+    result.a4 = plane.centre.x;
+    result.b4 = plane.centre.y;
+    result.c4 = plane.centre.z;
+    result.Inverse( );
+
+    return result;
 }
 
 // ------------------------------------------------------------------------------------------------
 void BlenderTessellatorP2T::TransformAndFlattenVectices( const aiMatrix4x4& transform, std::vector< Blender::PointP2T >& vertices ) const
 {
-	for ( unsigned int i = 0; i < vertices.size( ); ++i )
-	{
-		PointP2T& point = vertices[ i ];
-		point.point3D = transform * point.point3D;
-		point.point2D.set( point.point3D.y, point.point3D.z );
-	}
+    for ( unsigned int i = 0; i < vertices.size( ); ++i )
+    {
+        PointP2T& point = vertices[ i ];
+        point.point3D = transform * point.point3D;
+        point.point2D.set( point.point3D.y, point.point3D.z );
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 void BlenderTessellatorP2T::ReferencePoints( std::vector< Blender::PointP2T >& points, std::vector< p2t::Point* >& pointRefs ) const
 {
-	pointRefs.resize( points.size( ) );
-	for ( unsigned int i = 0; i < points.size( ); ++i )
-	{
-		pointRefs[ i ] = &points[ i ].point2D;
-	}
+    pointRefs.resize( points.size( ) );
+    for ( unsigned int i = 0; i < points.size( ); ++i )
+    {
+        pointRefs[ i ] = &points[ i ].point2D;
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 // Yes this is filthy... but we have no choice
 #define OffsetOf( Class, Member ) ( static_cast< unsigned int >( \
-	reinterpret_cast<uint8_t*>(&( reinterpret_cast< Class* >( NULL )->*( &Class::Member ) )) - \
-	static_cast<uint8_t*>(NULL) ) )
+    reinterpret_cast<uint8_t*>(&( reinterpret_cast< Class* >( NULL )->*( &Class::Member ) )) - \
+    static_cast<uint8_t*>(NULL) ) )
 
 inline PointP2T& BlenderTessellatorP2T::GetActualPointStructure( p2t::Point& point ) const
 {
-	unsigned int pointOffset = OffsetOf( PointP2T, point2D );
-	PointP2T& pointStruct = *reinterpret_cast< PointP2T* >( reinterpret_cast< char* >( &point ) - pointOffset );
-	if ( pointStruct.magic != static_cast<int>( BLEND_TESS_MAGIC ) )
-	{
-		ThrowException( "Point returned by poly2tri was probably not one of ours. This indicates we need a new way to store vertex information" );
-	}
-	return pointStruct;
+    unsigned int pointOffset = OffsetOf( PointP2T, point2D );
+    PointP2T& pointStruct = *reinterpret_cast< PointP2T* >( reinterpret_cast< char* >( &point ) - pointOffset );
+    if ( pointStruct.magic != static_cast<int>( BLEND_TESS_MAGIC ) )
+    {
+        ThrowException( "Point returned by poly2tri was probably not one of ours. This indicates we need a new way to store vertex information" );
+    }
+    return pointStruct;
 }
 
 // ------------------------------------------------------------------------------------------------
 void BlenderTessellatorP2T::MakeFacesFromTriangles( std::vector< p2t::Triangle* >& triangles ) const
 {
-	for ( unsigned int i = 0; i < triangles.size( ); ++i )
-	{
-		p2t::Triangle& Triangle = *triangles[ i ];
+    for ( unsigned int i = 0; i < triangles.size( ); ++i )
+    {
+        p2t::Triangle& Triangle = *triangles[ i ];
 
-		PointP2T& pointA = GetActualPointStructure( *Triangle.GetPoint( 0 ) );
-		PointP2T& pointB = GetActualPointStructure( *Triangle.GetPoint( 1 ) );
-		PointP2T& pointC = GetActualPointStructure( *Triangle.GetPoint( 2 ) );
+        PointP2T& pointA = GetActualPointStructure( *Triangle.GetPoint( 0 ) );
+        PointP2T& pointB = GetActualPointStructure( *Triangle.GetPoint( 1 ) );
+        PointP2T& pointC = GetActualPointStructure( *Triangle.GetPoint( 2 ) );
 
-		converter->AddFace( pointA.index, pointB.index, pointC.index );
-	}
+        converter->AddFace( pointA.index, pointB.index, pointC.index );
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 inline float p2tMax( float a, float b )
 {
-	return a > b ? a : b;
+    return a > b ? a : b;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html
 float BlenderTessellatorP2T::FindLargestMatrixElem( const aiMatrix3x3& mtx ) const
 {
-	float result = 0.0f;
+    float result = 0.0f;
 
-	for ( int x = 0; x < 3; ++x )
-	{
-		for ( int y = 0; y < 3; ++y )
-		{
-			result = p2tMax( fabs( mtx[ x ][ y ] ), result );
-		}
-	}
+    for ( int x = 0; x < 3; ++x )
+    {
+        for ( int y = 0; y < 3; ++y )
+        {
+            result = p2tMax( std::fabs( mtx[ x ][ y ] ), result );
+        }
+    }
 
-	return result;
+    return result;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Aparently Assimp doesn't have matrix scaling
 aiMatrix3x3 BlenderTessellatorP2T::ScaleMatrix( const aiMatrix3x3& mtx, float scale ) const
 {
-	aiMatrix3x3 result;
+    aiMatrix3x3 result;
 
-	for ( int x = 0; x < 3; ++x )
-	{
-		for ( int y = 0; y < 3; ++y )
-		{
-			result[ x ][ y ] = mtx[ x ][ y ] * scale;
-		}
-	}
+    for ( int x = 0; x < 3; ++x )
+    {
+        for ( int y = 0; y < 3; ++y )
+        {
+            result[ x ][ y ] = mtx[ x ][ y ] * scale;
+        }
+    }
 
-	return result;
+    return result;
 }
 
 
@@ -449,70 +448,70 @@ aiMatrix3x3 BlenderTessellatorP2T::ScaleMatrix( const aiMatrix3x3& mtx, float sc
 // Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html
 aiVector3D BlenderTessellatorP2T::GetEigenVectorFromLargestEigenValue( const aiMatrix3x3& mtx ) const
 {
-	float scale = FindLargestMatrixElem( mtx );
-	aiMatrix3x3 mc = ScaleMatrix( mtx, 1.0f / scale );
-	mc = mc * mc * mc;
-
-	aiVector3D v( 1.0f );
-	aiVector3D lastV = v;
-	for ( int i = 0; i < 100; ++i )
-	{
-		v = mc * v;
-		v.Normalize( );
-		if ( ( v - lastV ).SquareLength( ) < 1e-16f )
-		{
-			break;
-		}
-		lastV = v;
-	}
-	return v;
-} 
+    float scale = FindLargestMatrixElem( mtx );
+    aiMatrix3x3 mc = ScaleMatrix( mtx, 1.0f / scale );
+    mc = mc * mc * mc;
+
+    aiVector3D v( 1.0f );
+    aiVector3D lastV = v;
+    for ( int i = 0; i < 100; ++i )
+    {
+        v = mc * v;
+        v.Normalize( );
+        if ( ( v - lastV ).SquareLength( ) < 1e-16f )
+        {
+            break;
+        }
+        lastV = v;
+    }
+    return v;
+}
 
 // ------------------------------------------------------------------------------------------------
 // Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html
 PlaneP2T BlenderTessellatorP2T::FindLLSQPlane( const std::vector< PointP2T >& points ) const
 {
-	PlaneP2T result;
-
-	aiVector3D sum( 0.0f );
-	for ( unsigned int i = 0; i < points.size( ); ++i )
-	{
-		sum += points[ i ].point3D;
-	}
-	result.centre = sum * ( 1.0f / points.size( ) );
-
-	float sumXX = 0.0f;
-	float sumXY = 0.0f;
-	float sumXZ = 0.0f;
-	float sumYY = 0.0f;
-	float sumYZ = 0.0f;
-	float sumZZ = 0.0f;
-	for ( unsigned int i = 0; i < points.size( ); ++i )
-	{
-		aiVector3D offset = points[ i ].point3D - result.centre;
-		sumXX += offset.x * offset.x;
-		sumXY += offset.x * offset.y;
-		sumXZ += offset.x * offset.z;
-		sumYY += offset.y * offset.y;
-		sumYZ += offset.y * offset.z;
-		sumZZ += offset.z * offset.z;
-	}
-
-	aiMatrix3x3 mtx( sumXX, sumXY, sumXZ, sumXY, sumYY, sumYZ, sumXZ, sumYZ, sumZZ );
-
-	float det = mtx.Determinant( );
-	if ( det == 0.0f )
-	{
-		result.normal = aiVector3D( 0.0f );
-	}
-	else
-	{
-		aiMatrix3x3 invMtx = mtx;
-		invMtx.Inverse( );
-		result.normal = GetEigenVectorFromLargestEigenValue( invMtx );
-	}
-
-	return result;
+    PlaneP2T result;
+
+    aiVector3D sum( 0.0f );
+    for ( unsigned int i = 0; i < points.size( ); ++i )
+    {
+        sum += points[ i ].point3D;
+    }
+    result.centre = sum * ( 1.0f / points.size( ) );
+
+    float sumXX = 0.0f;
+    float sumXY = 0.0f;
+    float sumXZ = 0.0f;
+    float sumYY = 0.0f;
+    float sumYZ = 0.0f;
+    float sumZZ = 0.0f;
+    for ( unsigned int i = 0; i < points.size( ); ++i )
+    {
+        aiVector3D offset = points[ i ].point3D - result.centre;
+        sumXX += offset.x * offset.x;
+        sumXY += offset.x * offset.y;
+        sumXZ += offset.x * offset.z;
+        sumYY += offset.y * offset.y;
+        sumYZ += offset.y * offset.z;
+        sumZZ += offset.z * offset.z;
+    }
+
+    aiMatrix3x3 mtx( sumXX, sumXY, sumXZ, sumXY, sumYY, sumYZ, sumXZ, sumYZ, sumZZ );
+
+    float det = mtx.Determinant( );
+    if ( det == 0.0f )
+    {
+        result.normal = aiVector3D( 0.0f );
+    }
+    else
+    {
+        aiMatrix3x3 invMtx = mtx;
+        invMtx.Inverse( );
+        result.normal = GetEigenVectorFromLargestEigenValue( invMtx );
+    }
+
+    return result;
 }
 
 #endif // ASSIMP_BLEND_WITH_POLY_2_TRI

+ 135 - 135
assimplib.mod/assimp/code/BlenderTessellator.h

@@ -5,8 +5,8 @@ Open Asset Import Library (assimp)
 Copyright (c) 2006-2013, 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 
+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
@@ -23,16 +23,16 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -46,15 +46,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // Use these to toggle between GLU Tessellate or poly2tri
 // Note (acg) keep GLU Tesselate disabled by default - if it is turned on,
-// assimp needs to be linked against GLU, which is currently not yet 
+// assimp needs to be linked against GLU, which is currently not yet
 // made configurable in CMake and potentially not wanted by most users
 // as it requires a Gl environment.
 #ifndef ASSIMP_BLEND_WITH_GLU_TESSELLATE
-#	define ASSIMP_BLEND_WITH_GLU_TESSELLATE 0
+#   define ASSIMP_BLEND_WITH_GLU_TESSELLATE 0
 #endif
 
 #ifndef ASSIMP_BLEND_WITH_POLY_2_TRI
-#	define ASSIMP_BLEND_WITH_POLY_2_TRI 1
+#   define ASSIMP_BLEND_WITH_POLY_2_TRI 1
 #endif
 
 #include "LogAux.h"
@@ -68,74 +68,74 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 namespace Assimp
 {
-	class BlenderBMeshConverter;
-
-	// TinyFormatter.h
-	namespace Formatter
-	{
-		template < typename T,typename TR, typename A > class basic_formatter;
-		typedef class basic_formatter< char, std::char_traits< char >, std::allocator< char > > format;
-	}
-
-	// BlenderScene.h
-	namespace Blender
-	{
-		struct MLoop;
-		struct MVert;
-
-		struct VertexGL
-		{
-			GLdouble X;
-			GLdouble Y;
-			GLdouble Z;
-			int index;
-			int magic;
-
-			VertexGL( GLdouble X, GLdouble Y, GLdouble Z, int index, int magic ): X( X ), Y( Y ), Z( Z ), index( index ), magic( magic ) { }
-		};
-
-		struct DrawCallGL
-		{
-			GLenum drawMode;
-			int baseVertex;
-			int vertexCount;
-
-			DrawCallGL( GLenum drawMode, int baseVertex ): drawMode( drawMode ), baseVertex( baseVertex ), vertexCount( 0 ) { }
-		};
-
-		struct TessDataGL
-		{
-			std::vector< DrawCallGL > drawCalls;
-			std::vector< VertexGL > vertices;
-		};
-	}
-
-	class BlenderTessellatorGL: public LogFunctions< BlenderTessellatorGL >
-	{
-	public:
-		BlenderTessellatorGL( BlenderBMeshConverter& converter );
-		~BlenderTessellatorGL( );
-
-		void Tessellate( const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices );
-
-	private:
-		void AssertVertexCount( int vertexCount );
-		void GenerateLoopVerts( std::vector< Blender::VertexGL >& polyLoopGL, const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices );
-		void Tesssellate( std::vector< Blender::VertexGL >& polyLoopGL, Blender::TessDataGL& tessData );
-		void TriangulateDrawCalls( const Blender::TessDataGL& tessData );
-		void MakeFacesFromTris( const Blender::VertexGL* vertices, int vertexCount );
-		void MakeFacesFromTriStrip( const Blender::VertexGL* vertices, int vertexCount );
-		void MakeFacesFromTriFan( const Blender::VertexGL* vertices, int vertexCount );
-
-		static void TessellateBegin( GLenum drawModeGL, void* userData );
-		static void TessellateEnd( void* userData );
-		static void TessellateVertex( const void* vtxData, void* userData );
-		static void TessellateCombine( const GLdouble intersection[ 3 ], const GLdouble* [ 4 ], const GLfloat [ 4 ], GLdouble** out, void* userData );
-		static void TessellateEdgeFlag( GLboolean edgeFlag, void* userData );
-		static void TessellateError( GLenum errorCode, void* userData );
-
-		BlenderBMeshConverter* converter;
-	};
+    class BlenderBMeshConverter;
+
+    // TinyFormatter.h
+    namespace Formatter
+    {
+        template < typename T,typename TR, typename A > class basic_formatter;
+        typedef class basic_formatter< char, std::char_traits< char >, std::allocator< char > > format;
+    }
+
+    // BlenderScene.h
+    namespace Blender
+    {
+        struct MLoop;
+        struct MVert;
+
+        struct VertexGL
+        {
+            GLdouble X;
+            GLdouble Y;
+            GLdouble Z;
+            int index;
+            int magic;
+
+            VertexGL( GLdouble X, GLdouble Y, GLdouble Z, int index, int magic ): X( X ), Y( Y ), Z( Z ), index( index ), magic( magic ) { }
+        };
+
+        struct DrawCallGL
+        {
+            GLenum drawMode;
+            int baseVertex;
+            int vertexCount;
+
+            DrawCallGL( GLenum drawMode, int baseVertex ): drawMode( drawMode ), baseVertex( baseVertex ), vertexCount( 0 ) { }
+        };
+
+        struct TessDataGL
+        {
+            std::vector< DrawCallGL > drawCalls;
+            std::vector< VertexGL > vertices;
+        };
+    }
+
+    class BlenderTessellatorGL: public LogFunctions< BlenderTessellatorGL >
+    {
+    public:
+        BlenderTessellatorGL( BlenderBMeshConverter& converter );
+        ~BlenderTessellatorGL( );
+
+        void Tessellate( const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices );
+
+    private:
+        void AssertVertexCount( int vertexCount );
+        void GenerateLoopVerts( std::vector< Blender::VertexGL >& polyLoopGL, const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices );
+        void Tesssellate( std::vector< Blender::VertexGL >& polyLoopGL, Blender::TessDataGL& tessData );
+        void TriangulateDrawCalls( const Blender::TessDataGL& tessData );
+        void MakeFacesFromTris( const Blender::VertexGL* vertices, int vertexCount );
+        void MakeFacesFromTriStrip( const Blender::VertexGL* vertices, int vertexCount );
+        void MakeFacesFromTriFan( const Blender::VertexGL* vertices, int vertexCount );
+
+        static void TessellateBegin( GLenum drawModeGL, void* userData );
+        static void TessellateEnd( void* userData );
+        static void TessellateVertex( const void* vtxData, void* userData );
+        static void TessellateCombine( const GLdouble intersection[ 3 ], const GLdouble* [ 4 ], const GLfloat [ 4 ], GLdouble** out, void* userData );
+        static void TessellateEdgeFlag( GLboolean edgeFlag, void* userData );
+        static void TessellateError( GLenum errorCode, void* userData );
+
+        BlenderBMeshConverter* converter;
+    };
 } // end of namespace Assimp
 
 #endif // ASSIMP_BLEND_WITH_GLU_TESSELLATE
@@ -146,61 +146,61 @@ namespace Assimp
 
 namespace Assimp
 {
-	class BlenderBMeshConverter;
-
-	// TinyFormatter.h
-	namespace Formatter
-	{
-		template < typename T,typename TR, typename A > class basic_formatter;
-		typedef class basic_formatter< char, std::char_traits< char >, std::allocator< char > > format;
-	}
-
-	// BlenderScene.h
-	namespace Blender
-	{
-		struct MLoop;
-		struct MVert;
-
-		struct PointP2T
-		{
-			aiVector3D point3D;
-			p2t::Point point2D;
-			int magic;
-			int index;
-		};
-
-		struct PlaneP2T
-		{
-			aiVector3D centre;
-			aiVector3D normal;
-		};
-	}
-
-	class BlenderTessellatorP2T: public LogFunctions< BlenderTessellatorP2T >
-	{
-	public:
-		BlenderTessellatorP2T( BlenderBMeshConverter& converter );
-		~BlenderTessellatorP2T( );
-
-		void Tessellate( const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices );
-
-	private:
-		void AssertVertexCount( int vertexCount );
-		void Copy3DVertices( const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices, std::vector< Blender::PointP2T >& targetVertices ) const;
-		aiMatrix4x4 GeneratePointTransformMatrix( const Blender::PlaneP2T& plane ) const;
-		void TransformAndFlattenVectices( const aiMatrix4x4& transform, std::vector< Blender::PointP2T >& vertices ) const;
-		void ReferencePoints( std::vector< Blender::PointP2T >& points, std::vector< p2t::Point* >& pointRefs ) const;
-		inline Blender::PointP2T& GetActualPointStructure( p2t::Point& point ) const;
-		void MakeFacesFromTriangles( std::vector< p2t::Triangle* >& triangles ) const;
-
-		// Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html
-		float FindLargestMatrixElem( const aiMatrix3x3& mtx ) const;
-		aiMatrix3x3 ScaleMatrix( const aiMatrix3x3& mtx, float scale ) const;
-		aiVector3D GetEigenVectorFromLargestEigenValue( const aiMatrix3x3& mtx ) const;
-		Blender::PlaneP2T FindLLSQPlane( const std::vector< Blender::PointP2T >& points ) const;
-
-		BlenderBMeshConverter* converter;
-	};
+    class BlenderBMeshConverter;
+
+    // TinyFormatter.h
+    namespace Formatter
+    {
+        template < typename T,typename TR, typename A > class basic_formatter;
+        typedef class basic_formatter< char, std::char_traits< char >, std::allocator< char > > format;
+    }
+
+    // BlenderScene.h
+    namespace Blender
+    {
+        struct MLoop;
+        struct MVert;
+
+        struct PointP2T
+        {
+            aiVector3D point3D;
+            p2t::Point point2D;
+            int magic;
+            int index;
+        };
+
+        struct PlaneP2T
+        {
+            aiVector3D centre;
+            aiVector3D normal;
+        };
+    }
+
+    class BlenderTessellatorP2T: public LogFunctions< BlenderTessellatorP2T >
+    {
+    public:
+        BlenderTessellatorP2T( BlenderBMeshConverter& converter );
+        ~BlenderTessellatorP2T( );
+
+        void Tessellate( const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices );
+
+    private:
+        void AssertVertexCount( int vertexCount );
+        void Copy3DVertices( const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices, std::vector< Blender::PointP2T >& targetVertices ) const;
+        aiMatrix4x4 GeneratePointTransformMatrix( const Blender::PlaneP2T& plane ) const;
+        void TransformAndFlattenVectices( const aiMatrix4x4& transform, std::vector< Blender::PointP2T >& vertices ) const;
+        void ReferencePoints( std::vector< Blender::PointP2T >& points, std::vector< p2t::Point* >& pointRefs ) const;
+        inline Blender::PointP2T& GetActualPointStructure( p2t::Point& point ) const;
+        void MakeFacesFromTriangles( std::vector< p2t::Triangle* >& triangles ) const;
+
+        // Adapted from: http://missingbytes.blogspot.co.uk/2012/06/fitting-plane-to-point-cloud.html
+        float FindLargestMatrixElem( const aiMatrix3x3& mtx ) const;
+        aiMatrix3x3 ScaleMatrix( const aiMatrix3x3& mtx, float scale ) const;
+        aiVector3D GetEigenVectorFromLargestEigenValue( const aiMatrix3x3& mtx ) const;
+        Blender::PlaneP2T FindLLSQPlane( const std::vector< Blender::PointP2T >& points ) const;
+
+        BlenderBMeshConverter* converter;
+    };
 } // end of namespace Assimp
 
 #endif // ASSIMP_BLEND_WITH_POLY_2_TRI

+ 223 - 212
assimplib.mod/assimp/code/BlobIOSystem.h

@@ -3,12 +3,12 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -25,16 +25,16 @@ conditions are met:
   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 
+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 
+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 
+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 
+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.
 ---------------------------------------------------------------------------
 */
@@ -45,8 +45,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_BLOBIOSYSTEM_H_INCLUDED
 #define AI_BLOBIOSYSTEM_H_INCLUDED
 
-namespace Assimp	{
-	class BlobIOSystem;
+#include "./../include/assimp/IOStream.hpp"
+#include "./../include/assimp/cexport.h"
+#include "./../include/assimp/IOSystem.hpp"
+#include "./../include/assimp/DefaultLogger.hpp"
+#include <boost/foreach.hpp>
+#include <stdint.h>
+#include <set>
+#include <vector>
+
+namespace Assimp    {
+    class BlobIOSystem;
 
 // --------------------------------------------------------------------------------------------
 /** Redirect IOStream to a blob */
@@ -55,142 +64,144 @@ class BlobIOStream : public IOStream
 {
 public:
 
-	BlobIOStream(BlobIOSystem* creator, const std::string& file, size_t initial = 4096)
-		: buffer()
-		, cur_size()
-		, file_size()
-		, cursor()
-		, initial(initial)
-		, file(file)
-		, creator(creator)
-	{
-	}
+    BlobIOStream(BlobIOSystem* creator, const std::string& file, size_t initial = 4096)
+        : buffer()
+        , cur_size()
+        , file_size()
+        , cursor()
+        , initial(initial)
+        , file(file)
+        , creator(creator)
+    {
+    }
 
 
-	virtual ~BlobIOStream();
+    virtual ~BlobIOStream();
 
 public:
 
-	// -------------------------------------------------------------------
-	aiExportDataBlob* GetBlob()
-	{
-		aiExportDataBlob* blob = new aiExportDataBlob();
-		blob->size = file_size;
-		blob->data = buffer;
+    // -------------------------------------------------------------------
+    aiExportDataBlob* GetBlob()
+    {
+        aiExportDataBlob* blob = new aiExportDataBlob();
+        blob->size = file_size;
+        blob->data = buffer;
 
-		buffer = NULL;
+        buffer = NULL;
 
-		return blob;
-	}
+        return blob;
+    }
 
 
 public:
 
 
-	// -------------------------------------------------------------------
-    virtual size_t Read( void *, 
-		size_t, 
-		size_t ) 
-	{
-		return 0;
-	}
-
-	// -------------------------------------------------------------------
-    virtual size_t Write(const void* pvBuffer, 
-		size_t pSize,
-		size_t pCount) 
-	{
-		pSize *= pCount;
-		if (cursor + pSize > cur_size) {
-			Grow(cursor + pSize);
-		}
-
-		memcpy(buffer+cursor, pvBuffer, pSize);
-		cursor += pSize;
-
-		file_size = std::max(file_size,cursor);
-		return pCount; 
-	}
-
-	// -------------------------------------------------------------------
-	virtual aiReturn Seek(size_t pOffset,
-		aiOrigin pOrigin)
-	{
-		switch(pOrigin) 
-		{
-		case aiOrigin_CUR:
-			cursor += pOffset;
-
-		case aiOrigin_END:
-			cursor = file_size - pOffset;
-
-		case aiOrigin_SET:
-			cursor = pOffset;
-			break;
-
-		default:
-			return AI_FAILURE;
-		}
-
-		if (cursor > file_size) {
-			Grow(cursor);
-		}
-
-		file_size = std::max(cursor,file_size);
-		return AI_SUCCESS;
-	}
-
-	// -------------------------------------------------------------------
+    // -------------------------------------------------------------------
+    virtual size_t Read( void *,
+        size_t,
+        size_t )
+    {
+        return 0;
+    }
+
+    // -------------------------------------------------------------------
+    virtual size_t Write(const void* pvBuffer,
+        size_t pSize,
+        size_t pCount)
+    {
+        pSize *= pCount;
+        if (cursor + pSize > cur_size) {
+            Grow(cursor + pSize);
+        }
+
+        memcpy(buffer+cursor, pvBuffer, pSize);
+        cursor += pSize;
+
+        file_size = std::max(file_size,cursor);
+        return pCount;
+    }
+
+    // -------------------------------------------------------------------
+    virtual aiReturn Seek(size_t pOffset,
+        aiOrigin pOrigin)
+    {
+        switch(pOrigin)
+        {
+        case aiOrigin_CUR:
+            cursor += pOffset;
+            break;
+
+        case aiOrigin_END:
+            cursor = file_size - pOffset;
+            break;
+
+        case aiOrigin_SET:
+            cursor = pOffset;
+            break;
+
+        default:
+            return AI_FAILURE;
+        }
+
+        if (cursor > file_size) {
+            Grow(cursor);
+        }
+
+        file_size = std::max(cursor,file_size);
+        return AI_SUCCESS;
+    }
+
+    // -------------------------------------------------------------------
     virtual size_t Tell() const
-	{
-		return cursor;
-	}
+    {
+        return cursor;
+    }
 
-	// -------------------------------------------------------------------
-	virtual size_t FileSize() const
-	{
-		return file_size;
-	}
+    // -------------------------------------------------------------------
+    virtual size_t FileSize() const
+    {
+        return file_size;
+    }
 
-	// -------------------------------------------------------------------
-	virtual void Flush() 
-	{
-		// ignore
-	}
+    // -------------------------------------------------------------------
+    virtual void Flush()
+    {
+        // ignore
+    }
 
 
 
 private:
 
-	// -------------------------------------------------------------------
-	void Grow(size_t need = 0) 
-	{
-		// 1.5 and phi are very heap-friendly growth factors (the first
-		// allows for frequent re-use of heap blocks, the second
-		// forms a fibonacci sequence with similar characteristics -
-		// since this heavily depends on the heap implementation 
-		// and other factors as well, i'll just go with 1.5 since
-		// it is quicker to compute).
-		size_t new_size = std::max(initial, std::max( need, cur_size+(cur_size>>1) ));
+    // -------------------------------------------------------------------
+    void Grow(size_t need = 0)
+    {
+        // 1.5 and phi are very heap-friendly growth factors (the first
+        // allows for frequent re-use of heap blocks, the second
+        // forms a fibonacci sequence with similar characteristics -
+        // since this heavily depends on the heap implementation
+        // and other factors as well, i'll just go with 1.5 since
+        // it is quicker to compute).
+        size_t new_size = std::max(initial, std::max( need, cur_size+(cur_size>>1) ));
 
-		const uint8_t* const old = buffer;
-		buffer = new uint8_t[new_size];
+        const uint8_t* const old = buffer;
+        buffer = new uint8_t[new_size];
 
-		if (old) {
-			memcpy(buffer,old,cur_size);
-			delete[] old;
-		}
+        if (old) {
+            memcpy(buffer,old,cur_size);
+            delete[] old;
+        }
 
-		cur_size = new_size;
-	}
+        cur_size = new_size;
+    }
 
 private:
 
-	uint8_t* buffer;
-	size_t cur_size,file_size, cursor, initial;
+    uint8_t* buffer;
+    size_t cur_size,file_size, cursor, initial;
 
-	const std::string file;
-	BlobIOSystem* const creator;
+    const std::string file;
+    BlobIOSystem* const creator;
 };
 
 
@@ -202,125 +213,125 @@ private:
 class BlobIOSystem : public IOSystem
 {
 
-	friend class BlobIOStream;
-	typedef std::pair<std::string, aiExportDataBlob*> BlobEntry;
+    friend class BlobIOStream;
+    typedef std::pair<std::string, aiExportDataBlob*> BlobEntry;
 
 public:
 
-	BlobIOSystem()
-	{
-	}
+    BlobIOSystem()
+    {
+    }
 
-	virtual ~BlobIOSystem()
-	{
-		BOOST_FOREACH(BlobEntry& blobby, blobs) {
-			delete blobby.second;
-		}
-	}
+    virtual ~BlobIOSystem()
+    {
+        BOOST_FOREACH(BlobEntry& blobby, blobs) {
+            delete blobby.second;
+        }
+    }
 
 public:
 
-	// -------------------------------------------------------------------
-	const char* GetMagicFileName() const 
-	{
-		return AI_BLOBIO_MAGIC;
-	}
-
-
-	// -------------------------------------------------------------------
-	aiExportDataBlob* GetBlobChain()
-	{
-		// one must be the master
-		aiExportDataBlob* master = NULL, *cur;
-		BOOST_FOREACH(const BlobEntry& blobby, blobs) {
-			if (blobby.first == AI_BLOBIO_MAGIC) {
-				master = blobby.second;
-				break;
-			}
-		}
-		if (!master) {
-			DefaultLogger::get()->error("BlobIOSystem: no data written or master file was not closed properly.");
-			return NULL;
-		}
-
-		master->name.Set("");
-
-		cur = master;
-		BOOST_FOREACH(const BlobEntry& blobby, blobs) {
-			if (blobby.second == master) {
-				continue;
-			}
-
-			cur->next = blobby.second;
-			cur = cur->next;
-
-			// extract the file extension from the file written
-			const std::string::size_type s = blobby.first.find_first_of('.');
-			cur->name.Set(s == std::string::npos ? blobby.first : blobby.first.substr(s+1));
-		}
-
-		// give up blob ownership
-		blobs.clear();
-		return master;
-	}
+    // -------------------------------------------------------------------
+    const char* GetMagicFileName() const
+    {
+        return AI_BLOBIO_MAGIC;
+    }
+
+
+    // -------------------------------------------------------------------
+    aiExportDataBlob* GetBlobChain()
+    {
+        // one must be the master
+        aiExportDataBlob* master = NULL, *cur;
+        BOOST_FOREACH(const BlobEntry& blobby, blobs) {
+            if (blobby.first == AI_BLOBIO_MAGIC) {
+                master = blobby.second;
+                break;
+            }
+        }
+        if (!master) {
+            DefaultLogger::get()->error("BlobIOSystem: no data written or master file was not closed properly.");
+            return NULL;
+        }
+
+        master->name.Set("");
+
+        cur = master;
+        BOOST_FOREACH(const BlobEntry& blobby, blobs) {
+            if (blobby.second == master) {
+                continue;
+            }
+
+            cur->next = blobby.second;
+            cur = cur->next;
+
+            // extract the file extension from the file written
+            const std::string::size_type s = blobby.first.find_first_of('.');
+            cur->name.Set(s == std::string::npos ? blobby.first : blobby.first.substr(s+1));
+        }
+
+        // give up blob ownership
+        blobs.clear();
+        return master;
+    }
 
 public:
 
-	// -------------------------------------------------------------------
-	virtual bool Exists( const char* pFile) const {
-		return created.find(std::string(pFile)) != created.end();
-	}
+    // -------------------------------------------------------------------
+    virtual bool Exists( const char* pFile) const {
+        return created.find(std::string(pFile)) != created.end();
+    }
 
 
-	// -------------------------------------------------------------------
-	virtual char getOsSeparator() const {
-		return '/';
-	}
+    // -------------------------------------------------------------------
+    virtual char getOsSeparator() const {
+        return '/';
+    }
 
 
-	// -------------------------------------------------------------------
-	virtual IOStream* Open(const char* pFile,
-		const char* pMode)
-	{
-		if (pMode[0] != 'w') {
-			return NULL;
-		}
+    // -------------------------------------------------------------------
+    virtual IOStream* Open(const char* pFile,
+        const char* pMode)
+    {
+        if (pMode[0] != 'w') {
+            return NULL;
+        }
 
-		created.insert(std::string(pFile));
-		return new BlobIOStream(this,std::string(pFile));
-	}
+        created.insert(std::string(pFile));
+        return new BlobIOStream(this,std::string(pFile));
+    }
 
-	// -------------------------------------------------------------------
-	virtual void Close( IOStream* pFile) 
-	{
-		delete pFile;
-	}
+    // -------------------------------------------------------------------
+    virtual void Close( IOStream* pFile)
+    {
+        delete pFile;
+    }
 
 private:
 
-	// -------------------------------------------------------------------
-	void OnDestruct(const std::string& filename, BlobIOStream* child) 
-	{	
-		// we don't know in which the files are closed, so we
-		// can't reliably say that the first must be the master 
-		// file ...
-		blobs.push_back( BlobEntry(filename,child->GetBlob()) );
-	}
+    // -------------------------------------------------------------------
+    void OnDestruct(const std::string& filename, BlobIOStream* child)
+    {
+        // we don't know in which the files are closed, so we
+        // can't reliably say that the first must be the master
+        // file ...
+        blobs.push_back( BlobEntry(filename,child->GetBlob()) );
+    }
 
 private:
-	std::set<std::string> created;
-	std::vector< BlobEntry > blobs;
+    std::set<std::string> created;
+    std::vector< BlobEntry > blobs;
 };
 
 
 // --------------------------------------------------------------------------------------------
-BlobIOStream :: ~BlobIOStream() 
+BlobIOStream :: ~BlobIOStream()
 {
-	creator->OnDestruct(file,this);
-	delete[] buffer;
+    creator->OnDestruct(file,this);
+    delete[] buffer;
 }
 
-	
+
 } // end Assimp
 
 #endif

+ 1 - 0
assimplib.mod/assimp/code/BoostWorkaround/boost/format.hpp

@@ -13,6 +13,7 @@
 
 #include <string>
 #include <vector>
+#include <sstream> 
 
 namespace boost
 {

+ 3 - 0
assimplib.mod/assimp/code/BoostWorkaround/boost/shared_ptr.hpp

@@ -6,6 +6,9 @@
 
 // ------------------------------
 // Internal stub
+
+#include <stddef.h> //NULL
+#include <algorithm> //std::swap
 namespace boost {
 	namespace detail {
 		class controller {

+ 2 - 1
assimplib.mod/assimp/code/BoostWorkaround/boost/timer.hpp

@@ -19,6 +19,7 @@
 
 //#include <boost/config.hpp>
 #include <ctime>
+#include <limits>
 //#include <boost/limits.hpp>
 
 # ifdef BOOST_NO_STDC_NAMESPACE
@@ -69,4 +70,4 @@ class timer
 
 } // namespace boost
 
-#endif  // BOOST_TIMER_HPP
+#endif  // BOOST_TIMER_HPP

+ 3 - 3
assimplib.mod/assimp/code/BoostWorkaround/boost/tuple/tuple.hpp

@@ -100,7 +100,7 @@ namespace boost	{
 			};
 
 			// dummy
-			list_elem& operator = (const list_elem& other)	{
+			list_elem& operator = (const list_elem& /*other*/)	{
 				return *this;
 			}
 
@@ -142,7 +142,7 @@ namespace boost	{
 				return me.me;
 			}
 		};
-	};
+	}
 
 	// A very minimal implementation for up to 5 elements
 	template <typename T0  = detail::nulltype,
@@ -278,6 +278,6 @@ namespace boost	{
 		tuple <> t;
 		return t;
 	}
-};
+}
 
 #endif // !! BOOST_TUPLE_INCLUDED

+ 0 - 285
assimplib.mod/assimp/code/ByteSwap.h

@@ -1,285 +0,0 @@
-/*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-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.
-
-----------------------------------------------------------------------
-*/
-
-/** @file Helper class tp perform various byte oder swappings 
-   (e.g. little to big endian) */
-#ifndef AI_BYTESWAP_H_INC
-#define AI_BYTESWAP_H_INC
-
-#include "../include/assimp/ai_assert.h"
-#include "../include/assimp/types.h"
-
-#if _MSC_VER >= 1400 
-#include <stdlib.h>
-#endif
-
-namespace Assimp	{
-// --------------------------------------------------------------------------------------
-/** Defines some useful byte order swap routines.
- * 
- * This is required to read big-endian model formats on little-endian machines,
- * and vice versa. Direct use of this class is DEPRECATED. Use #StreamReader instead. */
-// --------------------------------------------------------------------------------------
-class ByteSwap
-{
-	ByteSwap() {}
-
-public:
-
-	// ----------------------------------------------------------------------
-	/** Swap two bytes of data
-	 *  @param[inout] _szOut A void* to save the reintcasts for the caller. */
-	static inline void Swap2(void* _szOut)
-	{
-		ai_assert(_szOut);
-
-#if _MSC_VER >= 1400
-		uint16_t* const szOut = reinterpret_cast<uint16_t*>(_szOut);
-		*szOut = _byteswap_ushort(*szOut);
-#else
-		uint8_t* const szOut = reinterpret_cast<uint8_t*>(_szOut);
-		std::swap(szOut[0],szOut[1]);
-#endif
-	}
-
-	// ----------------------------------------------------------------------
-	/** Swap four bytes of data
-	 *  @param[inout] _szOut A void* to save the reintcasts for the caller. */
-	static inline void Swap4(void* _szOut)
-	{
-		ai_assert(_szOut);
-
-#if _MSC_VER >= 1400
-		uint32_t* const szOut = reinterpret_cast<uint32_t*>(_szOut);
-		*szOut = _byteswap_ulong(*szOut);
-#else
-		uint8_t* const szOut = reinterpret_cast<uint8_t*>(_szOut);
-		std::swap(szOut[0],szOut[3]);
-		std::swap(szOut[1],szOut[2]);
-#endif
-	}
-
-	// ----------------------------------------------------------------------
-	/** Swap eight bytes of data
-	 *  @param[inout] _szOut A void* to save the reintcasts for the caller. */
-	static inline void Swap8(void* _szOut)
-	{
-	ai_assert(_szOut);
-
-#if _MSC_VER >= 1400
-		uint64_t* const szOut = reinterpret_cast<uint64_t*>(_szOut);
-		*szOut = _byteswap_uint64(*szOut);
-#else
-		uint8_t* const szOut = reinterpret_cast<uint8_t*>(_szOut);
-		std::swap(szOut[0],szOut[7]);
-		std::swap(szOut[1],szOut[6]);
-		std::swap(szOut[2],szOut[5]);
-		std::swap(szOut[3],szOut[4]);
-#endif
-	}
-
-	// ----------------------------------------------------------------------
-	/** ByteSwap a float. Not a joke.
-	 *  @param[inout] fOut ehm. .. */
-	static inline void Swap(float* fOut) {
-		Swap4(fOut);
-	}
-
-	// ----------------------------------------------------------------------
-	/** ByteSwap a double. Not a joke.
-	 *  @param[inout] fOut ehm. .. */
-	static inline void Swap(double* fOut) {
-		Swap8(fOut);
-	}
-
-
-	// ----------------------------------------------------------------------
-	/** ByteSwap an int16t. Not a joke.
-	 *  @param[inout] fOut ehm. .. */
-	static inline void Swap(int16_t* fOut) {
-		Swap2(fOut);
-	}
-
-	static inline void Swap(uint16_t* fOut) {
-		Swap2(fOut);
-	}
-
-	// ----------------------------------------------------------------------
-	/** ByteSwap an int32t. Not a joke.
-	 *  @param[inout] fOut ehm. .. */
-	static inline void Swap(int32_t* fOut){
-		Swap4(fOut);
-	}
-
-	static inline void Swap(uint32_t* fOut){
-		Swap4(fOut);
-	}
-
-	// ----------------------------------------------------------------------
-	/** ByteSwap an int64t. Not a joke.
-	 *  @param[inout] fOut ehm. .. */
-	static inline void Swap(int64_t* fOut) {
-		Swap8(fOut);
-	}
-
-	static inline void Swap(uint64_t* fOut) {
-		Swap8(fOut);
-	}
-
-	// ----------------------------------------------------------------------
-	//! Templatized ByteSwap
-	//! \returns param tOut as swapped
-	template<typename Type> 
-	static inline Type Swapped(Type tOut)
-	{
-		return _swapper<Type,sizeof(Type)>()(tOut);
-	}
-
-private:
-
-	template <typename T, size_t size> struct _swapper;
-};
-
-template <typename T> struct ByteSwap::_swapper<T,2> {
-	T operator() (T tOut) {
-		Swap2(&tOut); 
-		return tOut;
-	}
-};
-
-template <typename T> struct ByteSwap::_swapper<T,4> {
-	T operator() (T tOut) {
-		Swap4(&tOut); 
-		return tOut;
-	}
-};
-
-template <typename T> struct ByteSwap::_swapper<T,8> {
-	T operator() (T tOut) {
-		Swap8(&tOut); 
-		return tOut;
-	}
-};
-
-
-// --------------------------------------------------------------------------------------
-// ByteSwap macros for BigEndian/LittleEndian support 
-// --------------------------------------------------------------------------------------
-#if (defined AI_BUILD_BIG_ENDIAN)
-#	define AI_LE(t)	(t)
-#	define AI_BE(t) ByteSwap::Swapped(t)
-#	define AI_LSWAP2(p)
-#	define AI_LSWAP4(p)
-#	define AI_LSWAP8(p)
-#	define AI_LSWAP2P(p)
-#	define AI_LSWAP4P(p)
-#	define AI_LSWAP8P(p)
-#	define LE_NCONST const
-#	define AI_SWAP2(p) ByteSwap::Swap2(&(p))
-#	define AI_SWAP4(p) ByteSwap::Swap4(&(p))
-#	define AI_SWAP8(p) ByteSwap::Swap8(&(p))
-#	define AI_SWAP2P(p) ByteSwap::Swap2((p))
-#	define AI_SWAP4P(p) ByteSwap::Swap4((p))
-#	define AI_SWAP8P(p) ByteSwap::Swap8((p))
-#	define BE_NCONST
-#else
-#	define AI_BE(t)	(t)
-#	define AI_LE(t) ByteSwap::Swapped(t)
-#	define AI_SWAP2(p)
-#	define AI_SWAP4(p)
-#	define AI_SWAP8(p)
-#	define AI_SWAP2P(p)
-#	define AI_SWAP4P(p)
-#	define AI_SWAP8P(p)
-#	define BE_NCONST const
-#	define AI_LSWAP2(p)		ByteSwap::Swap2(&(p))
-#	define AI_LSWAP4(p)		ByteSwap::Swap4(&(p))
-#	define AI_LSWAP8(p)		ByteSwap::Swap8(&(p))
-#	define AI_LSWAP2P(p)	ByteSwap::Swap2((p))
-#	define AI_LSWAP4P(p)	ByteSwap::Swap4((p))
-#	define AI_LSWAP8P(p)	ByteSwap::Swap8((p))
-#	define LE_NCONST
-#endif
-
-
-namespace Intern {
-
-// --------------------------------------------------------------------------------------------
-template <typename T, bool doit>
-struct ByteSwapper	{
-	void operator() (T* inout) {
-		ByteSwap::Swap(inout);
-	}
-};
-
-template <typename T> 
-struct ByteSwapper<T,false>	{
-	void operator() (T*) {
-	}
-};
-
-// --------------------------------------------------------------------------------------------
-template <bool SwapEndianess, typename T, bool RuntimeSwitch>
-struct Getter {
-	void operator() (T* inout, bool le) {
-#ifdef AI_BUILD_BIG_ENDIAN
-		le =  le;
-#else
-		le =  !le;
-#endif
-		if (le) {
-			ByteSwapper<T,(sizeof(T)>1?true:false)> () (inout);
-		}
-		else ByteSwapper<T,false> () (inout);
-	}
-};
-
-template <bool SwapEndianess, typename T> 
-struct Getter<SwapEndianess,T,false> {
-
-	void operator() (T* inout, bool /*le*/) {
-		// static branch
-		ByteSwapper<T,(SwapEndianess && sizeof(T)>1)> () (inout);
-	}
-};
-} // end Intern
-} // end Assimp
-
-#endif //!! AI_BYTESWAP_H_INC

+ 286 - 0
assimplib.mod/assimp/code/ByteSwapper.h

@@ -0,0 +1,286 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2015, 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 Helper class tp perform various byte oder swappings
+   (e.g. little to big endian) */
+#ifndef AI_BYTESWAPPER_H_INC
+#define AI_BYTESWAPPER_H_INC
+
+#include "../include/assimp/ai_assert.h"
+#include "../include/assimp/types.h"
+#include <stdint.h>
+
+#if _MSC_VER >= 1400
+#include <stdlib.h>
+#endif
+
+namespace Assimp    {
+// --------------------------------------------------------------------------------------
+/** Defines some useful byte order swap routines.
+ *
+ * This is required to read big-endian model formats on little-endian machines,
+ * and vice versa. Direct use of this class is DEPRECATED. Use #StreamReader instead. */
+// --------------------------------------------------------------------------------------
+class ByteSwap
+{
+    ByteSwap() {}
+
+public:
+
+    // ----------------------------------------------------------------------
+    /** Swap two bytes of data
+     *  @param[inout] _szOut A void* to save the reintcasts for the caller. */
+    static inline void Swap2(void* _szOut)
+    {
+        ai_assert(_szOut);
+
+#if _MSC_VER >= 1400
+        uint16_t* const szOut = reinterpret_cast<uint16_t*>(_szOut);
+        *szOut = _byteswap_ushort(*szOut);
+#else
+        uint8_t* const szOut = reinterpret_cast<uint8_t*>(_szOut);
+        std::swap(szOut[0],szOut[1]);
+#endif
+    }
+
+    // ----------------------------------------------------------------------
+    /** Swap four bytes of data
+     *  @param[inout] _szOut A void* to save the reintcasts for the caller. */
+    static inline void Swap4(void* _szOut)
+    {
+        ai_assert(_szOut);
+
+#if _MSC_VER >= 1400
+        uint32_t* const szOut = reinterpret_cast<uint32_t*>(_szOut);
+        *szOut = _byteswap_ulong(*szOut);
+#else
+        uint8_t* const szOut = reinterpret_cast<uint8_t*>(_szOut);
+        std::swap(szOut[0],szOut[3]);
+        std::swap(szOut[1],szOut[2]);
+#endif
+    }
+
+    // ----------------------------------------------------------------------
+    /** Swap eight bytes of data
+     *  @param[inout] _szOut A void* to save the reintcasts for the caller. */
+    static inline void Swap8(void* _szOut)
+    {
+    ai_assert(_szOut);
+
+#if _MSC_VER >= 1400
+        uint64_t* const szOut = reinterpret_cast<uint64_t*>(_szOut);
+        *szOut = _byteswap_uint64(*szOut);
+#else
+        uint8_t* const szOut = reinterpret_cast<uint8_t*>(_szOut);
+        std::swap(szOut[0],szOut[7]);
+        std::swap(szOut[1],szOut[6]);
+        std::swap(szOut[2],szOut[5]);
+        std::swap(szOut[3],szOut[4]);
+#endif
+    }
+
+    // ----------------------------------------------------------------------
+    /** ByteSwap a float. Not a joke.
+     *  @param[inout] fOut ehm. .. */
+    static inline void Swap(float* fOut) {
+        Swap4(fOut);
+    }
+
+    // ----------------------------------------------------------------------
+    /** ByteSwap a double. Not a joke.
+     *  @param[inout] fOut ehm. .. */
+    static inline void Swap(double* fOut) {
+        Swap8(fOut);
+    }
+
+
+    // ----------------------------------------------------------------------
+    /** ByteSwap an int16t. Not a joke.
+     *  @param[inout] fOut ehm. .. */
+    static inline void Swap(int16_t* fOut) {
+        Swap2(fOut);
+    }
+
+    static inline void Swap(uint16_t* fOut) {
+        Swap2(fOut);
+    }
+
+    // ----------------------------------------------------------------------
+    /** ByteSwap an int32t. Not a joke.
+     *  @param[inout] fOut ehm. .. */
+    static inline void Swap(int32_t* fOut){
+        Swap4(fOut);
+    }
+
+    static inline void Swap(uint32_t* fOut){
+        Swap4(fOut);
+    }
+
+    // ----------------------------------------------------------------------
+    /** ByteSwap an int64t. Not a joke.
+     *  @param[inout] fOut ehm. .. */
+    static inline void Swap(int64_t* fOut) {
+        Swap8(fOut);
+    }
+
+    static inline void Swap(uint64_t* fOut) {
+        Swap8(fOut);
+    }
+
+    // ----------------------------------------------------------------------
+    //! Templatized ByteSwap
+    //! \returns param tOut as swapped
+    template<typename Type>
+    static inline Type Swapped(Type tOut)
+    {
+        return _swapper<Type,sizeof(Type)>()(tOut);
+    }
+
+private:
+
+    template <typename T, size_t size> struct _swapper;
+};
+
+template <typename T> struct ByteSwap::_swapper<T,2> {
+    T operator() (T tOut) {
+        Swap2(&tOut);
+        return tOut;
+    }
+};
+
+template <typename T> struct ByteSwap::_swapper<T,4> {
+    T operator() (T tOut) {
+        Swap4(&tOut);
+        return tOut;
+    }
+};
+
+template <typename T> struct ByteSwap::_swapper<T,8> {
+    T operator() (T tOut) {
+        Swap8(&tOut);
+        return tOut;
+    }
+};
+
+
+// --------------------------------------------------------------------------------------
+// ByteSwap macros for BigEndian/LittleEndian support
+// --------------------------------------------------------------------------------------
+#if (defined AI_BUILD_BIG_ENDIAN)
+#   define AI_LE(t) (t)
+#   define AI_BE(t) ByteSwap::Swapped(t)
+#   define AI_LSWAP2(p)
+#   define AI_LSWAP4(p)
+#   define AI_LSWAP8(p)
+#   define AI_LSWAP2P(p)
+#   define AI_LSWAP4P(p)
+#   define AI_LSWAP8P(p)
+#   define LE_NCONST const
+#   define AI_SWAP2(p) ByteSwap::Swap2(&(p))
+#   define AI_SWAP4(p) ByteSwap::Swap4(&(p))
+#   define AI_SWAP8(p) ByteSwap::Swap8(&(p))
+#   define AI_SWAP2P(p) ByteSwap::Swap2((p))
+#   define AI_SWAP4P(p) ByteSwap::Swap4((p))
+#   define AI_SWAP8P(p) ByteSwap::Swap8((p))
+#   define BE_NCONST
+#else
+#   define AI_BE(t) (t)
+#   define AI_LE(t) ByteSwap::Swapped(t)
+#   define AI_SWAP2(p)
+#   define AI_SWAP4(p)
+#   define AI_SWAP8(p)
+#   define AI_SWAP2P(p)
+#   define AI_SWAP4P(p)
+#   define AI_SWAP8P(p)
+#   define BE_NCONST const
+#   define AI_LSWAP2(p)     ByteSwap::Swap2(&(p))
+#   define AI_LSWAP4(p)     ByteSwap::Swap4(&(p))
+#   define AI_LSWAP8(p)     ByteSwap::Swap8(&(p))
+#   define AI_LSWAP2P(p)    ByteSwap::Swap2((p))
+#   define AI_LSWAP4P(p)    ByteSwap::Swap4((p))
+#   define AI_LSWAP8P(p)    ByteSwap::Swap8((p))
+#   define LE_NCONST
+#endif
+
+
+namespace Intern {
+
+// --------------------------------------------------------------------------------------------
+template <typename T, bool doit>
+struct ByteSwapper  {
+    void operator() (T* inout) {
+        ByteSwap::Swap(inout);
+    }
+};
+
+template <typename T>
+struct ByteSwapper<T,false> {
+    void operator() (T*) {
+    }
+};
+
+// --------------------------------------------------------------------------------------------
+template <bool SwapEndianess, typename T, bool RuntimeSwitch>
+struct Getter {
+    void operator() (T* inout, bool le) {
+#ifdef AI_BUILD_BIG_ENDIAN
+        le =  le;
+#else
+        le =  !le;
+#endif
+        if (le) {
+            ByteSwapper<T,(sizeof(T)>1?true:false)> () (inout);
+        }
+        else ByteSwapper<T,false> () (inout);
+    }
+};
+
+template <bool SwapEndianess, typename T>
+struct Getter<SwapEndianess,T,false> {
+
+    void operator() (T* inout, bool /*le*/) {
+        // static branch
+        ByteSwapper<T,(SwapEndianess && sizeof(T)>1)> () (inout);
+    }
+};
+} // end Intern
+} // end Assimp
+
+#endif //!! AI_BYTESWAPPER_H_INC

+ 644 - 0
assimplib.mod/assimp/code/C4DImporter.cpp

@@ -0,0 +1,644 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+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.
+
+----------------------------------------------------------------------
+*/
+
+/** @file  C4DImporter.cpp
+ *  @brief Implementation of the Cinema4D importer class.
+ */
+#ifndef ASSIMP_BUILD_NO_C4D_IMPORTER
+
+// no #ifdefing here, Cinema4D support is carried out in a branch of assimp
+// where it is turned on in the CMake settings.
+
+#ifndef _MSC_VER
+#   error C4D support is currently MSVC only
+#endif
+
+#include "C4DImporter.h"
+#include "TinyFormatter.h"
+
+#if defined(_M_X64) || defined(__amd64__)
+#   define __C4D_64BIT
+#endif
+
+#define __PC
+#include "c4d_file.h"
+#include "default_alien_overloads.h"
+
+using namespace _melange_;
+
+// overload this function and fill in your own unique data
+void GetWriterInfo(LONG &id, String &appname)
+{
+    id = 2424226;
+    appname = "Open Asset Import Library";
+}
+
+using namespace Assimp;
+using namespace Assimp::Formatter;
+
+namespace Assimp {
+    template<> const std::string LogFunctions<C4DImporter>::log_prefix = "C4D: ";
+}
+
+static const aiImporterDesc desc = {
+    "Cinema4D Importer",
+    "",
+    "",
+    "",
+    aiImporterFlags_SupportBinaryFlavour,
+    0,
+    0,
+    0,
+    0,
+    "c4d"
+};
+
+
+// ------------------------------------------------------------------------------------------------
+C4DImporter::C4DImporter()
+{}
+
+// ------------------------------------------------------------------------------------------------
+C4DImporter::~C4DImporter()
+{}
+
+// ------------------------------------------------------------------------------------------------
+bool C4DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
+{
+    const std::string& extension = GetExtension(pFile);
+    if (extension == "c4d") {
+        return true;
+    }
+
+    else if ((!extension.length() || checkSig) && pIOHandler)   {
+        // TODO
+    }
+    return false;
+}
+
+// ------------------------------------------------------------------------------------------------
+const aiImporterDesc* C4DImporter::GetInfo () const
+{
+    return &desc;
+}
+
+// ------------------------------------------------------------------------------------------------
+void C4DImporter::SetupProperties(const Importer* /*pImp*/)
+{
+    // nothing to be done for the moment
+}
+
+
+// ------------------------------------------------------------------------------------------------
+// Imports the given file into the given scene structure.
+void C4DImporter::InternReadFile( const std::string& pFile,
+    aiScene* pScene, IOSystem* pIOHandler)
+{
+    boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile));
+
+    if( file.get() == NULL) {
+        ThrowException("failed to open file " + pFile);
+    }
+
+    const size_t file_size = file->FileSize();
+
+    std::vector<uint8_t> mBuffer(file_size);
+    file->Read(&mBuffer[0], 1, file_size);
+
+    Filename f;
+    f.SetMemoryReadMode(&mBuffer[0], file_size);
+
+    // open document first
+    BaseDocument* doc = LoadDocument(f, SCENEFILTER_OBJECTS | SCENEFILTER_MATERIALS);
+    if(doc == NULL) {
+        ThrowException("failed to read document " + pFile);
+    }
+
+    pScene->mRootNode = new aiNode("<C4DRoot>");
+
+    // first convert all materials
+    ReadMaterials(doc->GetFirstMaterial());
+
+    // process C4D scenegraph recursively
+    try {
+        RecurseHierarchy(doc->GetFirstObject(), pScene->mRootNode);
+    }
+    catch(...) {
+        BOOST_FOREACH(aiMesh* mesh, meshes) {
+            delete mesh;
+        }
+        BaseDocument::Free(doc);
+        throw;
+    }
+    BaseDocument::Free(doc);
+
+    // copy meshes over
+    pScene->mNumMeshes = static_cast<unsigned int>(meshes.size());
+    pScene->mMeshes = new aiMesh*[pScene->mNumMeshes]();
+    std::copy(meshes.begin(), meshes.end(), pScene->mMeshes);
+
+    // copy materials over, adding a default material if necessary
+    unsigned int mat_count = static_cast<unsigned int>(materials.size());
+    BOOST_FOREACH(aiMesh* mesh, meshes) {
+        ai_assert(mesh->mMaterialIndex <= mat_count);
+        if(mesh->mMaterialIndex >= mat_count) {
+            ++mat_count;
+
+            ScopeGuard<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());
+            break;
+        }
+    }
+
+    pScene->mNumMaterials = static_cast<unsigned int>(materials.size());
+    pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]();
+    std::copy(materials.begin(), materials.end(), pScene->mMaterials);
+}
+
+
+// ------------------------------------------------------------------------------------------------
+bool C4DImporter::ReadShader(aiMaterial* out, _melange_::BaseShader* shader)
+{
+    // based on Melange sample code (C4DImportExport.cpp)
+    while(shader) {
+        if(shader->GetType() == Xlayer) {
+            BaseContainer* container = shader->GetDataInstance();
+            GeData blend = container->GetData(SLA_LAYER_BLEND);
+            iBlendDataType* blend_list = reinterpret_cast<iBlendDataType*>(blend.GetCustomDataType(CUSTOMDATA_BLEND_LIST));
+            if (!blend_list)
+            {
+                LogWarn("ignoring XLayer shader: no blend list given");
+                continue;
+            }
+
+            LayerShaderLayer *lsl = dynamic_cast<LayerShaderLayer*>(blend_list->m_BlendLayers.GetObject(0));
+
+            // Ignore the actual layer blending - models for real-time rendering should not
+            // use them in a non-trivial way. Just try to find textures that we can apply
+            // to the model.
+            while (lsl)
+            {
+                if (lsl->GetType() == TypeFolder)
+                {
+                    BlendFolder* const folder = dynamic_cast<BlendFolder*>(lsl);
+                    LayerShaderLayer *subLsl = dynamic_cast<LayerShaderLayer*>(folder->m_Children.GetObject(0));
+
+                    while (subLsl)
+                    {
+                        if (subLsl->GetType() == TypeShader) {
+                            BlendShader* const shader = dynamic_cast<BlendShader*>(subLsl);
+                            if(ReadShader(out, static_cast<BaseShader*>(shader->m_pLink->GetLink()))) {
+                                return true;
+                            }
+                        }
+
+                        subLsl = subLsl->GetNext();
+                    }
+                }
+                else if (lsl->GetType() == TypeShader) {
+                    BlendShader* const shader = dynamic_cast<BlendShader*>(lsl);
+                    if(ReadShader(out, static_cast<BaseShader*>(shader->m_pLink->GetLink()))) {
+                        return true;
+                    }
+                }
+
+                lsl = lsl->GetNext();
+            }
+        }
+        else if ( shader->GetType() == Xbitmap )
+        {
+            aiString path;
+            shader->GetFileName().GetString().GetCString(path.data, MAXLEN-1);
+            path.length = ::strlen(path.data);
+            out->AddProperty(&path, AI_MATKEY_TEXTURE_DIFFUSE(0));
+            return true;
+        }
+        else {
+            LogWarn("ignoring shader type: " + std::string(GetObjectTypeName(shader->GetType())));
+        }
+        shader = shader->GetNext();
+    }
+    return false;
+}
+
+
+// ------------------------------------------------------------------------------------------------
+void C4DImporter::ReadMaterials(_melange_::BaseMaterial* mat)
+{
+    // based on Melange sample code
+    while (mat)
+    {
+        const String& name = mat->GetName();
+        if (mat->GetType() == Mmaterial)
+        {
+            aiMaterial* out = new aiMaterial();
+            material_mapping[mat] = static_cast<unsigned int>(materials.size());
+            materials.push_back(out);
+
+            aiString ai_name;
+            name.GetCString(ai_name.data, MAXLEN-1);
+            ai_name.length = ::strlen(ai_name.data);
+            out->AddProperty(&ai_name, AI_MATKEY_NAME);
+
+            Material& m = dynamic_cast<Material&>(*mat);
+
+            if (m.GetChannelState(CHANNEL_COLOR))
+            {
+                GeData data;
+                mat->GetParameter(MATERIAL_COLOR_COLOR, data);
+                Vector color = data.GetVector();
+                mat->GetParameter(MATERIAL_COLOR_BRIGHTNESS, data);
+                const Real brightness = data.GetReal();
+
+                color *= brightness;
+
+                aiVector3D v;
+                v.x = color.x;
+                v.y = color.y;
+                v.z = color.z;
+                out->AddProperty(&v, 1, AI_MATKEY_COLOR_DIFFUSE);
+            }
+
+            BaseShader* const shader = m.GetShader(MATERIAL_COLOR_SHADER);
+            if(shader) {
+                ReadShader(out, shader);
+            }
+        }
+        else
+        {
+            LogWarn("ignoring plugin material: " + std::string(GetObjectTypeName(mat->GetType())));
+        }
+        mat = mat->GetNext();
+    }
+}
+
+// ------------------------------------------------------------------------------------------------
+void C4DImporter::RecurseHierarchy(BaseObject* object, aiNode* parent)
+{
+    ai_assert(parent != NULL);
+    std::vector<aiNode*> nodes;
+
+    // based on Melange sample code
+    while (object)
+    {
+        const String& name = object->GetName();
+        const LONG type = object->GetType();
+        const Matrix& ml = object->GetMl();
+
+        aiString string;
+        name.GetCString(string.data, MAXLEN-1);
+        string.length = ::strlen(string.data);
+        aiNode* const nd = new aiNode();
+
+        nd->mParent = parent;
+        nd->mName = string;
+
+        nd->mTransformation.a1 = ml.v1.x;
+        nd->mTransformation.b1 = ml.v1.y;
+        nd->mTransformation.c1 = ml.v1.z;
+
+        nd->mTransformation.a2 = ml.v2.x;
+        nd->mTransformation.b2 = ml.v2.y;
+        nd->mTransformation.c2 = ml.v2.z;
+
+        nd->mTransformation.a3 = ml.v3.x;
+        nd->mTransformation.b3 = ml.v3.y;
+        nd->mTransformation.c3 = ml.v3.z;
+
+        nd->mTransformation.a4 = ml.off.x;
+        nd->mTransformation.b4 = ml.off.y;
+        nd->mTransformation.c4 = ml.off.z;
+
+        nodes.push_back(nd);
+
+        GeData data;
+        if (type == Ocamera)
+        {
+            object->GetParameter(CAMERAOBJECT_FOV, data);
+            // TODO: read camera
+        }
+        else if (type == Olight)
+        {
+            // TODO: read light
+        }
+        else if (type == Opolygon)
+        {
+            aiMesh* const mesh = ReadMesh(object);
+            if(mesh != NULL) {
+                nd->mNumMeshes = 1;
+                nd->mMeshes = new unsigned int[1];
+                nd->mMeshes[0] = static_cast<unsigned int>(meshes.size());
+                meshes.push_back(mesh);
+            }
+        }
+        else {
+            LogWarn("ignoring object: " + std::string(GetObjectTypeName(type)));
+        }
+
+        RecurseHierarchy(object->GetDown(), nd);
+        object = object->GetNext();
+    }
+
+    // copy nodes over to parent
+    parent->mNumChildren = static_cast<unsigned int>(nodes.size());
+    parent->mChildren = new aiNode*[parent->mNumChildren]();
+    std::copy(nodes.begin(), nodes.end(), parent->mChildren);
+}
+
+
+// ------------------------------------------------------------------------------------------------
+aiMesh* C4DImporter::ReadMesh(BaseObject* object)
+{
+    assert(object != NULL && object->GetType() == Opolygon);
+
+    // based on Melange sample code
+    PolygonObject* const polyObject = dynamic_cast<PolygonObject*>(object);
+    ai_assert(polyObject != NULL);
+
+    const LONG pointCount = polyObject->GetPointCount();
+    const LONG polyCount = polyObject->GetPolygonCount();
+    if(!polyObject || !pointCount) {
+        LogWarn("ignoring mesh with zero vertices or faces");
+        return NULL;
+    }
+
+    const Vector* points = polyObject->GetPointR();
+    ai_assert(points != NULL);
+
+    const CPolygon* polys = polyObject->GetPolygonR();
+    ai_assert(polys != NULL);
+
+    ScopeGuard<aiMesh> mesh(new aiMesh());
+    mesh->mNumFaces = static_cast<unsigned int>(polyCount);
+    aiFace* face = mesh->mFaces = new aiFace[mesh->mNumFaces]();
+
+    mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
+    mesh->mMaterialIndex = 0;
+
+    unsigned int vcount = 0;
+
+    // first count vertices
+    for (LONG i = 0; i < polyCount; i++)
+    {
+        vcount += 3;
+
+        // TODO: do we also need to handle lines or points with similar checks?
+        if (polys[i].c != polys[i].d)
+        {
+            mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
+            ++vcount;
+        }
+    }
+
+    ai_assert(vcount > 0);
+
+    mesh->mNumVertices = vcount;
+    aiVector3D* verts = mesh->mVertices = new aiVector3D[mesh->mNumVertices];
+    aiVector3D* normals, *uvs, *tangents, *bitangents;
+    unsigned int n = 0;
+
+    // check if there are normals, tangents or UVW coordinates
+    BaseTag* tag = object->GetTag(Tnormal);
+    NormalTag* normals_src = NULL;
+    if(tag) {
+        normals_src = dynamic_cast<NormalTag*>(tag);
+        normals = mesh->mNormals = new aiVector3D[mesh->mNumVertices]();
+    }
+
+    tag = object->GetTag(Ttangent);
+    TangentTag* tangents_src = NULL;
+    if(tag) {
+        tangents_src = dynamic_cast<TangentTag*>(tag);
+        tangents = mesh->mTangents = new aiVector3D[mesh->mNumVertices]();
+        bitangents = mesh->mBitangents = new aiVector3D[mesh->mNumVertices]();
+    }
+
+    tag = object->GetTag(Tuvw);
+    UVWTag* uvs_src = NULL;
+    if(tag) {
+        uvs_src = dynamic_cast<UVWTag*>(tag);
+        uvs = mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices]();
+    }
+
+    // copy vertices and extra channels over and populate faces
+    for (LONG i = 0; i < polyCount; ++i, ++face)
+    {
+        ai_assert(polys[i].a < pointCount && polys[i].a >= 0);
+        const Vector& pointA = points[polys[i].a];
+        verts->x = pointA.x;
+        verts->y = pointA.y;
+        verts->z = pointA.z;
+        ++verts;
+
+        ai_assert(polys[i].b < pointCount && polys[i].b >= 0);
+        const Vector& pointB = points[polys[i].b];
+        verts->x = pointB.x;
+        verts->y = pointB.y;
+        verts->z = pointB.z;
+        ++verts;
+
+        ai_assert(polys[i].c < pointCount && polys[i].c >= 0);
+        const Vector& pointC = points[polys[i].c];
+        verts->x = pointC.x;
+        verts->y = pointC.y;
+        verts->z = pointC.z;
+        ++verts;
+
+        // TODO: do we also need to handle lines or points with similar checks?
+        if (polys[i].c != polys[i].d)
+        {
+            ai_assert(polys[i].d < pointCount && polys[i].d >= 0);
+
+            face->mNumIndices = 4;
+            mesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
+            const Vector& pointD = points[polys[i].d];
+            verts->x = pointD.x;
+            verts->y = pointD.y;
+            verts->z = pointD.z;
+            ++verts;
+        }
+        else {
+            face->mNumIndices = 3;
+        }
+        face->mIndices = new unsigned int[face->mNumIndices];
+        for(unsigned int j = 0; j < face->mNumIndices; ++j) {
+            face->mIndices[j] = n++;
+        }
+
+        // copy normals
+        if (normals_src) {
+            if(i >= normals_src->GetNormalCount()) {
+                LogError("unexpected number of normals, ignoring");
+            }
+            else {
+                const NormalStruct& nor = normals_src->GetNormals(i);
+                normals->x = nor.a.x;
+                normals->y = nor.a.y;
+                normals->z = nor.a.z;
+                ++normals;
+
+                normals->x = nor.b.x;
+                normals->y = nor.b.y;
+                normals->z = nor.b.z;
+                ++normals;
+
+                normals->x = nor.c.x;
+                normals->y = nor.c.y;
+                normals->z = nor.c.z;
+                ++normals;
+
+                if(face->mNumIndices == 4) {
+                    normals->x = nor.d.x;
+                    normals->y = nor.d.y;
+                    normals->z = nor.d.z;
+                    ++normals;
+                }
+            }
+        }
+
+        // copy tangents and bitangents
+        if (tangents_src) {
+
+            for(unsigned int k = 0; k < face->mNumIndices; ++k) {
+                LONG l;
+                switch(k) {
+                case 0:
+                    l = polys[i].a;
+                    break;
+                case 1:
+                    l = polys[i].b;
+                    break;
+                case 2:
+                    l = polys[i].c;
+                    break;
+                case 3:
+                    l = polys[i].d;
+                    break;
+                default:
+                    ai_assert(false);
+                }
+                if(l >= tangents_src->GetDataCount()) {
+                    LogError("unexpected number of tangents, ignoring");
+                    break;
+                }
+
+                Tangent tan = tangents_src->GetDataR()[l];
+                tangents->x = tan.vl.x;
+                tangents->y = tan.vl.y;
+                tangents->z = tan.vl.z;
+                ++tangents;
+
+                bitangents->x = tan.vr.x;
+                bitangents->y = tan.vr.y;
+                bitangents->z = tan.vr.z;
+                ++bitangents;
+            }
+        }
+
+        // copy UVs
+        if (uvs_src) {
+            if(i >= uvs_src->GetDataCount()) {
+                LogError("unexpected number of UV coordinates, ignoring");
+            }
+            else {
+                UVWStruct uvw;
+                uvs_src->Get(uvs_src->GetDataAddressR(),i,uvw);
+
+                uvs->x = uvw.a.x;
+                uvs->y = 1.0f-uvw.a.y;
+                uvs->z = uvw.a.z;
+                ++uvs;
+
+                uvs->x = uvw.b.x;
+                uvs->y = 1.0f-uvw.b.y;
+                uvs->z = uvw.b.z;
+                ++uvs;
+
+                uvs->x = uvw.c.x;
+                uvs->y = 1.0f-uvw.c.y;
+                uvs->z = uvw.c.z;
+                ++uvs;
+
+                if(face->mNumIndices == 4) {
+                    uvs->x = uvw.d.x;
+                    uvs->y = 1.0f-uvw.d.y;
+                    uvs->z = uvw.d.z;
+                    ++uvs;
+                }
+            }
+        }
+    }
+
+    mesh->mMaterialIndex = ResolveMaterial(polyObject);
+    return mesh.dismiss();
+}
+
+
+// ------------------------------------------------------------------------------------------------
+unsigned int C4DImporter::ResolveMaterial(PolygonObject* obj)
+{
+    ai_assert(obj != NULL);
+
+    const unsigned int mat_count = static_cast<unsigned int>(materials.size());
+
+    BaseTag* tag = obj->GetTag(Ttexture);
+    if(tag == NULL) {
+        return mat_count;
+    }
+
+    TextureTag& ttag = dynamic_cast<TextureTag&>(*tag);
+
+    BaseMaterial* const mat = ttag.GetMaterial();
+    assert(mat != NULL);
+
+    const MaterialMap::const_iterator it = material_mapping.find(mat);
+    if(it == material_mapping.end()) {
+        return mat_count;
+    }
+
+    ai_assert((*it).second < mat_count);
+    return (*it).second;
+}
+
+#endif // ASSIMP_BUILD_NO_C4D_IMPORTER
+

+ 123 - 0
assimplib.mod/assimp/code/C4DImporter.h

@@ -0,0 +1,123 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+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.
+
+----------------------------------------------------------------------
+*/
+
+/** @file  C4DImporter.h
+ *  @brief Declaration of the Cinema4D (*.c4d) importer class.
+ */
+#ifndef INCLUDED_AI_CINEMA_4D_LOADER_H
+#define INCLUDED_AI_CINEMA_4D_LOADER_H
+
+#include "BaseImporter.h"
+#include "LogAux.h"
+
+#include <set>
+struct aiNode;
+struct aiMesh;
+struct aiMaterial;
+
+struct aiImporterDesc;
+
+namespace _melange_ {
+    class BaseObject; // c4d_file.h
+    class PolygonObject;
+    class BaseMaterial;
+    class BaseShader;
+}
+
+namespace Assimp    {
+
+    // TinyFormatter.h
+    namespace Formatter {
+        template <typename T,typename TR, typename A> class basic_formatter;
+        typedef class basic_formatter< char, std::char_traits<char>, std::allocator<char> > format;
+    }
+
+// -------------------------------------------------------------------------------------------
+/** Importer class to load Cinema4D files using the Melange library to be obtained from
+ *  www.plugincafe.com
+ *
+ *  Note that Melange is not free software. */
+// -------------------------------------------------------------------------------------------
+class C4DImporter : public BaseImporter, public LogFunctions<C4DImporter>
+{
+public:
+
+    C4DImporter();
+    ~C4DImporter();
+
+
+public:
+
+    // --------------------
+    bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+        bool checkSig) const;
+
+protected:
+
+    // --------------------
+    const aiImporterDesc* GetInfo () const;
+
+    // --------------------
+    void SetupProperties(const Importer* pImp);
+
+    // --------------------
+    void InternReadFile( const std::string& pFile, aiScene* pScene,
+        IOSystem* pIOHandler);
+
+private:
+
+    void ReadMaterials(_melange_::BaseMaterial* mat);
+    void RecurseHierarchy(_melange_::BaseObject* object, aiNode* parent);
+    aiMesh* ReadMesh(_melange_::BaseObject* object);
+    unsigned int ResolveMaterial(_melange_::PolygonObject* obj);
+
+    bool ReadShader(aiMaterial* out, _melange_::BaseShader* shader);
+
+    std::vector<aiMesh*> meshes;
+    std::vector<aiMaterial*> materials;
+
+    typedef std::map<_melange_::BaseMaterial*, unsigned int> MaterialMap;
+    MaterialMap material_mapping;
+
+}; // !class C4DImporter
+
+} // end of namespace Assimp
+#endif // INCLUDED_AI_CINEMA_4D_LOADER_H
+

+ 97 - 95
assimplib.mod/assimp/code/CInterfaceIOWrapper.h

@@ -3,12 +3,12 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -25,16 +25,16 @@ conditions are met:
   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 
+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 
+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 
+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 
+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.
 ---------------------------------------------------------------------------
 */
@@ -45,62 +45,64 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define AI_CIOSYSTEM_H_INCLUDED
 
 #include "../include/assimp/cfileio.h"
+#include "../include/assimp/IOStream.hpp"
+#include "../include/assimp/IOSystem.hpp"
+
+namespace Assimp    {
 
-namespace Assimp	{
-	
 // ------------------------------------------------------------------------------------------------
 // Custom IOStream implementation for the C-API
 class CIOStreamWrapper : public IOStream
 {
-	friend class CIOSystemWrapper;
+    friend class CIOSystemWrapper;
 public:
 
-	CIOStreamWrapper(aiFile* pFile)
-		: mFile(pFile)
-	{}
-
-	// ...................................................................
-	size_t Read(void* pvBuffer, 
-		size_t pSize, 
-		size_t pCount
-	){
-		// need to typecast here as C has no void*
-		return mFile->ReadProc(mFile,(char*)pvBuffer,pSize,pCount);
-	}
-
-	// ...................................................................
-	size_t Write(const void* pvBuffer, 
-		size_t pSize,
-		size_t pCount
-	){
-		// need to typecast here as C has no void*
-		return mFile->WriteProc(mFile,(const char*)pvBuffer,pSize,pCount);
-	}
-
-	// ...................................................................
-	aiReturn Seek(size_t pOffset,
-		aiOrigin pOrigin
-	){
-		return mFile->SeekProc(mFile,pOffset,pOrigin);
-	}
-
-	// ...................................................................
-	size_t Tell(void) const {
-		return mFile->TellProc(mFile);
-	}
-
-	// ...................................................................
-	size_t	FileSize() const {
-		return mFile->FileSizeProc(mFile);
-	}
-
-	// ...................................................................
-	void Flush () {
-		return mFile->FlushProc(mFile);
-	}
+    explicit CIOStreamWrapper(aiFile* pFile)
+        : mFile(pFile)
+    {}
+
+    // ...................................................................
+    size_t Read(void* pvBuffer,
+        size_t pSize,
+        size_t pCount
+    ){
+        // need to typecast here as C has no void*
+        return mFile->ReadProc(mFile,(char*)pvBuffer,pSize,pCount);
+    }
+
+    // ...................................................................
+    size_t Write(const void* pvBuffer,
+        size_t pSize,
+        size_t pCount
+    ){
+        // need to typecast here as C has no void*
+        return mFile->WriteProc(mFile,(const char*)pvBuffer,pSize,pCount);
+    }
+
+    // ...................................................................
+    aiReturn Seek(size_t pOffset,
+        aiOrigin pOrigin
+    ){
+        return mFile->SeekProc(mFile,pOffset,pOrigin);
+    }
+
+    // ...................................................................
+    size_t Tell(void) const {
+        return mFile->TellProc(mFile);
+    }
+
+    // ...................................................................
+    size_t  FileSize() const {
+        return mFile->FileSizeProc(mFile);
+    }
+
+    // ...................................................................
+    void Flush () {
+        return mFile->FlushProc(mFile);
+    }
 
 private:
-	aiFile* mFile;
+    aiFile* mFile;
 };
 
 // ------------------------------------------------------------------------------------------------
@@ -108,48 +110,48 @@ private:
 class CIOSystemWrapper : public IOSystem
 {
 public:
-	CIOSystemWrapper(aiFileIO* pFile)
-		: mFileSystem(pFile)
-	{}
-
-	// ...................................................................
-	bool Exists( const char* pFile) const {
-		aiFile* p = mFileSystem->OpenProc(mFileSystem,pFile,"rb");		
-		if (p){
-			mFileSystem->CloseProc(mFileSystem,p);
-			return true;
-		}
-		return false;
-	}
-
-	// ...................................................................
-	char getOsSeparator() const {
+    explicit CIOSystemWrapper(aiFileIO* pFile)
+        : mFileSystem(pFile)
+    {}
+
+    // ...................................................................
+    bool Exists( const char* pFile) const {
+        aiFile* p = mFileSystem->OpenProc(mFileSystem,pFile,"rb");
+        if (p){
+            mFileSystem->CloseProc(mFileSystem,p);
+            return true;
+        }
+        return false;
+    }
+
+    // ...................................................................
+    char getOsSeparator() const {
 #ifndef _WIN32
-		return '/';
+        return '/';
 #else
-		return '\\';
+        return '\\';
 #endif
-	}
-
-	// ...................................................................
-	IOStream* Open(const char* pFile,const char* pMode = "rb") {
-		aiFile* p = mFileSystem->OpenProc(mFileSystem,pFile,pMode);
-		if (!p) {
-			return NULL;
-		}
-		return new CIOStreamWrapper(p);
-	}
-
-	// ...................................................................
-	void Close( IOStream* pFile) {
-		if (!pFile) {
-			return;
-		}
-		mFileSystem->CloseProc(mFileSystem,((CIOStreamWrapper*) pFile)->mFile);
-		delete pFile;
-	}
+    }
+
+    // ...................................................................
+    IOStream* Open(const char* pFile,const char* pMode = "rb") {
+        aiFile* p = mFileSystem->OpenProc(mFileSystem,pFile,pMode);
+        if (!p) {
+            return NULL;
+        }
+        return new CIOStreamWrapper(p);
+    }
+
+    // ...................................................................
+    void Close( IOStream* pFile) {
+        if (!pFile) {
+            return;
+        }
+        mFileSystem->CloseProc(mFileSystem,((CIOStreamWrapper*) pFile)->mFile);
+        delete pFile;
+    }
 private:
-	aiFileIO* mFileSystem;
+    aiFileIO* mFileSystem;
 };
 
 }

+ 630 - 586
assimplib.mod/assimp/code/CMakeLists.txt

@@ -8,735 +8,779 @@ cmake_minimum_required( VERSION 2.6 )
 SET( HEADER_PATH ../include/assimp )
 
 SET( COMPILER_HEADERS
-	${HEADER_PATH}/Compiler/pushpack1.h
-	${HEADER_PATH}/Compiler/poppack1.h
-	${HEADER_PATH}/Compiler/pstdint.h
+  ${HEADER_PATH}/Compiler/pushpack1.h
+  ${HEADER_PATH}/Compiler/poppack1.h
+  ${HEADER_PATH}/Compiler/pstdint.h
 )
 SOURCE_GROUP( Compiler FILES ${COMPILER_HEADERS})
 
 SET( PUBLIC_HEADERS
-	${HEADER_PATH}/anim.h
-	${HEADER_PATH}/ai_assert.h
-	${HEADER_PATH}/camera.h
-	${HEADER_PATH}/color4.h
-	${HEADER_PATH}/color4.inl
-	${HEADER_PATH}/config.h
-	${HEADER_PATH}/defs.h
-	${HEADER_PATH}/cfileio.h
-	${HEADER_PATH}/light.h
-	${HEADER_PATH}/material.h
-	${HEADER_PATH}/material.inl
-	${HEADER_PATH}/matrix3x3.h
-	${HEADER_PATH}/matrix3x3.inl
-	${HEADER_PATH}/matrix4x4.h
-	${HEADER_PATH}/matrix4x4.inl
-	${HEADER_PATH}/mesh.h
-	${HEADER_PATH}/postprocess.h
-	${HEADER_PATH}/quaternion.h
-	${HEADER_PATH}/quaternion.inl
-	${HEADER_PATH}/scene.h
-	${HEADER_PATH}/metadata.h
-	${HEADER_PATH}/texture.h
-	${HEADER_PATH}/types.h
-	${HEADER_PATH}/vector2.h
-	${HEADER_PATH}/vector2.inl
-	${HEADER_PATH}/vector3.h
-	${HEADER_PATH}/vector3.inl
-	${HEADER_PATH}/version.h
-	${HEADER_PATH}/cimport.h
-	${HEADER_PATH}/importerdesc.h
-	${HEADER_PATH}/Importer.hpp
-	${HEADER_PATH}/DefaultLogger.hpp
-	${HEADER_PATH}/ProgressHandler.hpp
-	${HEADER_PATH}/IOStream.hpp
-	${HEADER_PATH}/IOSystem.hpp
-	${HEADER_PATH}/Logger.hpp
-	${HEADER_PATH}/LogStream.hpp
-	${HEADER_PATH}/NullLogger.hpp
-	${HEADER_PATH}/cexport.h
-	${HEADER_PATH}/Exporter.hpp
+  ${HEADER_PATH}/anim.h
+  ${HEADER_PATH}/ai_assert.h
+  ${HEADER_PATH}/camera.h
+  ${HEADER_PATH}/color4.h
+  ${HEADER_PATH}/color4.inl
+  ${HEADER_PATH}/config.h
+  ${HEADER_PATH}/defs.h
+  ${HEADER_PATH}/cfileio.h
+  ${HEADER_PATH}/light.h
+  ${HEADER_PATH}/material.h
+  ${HEADER_PATH}/material.inl
+  ${HEADER_PATH}/matrix3x3.h
+  ${HEADER_PATH}/matrix3x3.inl
+  ${HEADER_PATH}/matrix4x4.h
+  ${HEADER_PATH}/matrix4x4.inl
+  ${HEADER_PATH}/mesh.h
+  ${HEADER_PATH}/postprocess.h
+  ${HEADER_PATH}/quaternion.h
+  ${HEADER_PATH}/quaternion.inl
+  ${HEADER_PATH}/scene.h
+  ${HEADER_PATH}/metadata.h
+  ${HEADER_PATH}/texture.h
+  ${HEADER_PATH}/types.h
+  ${HEADER_PATH}/vector2.h
+  ${HEADER_PATH}/vector2.inl
+  ${HEADER_PATH}/vector3.h
+  ${HEADER_PATH}/vector3.inl
+  ${HEADER_PATH}/version.h
+  ${HEADER_PATH}/cimport.h
+  ${HEADER_PATH}/importerdesc.h
+  ${HEADER_PATH}/Importer.hpp
+  ${HEADER_PATH}/DefaultLogger.hpp
+  ${HEADER_PATH}/ProgressHandler.hpp
+  ${HEADER_PATH}/IOStream.hpp
+  ${HEADER_PATH}/IOSystem.hpp
+  ${HEADER_PATH}/Logger.hpp
+  ${HEADER_PATH}/LogStream.hpp
+  ${HEADER_PATH}/NullLogger.hpp
+  ${HEADER_PATH}/cexport.h
+  ${HEADER_PATH}/Exporter.hpp
 )
 
 SET( Core_SRCS
-	Assimp.cpp
+  Assimp.cpp
 )
 
 SET( Boost_SRCS
-	BoostWorkaround/boost/math/common_factor_rt.hpp
-	BoostWorkaround/boost/foreach.hpp
-	BoostWorkaround/boost/format.hpp
-	BoostWorkaround/boost/scoped_array.hpp
-	BoostWorkaround/boost/scoped_ptr.hpp
-	BoostWorkaround/boost/shared_array.hpp
-	BoostWorkaround/boost/shared_ptr.hpp
-	BoostWorkaround/boost/make_shared.hpp
-	BoostWorkaround/boost/static_assert.hpp
-	BoostWorkaround/boost/tuple/tuple.hpp
+  BoostWorkaround/boost/math/common_factor_rt.hpp
+  BoostWorkaround/boost/foreach.hpp
+  BoostWorkaround/boost/format.hpp
+  BoostWorkaround/boost/scoped_array.hpp
+  BoostWorkaround/boost/scoped_ptr.hpp
+  BoostWorkaround/boost/shared_array.hpp
+  BoostWorkaround/boost/shared_ptr.hpp
+  BoostWorkaround/boost/make_shared.hpp
+  BoostWorkaround/boost/static_assert.hpp
+  BoostWorkaround/boost/tuple/tuple.hpp
 )
 SOURCE_GROUP(Boost FILES ${Boost_SRCS})
 
 SET( Logging_SRCS
-	${HEADER_PATH}/DefaultLogger.hpp
-	${HEADER_PATH}/LogStream.hpp
-	${HEADER_PATH}/Logger.hpp
-	${HEADER_PATH}/NullLogger.hpp
-	Win32DebugLogStream.h
-	DefaultLogger.cpp
-	FileLogStream.h
-	StdOStreamLogStream.h
+  ${HEADER_PATH}/DefaultLogger.hpp
+  ${HEADER_PATH}/LogStream.hpp
+  ${HEADER_PATH}/Logger.hpp
+  ${HEADER_PATH}/NullLogger.hpp
+  Win32DebugLogStream.h
+  DefaultLogger.cpp
+  FileLogStream.h
+  StdOStreamLogStream.h
 )
 SOURCE_GROUP(Logging FILES ${Logging_SRCS})
 
 SET( Common_SRCS
-	fast_atof.h
-	qnan.h
-	BaseImporter.cpp
-	BaseImporter.h
-	BaseProcess.cpp
-	BaseProcess.h
-	Importer.h
-	ScenePrivate.h
-	PostStepRegistry.cpp
-	ImporterRegistry.cpp
-	ByteSwap.h
-	DefaultProgressHandler.h
-	DefaultIOStream.cpp
-	DefaultIOStream.h
-	DefaultIOSystem.cpp
-	DefaultIOSystem.h
-	CInterfaceIOWrapper.h
-	Hash.h
-	Importer.cpp
-	IFF.h
-	MemoryIOWrapper.h
-	ParsingUtils.h
-	StreamReader.h
-	StringComparison.h
-	SGSpatialSort.cpp
-	SGSpatialSort.h
-	VertexTriangleAdjacency.cpp
-	VertexTriangleAdjacency.h
-	GenericProperty.h
-	SpatialSort.cpp
-	SpatialSort.h
-	SceneCombiner.cpp
-	SceneCombiner.h
-	ScenePreprocessor.cpp
-	ScenePreprocessor.h
-	SkeletonMeshBuilder.cpp
-	SkeletonMeshBuilder.h
-	SplitByBoneCountProcess.cpp
-	SplitByBoneCountProcess.h
-	SmoothingGroups.h
-	StandardShapes.cpp
-	StandardShapes.h
-	TargetAnimation.cpp
-	TargetAnimation.h
-	RemoveComments.cpp
-	RemoveComments.h
-	Subdivision.cpp
-	Subdivision.h
-	Vertex.h
-	LineSplitter.h
-	TinyFormatter.h
-	Profiler.h
-	LogAux.h
-	Bitmap.cpp
-	Bitmap.h
+  fast_atof.h
+  qnan.h
+  BaseImporter.cpp
+  BaseImporter.h
+  BaseProcess.cpp
+  BaseProcess.h
+  Importer.h
+  ScenePrivate.h
+  PostStepRegistry.cpp
+  ImporterRegistry.cpp
+  ByteSwapper.h
+  DefaultProgressHandler.h
+  DefaultIOStream.cpp
+  DefaultIOStream.h
+  DefaultIOSystem.cpp
+  DefaultIOSystem.h
+  CInterfaceIOWrapper.h
+  Hash.h
+  Importer.cpp
+  IFF.h
+  MemoryIOWrapper.h
+  ParsingUtils.h
+  StreamReader.h
+  StreamWriter.h
+  StringComparison.h
+  SGSpatialSort.cpp
+  SGSpatialSort.h
+  VertexTriangleAdjacency.cpp
+  VertexTriangleAdjacency.h
+  GenericProperty.h
+  SpatialSort.cpp
+  SpatialSort.h
+  SceneCombiner.cpp
+  SceneCombiner.h
+  ScenePreprocessor.cpp
+  ScenePreprocessor.h
+  SkeletonMeshBuilder.cpp
+  SkeletonMeshBuilder.h
+  SplitByBoneCountProcess.cpp
+  SplitByBoneCountProcess.h
+  SmoothingGroups.h
+  StandardShapes.cpp
+  StandardShapes.h
+  TargetAnimation.cpp
+  TargetAnimation.h
+  RemoveComments.cpp
+  RemoveComments.h
+  Subdivision.cpp
+  Subdivision.h
+  Vertex.h
+  LineSplitter.h
+  TinyFormatter.h
+  Profiler.h
+  LogAux.h
+  Bitmap.cpp
+  Bitmap.h
+  XMLTools.h
+  Version.cpp
 )
 SOURCE_GROUP(Common FILES ${Common_SRCS})
 
-SET( 3DS_SRCS
-	3DSConverter.cpp
-	3DSHelper.h
-	3DSLoader.cpp
-	3DSLoader.h
+IF ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER )
+  SET( C4D_SRCS
+    C4DImporter.cpp
+    C4DImporter.h
+  )
+  SOURCE_GROUP( C4D FILES ${C4D_SRCS})
+ENDIF ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER )
+
+# 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)
+  IF(ASSIMP_BUILD_${name}_IMPORTER)
+    LIST(APPEND ASSIMP_LOADER_SRCS ${ARGN})
+    SET(ASSIMP_IMPORTERS_ENABLED "${ASSIMP_IMPORTERS_ENABLED} ${name}")
+    SET(${name}_SRCS ${ARGN})
+    SOURCE_GROUP(${name} FILES ${ARGN})
+  ELSE()
+    SET(${name}_SRC "")
+    SET(ASSIMP_IMPORTERS_DISABLED "${ASSIMP_IMPORTERS_DISABLED} ${name}")
+    add_definitions(-DASSIMP_BUILD_NO_${name}_IMPORTER)
+  ENDIF()
+ENDMACRO()
+
+SET(ASSIMP_LOADER_SRCS "")
+SET(ASSIMP_IMPORTERS_ENABLED "") # list of enabled importers
+SET(ASSIMP_IMPORTERS_DISABLED "") # disabled list (used to print)
+
+ADD_ASSIMP_IMPORTER(3DS
+  3DSConverter.cpp
+  3DSHelper.h
+  3DSLoader.cpp
+  3DSLoader.h
+  3DSExporter.h
+  3DSExporter.cpp
 )
-SOURCE_GROUP(3DS FILES ${3DS_SRCS})
 
-SET( AC_SRCS
-	ACLoader.cpp
-	ACLoader.h
+ADD_ASSIMP_IMPORTER(AC
+  ACLoader.cpp
+  ACLoader.h
 )
-SOURCE_GROUP( AC FILES ${AC_SRCS})
 
-SET( ASE_SRCS
-	ASELoader.cpp
-	ASELoader.h
-	ASEParser.cpp
-	ASEParser.h
+ADD_ASSIMP_IMPORTER(ASE
+  ASELoader.cpp
+  ASELoader.h
+  ASEParser.cpp
+  ASEParser.h
 )
-SOURCE_GROUP( ASE FILES ${ASE_SRCS})
 
-SET( B3D_SRCS
-	B3DImporter.cpp
-	B3DImporter.h
+ADD_ASSIMP_IMPORTER(ASSBIN
+  AssbinExporter.h
+  AssbinExporter.cpp
+  AssbinLoader.h
+  AssbinLoader.cpp
 )
-SOURCE_GROUP( B3D FILES ${B3D_SRCS})
 
-SET( BVH_SRCS
-	BVHLoader.cpp
-	BVHLoader.h
+ADD_ASSIMP_IMPORTER(ASSXML
+  AssxmlExporter.h
+  AssxmlExporter.cpp
 )
-SOURCE_GROUP( BVH FILES ${BVH_SRCS})
 
-SET( Collada_SRCS
-	ColladaHelper.h
-	ColladaLoader.cpp
-	ColladaLoader.h
-	ColladaParser.cpp
-	ColladaParser.h
-	ColladaExporter.h
-	ColladaExporter.cpp
+ADD_ASSIMP_IMPORTER(B3D
+  B3DImporter.cpp
+  B3DImporter.h
 )
-SOURCE_GROUP( Collada FILES ${Collada_SRCS})
 
-SET( DXF_SRCS
-	DXFLoader.cpp
-	DXFLoader.h
-	DXFHelper.h
+ADD_ASSIMP_IMPORTER(BVH
+  BVHLoader.cpp
+  BVHLoader.h
 )
-SOURCE_GROUP( DXF FILES ${DXF_SRCS})
 
-SET( CSM_SRCS
-	CSMLoader.cpp
-	CSMLoader.h
+ADD_ASSIMP_IMPORTER(COLLADA
+  ColladaHelper.h
+  ColladaLoader.cpp
+  ColladaLoader.h
+  ColladaParser.cpp
+  ColladaParser.h
+  ColladaExporter.h
+  ColladaExporter.cpp
 )
-SOURCE_GROUP( CSM FILES ${CSM_SRCS})
 
-SET( HMP_SRCS
-	HMPFileData.h
-	HMPLoader.cpp
-	HMPLoader.h
-	HalfLifeFileData.h
+ADD_ASSIMP_IMPORTER(DXF
+  DXFLoader.cpp
+  DXFLoader.h
+  DXFHelper.h
 )
-SOURCE_GROUP( HMP FILES ${HMP_SRCS})
 
-SET( Irr_SRCS
-	IRRLoader.cpp
-	IRRLoader.h
-	IRRMeshLoader.cpp
-	IRRMeshLoader.h
-	IRRShared.cpp
-	IRRShared.h
+ADD_ASSIMP_IMPORTER(CSM
+  CSMLoader.cpp
+  CSMLoader.h
 )
-SOURCE_GROUP( Irr FILES ${Irr_SRCS})
 
-SET( LWO_SRCS
-	LWOAnimation.cpp
-	LWOAnimation.h
-	LWOBLoader.cpp
-	LWOFileData.h
-	LWOLoader.cpp
-	LWOLoader.h
-	LWOMaterial.cpp
+ADD_ASSIMP_IMPORTER(HMP
+  HMPFileData.h
+  HMPLoader.cpp
+  HMPLoader.h
+  HalfLifeFileData.h
 )
-SOURCE_GROUP( LWO FILES ${LWO_SRCS})
 
-SET( LWS_SRCS
-	LWSLoader.cpp
-	LWSLoader.h
+#FIXME: allow to set IRRMESH by option
+ADD_ASSIMP_IMPORTER(IRR
+  IRRLoader.cpp
+  IRRLoader.h
+  IRRMeshLoader.cpp
+  IRRMeshLoader.h
+  IRRShared.cpp
+  IRRShared.h
 )
-SOURCE_GROUP( LWS FILES ${LWS_SRCS})
 
+ADD_ASSIMP_IMPORTER(LWO
+  LWOAnimation.cpp
+  LWOAnimation.h
+  LWOBLoader.cpp
+  LWOFileData.h
+  LWOLoader.cpp
+  LWOLoader.h
+  LWOMaterial.cpp
+)
 
+ADD_ASSIMP_IMPORTER(LWS
+  LWSLoader.cpp
+  LWSLoader.h
+)
 
-SET( MD2_SRCS
-	MD2FileData.h
-	MD2Loader.cpp
-	MD2Loader.h
-	MD2NormalTable.h
+ADD_ASSIMP_IMPORTER(MD2
+  MD2FileData.h
+  MD2Loader.cpp
+  MD2Loader.h
+  MD2NormalTable.h
 )
-SOURCE_GROUP( MD2 FILES ${MD2_SRCS})
 
-SET( MD3_SRCS
-	MD3FileData.h
-	MD3Loader.cpp
-	MD3Loader.h
+ADD_ASSIMP_IMPORTER(MD3
+  MD3FileData.h
+  MD3Loader.cpp
+  MD3Loader.h
 )
-SOURCE_GROUP( MD3 FILES ${MD3_SRCS})
 
-SET( MD5_SRCS
-	MD5Loader.cpp
-	MD5Loader.h
-	MD5Parser.cpp
-	MD5Parser.h
+ADD_ASSIMP_IMPORTER(MD5
+  MD5Loader.cpp
+  MD5Loader.h
+  MD5Parser.cpp
+  MD5Parser.h
 )
-SOURCE_GROUP( MD5 FILES ${MD5_SRCS})
 
-SET( MDC_SRCS
-	MDCFileData.h
-	MDCLoader.cpp
-	MDCLoader.h
-	MDCNormalTable.h
+ADD_ASSIMP_IMPORTER(MDC
+  MDCFileData.h
+  MDCLoader.cpp
+  MDCLoader.h
+  MDCNormalTable.h
 )
-SOURCE_GROUP( MDC FILES ${MDC_SRCS})
 
-SET( MDL_SRCS
-	MDLDefaultColorMap.h
-	MDLFileData.h
-	MDLLoader.cpp
-	MDLLoader.h
-	MDLMaterialLoader.cpp
+ADD_ASSIMP_IMPORTER(MDL
+  MDLDefaultColorMap.h
+  MDLFileData.h
+  MDLLoader.cpp
+  MDLLoader.h
+  MDLMaterialLoader.cpp
 )
-SOURCE_GROUP( MDL FILES ${MDL_SRCS})
 
 SET( MaterialSystem_SRCS
-	MaterialSystem.cpp
-	MaterialSystem.h
+  MaterialSystem.cpp
+  MaterialSystem.h
 )
 SOURCE_GROUP( MaterialSystem FILES ${MaterialSystem_SRCS})
 
-SET( NFF_SRCS
-	NFFLoader.cpp
-	NFFLoader.h
-)
-SOURCE_GROUP( NFF FILES ${NFF_SRCS})
-
-SET( NDO_SRCS
-	NDOLoader.cpp
-	NDOLoader.h
-)
-SOURCE_GROUP( NDO FILES ${NDO_SRCS})
-
-SET( OFFFormat_SRCS
-	OFFLoader.cpp
-	OFFLoader.h
-)
-SOURCE_GROUP( OFFFormat FILES ${OFFFormat_SRCS})
-
-SET( Obj_SRCS
-	ObjFileData.h
-	ObjFileImporter.cpp
-	ObjFileImporter.h
-	ObjFileMtlImporter.cpp
-	ObjFileMtlImporter.h
-	ObjFileParser.cpp
-	ObjFileParser.h
-	ObjTools.h
-	
-	ObjExporter.h
-	ObjExporter.cpp
-)
-SOURCE_GROUP( Obj FILES ${Obj_SRCS})
-
-SET( Ogre_SRCS
-	OgreImporter.h
-	OgreStructs.h
-	OgreParsingUtils.h
-	OgreBinarySerializer.h
-	OgreXmlSerializer.h
-	OgreImporter.cpp
-	OgreStructs.cpp
-	OgreBinarySerializer.cpp
-	OgreXmlSerializer.cpp
-	OgreMaterial.cpp
-)
-SOURCE_GROUP( Ogre FILES ${Ogre_SRCS})
-
-SET( Ply_SRCS
-	PlyLoader.cpp
-	PlyLoader.h
-	PlyParser.cpp
-	PlyParser.h
-	PlyExporter.cpp
-	PlyExporter.h
-)
-SOURCE_GROUP( Ply FILES ${Ply_SRCS})
-
-SET(MS3D_SRCS
-	MS3DLoader.cpp
-	MS3DLoader.h
-)
-SOURCE_GROUP( MS3D FILES ${MS3D_SRCS})
-
-SET(COB_SRCS
-	COBLoader.cpp
-	COBLoader.h
-	COBScene.h
-)
-SOURCE_GROUP( COB FILES ${COB_SRCS})
-
-SET(BLENDER_SRCS
-	BlenderLoader.cpp
-	BlenderLoader.h
-	BlenderDNA.cpp
-	BlenderDNA.h
-	BlenderDNA.inl
-	BlenderScene.cpp
-	BlenderScene.h
-	BlenderSceneGen.h
-	BlenderIntermediate.h
-	BlenderModifier.h
-	BlenderModifier.cpp
-	BlenderBMesh.h
-	BlenderBMesh.cpp
-	BlenderTessellator.h
-	BlenderTessellator.cpp
-)
-SOURCE_GROUP( BLENDER FILES ${BLENDER_SRCS})
-
-SET(IFC_SRCS
-	IFCLoader.cpp
-	IFCLoader.h
-	IFCReaderGen.cpp
-	IFCReaderGen.h
-	IFCUtil.h
-	IFCUtil.cpp
-	IFCGeometry.cpp
-	IFCMaterial.cpp
-	IFCProfile.cpp
-	IFCCurve.cpp
-	IFCBoolean.cpp
-	IFCOpenings.cpp
-	STEPFile.h
-	STEPFileReader.h
-	STEPFileReader.cpp
-	STEPFileEncoding.cpp
-	STEPFileEncoding.h
-)
-SOURCE_GROUP( IFC FILES ${IFC_SRCS})
-
-SET( XGL_SRCS
-	XGLLoader.cpp
-	XGLLoader.h
-)
-SOURCE_GROUP( XGL FILES ${XGL_SRCS})
-
-
-SET(FBX_SRCS
-	FBXImporter.cpp
-	FBXCompileConfig.h
-	FBXImporter.h
-	FBXParser.cpp
-	FBXParser.h
-	FBXTokenizer.cpp
-	FBXTokenizer.h
-	FBXImportSettings.h
-	FBXConverter.h
-	FBXConverter.cpp
-	FBXUtil.h
-	FBXUtil.cpp
-	FBXDocument.h
-	FBXDocument.cpp
-	FBXProperties.h
-	FBXProperties.cpp
-	FBXMeshGeometry.cpp
-	FBXMaterial.cpp
-	FBXModel.cpp
-	FBXAnimation.cpp
-	FBXNodeAttribute.cpp
-	FBXDeformer.cpp
-	FBXBinaryTokenizer.cpp
-	FBXDocumentUtil.cpp
-)
-SOURCE_GROUP( FBX FILES ${FBX_SRCS})
-
+ADD_ASSIMP_IMPORTER(NFF
+  NFFLoader.cpp
+  NFFLoader.h
+)
+
+ADD_ASSIMP_IMPORTER(NDO
+  NDOLoader.cpp
+  NDOLoader.h
+)
+
+ADD_ASSIMP_IMPORTER(OFF
+  OFFLoader.cpp
+  OFFLoader.h
+)
+
+ADD_ASSIMP_IMPORTER(OBJ
+  ObjFileData.h
+  ObjFileImporter.cpp
+  ObjFileImporter.h
+  ObjFileMtlImporter.cpp
+  ObjFileMtlImporter.h
+  ObjFileParser.cpp
+  ObjFileParser.h
+  ObjTools.h
+
+  ObjExporter.h
+  ObjExporter.cpp
+)
+
+ADD_ASSIMP_IMPORTER(OGRE
+  OgreImporter.h
+  OgreStructs.h
+  OgreParsingUtils.h
+  OgreBinarySerializer.h
+  OgreXmlSerializer.h
+  OgreImporter.cpp
+  OgreStructs.cpp
+  OgreBinarySerializer.cpp
+  OgreXmlSerializer.cpp
+  OgreMaterial.cpp
+)
+
+ADD_ASSIMP_IMPORTER(OPENGEX
+  OpenGEXExporter.cpp
+  OpenGEXExporter.h
+  OpenGEXImporter.cpp
+  OpenGEXImporter.h
+  OpenGEXStructs.h
+)
+
+ADD_ASSIMP_IMPORTER(PLY
+  PlyLoader.cpp
+  PlyLoader.h
+  PlyParser.cpp
+  PlyParser.h
+  PlyExporter.cpp
+  PlyExporter.h
+)
+
+ADD_ASSIMP_IMPORTER(MS3D
+  MS3DLoader.cpp
+  MS3DLoader.h
+)
+
+ADD_ASSIMP_IMPORTER(COB
+  COBLoader.cpp
+  COBLoader.h
+  COBScene.h
+)
+
+ADD_ASSIMP_IMPORTER(BLEND
+  BlenderLoader.cpp
+  BlenderLoader.h
+  BlenderDNA.cpp
+  BlenderDNA.h
+  BlenderDNA.inl
+  BlenderScene.cpp
+  BlenderScene.h
+  BlenderSceneGen.h
+  BlenderIntermediate.h
+  BlenderModifier.h
+  BlenderModifier.cpp
+  BlenderBMesh.h
+  BlenderBMesh.cpp
+  BlenderTessellator.h
+  BlenderTessellator.cpp
+)
+
+ADD_ASSIMP_IMPORTER(IFC
+  IFCLoader.cpp
+  IFCLoader.h
+  IFCReaderGen.cpp
+  IFCReaderGen.h
+  IFCUtil.h
+  IFCUtil.cpp
+  IFCGeometry.cpp
+  IFCMaterial.cpp
+  IFCProfile.cpp
+  IFCCurve.cpp
+  IFCBoolean.cpp
+  IFCOpenings.cpp
+  STEPFile.h
+  STEPFileReader.h
+  STEPFileReader.cpp
+  STEPFileEncoding.cpp
+  STEPFileEncoding.h
+)
+
+ADD_ASSIMP_IMPORTER(XGL
+  XGLLoader.cpp
+  XGLLoader.h
+)
+
+
+ADD_ASSIMP_IMPORTER(FBX
+  FBXImporter.cpp
+  FBXCompileConfig.h
+  FBXImporter.h
+  FBXParser.cpp
+  FBXParser.h
+  FBXTokenizer.cpp
+  FBXTokenizer.h
+  FBXImportSettings.h
+  FBXConverter.h
+  FBXConverter.cpp
+  FBXUtil.h
+  FBXUtil.cpp
+  FBXDocument.h
+  FBXDocument.cpp
+  FBXProperties.h
+  FBXProperties.cpp
+  FBXMeshGeometry.cpp
+  FBXMaterial.cpp
+  FBXModel.cpp
+  FBXAnimation.cpp
+  FBXNodeAttribute.cpp
+  FBXDeformer.cpp
+  FBXBinaryTokenizer.cpp
+  FBXDocumentUtil.cpp
+)
 
 SET( PostProcessing_SRCS
-	CalcTangentsProcess.cpp
-	CalcTangentsProcess.h
-	ComputeUVMappingProcess.cpp
-	ComputeUVMappingProcess.h
-	ConvertToLHProcess.cpp
-	ConvertToLHProcess.h
-	FindDegenerates.cpp
-	FindDegenerates.h
-	FindInstancesProcess.cpp
-	FindInstancesProcess.h
-	FindInvalidDataProcess.cpp
-	FindInvalidDataProcess.h
-	FixNormalsStep.cpp
-	FixNormalsStep.h
-	GenFaceNormalsProcess.cpp
-	GenFaceNormalsProcess.h
-	GenVertexNormalsProcess.cpp
-	GenVertexNormalsProcess.h
-	PretransformVertices.cpp
-	PretransformVertices.h
-	ImproveCacheLocality.cpp
-	ImproveCacheLocality.h
-	JoinVerticesProcess.cpp
-	JoinVerticesProcess.h
-	LimitBoneWeightsProcess.cpp
-	LimitBoneWeightsProcess.h
-	RemoveRedundantMaterials.cpp
-	RemoveRedundantMaterials.h
-	RemoveVCProcess.cpp
-	RemoveVCProcess.h
-	SortByPTypeProcess.cpp
-	SortByPTypeProcess.h
-	SplitLargeMeshes.cpp
-	SplitLargeMeshes.h
-	TextureTransform.cpp
-	TextureTransform.h
-	TriangulateProcess.cpp
-	TriangulateProcess.h
-	ValidateDataStructure.cpp
-	ValidateDataStructure.h
-	OptimizeGraph.cpp
-	OptimizeGraph.h
-	OptimizeMeshes.cpp
-	OptimizeMeshes.h
-	DeboneProcess.cpp
-	DeboneProcess.h
-	ProcessHelper.h
-	ProcessHelper.cpp
-	PolyTools.h
-	MakeVerboseFormat.cpp
-	MakeVerboseFormat.h
+  CalcTangentsProcess.cpp
+  CalcTangentsProcess.h
+  ComputeUVMappingProcess.cpp
+  ComputeUVMappingProcess.h
+  ConvertToLHProcess.cpp
+  ConvertToLHProcess.h
+  FindDegenerates.cpp
+  FindDegenerates.h
+  FindInstancesProcess.cpp
+  FindInstancesProcess.h
+  FindInvalidDataProcess.cpp
+  FindInvalidDataProcess.h
+  FixNormalsStep.cpp
+  FixNormalsStep.h
+  GenFaceNormalsProcess.cpp
+  GenFaceNormalsProcess.h
+  GenVertexNormalsProcess.cpp
+  GenVertexNormalsProcess.h
+  PretransformVertices.cpp
+  PretransformVertices.h
+  ImproveCacheLocality.cpp
+  ImproveCacheLocality.h
+  JoinVerticesProcess.cpp
+  JoinVerticesProcess.h
+  LimitBoneWeightsProcess.cpp
+  LimitBoneWeightsProcess.h
+  RemoveRedundantMaterials.cpp
+  RemoveRedundantMaterials.h
+  RemoveVCProcess.cpp
+  RemoveVCProcess.h
+  SortByPTypeProcess.cpp
+  SortByPTypeProcess.h
+  SplitLargeMeshes.cpp
+  SplitLargeMeshes.h
+  TextureTransform.cpp
+  TextureTransform.h
+  TriangulateProcess.cpp
+  TriangulateProcess.h
+  ValidateDataStructure.cpp
+  ValidateDataStructure.h
+  OptimizeGraph.cpp
+  OptimizeGraph.h
+  OptimizeMeshes.cpp
+  OptimizeMeshes.h
+  DeboneProcess.cpp
+  DeboneProcess.h
+  ProcessHelper.h
+  ProcessHelper.cpp
+  PolyTools.h
+  MakeVerboseFormat.cpp
+  MakeVerboseFormat.h
 )
 SOURCE_GROUP( PostProcessing FILES ${PostProcessing_SRCS})
 
-SET( Q3D_SRCS
-	Q3DLoader.cpp
-	Q3DLoader.h
+ADD_ASSIMP_IMPORTER(Q3D
+  Q3DLoader.cpp
+  Q3DLoader.h
 )
-SOURCE_GROUP( Q3D FILES ${Q3D_SRCS})
 
-SET( Q3BSP_SRCS
-	Q3BSPFileData.h
-	Q3BSPFileParser.h
-	Q3BSPFileParser.cpp
-	Q3BSPFileImporter.h
-	Q3BSPFileImporter.cpp
-	Q3BSPZipArchive.h
-	Q3BSPZipArchive.cpp
+ADD_ASSIMP_IMPORTER(Q3BSP
+  Q3BSPFileData.h
+  Q3BSPFileParser.h
+  Q3BSPFileParser.cpp
+  Q3BSPFileImporter.h
+  Q3BSPFileImporter.cpp
+  Q3BSPZipArchive.h
+  Q3BSPZipArchive.cpp
 )
-SOURCE_GROUP( Q3BSP FILES ${Q3BSP_SRCS})
 
-SET( Raw_SRCS
-	RawLoader.cpp
-	RawLoader.h
+ADD_ASSIMP_IMPORTER(RAW
+  RawLoader.cpp
+  RawLoader.h
 )
-SOURCE_GROUP( Raw FILES ${Raw_SRCS})
 
-SET( SMD_SRCS
-	SMDLoader.cpp
-	SMDLoader.h
+ADD_ASSIMP_IMPORTER(SMD
+  SMDLoader.cpp
+  SMDLoader.h
 )
-SOURCE_GROUP( SMD FILES ${SMD_SRCS})
 
-SET( STL_SRCS
-	STLLoader.cpp
-	STLLoader.h
-	STLExporter.h
-	STLExporter.cpp
+ADD_ASSIMP_IMPORTER(STL
+  STLLoader.cpp
+  STLLoader.h
+  STLExporter.h
+  STLExporter.cpp
 )
-SOURCE_GROUP( STL FILES ${STL_SRCS})
 
-SET( Terragen_SRCS
-	TerragenLoader.cpp
-	TerragenLoader.h
+ADD_ASSIMP_IMPORTER(TERRAGEN
+  TerragenLoader.cpp
+  TerragenLoader.h
 )
-SOURCE_GROUP( Terragen FILES ${Terragen_SRCS})
 
-SET( Unreal_SRCS
-	UnrealLoader.cpp
-	UnrealLoader.h
+ADD_ASSIMP_IMPORTER(3D
+  UnrealLoader.cpp
+  UnrealLoader.h
 )
-SOURCE_GROUP( Unreal FILES ${Unreal_SRCS})
 
-SET( XFile_SRCS
-	XFileHelper.h
-	XFileImporter.cpp
-	XFileImporter.h
-	XFileParser.cpp
-	XFileParser.h
+ADD_ASSIMP_IMPORTER(X
+  XFileHelper.h
+  XFileImporter.cpp
+  XFileImporter.h
+  XFileParser.cpp
+  XFileParser.h
+  XFileExporter.h
+  XFileExporter.cpp
 )
-SOURCE_GROUP( XFile FILES ${XFile_SRCS})
+
+SET( Step_SRCS
+  StepExporter.h
+  StepExporter.cpp
+)
+SOURCE_GROUP( Step FILES ${Step_SRCS})
 
 SET( Exporter_SRCS
-	Exporter.cpp
-	AssimpCExport.cpp
-	BlobIOSystem.h
+  Exporter.cpp
+  AssimpCExport.cpp
+  BlobIOSystem.h
 )
 SOURCE_GROUP( Exporter FILES ${Exporter_SRCS})
 
 SET( Extra_SRCS
-	MD4FileData.h
+  MD4FileData.h
 )
 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
+  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
+  ../contrib/ConvertUTF/ConvertUTF.h
+  ../contrib/ConvertUTF/ConvertUTF.c
 )
 SOURCE_GROUP( ConvertUTF FILES ${ConvertUTF_SRCS})
 
-SET( Clipper_SRCS 
-	../contrib/clipper/clipper.hpp
-	../contrib/clipper/clipper.cpp
+SET( Clipper_SRCS
+  ../contrib/clipper/clipper.hpp
+  ../contrib/clipper/clipper.cpp
 )
 SOURCE_GROUP( Clipper FILES ${Clipper_SRCS})
 
 
-SET( Poly2Tri_SRCS 
-	../contrib/poly2tri/poly2tri/common/shapes.cc
-	../contrib/poly2tri/poly2tri/common/shapes.h
-	../contrib/poly2tri/poly2tri/common/utils.h
-	../contrib/poly2tri/poly2tri/sweep/advancing_front.h
-	../contrib/poly2tri/poly2tri/sweep/advancing_front.cc
-	../contrib/poly2tri/poly2tri/sweep/cdt.cc
-	../contrib/poly2tri/poly2tri/sweep/cdt.h
-	../contrib/poly2tri/poly2tri/sweep/sweep.cc
-	../contrib/poly2tri/poly2tri/sweep/sweep.h
-	../contrib/poly2tri/poly2tri/sweep/sweep_context.cc
-	../contrib/poly2tri/poly2tri/sweep/sweep_context.h
+SET( Poly2Tri_SRCS
+  ../contrib/poly2tri/poly2tri/common/shapes.cc
+  ../contrib/poly2tri/poly2tri/common/shapes.h
+  ../contrib/poly2tri/poly2tri/common/utils.h
+  ../contrib/poly2tri/poly2tri/sweep/advancing_front.h
+  ../contrib/poly2tri/poly2tri/sweep/advancing_front.cc
+  ../contrib/poly2tri/poly2tri/sweep/cdt.cc
+  ../contrib/poly2tri/poly2tri/sweep/cdt.h
+  ../contrib/poly2tri/poly2tri/sweep/sweep.cc
+  ../contrib/poly2tri/poly2tri/sweep/sweep.h
+  ../contrib/poly2tri/poly2tri/sweep/sweep_context.cc
+  ../contrib/poly2tri/poly2tri/sweep/sweep_context.h
 )
 SOURCE_GROUP( Poly2Tri FILES ${Poly2Tri_SRCS})
 
 SET( unzip_SRCS
-	../contrib/unzip/crypt.h
-	../contrib/unzip/ioapi.c
-	../contrib/unzip/ioapi.h
-	../contrib/unzip/unzip.c
-	../contrib/unzip/unzip.h
+  ../contrib/unzip/crypt.h
+  ../contrib/unzip/ioapi.c
+  ../contrib/unzip/ioapi.h
+  ../contrib/unzip/unzip.c
+  ../contrib/unzip/unzip.h
 )
 SOURCE_GROUP( unzip FILES ${unzip_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/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/DDLNode.h
+  ../contrib/openddlparser/include/openddlparser/Value.h
+)
+SOURCE_GROUP( openddl_parser FILES ${openddl_parser_SRCS})
 
 # VC2010 fixes
 if(MSVC10)
-	OPTION( VC10_STDINT_FIX "Fix for VC10 Compiler regarding pstdint.h redefinition errors" OFF )
-	if( VC10_STDINT_FIX )
-		ADD_DEFINITIONS( -D_STDINT )
-	endif( VC10_STDINT_FIX )
+  option( VC10_STDINT_FIX "Fix for VC10 Compiler regarding pstdint.h redefinition errors" OFF )
+  if( VC10_STDINT_FIX )
+    ADD_DEFINITIONS( -D_STDINT )
+  endif( VC10_STDINT_FIX )
 endif(MSVC10)
 
 ADD_DEFINITIONS( -DASSIMP_BUILD_DLL_EXPORT )
 
 if ( MSVC )
-	ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
-	ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
+  ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
+  ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
 endif ( MSVC )
 
 if (UNZIP_FOUND)
-	SET (unzip_compile_SRCS "")
+  SET (unzip_compile_SRCS "")
 else (UNZIP_FOUND)
-	SET (unzip_compile_SRCS ${unzip_SRCS})
+  SET (unzip_compile_SRCS ${unzip_SRCS})
 endif (UNZIP_FOUND)
 
+MESSAGE(STATUS "Enabled formats:${ASSIMP_IMPORTERS_ENABLED}")
+MESSAGE(STATUS "Disabled formats:${ASSIMP_IMPORTERS_DISABLED}")
+
 SET( assimp_src
-	# Assimp Files
-	${Core_SRCS}
-	${Common_SRCS}
-	${Logging_SRCS}
-	${Exporter_SRCS}
-	${PostProcessing_SRCS}
-
-	# Model Support
-	${3DS_SRCS}
-	${AC_SRCS}
-	${ASE_SRCS}
-	${B3D_SRCS}
-	${BVH_SRCS}
-	${Collada_SRCS}
-	${DXF_SRCS}
-	${CSM_SRCS}
-	${HMP_SRCS}
-	${Irr_SRCS}
-	${LWO_SRCS}
-	${LWS_SRCS}
-	${MD2_SRCS}
-	${MD3_SRCS}
-	${MD5_SRCS}
-	${MDC_SRCS}
-	${MDL_SRCS}
-	${MaterialSystem_SRCS}
-	${NFF_SRCS}
-	${OFFFormat_SRCS}
-	${Obj_SRCS}
-	${Ogre_SRCS}
-	${Ply_SRCS}
-	${Q3D_SRCS}
-	${Q3BSP_SRCS}
-	${Raw_SRCS}
-	${SMD_SRCS}
-	${STL_SRCS}
-	${Terragen_SRCS}
-	${Unreal_SRCS}
-	${XFile_SRCS}
-	${Extra_SRCS}
-	${MS3D_SRCS}
-	${COB_SRCS}
-	${BLENDER_SRCS}
-	${NDO_SRCS}
-	${IFC_SRCS}
-	${XGL_SRCS}
-	${FBX_SRCS}
-	
-	# Third-party libraries
-	${IrrXML_SRCS}
-	${ConvertUTF_SRCS}
-	${unzip_compile_SRCS}
-	${Poly2Tri_SRCS}
-	${Clipper_SRCS}
-	# Necessary to show the headers in the project when using the VC++ generator:
-	${Boost_SRCS}
-
-	${PUBLIC_HEADERS}
-	${COMPILER_HEADERS}
-	
-	# Old precompiled header
-	# (removed because the precompiled header is not updated when visual studio switch configuration which leads to failed compilation.
-	# Moreover it's a drag to recompile assimp entirely each time a modification is made to one of the included header, which is definitely counter-productive.)
-	AssimpPCH.cpp
-)
-
-#ADD_MSVC_PRECOMPILED_HEADER("AssimpPCH.h" "AssimpPCH.cpp" assimp_src)
+  # Assimp Files
+  ${Core_SRCS}
+  ${Common_SRCS}
+  ${Logging_SRCS}
+  ${Exporter_SRCS}
+  ${PostProcessing_SRCS}
+  ${MaterialSystem_SRCS}
+  ${Step_SRCS}
+
+  # Model Support
+  ${ASSIMP_LOADER_SRCS}
+
+  # Third-party libraries
+  ${IrrXML_SRCS}
+  ${ConvertUTF_SRCS}
+  ${unzip_compile_SRCS}
+  ${Poly2Tri_SRCS}
+  ${Clipper_SRCS}
+  ${openddl_parser_SRCS}
+  # Necessary to show the headers in the project when using the VC++ generator:
+  ${Boost_SRCS}
+
+  ${PUBLIC_HEADERS}
+  ${COMPILER_HEADERS}
+
+)
+add_definitions( -DOPENDDLPARSER_BUILD )
+
+INCLUDE_DIRECTORIES(
+  ../contrib/openddlparser/include
+)
+
+IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
+  SET( assimp_src ${assimp_src} ${C4D_SRCS})
+  INCLUDE_DIRECTORIES(${C4D_INCLUDES})
+ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
 
 ADD_LIBRARY( assimp ${assimp_src} )
 
-SET_PROPERTY(TARGET assimp PROPERTY DEBUG_POSTFIX ${ASSIMP_DEBUG_POSTFIX})
+TARGET_LINK_LIBRARIES(assimp ${ZLIB_LIBRARIES} ${OPENDDL_PARSER_LIBRARIES} )
+
+if(ANDROID AND ASSIMP_ANDROID_JNIIOSYSTEM)
+  set(ASSIMP_ANDROID_JNIIOSYSTEM_PATH port/AndroidJNI)
+  add_subdirectory(../${ASSIMP_ANDROID_JNIIOSYSTEM_PATH}/ ../${ASSIMP_ANDROID_JNIIOSYSTEM_PATH}/)
+  target_link_libraries(assimp android_jniiosystem)
+endif(ANDROID AND ASSIMP_ANDROID_JNIIOSYSTEM)
+
+IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
+  TARGET_LINK_LIBRARIES(assimp optimized ${C4D_RELEASE_LIBRARY})
+  TARGET_LINK_LIBRARIES(assimp debug ${C4D_DEBUG_LIBRARY})
+  TARGET_LINK_LIBRARIES(assimp ${C4D_EXTRA_LIBRARIES})
+ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
+
+if( MSVC )
+  # in order to prevent DLL hell, each of the DLLs have to be suffixed with the major version and msvc prefix
+  if( MSVC70 OR MSVC71 )
+    set(MSVC_PREFIX "vc70")
+  elseif( MSVC80 )
+    set(MSVC_PREFIX "vc80")
+  elseif( MSVC90 )
+    set(MSVC_PREFIX "vc90")
+  elseif( MSVC10 )
+    set(MSVC_PREFIX "vc100")
+  elseif( MSVC11 )
+    set(MSVC_PREFIX "vc110")
+  elseif( MSVC12 )
+    set(MSVC_PREFIX "vc120")
+  else()
+    set(MSVC_PREFIX "vc130")
+  endif()
+  set(LIBRARY_SUFFIX "${ASSIMP_LIBRARY_SUFFIX}-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library")
+endif()
 
-TARGET_LINK_LIBRARIES(assimp ${ZLIB_LIBRARIES})
 SET_TARGET_PROPERTIES( assimp PROPERTIES
-	VERSION ${ASSIMP_VERSION}
-	SOVERSION ${ASSIMP_SOVERSION} # use full version 
-    OUTPUT_NAME assimp${ASSIMP_LIBRARY_SUFFIX}
+  VERSION ${ASSIMP_VERSION}
+  SOVERSION ${ASSIMP_SOVERSION} # use full version
+  OUTPUT_NAME assimp${LIBRARY_SUFFIX}
 )
 
 if (APPLE)
-    SET_TARGET_PROPERTIES( assimp PROPERTIES INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_DIR}")
+  SET_TARGET_PROPERTIES( assimp PROPERTIES INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/${LIB_INSTALL_DIR}")
 endif()
 
 # Build against external unzip, or add ../contrib/unzip so
 # assimp can #include "unzip.h"
 if (UNZIP_FOUND)
-	INCLUDE_DIRECTORIES(${UNZIP_INCLUDE_DIRS})
-	TARGET_LINK_LIBRARIES(assimp ${UNZIP_LIBRARIES})
+  INCLUDE_DIRECTORIES(${UNZIP_INCLUDE_DIRS})
+  TARGET_LINK_LIBRARIES(assimp ${UNZIP_LIBRARIES})
 else (UNZIP_FOUND)
-	INCLUDE_DIRECTORIES("../contrib/unzip")
+  INCLUDE_DIRECTORIES("../contrib/unzip")
 endif (UNZIP_FOUND)
 
 INSTALL( TARGETS assimp
-         LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
-         ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
-         RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR}
-         COMPONENT ${LIBASSIMP_COMPONENT})
+  LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
+  ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
+  RUNTIME DESTINATION ${ASSIMP_BIN_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}
+    COMPONENT assimp-dev)
+endif(ASSIMP_ANDROID_JNIIOSYSTEM)
 
 if(MSVC AND ASSIMP_INSTALL_PDB)
-	install(FILES ${Assimp_BINARY_DIR}/code/Debug/assimp${ASSIMP_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
-	)
+  install(FILES ${Assimp_BINARY_DIR}/code/Debug/assimp${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
+  )
 endif ()

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 716 - 706
assimplib.mod/assimp/code/COBLoader.cpp


+ 91 - 87
assimplib.mod/assimp/code/COBLoader.h

@@ -2,11 +2,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -23,16 +23,16 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -45,123 +45,127 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define INCLUDED_AI_COB_LOADER_H
 
 #include "BaseImporter.h"
-namespace Assimp	{
-	class LineSplitter;
-	
-	// TinyFormatter.h
-	namespace Formatter {
-		template <typename T,typename TR, typename A> class basic_formatter;
-		typedef class basic_formatter< char, std::char_traits<char>, std::allocator<char> > format;
-	}
-
-	// COBScene.h
-	namespace COB {
-		struct ChunkInfo;
-		struct Node;
-		struct Scene;
-	}
+#include "StreamReader.h"
+
+struct aiNode;
+
+namespace Assimp    {
+    class LineSplitter;
+
+    // TinyFormatter.h
+    namespace Formatter {
+        template <typename T,typename TR, typename A> class basic_formatter;
+        typedef class basic_formatter< char, std::char_traits<char>, std::allocator<char> > format;
+    }
+
+    // COBScene.h
+    namespace COB {
+        struct ChunkInfo;
+        struct Node;
+        struct Scene;
+    }
 
 // -------------------------------------------------------------------------------------------
-/** Importer class to load TrueSpace files (cob,scn) up to v6. 
+/** Importer class to load TrueSpace files (cob,scn) up to v6.
  *
  *  Currently relatively limited, loads only ASCII files and needs more test coverage. */
 // -------------------------------------------------------------------------------------------
 class COBImporter : public BaseImporter
 {
 public:
-	COBImporter();
-	~COBImporter();
+    COBImporter();
+    ~COBImporter();
 
 
 public:
 
-	// --------------------
-	bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
-		bool checkSig) const;
+    // --------------------
+    bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+        bool checkSig) const;
 
 protected:
 
-	// --------------------
-	const aiImporterDesc* GetInfo () const;
+    // --------------------
+    const aiImporterDesc* GetInfo () const;
 
-	// --------------------
-	void SetupProperties(const Importer* pImp);
+    // --------------------
+    void SetupProperties(const Importer* pImp);
 
-	// --------------------
-	void InternReadFile( const std::string& pFile, aiScene* pScene, 
-		IOSystem* pIOHandler);
+    // --------------------
+    void InternReadFile( const std::string& pFile, aiScene* pScene,
+        IOSystem* pIOHandler);
 
 private:
 
-	// -------------------------------------------------------------------
-	/** Prepend 'COB: ' and throw msg.*/
-	static void ThrowException(const std::string& msg);
+    // -------------------------------------------------------------------
+    /** Prepend 'COB: ' and throw msg.*/
+    AI_WONT_RETURN static void ThrowException(const std::string& msg) AI_WONT_RETURN_SUFFIX;
 
-	// -------------------------------------------------------------------
-	/** @brief Read from an ascii scene/object file
-	 *  @param out Receives output data.
-	 *  @param stream Stream to read from. */
-	void ReadAsciiFile(COB::Scene& out, StreamReaderLE* stream);
+    // -------------------------------------------------------------------
+    /** @brief Read from an ascii scene/object file
+     *  @param out Receives output data.
+     *  @param stream Stream to read from. */
+    void ReadAsciiFile(COB::Scene& out, StreamReaderLE* stream);
 
-	// -------------------------------------------------------------------
-	/** @brief Read from a binary scene/object file
-	 *  @param out Receives output data.
-	 *  @param stream Stream to read from.  */
-	void ReadBinaryFile(COB::Scene& out, StreamReaderLE* stream);
+    // -------------------------------------------------------------------
+    /** @brief Read from a binary scene/object file
+     *  @param out Receives output data.
+     *  @param stream Stream to read from.  */
+    void ReadBinaryFile(COB::Scene& out, StreamReaderLE* stream);
 
 
 private:
 
-	// Conversion to Assimp output format
+    // Conversion to Assimp output format
 
-	aiNode* BuildNodes(const COB::Node& root,const COB::Scene& scin,aiScene* fill);
+    aiNode* BuildNodes(const COB::Node& root,const COB::Scene& scin,aiScene* fill);
 
 private:
 
-	// ASCII file support
+    // ASCII file support
 
-	void UnsupportedChunk_Ascii(LineSplitter& splitter, const COB::ChunkInfo& nfo, const char* name);
-	void ReadChunkInfo_Ascii(COB::ChunkInfo& out, const LineSplitter& splitter);
-	void ReadBasicNodeInfo_Ascii(COB::Node& msh, LineSplitter& splitter, const COB::ChunkInfo& nfo);
-	template <typename T> void ReadFloat3Tuple_Ascii(T& fill, const char** in);
+    void UnsupportedChunk_Ascii(LineSplitter& splitter, const COB::ChunkInfo& nfo, const char* name);
+    void ReadChunkInfo_Ascii(COB::ChunkInfo& out, const LineSplitter& splitter);
+    void ReadBasicNodeInfo_Ascii(COB::Node& msh, LineSplitter& splitter, const COB::ChunkInfo& nfo);
+    template <typename T> void ReadFloat3Tuple_Ascii(T& fill, const char** in);
 
-	void ReadPolH_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
-	void ReadBitM_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
-	void ReadMat1_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
-	void ReadGrou_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
-	void ReadBone_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
-	void ReadCame_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
-	void ReadLght_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
-	void ReadUnit_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
-	void ReadChan_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
+    void ReadPolH_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
+    void ReadBitM_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
+    void ReadMat1_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
+    void ReadGrou_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
+    void ReadBone_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
+    void ReadCame_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
+    void ReadLght_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
+    void ReadUnit_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
+    void ReadChan_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
 
 
-	// ASCII file logging stuff to add proper line numbers to messages
+    // ASCII file logging stuff to add proper line numbers to messages
 
-	static void LogWarn_Ascii (const LineSplitter& splitter, const Formatter::format& message);
-	static void LogError_Ascii(const LineSplitter& splitter, const Formatter::format& message);
-	static void LogInfo_Ascii (const LineSplitter& splitter, const Formatter::format& message);
-	static void LogDebug_Ascii(const LineSplitter& splitter, const Formatter::format& message);
+    static void LogWarn_Ascii (const LineSplitter& splitter, const Formatter::format& message);
+    static void LogError_Ascii(const LineSplitter& splitter, const Formatter::format& message);
+    static void LogInfo_Ascii (const LineSplitter& splitter, const Formatter::format& message);
+    static void LogDebug_Ascii(const LineSplitter& splitter, const Formatter::format& message);
 
-	static void LogWarn_Ascii  (const Formatter::format& message);
-	static void LogError_Ascii (const Formatter::format& message);
-	static void LogInfo_Ascii  (const Formatter::format& message);
-	static void LogDebug_Ascii (const Formatter::format& message);
+    static void LogWarn_Ascii  (const Formatter::format& message);
+    static void LogError_Ascii (const Formatter::format& message);
+    static void LogInfo_Ascii  (const Formatter::format& message);
+    static void LogDebug_Ascii (const Formatter::format& message);
 
 
-	// Binary file support
+    // Binary file support
 
-	void UnsupportedChunk_Binary(StreamReaderLE& reader, const COB::ChunkInfo& nfo, const char* name);
-	void ReadString_Binary(std::string& out, StreamReaderLE& reader);
-	void ReadBasicNodeInfo_Binary(COB::Node& msh, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
+    void UnsupportedChunk_Binary(StreamReaderLE& reader, const COB::ChunkInfo& nfo, const char* name);
+    void ReadString_Binary(std::string& out, StreamReaderLE& reader);
+    void ReadBasicNodeInfo_Binary(COB::Node& msh, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
 
-	void ReadPolH_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
-	void ReadBitM_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
-	void ReadMat1_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
-	void ReadCame_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
-	void ReadLght_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
-	void ReadGrou_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
-	void ReadUnit_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
+    void ReadPolH_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
+    void ReadBitM_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
+    void ReadMat1_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
+    void ReadCame_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
+    void ReadLght_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
+    void ReadGrou_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
+    void ReadUnit_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
 
 
 }; // !class COBImporter

+ 128 - 125
assimplib.mod/assimp/code/COBScene.h

@@ -2,11 +2,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -23,16 +23,16 @@ 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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -45,210 +45,213 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define INCLUDED_AI_COB_SCENE_H
 
 #include <boost/shared_ptr.hpp>
+#include <deque>
+
 #include "BaseImporter.h"
+#include "./../include/assimp/material.h"
 
-namespace Assimp	{
-	namespace COB {
+namespace Assimp    {
+    namespace COB {
 
 // ------------------
 /** Represents a single vertex index in a face */
 struct VertexIndex
 {
-	// intentionally uninitialized
-	unsigned int pos_idx,uv_idx;
+    // intentionally uninitialized
+    unsigned int pos_idx,uv_idx;
 };
 
 // ------------------
 /** COB Face data structure */
 struct Face
 {
-	// intentionally uninitialized
-	unsigned int material, flags;
-	std::vector<VertexIndex> indices;
+    // intentionally uninitialized
+    unsigned int material, flags;
+    std::vector<VertexIndex> indices;
 };
 
 // ------------------
 /** COB chunk header information */
 struct ChunkInfo
 {
-	enum {NO_SIZE=UINT_MAX};
+    enum {NO_SIZE=UINT_MAX};
 
-	ChunkInfo ()
-		:	id        (0)
-		,	parent_id (0)
-		,	version	  (0)
-		,	size	  (NO_SIZE)
-	{}
+    ChunkInfo ()
+        :   id        (0)
+        ,   parent_id (0)
+        ,   version   (0)
+        ,   size      (NO_SIZE)
+    {}
 
-	// Id of this chunk, unique within file
-	unsigned int id;
+    // Id of this chunk, unique within file
+    unsigned int id;
 
-	// and the corresponding parent
-	unsigned int parent_id;
+    // and the corresponding parent
+    unsigned int parent_id;
 
-	// version. v1.23 becomes 123
-	unsigned int version;
+    // version. v1.23 becomes 123
+    unsigned int version;
 
-	// chunk size in bytes, only relevant for binary files
-	// NO_SIZE is also valid.
-	unsigned int size;
+    // chunk size in bytes, only relevant for binary files
+    // NO_SIZE is also valid.
+    unsigned int size;
 };
 
 // ------------------
 /** A node in the scenegraph */
 struct Node : public ChunkInfo
 {
-	enum Type {
-		TYPE_MESH,TYPE_GROUP,TYPE_LIGHT,TYPE_CAMERA,TYPE_BONE
-	};
+    enum Type {
+        TYPE_MESH,TYPE_GROUP,TYPE_LIGHT,TYPE_CAMERA,TYPE_BONE
+    };
 
-	virtual ~Node() {}
-	Node(Type type) : type(type), unit_scale(1.f){}
+    virtual ~Node() {}
+    Node(Type type) : type(type), unit_scale(1.f){}
 
-	Type type;
+    Type type;
 
-	// used during resolving
-	typedef std::deque<const Node*> ChildList;
-	mutable ChildList temp_children;
+    // used during resolving
+    typedef std::deque<const Node*> ChildList;
+    mutable ChildList temp_children;
 
-	// unique name
-	std::string name;
+    // unique name
+    std::string name;
 
-	// local mesh transformation
-	aiMatrix4x4 transform;
+    // local mesh transformation
+    aiMatrix4x4 transform;
 
-	// scaling for this node to get to the metric system
-	float unit_scale;
+    // scaling for this node to get to the metric system
+    float unit_scale;
 };
 
 // ------------------
 /** COB Mesh data structure */
 struct Mesh : public Node
 {
-	using ChunkInfo::operator=;
-	enum DrawFlags {
-		SOLID = 0x1,
-		TRANS = 0x2,
-		WIRED = 0x4,
-		BBOX  = 0x8,
-		HIDE  = 0x10
-	};
-
-	Mesh() 
-		: Node(TYPE_MESH)
-		, draw_flags(SOLID) 
-	{}
-
-	// vertex elements
-	std::vector<aiVector2D> texture_coords;
-	std::vector<aiVector3D> vertex_positions;
-
-	// face data
-	std::vector<Face> faces;
-
-	// misc. drawing flags
-	unsigned int draw_flags;
-
-	// used during resolving
-	typedef std::deque<Face*> FaceRefList;
-	typedef std::map< unsigned int,FaceRefList > TempMap;
-	TempMap temp_map;
+    using ChunkInfo::operator=;
+    enum DrawFlags {
+        SOLID = 0x1,
+        TRANS = 0x2,
+        WIRED = 0x4,
+        BBOX  = 0x8,
+        HIDE  = 0x10
+    };
+
+    Mesh()
+        : Node(TYPE_MESH)
+        , draw_flags(SOLID)
+    {}
+
+    // vertex elements
+    std::vector<aiVector2D> texture_coords;
+    std::vector<aiVector3D> vertex_positions;
+
+    // face data
+    std::vector<Face> faces;
+
+    // misc. drawing flags
+    unsigned int draw_flags;
+
+    // used during resolving
+    typedef std::deque<Face*> FaceRefList;
+    typedef std::map< unsigned int,FaceRefList > TempMap;
+    TempMap temp_map;
 };
 
 // ------------------
 /** COB Group data structure */
 struct Group : public Node
 {
-	using ChunkInfo::operator=;
-	Group() : Node(TYPE_GROUP) {}
+    using ChunkInfo::operator=;
+    Group() : Node(TYPE_GROUP) {}
 };
 
 // ------------------
 /** COB Bone data structure */
 struct Bone : public Node
 {
-	using ChunkInfo::operator=;
-	Bone() : Node(TYPE_BONE) {}
+    using ChunkInfo::operator=;
+    Bone() : Node(TYPE_BONE) {}
 };
 
 // ------------------
 /** COB Light data structure */
 struct Light : public Node
 {
-	enum LightType {
-		SPOT,LOCAL,INFINITE
-	};
+    enum LightType {
+        SPOT,LOCAL,INFINITE
+    };
 
-	using ChunkInfo::operator=;
-	Light() : Node(TYPE_LIGHT),angle(),inner_angle(),ltype(SPOT) {}
+    using ChunkInfo::operator=;
+    Light() : Node(TYPE_LIGHT),angle(),inner_angle(),ltype(SPOT) {}
 
-	aiColor3D color;
-	float angle,inner_angle;
+    aiColor3D color;
+    float angle,inner_angle;
 
-	LightType ltype;
+    LightType ltype;
 };
 
 // ------------------
 /** COB Camera data structure */
 struct Camera : public Node
 {
-	using ChunkInfo::operator=;
-	Camera() : Node(TYPE_CAMERA) {}
+    using ChunkInfo::operator=;
+    Camera() : Node(TYPE_CAMERA) {}
 };
 
 // ------------------
 /** COB Texture data structure */
 struct Texture
 {
-	std::string path;
-	aiUVTransform transform;
+    std::string path;
+    aiUVTransform transform;
 };
 
 // ------------------
 /** COB Material data structure */
 struct Material : ChunkInfo
 {
-	using ChunkInfo::operator=;
-	enum Shader {
-		FLAT,PHONG,METAL
-	};
+    using ChunkInfo::operator=;
+    enum Shader {
+        FLAT,PHONG,METAL
+    };
 
-	enum AutoFacet {
-		FACETED,AUTOFACETED,SMOOTH
-	};
+    enum AutoFacet {
+        FACETED,AUTOFACETED,SMOOTH
+    };
 
-	Material() : alpha(),exp(),ior(),ka(),ks(1.f),
-		matnum(UINT_MAX),
-		shader(FLAT),autofacet(FACETED),
-		autofacet_angle()
-	{}
+    Material() : alpha(),exp(),ior(),ka(),ks(1.f),
+        matnum(UINT_MAX),
+        shader(FLAT),autofacet(FACETED),
+        autofacet_angle()
+    {}
 
-	std::string type;
+    std::string type;
 
-	aiColor3D rgb;
-	float alpha, exp, ior,ka,ks;
+    aiColor3D rgb;
+    float alpha, exp, ior,ka,ks;
 
-	unsigned int matnum;
-	Shader shader; 
+    unsigned int matnum;
+    Shader shader;
 
-	AutoFacet autofacet;
-	float autofacet_angle;
+    AutoFacet autofacet;
+    float autofacet_angle;
 
-	boost::shared_ptr<Texture> tex_env,tex_bump,tex_color;
+    boost::shared_ptr<Texture> tex_env,tex_bump,tex_color;
 };
 
 // ------------------
 /** Embedded bitmap, for instance for the thumbnail image */
 struct Bitmap : ChunkInfo
 {
-	Bitmap() : orig_size() {}
-	struct BitmapHeader 
-	{
-	};
-
-	BitmapHeader head;
-	size_t orig_size;
-	std::vector<char> buff_zipped;
+    Bitmap() : orig_size() {}
+    struct BitmapHeader
+    {
+    };
+
+    BitmapHeader head;
+    size_t orig_size;
+    std::vector<char> buff_zipped;
 };
 
 typedef std::deque< boost::shared_ptr<Node> > NodeList;
@@ -258,14 +261,14 @@ typedef std::vector< Material > MaterialList;
 /** Represents a master COB scene, even if we loaded just a single COB file */
 struct Scene
 {
-	NodeList nodes;
-	MaterialList materials;
+    NodeList nodes;
+    MaterialList materials;
 
-	// becomes *0 later
-	Bitmap thumbnail;
+    // becomes *0 later
+    Bitmap thumbnail;
 };
 
-	} // end COB
+    } // end COB
 } // end Assimp
 
 #endif

+ 225 - 218
assimplib.mod/assimp/code/CSMLoader.cpp

@@ -3,12 +3,12 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -25,16 +25,16 @@ conditions are met:
   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 
+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 
+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 
+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 
+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.
 ---------------------------------------------------------------------------
 */
@@ -43,7 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *  Implementation of the CSM importer class.
  */
 
-#include "AssimpPCH.h"
+
 
 #ifndef ASSIMP_BUILD_NO_CSM_IMPORTER
 
@@ -51,20 +51,27 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "SkeletonMeshBuilder.h"
 #include "ParsingUtils.h"
 #include "fast_atof.h"
+#include "../include/assimp/Importer.hpp"
+#include <boost/scoped_ptr.hpp>
+#include "../include/assimp/IOSystem.hpp"
+#include "../include/assimp/anim.h"
+#include "../include/assimp/DefaultLogger.hpp"
+#include "../include/assimp/scene.h"
+
 
 using namespace Assimp;
 
 static const aiImporterDesc desc = {
-	"CharacterStudio Motion Importer (MoCap)",
-	"",
-	"",
-	"",
-	aiImporterFlags_SupportTextFlavour,
-	0,
-	0,
-	0,
-	0,
-	"csm" 
+    "CharacterStudio Motion Importer (MoCap)",
+    "",
+    "",
+    "",
+    aiImporterFlags_SupportTextFlavour,
+    0,
+    0,
+    0,
+    0,
+    "csm"
 };
 
 
@@ -75,225 +82,225 @@ CSMImporter::CSMImporter()
 {}
 
 // ------------------------------------------------------------------------------------------------
-// Destructor, private as well 
+// Destructor, private as well
 CSMImporter::~CSMImporter()
 {}
 
 // ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file. 
+// Returns whether the class can handle the format of the given file.
 bool CSMImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
 {
-	// check file extension 
-	const std::string extension = GetExtension(pFile);
-	
-	if( extension == "csm")
-		return true;
-
-	if ((checkSig || !extension.length()) && pIOHandler) {
-		const char* tokens[] = {"$Filename"};
-		return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
-	}
-	return false;
+    // check file extension
+    const std::string extension = GetExtension(pFile);
+
+    if( extension == "csm")
+        return true;
+
+    if ((checkSig || !extension.length()) && pIOHandler) {
+        const char* tokens[] = {"$Filename"};
+        return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
+    }
+    return false;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Build a string of all file extensions supported
 const aiImporterDesc* CSMImporter::GetInfo () const
 {
-	return &desc;
+    return &desc;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Setup configuration properties for the loader
 void CSMImporter::SetupProperties(const Importer* pImp)
 {
-	noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
+    noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
 }
 
 // ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure. 
-void CSMImporter::InternReadFile( const std::string& pFile, 
-	aiScene* pScene, IOSystem* pIOHandler)
+// Imports the given file into the given scene structure.
+void CSMImporter::InternReadFile( const std::string& pFile,
+    aiScene* pScene, IOSystem* pIOHandler)
 {
-	boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
-
-	// Check whether we can read from the file
-	if( file.get() == NULL) {
-		throw DeadlyImportError( "Failed to open CSM file " + pFile + ".");
-	}
-
-	// allocate storage and copy the contents of the file to a memory buffer
-	std::vector<char> mBuffer2;
-	TextFileToBuffer(file.get(),mBuffer2);
-	const char* buffer = &mBuffer2[0];
-
-	aiAnimation* anim = new aiAnimation();
-	int first = 0, last = 0x00ffffff;
-
-	// now process the file and look out for '$' sections
-	while (1)	{
-		SkipSpaces(&buffer);
-		if ('\0' == *buffer)
-			break;
-
-		if ('$'  == *buffer)	{
-			++buffer;
-			if (TokenMatchI(buffer,"firstframe",10))	{
-				SkipSpaces(&buffer);
-				first = strtol10(buffer,&buffer);
-			}
-			else if (TokenMatchI(buffer,"lastframe",9))		{
-				SkipSpaces(&buffer);
-				last = strtol10(buffer,&buffer);
-			}
-			else if (TokenMatchI(buffer,"rate",4))	{
-				SkipSpaces(&buffer);
-				float d;
-				buffer = fast_atoreal_move<float>(buffer,d);
-				anim->mTicksPerSecond = d;
-			}
-			else if (TokenMatchI(buffer,"order",5))	{
-				std::vector< aiNodeAnim* > anims_temp;
-				anims_temp.reserve(30);
-				while (1)	{
-					SkipSpaces(&buffer);
-					if (IsLineEnd(*buffer) && SkipSpacesAndLineEnd(&buffer) && *buffer == '$')
-						break; // next section
-
-					// Construct a new node animation channel and setup its name
-					anims_temp.push_back(new aiNodeAnim());
-					aiNodeAnim* nda = anims_temp.back();
-
-					char* ot = nda->mNodeName.data;
-					while (!IsSpaceOrNewLine(*buffer))
-						*ot++ = *buffer++;
-
-					*ot = '\0';
-					nda->mNodeName.length = (size_t)(ot-nda->mNodeName.data);
-				}
-
-				anim->mNumChannels = anims_temp.size();
-				if (!anim->mNumChannels)
-					throw DeadlyImportError("CSM: Empty $order section");
-
-				// copy over to the output animation
-				anim->mChannels = new aiNodeAnim*[anim->mNumChannels];
-				::memcpy(anim->mChannels,&anims_temp[0],sizeof(aiNodeAnim*)*anim->mNumChannels);
-			}
-			else if (TokenMatchI(buffer,"points",6))	{
-				if (!anim->mNumChannels)
-					throw DeadlyImportError("CSM: \'$order\' section is required to appear prior to \'$points\'");
-
-				// If we know how many frames we'll read, we can preallocate some storage
-				unsigned int alloc = 100;
-				if (last != 0x00ffffff)
-				{
-					alloc = last-first;
-					alloc += alloc>>2u; // + 25%
-					for (unsigned int i = 0; i < anim->mNumChannels;++i)
-						anim->mChannels[i]->mPositionKeys = new aiVectorKey[alloc];
-				}
-
-				unsigned int filled = 0;
-
-				// Now read all point data.
-				while (1)	{
-					SkipSpaces(&buffer);
-					if (IsLineEnd(*buffer) && (!SkipSpacesAndLineEnd(&buffer) || *buffer == '$'))	{
-						break; // next section
-					}
-
-					// read frame
-					const int frame = ::strtoul10(buffer,&buffer);
-					last  = std::max(frame,last);
-					first = std::min(frame,last);
-					for (unsigned int i = 0; i < anim->mNumChannels;++i)	{
-
-						aiNodeAnim* s = anim->mChannels[i];
-						if (s->mNumPositionKeys == alloc)	{ /* need to reallocate? */
-
-							aiVectorKey* old = s->mPositionKeys;
-							s->mPositionKeys = new aiVectorKey[s->mNumPositionKeys = alloc*2];
-							::memcpy(s->mPositionKeys,old,sizeof(aiVectorKey)*alloc);
-							delete[] old;
-						}
-
-						// read x,y,z
-						if(!SkipSpacesAndLineEnd(&buffer))
-							throw DeadlyImportError("CSM: Unexpected EOF occured reading sample x coord");
-
-						if (TokenMatchI(buffer, "DROPOUT", 7))	{
-							// seems this is invalid marker data; at least the doc says it's possible
-							DefaultLogger::get()->warn("CSM: Encountered invalid marker data (DROPOUT)");
-						}
-						else	{
-							aiVectorKey* sub = s->mPositionKeys + s->mNumPositionKeys;
-							sub->mTime = (double)frame;
-							buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.x);
-
-							if(!SkipSpacesAndLineEnd(&buffer))
-								throw DeadlyImportError("CSM: Unexpected EOF occured reading sample y coord");
-							buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.y);
-
-							if(!SkipSpacesAndLineEnd(&buffer))
-								throw DeadlyImportError("CSM: Unexpected EOF occured reading sample z coord");
-							buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.z);
-
-							++s->mNumPositionKeys;
-						}
-					}
-
-					// update allocation granularity
-					if (filled == alloc)
-						alloc *= 2;
-
-					++filled;
-				}
-				// all channels must be complete in order to continue safely.
-				for (unsigned int i = 0; i < anim->mNumChannels;++i)	{
-
-					if (!anim->mChannels[i]->mNumPositionKeys)
-						throw DeadlyImportError("CSM: Invalid marker track");
-				}
-			}
-		}
-		else	{
-			// advance to the next line
-			SkipLine(&buffer);
-		}
-	}
-
-	// Setup a proper animation duration
-	anim->mDuration = last - std::min( first, 0 );
-
-	// build a dummy root node with the tiny markers as children
-	pScene->mRootNode = new aiNode();
-	pScene->mRootNode->mName.Set("$CSM_DummyRoot");
-
-	pScene->mRootNode->mNumChildren = anim->mNumChannels;
-	pScene->mRootNode->mChildren = new aiNode* [anim->mNumChannels];
-
-	for (unsigned int i = 0; i < anim->mNumChannels;++i)	{
-		aiNodeAnim* na = anim->mChannels[i]; 
-
-		aiNode* nd  = pScene->mRootNode->mChildren[i] = new aiNode();
-		nd->mName   = anim->mChannels[i]->mNodeName;
-		nd->mParent = pScene->mRootNode;
-
-		aiMatrix4x4::Translation(na->mPositionKeys[0].mValue, nd->mTransformation);
-	}
-
-	// Store the one and only animation in the scene
-	pScene->mAnimations    = new aiAnimation*[pScene->mNumAnimations=1];
-	pScene->mAnimations[0] = anim;
-	anim->mName.Set("$CSM_MasterAnim");
-
-	// mark the scene as incomplete and run SkeletonMeshBuilder on it
-	pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
-	
-	if (!noSkeletonMesh) {
-		SkeletonMeshBuilder maker(pScene,pScene->mRootNode,true);
-	}
+    boost::scoped_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
+
+    // Check whether we can read from the file
+    if( file.get() == NULL) {
+        throw DeadlyImportError( "Failed to open CSM file " + pFile + ".");
+    }
+
+    // allocate storage and copy the contents of the file to a memory buffer
+    std::vector<char> mBuffer2;
+    TextFileToBuffer(file.get(),mBuffer2);
+    const char* buffer = &mBuffer2[0];
+
+    aiAnimation* anim = new aiAnimation();
+    int first = 0, last = 0x00ffffff;
+
+    // now process the file and look out for '$' sections
+    while (1)   {
+        SkipSpaces(&buffer);
+        if ('\0' == *buffer)
+            break;
+
+        if ('$'  == *buffer)    {
+            ++buffer;
+            if (TokenMatchI(buffer,"firstframe",10))    {
+                SkipSpaces(&buffer);
+                first = strtol10(buffer,&buffer);
+            }
+            else if (TokenMatchI(buffer,"lastframe",9))     {
+                SkipSpaces(&buffer);
+                last = strtol10(buffer,&buffer);
+            }
+            else if (TokenMatchI(buffer,"rate",4))  {
+                SkipSpaces(&buffer);
+                float d;
+                buffer = fast_atoreal_move<float>(buffer,d);
+                anim->mTicksPerSecond = d;
+            }
+            else if (TokenMatchI(buffer,"order",5)) {
+                std::vector< aiNodeAnim* > anims_temp;
+                anims_temp.reserve(30);
+                while (1)   {
+                    SkipSpaces(&buffer);
+                    if (IsLineEnd(*buffer) && SkipSpacesAndLineEnd(&buffer) && *buffer == '$')
+                        break; // next section
+
+                    // Construct a new node animation channel and setup its name
+                    anims_temp.push_back(new aiNodeAnim());
+                    aiNodeAnim* nda = anims_temp.back();
+
+                    char* ot = nda->mNodeName.data;
+                    while (!IsSpaceOrNewLine(*buffer))
+                        *ot++ = *buffer++;
+
+                    *ot = '\0';
+                    nda->mNodeName.length = (size_t)(ot-nda->mNodeName.data);
+                }
+
+                anim->mNumChannels = anims_temp.size();
+                if (!anim->mNumChannels)
+                    throw DeadlyImportError("CSM: Empty $order section");
+
+                // copy over to the output animation
+                anim->mChannels = new aiNodeAnim*[anim->mNumChannels];
+                ::memcpy(anim->mChannels,&anims_temp[0],sizeof(aiNodeAnim*)*anim->mNumChannels);
+            }
+            else if (TokenMatchI(buffer,"points",6))    {
+                if (!anim->mNumChannels)
+                    throw DeadlyImportError("CSM: \'$order\' section is required to appear prior to \'$points\'");
+
+                // If we know how many frames we'll read, we can preallocate some storage
+                unsigned int alloc = 100;
+                if (last != 0x00ffffff)
+                {
+                    alloc = last-first;
+                    alloc += alloc>>2u; // + 25%
+                    for (unsigned int i = 0; i < anim->mNumChannels;++i)
+                        anim->mChannels[i]->mPositionKeys = new aiVectorKey[alloc];
+                }
+
+                unsigned int filled = 0;
+
+                // Now read all point data.
+                while (1)   {
+                    SkipSpaces(&buffer);
+                    if (IsLineEnd(*buffer) && (!SkipSpacesAndLineEnd(&buffer) || *buffer == '$'))   {
+                        break; // next section
+                    }
+
+                    // read frame
+                    const int frame = ::strtoul10(buffer,&buffer);
+                    last  = std::max(frame,last);
+                    first = std::min(frame,last);
+                    for (unsigned int i = 0; i < anim->mNumChannels;++i)    {
+
+                        aiNodeAnim* s = anim->mChannels[i];
+                        if (s->mNumPositionKeys == alloc)   { /* need to reallocate? */
+
+                            aiVectorKey* old = s->mPositionKeys;
+                            s->mPositionKeys = new aiVectorKey[s->mNumPositionKeys = alloc*2];
+                            ::memcpy(s->mPositionKeys,old,sizeof(aiVectorKey)*alloc);
+                            delete[] old;
+                        }
+
+                        // read x,y,z
+                        if(!SkipSpacesAndLineEnd(&buffer))
+                            throw DeadlyImportError("CSM: Unexpected EOF occured reading sample x coord");
+
+                        if (TokenMatchI(buffer, "DROPOUT", 7))  {
+                            // seems this is invalid marker data; at least the doc says it's possible
+                            DefaultLogger::get()->warn("CSM: Encountered invalid marker data (DROPOUT)");
+                        }
+                        else    {
+                            aiVectorKey* sub = s->mPositionKeys + s->mNumPositionKeys;
+                            sub->mTime = (double)frame;
+                            buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.x);
+
+                            if(!SkipSpacesAndLineEnd(&buffer))
+                                throw DeadlyImportError("CSM: Unexpected EOF occured reading sample y coord");
+                            buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.y);
+
+                            if(!SkipSpacesAndLineEnd(&buffer))
+                                throw DeadlyImportError("CSM: Unexpected EOF occured reading sample z coord");
+                            buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.z);
+
+                            ++s->mNumPositionKeys;
+                        }
+                    }
+
+                    // update allocation granularity
+                    if (filled == alloc)
+                        alloc *= 2;
+
+                    ++filled;
+                }
+                // all channels must be complete in order to continue safely.
+                for (unsigned int i = 0; i < anim->mNumChannels;++i)    {
+
+                    if (!anim->mChannels[i]->mNumPositionKeys)
+                        throw DeadlyImportError("CSM: Invalid marker track");
+                }
+            }
+        }
+        else    {
+            // advance to the next line
+            SkipLine(&buffer);
+        }
+    }
+
+    // Setup a proper animation duration
+    anim->mDuration = last - std::min( first, 0 );
+
+    // build a dummy root node with the tiny markers as children
+    pScene->mRootNode = new aiNode();
+    pScene->mRootNode->mName.Set("$CSM_DummyRoot");
+
+    pScene->mRootNode->mNumChildren = anim->mNumChannels;
+    pScene->mRootNode->mChildren = new aiNode* [anim->mNumChannels];
+
+    for (unsigned int i = 0; i < anim->mNumChannels;++i)    {
+        aiNodeAnim* na = anim->mChannels[i];
+
+        aiNode* nd  = pScene->mRootNode->mChildren[i] = new aiNode();
+        nd->mName   = anim->mChannels[i]->mNodeName;
+        nd->mParent = pScene->mRootNode;
+
+        aiMatrix4x4::Translation(na->mPositionKeys[0].mValue, nd->mTransformation);
+    }
+
+    // Store the one and only animation in the scene
+    pScene->mAnimations    = new aiAnimation*[pScene->mNumAnimations=1];
+    pScene->mAnimations[0] = anim;
+    anim->mName.Set("$CSM_MasterAnim");
+
+    // mark the scene as incomplete and run SkeletonMeshBuilder on it
+    pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
+
+    if (!noSkeletonMesh) {
+        SkeletonMeshBuilder maker(pScene,pScene->mRootNode,true);
+    }
 }
 
 #endif // !! ASSIMP_BUILD_NO_CSM_IMPORTER

+ 27 - 24
assimplib.mod/assimp/code/CSMLoader.h

@@ -2,11 +2,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -23,16 +23,16 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -43,7 +43,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #ifndef INCLUDED_AI_CSM_LOADER_H
 #define INCLUDED_AI_CSM_LOADER_H
-namespace Assimp	{
+
+#include "BaseImporter.h"
+
+namespace Assimp    {
 
 // ---------------------------------------------------------------------------
 /** Importer class to load MOCAPs in CharacterStudio Motion format.
@@ -57,30 +60,30 @@ namespace Assimp	{
 class CSMImporter : public BaseImporter
 {
 public:
-	CSMImporter();
-	~CSMImporter();
+    CSMImporter();
+    ~CSMImporter();
 
 
 public:
-	// -------------------------------------------------------------------
-	bool CanRead( const std::string& pFile, IOSystem* pIOHandler, 
-		bool checkSig) const;
+    // -------------------------------------------------------------------
+    bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+        bool checkSig) const;
 
 protected:
 
-	// -------------------------------------------------------------------
-	const aiImporterDesc* GetInfo () const;
+    // -------------------------------------------------------------------
+    const aiImporterDesc* GetInfo () const;
 
-	// -------------------------------------------------------------------
-	void SetupProperties(const Importer* pImp);
+    // -------------------------------------------------------------------
+    void SetupProperties(const Importer* pImp);
 
-	// -------------------------------------------------------------------
-	void InternReadFile( const std::string& pFile, aiScene* pScene, 
-		IOSystem* pIOHandler);
+    // -------------------------------------------------------------------
+    void InternReadFile( const std::string& pFile, aiScene* pScene,
+        IOSystem* pIOHandler);
 
 private:
 
-	bool noSkeletonMesh;
+    bool noSkeletonMesh;
 
 }; // end of class CSMImporter
 } // end of namespace Assimp

+ 196 - 197
assimplib.mod/assimp/code/CalcTangentsProcess.cpp

@@ -3,12 +3,12 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -25,30 +25,29 @@ conditions are met:
   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 
+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 
+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 
+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 
+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 Implementation of the post processing step to calculate 
+/** @file Implementation of the post processing step to calculate
  *  tangents and bitangents for all imported meshes
  */
 
-#include "AssimpPCH.h"
-
 // internal headers
 #include "CalcTangentsProcess.h"
 #include "ProcessHelper.h"
 #include "TinyFormatter.h"
+#include "qnan.h"
 
 using namespace Assimp;
 
@@ -57,21 +56,21 @@ using namespace Assimp;
 CalcTangentsProcess::CalcTangentsProcess()
 : configMaxAngle( AI_DEG_TO_RAD(45.f) )
 , configSourceUV( 0 ) {
-	// nothing to do here
+    // nothing to do here
 }
 
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 CalcTangentsProcess::~CalcTangentsProcess()
 {
-	// nothing to do here
+    // nothing to do here
 }
 
 // ------------------------------------------------------------------------------------------------
 // Returns whether the processing step is present in the given flag field.
 bool CalcTangentsProcess::IsActive( unsigned int pFlags) const
 {
-	return (pFlags & aiProcess_CalcTangentSpace) != 0;
+    return (pFlags & aiProcess_CalcTangentSpace) != 0;
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -80,12 +79,12 @@ void CalcTangentsProcess::SetupProperties(const Importer* pImp)
 {
     ai_assert( NULL != pImp );
 
-	// get the current value of the property
-	configMaxAngle = pImp->GetPropertyFloat(AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE,45.f);
-	configMaxAngle = std::max(std::min(configMaxAngle,45.0f),0.0f);
-	configMaxAngle = AI_DEG_TO_RAD(configMaxAngle);
+    // get the current value of the property
+    configMaxAngle = pImp->GetPropertyFloat(AI_CONFIG_PP_CT_MAX_SMOOTHING_ANGLE,45.f);
+    configMaxAngle = std::max(std::min(configMaxAngle,45.0f),0.0f);
+    configMaxAngle = AI_DEG_TO_RAD(configMaxAngle);
 
-	configSourceUV = pImp->GetPropertyInteger(AI_CONFIG_PP_CT_TEXTURE_CHANNEL_INDEX,0);
+    configSourceUV = pImp->GetPropertyInteger(AI_CONFIG_PP_CT_TEXTURE_CHANNEL_INDEX,0);
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -96,12 +95,12 @@ void CalcTangentsProcess::Execute( aiScene* pScene)
 
     DefaultLogger::get()->debug("CalcTangentsProcess begin");
 
-	bool bHas = false;
-	for ( unsigned int a = 0; a < pScene->mNumMeshes; a++ ) {
-		if(ProcessMesh( pScene->mMeshes[a],a))bHas = true;
+    bool bHas = false;
+    for ( unsigned int a = 0; a < pScene->mNumMeshes; a++ ) {
+        if(ProcessMesh( pScene->mMeshes[a],a))bHas = true;
     }
 
-	if ( bHas ) {
+    if ( bHas ) {
         DefaultLogger::get()->info("CalcTangentsProcess finished. Tangents have been calculated");
     } else {
         DefaultLogger::get()->debug("CalcTangentsProcess finished");
@@ -112,106 +111,106 @@ void CalcTangentsProcess::Execute( aiScene* pScene)
 // Calculates tangents and bitangents for the given mesh
 bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
 {
-	// we assume that the mesh is still in the verbose vertex format where each face has its own set
-	// of vertices and no vertices are shared between faces. Sadly I don't know any quick test to 
-	// assert() it here.
-    //assert( must be verbose, dammit);
-
-	if (pMesh->mTangents) // thisimplies that mBitangents is also there
-		return false;
-
-	// If the mesh consists of lines and/or points but not of
-	// triangles or higher-order polygons the normal vectors
-	// are undefined.
-	if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON)))
-	{
-		DefaultLogger::get()->info("Tangents are undefined for line and point meshes");
-		return false;
-	}
-
-	// what we can check, though, is if the mesh has normals and texture coordinates. That's a requirement
-	if( pMesh->mNormals == NULL)
-	{
-		DefaultLogger::get()->error("Failed to compute tangents; need normals");
-		return false;
-	}
-	if( configSourceUV >= AI_MAX_NUMBER_OF_TEXTURECOORDS || !pMesh->mTextureCoords[configSourceUV] )
-	{
-		DefaultLogger::get()->error((Formatter::format("Failed to compute tangents; need UV data in channel"),configSourceUV));
-		return false;
-	}
-	 
-	const float angleEpsilon = 0.9999f;
-
-	std::vector<bool> vertexDone( pMesh->mNumVertices, false);
-	const float qnan = get_qnan();
-
-	// create space for the tangents and bitangents
-	pMesh->mTangents = new aiVector3D[pMesh->mNumVertices];
-	pMesh->mBitangents = new aiVector3D[pMesh->mNumVertices];
-
-	const aiVector3D* meshPos = pMesh->mVertices;
-	const aiVector3D* meshNorm = pMesh->mNormals;
-	const aiVector3D* meshTex = pMesh->mTextureCoords[configSourceUV];
-	aiVector3D* meshTang = pMesh->mTangents;
-	aiVector3D* meshBitang = pMesh->mBitangents;
-	
-	// calculate the tangent and bitangent for every face
-	for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
-	{
-		const aiFace& face = pMesh->mFaces[a];
-		if (face.mNumIndices < 3)
-		{
-			// There are less than three indices, thus the tangent vector
-			// is not defined. We are finished with these vertices now,
-			// their tangent vectors are set to qnan.
-			for (unsigned int i = 0; i < face.mNumIndices;++i)
-			{
-				register unsigned int idx = face.mIndices[i];
-				vertexDone  [idx] = true;
-				meshTang    [idx] = aiVector3D(qnan);
-				meshBitang  [idx] = aiVector3D(qnan);
-			}
-
-			continue;
-		}
-
-		// triangle or polygon... we always use only the first three indices. A polygon
-		// is supposed to be planar anyways....
-		// FIXME: (thom) create correct calculation for multi-vertex polygons maybe?
-		const unsigned int p0 = face.mIndices[0], p1 = face.mIndices[1], p2 = face.mIndices[2];
-
-		// position differences p1->p2 and p1->p3
-		aiVector3D v = meshPos[p1] - meshPos[p0], w = meshPos[p2] - meshPos[p0];
-
-		// texture offset p1->p2 and p1->p3
-		float sx = meshTex[p1].x - meshTex[p0].x, sy = meshTex[p1].y - meshTex[p0].y;
+    // we assume that the mesh is still in the verbose vertex format where each face has its own set
+    // of vertices and no vertices are shared between faces. Sadly I don't know any quick test to
+    // assert() it here.
+    // assert( must be verbose, dammit);
+
+    if (pMesh->mTangents) // this implies that mBitangents is also there
+        return false;
+
+    // If the mesh consists of lines and/or points but not of
+    // triangles or higher-order polygons the normal vectors
+    // are undefined.
+    if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON)))
+    {
+        DefaultLogger::get()->info("Tangents are undefined for line and point meshes");
+        return false;
+    }
+
+    // what we can check, though, is if the mesh has normals and texture coordinates. That's a requirement
+    if( pMesh->mNormals == NULL)
+    {
+        DefaultLogger::get()->error("Failed to compute tangents; need normals");
+        return false;
+    }
+    if( configSourceUV >= AI_MAX_NUMBER_OF_TEXTURECOORDS || !pMesh->mTextureCoords[configSourceUV] )
+    {
+        DefaultLogger::get()->error((Formatter::format("Failed to compute tangents; need UV data in channel"),configSourceUV));
+        return false;
+    }
+
+    const float angleEpsilon = 0.9999f;
+
+    std::vector<bool> vertexDone( pMesh->mNumVertices, false);
+    const float qnan = get_qnan();
+
+    // create space for the tangents and bitangents
+    pMesh->mTangents = new aiVector3D[pMesh->mNumVertices];
+    pMesh->mBitangents = new aiVector3D[pMesh->mNumVertices];
+
+    const aiVector3D* meshPos = pMesh->mVertices;
+    const aiVector3D* meshNorm = pMesh->mNormals;
+    const aiVector3D* meshTex = pMesh->mTextureCoords[configSourceUV];
+    aiVector3D* meshTang = pMesh->mTangents;
+    aiVector3D* meshBitang = pMesh->mBitangents;
+
+    // calculate the tangent and bitangent for every face
+    for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
+    {
+        const aiFace& face = pMesh->mFaces[a];
+        if (face.mNumIndices < 3)
+        {
+            // There are less than three indices, thus the tangent vector
+            // is not defined. We are finished with these vertices now,
+            // their tangent vectors are set to qnan.
+            for (unsigned int i = 0; i < face.mNumIndices;++i)
+            {
+                unsigned int idx = face.mIndices[i];
+                vertexDone  [idx] = true;
+                meshTang    [idx] = aiVector3D(qnan);
+                meshBitang  [idx] = aiVector3D(qnan);
+            }
+
+            continue;
+        }
+
+        // triangle or polygon... we always use only the first three indices. A polygon
+        // is supposed to be planar anyways....
+        // FIXME: (thom) create correct calculation for multi-vertex polygons maybe?
+        const unsigned int p0 = face.mIndices[0], p1 = face.mIndices[1], p2 = face.mIndices[2];
+
+        // position differences p1->p2 and p1->p3
+        aiVector3D v = meshPos[p1] - meshPos[p0], w = meshPos[p2] - meshPos[p0];
+
+        // texture offset p1->p2 and p1->p3
+        float sx = meshTex[p1].x - meshTex[p0].x, sy = meshTex[p1].y - meshTex[p0].y;
         float tx = meshTex[p2].x - meshTex[p0].x, ty = meshTex[p2].y - meshTex[p0].y;
-		float dirCorrection = (tx * sy - ty * sx) < 0.0f ? -1.0f : 1.0f;
+        float dirCorrection = (tx * sy - ty * sx) < 0.0f ? -1.0f : 1.0f;
         // when t1, t2, t3 in same position in UV space, just use default UV direction.
         if ( 0 == sx && 0 ==sy && 0 == tx && 0 == ty ) {
             sx = 0.0; sy = 1.0;
             tx = 1.0; ty = 0.0;
         }
 
-		// tangent points in the direction where to positive X axis of the texture coord's would point in model space
-		// bitangent's points along the positive Y axis of the texture coord's, respectively
-		aiVector3D tangent, bitangent;
-		tangent.x = (w.x * sy - v.x * ty) * dirCorrection;
+        // tangent points in the direction where to positive X axis of the texture coord's would point in model space
+        // bitangent's points along the positive Y axis of the texture coord's, respectively
+        aiVector3D tangent, bitangent;
+        tangent.x = (w.x * sy - v.x * ty) * dirCorrection;
         tangent.y = (w.y * sy - v.y * ty) * dirCorrection;
         tangent.z = (w.z * sy - v.z * ty) * dirCorrection;
         bitangent.x = (w.x * sx - v.x * tx) * dirCorrection;
         bitangent.y = (w.y * sx - v.y * tx) * dirCorrection;
         bitangent.z = (w.z * sx - v.z * tx) * dirCorrection;
 
-		// store for every vertex of that face
-		for( unsigned int b = 0; b < face.mNumIndices; ++b ) {
-			unsigned int p = face.mIndices[b];
+        // store for every vertex of that face
+        for( unsigned int b = 0; b < face.mNumIndices; ++b ) {
+            unsigned int p = face.mIndices[b];
 
-			// project tangent and bitangent into the plane formed by the vertex' normal
-			aiVector3D localTangent = tangent - meshNorm[p] * (tangent * meshNorm[p]);
-			aiVector3D localBitangent = bitangent - meshNorm[p] * (bitangent * meshNorm[p]);
-			localTangent.Normalize(); localBitangent.Normalize();
+            // project tangent and bitangent into the plane formed by the vertex' normal
+            aiVector3D localTangent = tangent - meshNorm[p] * (tangent * meshNorm[p]);
+            aiVector3D localBitangent = bitangent - meshNorm[p] * (bitangent * meshNorm[p]);
+            localTangent.Normalize(); localBitangent.Normalize();
 
             // reconstruct tangent/bitangent according to normal and bitangent/tangent when it's infinite or NaN.
             bool invalid_tangent = is_special_float(localTangent.x) || is_special_float(localTangent.y) || is_special_float(localTangent.z);
@@ -221,98 +220,98 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
                     localTangent = meshNorm[p] ^ localBitangent;
                     localTangent.Normalize();
                 } else {
-                    localBitangent = localTangent ^ meshNorm[p]; 
+                    localBitangent = localTangent ^ meshNorm[p];
                     localBitangent.Normalize();
                 }
             }
 
             // and write it into the mesh.
-			meshTang[ p ]   = localTangent;
-			meshBitang[ p ] = localBitangent;
-		}
+            meshTang[ p ]   = localTangent;
+            meshBitang[ p ] = localBitangent;
+        }
     }
 
 
-	// create a helper to quickly find locally close vertices among the vertex array
-	// FIX: check whether we can reuse the SpatialSort of a previous step
-	SpatialSort* vertexFinder = NULL;
-	SpatialSort  _vertexFinder;
-	float posEpsilon;
-	if (shared)
-	{
-		std::vector<std::pair<SpatialSort,float> >* avf;
-		shared->GetProperty(AI_SPP_SPATIAL_SORT,avf);
-		if (avf)
-		{
-			std::pair<SpatialSort,float>& blubb = avf->operator [] (meshIndex);
-			vertexFinder = &blubb.first;
-			posEpsilon = blubb.second;;
-		}
-	}
-	if (!vertexFinder)
-	{
-		_vertexFinder.Fill(pMesh->mVertices, pMesh->mNumVertices, sizeof( aiVector3D));
-		vertexFinder = &_vertexFinder;
-		posEpsilon = ComputePositionEpsilon(pMesh);
-	}
-	std::vector<unsigned int> verticesFound;
-
-	const float fLimit = cosf(configMaxAngle); 
-	std::vector<unsigned int> closeVertices;
-
-	// in the second pass we now smooth out all tangents and bitangents at the same local position 
-	// if they are not too far off.
-	for( unsigned int a = 0; a < pMesh->mNumVertices; a++)
-	{
-		if( vertexDone[a])
-			continue;
-
-		const aiVector3D& origPos = pMesh->mVertices[a];
-		const aiVector3D& origNorm = pMesh->mNormals[a];
-		const aiVector3D& origTang = pMesh->mTangents[a];
-		const aiVector3D& origBitang = pMesh->mBitangents[a];
-		closeVertices.clear();
-
-		// find all vertices close to that position
-		vertexFinder->FindPositions( origPos, posEpsilon, verticesFound);
-
-		closeVertices.reserve (verticesFound.size()+5);
-		closeVertices.push_back( a);
-
-		// look among them for other vertices sharing the same normal and a close-enough tangent/bitangent
-		for( unsigned int b = 0; b < verticesFound.size(); b++)
-		{
-			unsigned int idx = verticesFound[b];
-			if( vertexDone[idx])
-				continue;
-			if( meshNorm[idx] * origNorm < angleEpsilon)
-				continue;
-			if(  meshTang[idx] * origTang < fLimit)
-				continue;
-			if( meshBitang[idx] * origBitang < fLimit)
-				continue;
-
-			// it's similar enough -> add it to the smoothing group
-			closeVertices.push_back( idx);
-			vertexDone[idx] = true;
-		}
-
-		// smooth the tangents and bitangents of all vertices that were found to be close enough
-		aiVector3D smoothTangent( 0, 0, 0), smoothBitangent( 0, 0, 0);
-		for( unsigned int b = 0; b < closeVertices.size(); ++b)
-		{
-			smoothTangent += meshTang[ closeVertices[b] ];
-			smoothBitangent += meshBitang[ closeVertices[b] ];
-		}
-		smoothTangent.Normalize();
-		smoothBitangent.Normalize();
-
-		// and write it back into all affected tangents
-		for( unsigned int b = 0; b < closeVertices.size(); ++b)
-		{
-			meshTang[ closeVertices[b] ] = smoothTangent;
-			meshBitang[ closeVertices[b] ] = smoothBitangent;
-		}
-	}
-	return true;
+    // create a helper to quickly find locally close vertices among the vertex array
+    // FIX: check whether we can reuse the SpatialSort of a previous step
+    SpatialSort* vertexFinder = NULL;
+    SpatialSort  _vertexFinder;
+    float posEpsilon;
+    if (shared)
+    {
+        std::vector<std::pair<SpatialSort,float> >* avf;
+        shared->GetProperty(AI_SPP_SPATIAL_SORT,avf);
+        if (avf)
+        {
+            std::pair<SpatialSort,float>& blubb = avf->operator [] (meshIndex);
+            vertexFinder = &blubb.first;
+            posEpsilon = blubb.second;;
+        }
+    }
+    if (!vertexFinder)
+    {
+        _vertexFinder.Fill(pMesh->mVertices, pMesh->mNumVertices, sizeof( aiVector3D));
+        vertexFinder = &_vertexFinder;
+        posEpsilon = ComputePositionEpsilon(pMesh);
+    }
+    std::vector<unsigned int> verticesFound;
+
+    const float fLimit = cosf(configMaxAngle);
+    std::vector<unsigned int> closeVertices;
+
+    // in the second pass we now smooth out all tangents and bitangents at the same local position
+    // if they are not too far off.
+    for( unsigned int a = 0; a < pMesh->mNumVertices; a++)
+    {
+        if( vertexDone[a])
+            continue;
+
+        const aiVector3D& origPos = pMesh->mVertices[a];
+        const aiVector3D& origNorm = pMesh->mNormals[a];
+        const aiVector3D& origTang = pMesh->mTangents[a];
+        const aiVector3D& origBitang = pMesh->mBitangents[a];
+        closeVertices.resize( 0 );
+
+        // find all vertices close to that position
+        vertexFinder->FindPositions( origPos, posEpsilon, verticesFound);
+
+        closeVertices.reserve (verticesFound.size()+5);
+        closeVertices.push_back( a);
+
+        // look among them for other vertices sharing the same normal and a close-enough tangent/bitangent
+        for( unsigned int b = 0; b < verticesFound.size(); b++)
+        {
+            unsigned int idx = verticesFound[b];
+            if( vertexDone[idx])
+                continue;
+            if( meshNorm[idx] * origNorm < angleEpsilon)
+                continue;
+            if(  meshTang[idx] * origTang < fLimit)
+                continue;
+            if( meshBitang[idx] * origBitang < fLimit)
+                continue;
+
+            // it's similar enough -> add it to the smoothing group
+            closeVertices.push_back( idx);
+            vertexDone[idx] = true;
+        }
+
+        // smooth the tangents and bitangents of all vertices that were found to be close enough
+        aiVector3D smoothTangent( 0, 0, 0), smoothBitangent( 0, 0, 0);
+        for( unsigned int b = 0; b < closeVertices.size(); ++b)
+        {
+            smoothTangent += meshTang[ closeVertices[b] ];
+            smoothBitangent += meshBitang[ closeVertices[b] ];
+        }
+        smoothTangent.Normalize();
+        smoothBitangent.Normalize();
+
+        // and write it back into all affected tangents
+        for( unsigned int b = 0; b < closeVertices.size(); ++b)
+        {
+            meshTang[ closeVertices[b] ] = smoothTangent;
+            meshBitang[ closeVertices[b] ] = smoothBitangent;
+        }
+    }
+    return true;
 }

+ 50 - 50
assimplib.mod/assimp/code/CalcTangentsProcess.h

@@ -2,11 +2,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -23,23 +23,23 @@ following conditions are met:
   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 
+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 
+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 
+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 
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ----------------------------------------------------------------------
 */
 
 
-/** @file Defines a post processing step to calculate tangents and 
+/** @file Defines a post processing step to calculate tangents and
     bitangents on all imported meshes.*/
 #ifndef AI_CALCTANGENTSPROCESS_H_INC
 #define AI_CALCTANGENTSPROCESS_H_INC
@@ -54,60 +54,60 @@ namespace Assimp
 // ---------------------------------------------------------------------------
 /** The CalcTangentsProcess calculates the tangent and bitangent for any vertex
  * of all meshes. It is expected to be run before the JoinVerticesProcess runs
- * because the joining of vertices also considers tangents and bitangents for 
+ * because the joining of vertices also considers tangents and bitangents for
  * uniqueness.
  */
 class ASSIMP_API_WINONLY CalcTangentsProcess : public BaseProcess
 {
 public:
 
-	CalcTangentsProcess();
-	~CalcTangentsProcess();
+    CalcTangentsProcess();
+    ~CalcTangentsProcess();
 
 public:
-	// -------------------------------------------------------------------
-	/** Returns whether the processing step is present in the given flag.
-	* @param pFlags The processing flags the importer was called with.
-	*   A bitwise combination of #aiPostProcessSteps.
-	* @return true if the process is present in this flag fields,
-	*   false if not.
-	*/
-	bool IsActive( unsigned int pFlags) const;
-
-	// -------------------------------------------------------------------
-	/** Called prior to ExecuteOnScene().
-	* The function is a request to the process to update its configuration
-	* basing on the Importer's configuration property list.
-	*/
-	void SetupProperties(const Importer* pImp);
-
-
-	// setter for configMaxAngle
-	inline void SetMaxSmoothAngle(float f)
-	{
-		configMaxAngle =f;
-	}
+    // -------------------------------------------------------------------
+    /** Returns whether the processing step is present in the given flag.
+    * @param pFlags The processing flags the importer was called with.
+    *   A bitwise combination of #aiPostProcessSteps.
+    * @return true if the process is present in this flag fields,
+    *   false if not.
+    */
+    bool IsActive( unsigned int pFlags) const;
+
+    // -------------------------------------------------------------------
+    /** Called prior to ExecuteOnScene().
+    * The function is a request to the process to update its configuration
+    * basing on the Importer's configuration property list.
+    */
+    void SetupProperties(const Importer* pImp);
+
+
+    // setter for configMaxAngle
+    inline void SetMaxSmoothAngle(float f)
+    {
+        configMaxAngle =f;
+    }
 
 protected:
 
-	// -------------------------------------------------------------------
-	/** Calculates tangents and bitangents for a specific mesh.
-	* @param pMesh The mesh to process.
-	* @param meshIndex Index of the mesh
-	*/
-	bool ProcessMesh( aiMesh* pMesh, unsigned int meshIndex);
+    // -------------------------------------------------------------------
+    /** Calculates tangents and bitangents for a specific mesh.
+    * @param pMesh The mesh to process.
+    * @param meshIndex Index of the mesh
+    */
+    bool ProcessMesh( aiMesh* pMesh, unsigned int meshIndex);
 
-	// -------------------------------------------------------------------
-	/** Executes the post processing step on the given imported data.
-	* @param pScene The imported data to work at.
-	*/
-	void Execute( aiScene* pScene);
+    // -------------------------------------------------------------------
+    /** Executes the post processing step on the given imported data.
+    * @param pScene The imported data to work at.
+    */
+    void Execute( aiScene* pScene);
 
 private:
 
-	/** Configuration option: maximum smoothing angle, in radians*/
-	float configMaxAngle;
-	unsigned int configSourceUV;
+    /** Configuration option: maximum smoothing angle, in radians*/
+    float configMaxAngle;
+    unsigned int configSourceUV;
 };
 
 } // end of namespace Assimp

+ 750 - 480
assimplib.mod/assimp/code/ColladaExporter.cpp

@@ -2,11 +2,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -23,22 +23,22 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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 "AssimpPCH.h"
+
 
 #ifndef ASSIMP_BUILD_NO_EXPORT
 #ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER
@@ -46,8 +46,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include "Bitmap.h"
 #include "fast_atof.h"
-#include "SceneCombiner.h" 
+#include "SceneCombiner.h"
+#include "DefaultIOSystem.h"
+#include "XMLTools.h"
+#include "../include/assimp/IOSystem.hpp"
+#include "../include/assimp/Exporter.hpp"
+#include "../include/assimp/scene.h"
+
+#include "Exceptional.h"
 
+#include <boost/scoped_ptr.hpp>
 #include <ctime>
 #include <set>
 
@@ -58,222 +66,419 @@ 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)
+void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
 {
-	std::string path = "";
-	std::string file = pFile;
-
-	// We need to test both types of folder separators because pIOSystem->getOsSeparator() is not reliable.
-	// Moreover, the path given by some applications is not even consistent with the OS specific type of separator.
-	const char* end_path = std::max(strrchr(pFile, '\\'), strrchr(pFile, '/'));
-
-	if(end_path != NULL) {
-		path = std::string(pFile, end_path + 1 - pFile);
-		file = file.substr(end_path + 1 - pFile, file.npos);
-
-		std::size_t pos = file.find_last_of('.');
-		if(pos != file.npos) {
-			file = file.substr(0, pos);
-		}
-	}
-
-	// invoke the exporter 
-	ColladaExporter iDoTheExportThing( pScene, pIOSystem, path, file);
-
-	// we're still here - export successfully completed. Write result to the given IOSYstem
-	boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
-	if(outfile == NULL) {
-		throw DeadlyExportError("could not open output .dae file: " + std::string(pFile));
-	}
-
-	// XXX maybe use a small wrapper around IOStream that behaves like std::stringstream in order to avoid the extra copy.
-	outfile->Write( iDoTheExportThing.mOutput.str().c_str(), static_cast<size_t>(iDoTheExportThing.mOutput.tellp()),1);
+    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);
+
+    // we're still here - export successfully completed. Write result to the given IOSYstem
+    boost::scoped_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
+    if(outfile == NULL) {
+        throw DeadlyExportError("could not open output .dae file: " + std::string(pFile));
+    }
+
+    // XXX maybe use a small wrapper around IOStream that behaves like std::stringstream in order to avoid the extra copy.
+    outfile->Write( iDoTheExportThing.mOutput.str().c_str(), static_cast<size_t>(iDoTheExportThing.mOutput.tellp()),1);
 }
 
 } // end of namespace Assimp
 
 
+
 // ------------------------------------------------------------------------------------------------
 // Constructor for a specific scene to export
 ColladaExporter::ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file) : mIOSystem(pIOSystem), mPath(path), mFile(file)
 {
-	// make sure that all formatting happens using the standard, C locale and not the user's current locale
-	mOutput.imbue( std::locale("C") );
+    // make sure that all formatting happens using the standard, C locale and not the user's current locale
+    mOutput.imbue( std::locale("C") );
 
-	mScene = pScene;
-	mSceneOwned = false;
+    mScene = pScene;
+    mSceneOwned = false;
 
-	// set up strings
-	endstr = "\n"; 
+    // set up strings
+    endstr = "\n";
 
-	// start writing
-	WriteFile();
+    // start writing
+    WriteFile();
 }
 
 // ------------------------------------------------------------------------------------------------
 // Destructor
 ColladaExporter::~ColladaExporter()
 {
-	if(mSceneOwned) {
-		delete mScene;
-	}
+    if(mSceneOwned) {
+        delete mScene;
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 // Starts writing the contents
 void ColladaExporter::WriteFile()
 {
-	// write the DTD
-	mOutput << "<?xml version=\"1.0\"?>" << endstr;
-	// COLLADA element start
-	mOutput << "<COLLADA xmlns=\"http://www.collada.org/2005/11/COLLADASchema\" version=\"1.4.1\">" << endstr;
-	PushTag();
-
-	WriteTextures();
-	WriteHeader();
-
-	WriteMaterials();
-	WriteGeometryLibrary();
-
-	WriteSceneLibrary();
-
-	// useless Collada fu at the end, just in case we haven't had enough indirections, yet. 
-	mOutput << startstr << "<scene>" << endstr;
-	PushTag();
-	mOutput << startstr << "<instance_visual_scene url=\"#" + std::string(mScene->mRootNode->mName.C_Str()) + "\" />" << endstr;
-	PopTag();
-	mOutput << startstr << "</scene>" << endstr;
-	PopTag();
-	mOutput << "</COLLADA>" << endstr;
+    // write the DTD
+    mOutput << "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>" << endstr;
+    // COLLADA element start
+    mOutput << "<COLLADA xmlns=\"http://www.collada.org/2005/11/COLLADASchema\" version=\"1.4.1\">" << endstr;
+    PushTag();
+
+    WriteTextures();
+    WriteHeader();
+
+    WriteCamerasLibrary();
+    WriteLightsLibrary();
+    WriteMaterials();
+    WriteGeometryLibrary();
+
+    WriteSceneLibrary();
+
+    // useless Collada fu at the end, just in case we haven't had enough indirections, yet.
+    mOutput << startstr << "<scene>" << endstr;
+    PushTag();
+    mOutput << startstr << "<instance_visual_scene url=\"#" + XMLEscape(mScene->mRootNode->mName.C_Str()) + "\" />" << endstr;
+    PopTag();
+    mOutput << startstr << "</scene>" << endstr;
+    PopTag();
+    mOutput << "</COLLADA>" << endstr;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Writes the asset header
 void ColladaExporter::WriteHeader()
 {
-	static const float epsilon = 0.000001f;
-	static const aiQuaternion x_rot(aiMatrix3x3( 
-		0, -1,  0,
-		1,  0,  0,
-		0,  0,  1));
-	static const aiQuaternion y_rot(aiMatrix3x3(
-		1,  0,  0,
-		0,  1,  0,
-		0,  0,  1));
-	static const aiQuaternion z_rot(aiMatrix3x3(
-		1,  0,  0,
-		0,  0,  1,
-		0, -1,  0));
-
-	static const unsigned int date_nb_chars = 20;
-	char date_str[date_nb_chars];
-	std::time_t date = std::time(NULL);
-	std::strftime(date_str, date_nb_chars, "%Y-%m-%dT%H:%M:%S", std::localtime(&date));
-
-	std::string scene_name = mScene->mRootNode->mName.C_Str();
-
-	aiVector3D scaling;
-	aiQuaternion rotation;
-	aiVector3D position;
-	mScene->mRootNode->mTransformation.Decompose(scaling, rotation, position);
-
-	bool add_root_node = false;
-
-	float scale = 1.0;
-	if(std::abs(scaling.x - scaling.y) <= epsilon && std::abs(scaling.x - scaling.z) <= epsilon && std::abs(scaling.y - scaling.z) <= epsilon) {
-		scale = (float) ((((double) scaling.x) + ((double) scaling.y) + ((double) scaling.z)) / 3.0);
-	} else {
-		add_root_node = true;
-	}
-
-	std::string up_axis = "Y_UP";
-	if(rotation.Equal(x_rot, epsilon)) {
-		up_axis = "X_UP";
-	} else if(rotation.Equal(y_rot, epsilon)) {
-		up_axis = "Y_UP";
-	} else if(rotation.Equal(z_rot, epsilon)) {
-		up_axis = "Z_UP";
-	} else {
-		add_root_node = true;
-	}
-
-	if(! position.Equal(aiVector3D(0, 0, 0))) {
-		add_root_node = true;
-	}
-
-	if(mScene->mRootNode->mNumChildren == 0) {
-		add_root_node = true;
-	}
-
-	if(add_root_node) {
-		aiScene* scene;
-		SceneCombiner::CopyScene(&scene, mScene);
-
-		aiNode* root = new aiNode("Scene");
-
-		root->mNumChildren = 1;
-		root->mChildren = new aiNode*[root->mNumChildren];
-
-		root->mChildren[0] = scene->mRootNode;
-		scene->mRootNode->mParent = root;
-		scene->mRootNode = root;
-
-		mScene = scene;
-		mSceneOwned = true;
-
-		up_axis = "Y_UP";
-		scale = 1.0;
-	}
-
-	mOutput << startstr << "<asset>" << endstr;
-	PushTag();
-	mOutput << startstr << "<contributor>" << endstr;
-	PushTag();
-	mOutput << startstr << "<author>Assimp</author>" << endstr;
-	mOutput << startstr << "<authoring_tool>Assimp Collada Exporter</authoring_tool>" << endstr;
-	PopTag();
-	mOutput << startstr << "</contributor>" << endstr;
-	mOutput << startstr << "<created>" << date_str << "</created>" << endstr;
-	mOutput << startstr << "<modified>" << date_str << "</modified>" << endstr;
-	mOutput << startstr << "<unit name=\"meter\" meter=\"" << scale << "\" />" << endstr;
-	mOutput << startstr << "<up_axis>" << up_axis << "</up_axis>" << endstr;
-	PopTag();
-	mOutput << startstr << "</asset>" << endstr;
+    static const float epsilon = 0.00001f;
+    static const aiQuaternion x_rot(aiMatrix3x3(
+        0, -1,  0,
+        1,  0,  0,
+        0,  0,  1));
+    static const aiQuaternion y_rot(aiMatrix3x3(
+        1,  0,  0,
+        0,  1,  0,
+        0,  0,  1));
+    static const aiQuaternion z_rot(aiMatrix3x3(
+        1,  0,  0,
+        0,  0,  1,
+        0, -1,  0));
+
+    static const unsigned int date_nb_chars = 20;
+    char date_str[date_nb_chars];
+    std::time_t date = std::time(NULL);
+    std::strftime(date_str, date_nb_chars, "%Y-%m-%dT%H:%M:%S", std::localtime(&date));
+
+    aiVector3D scaling;
+    aiQuaternion rotation;
+    aiVector3D position;
+    mScene->mRootNode->mTransformation.Decompose(scaling, rotation, position);
+    rotation.Normalize();
+
+    bool add_root_node = false;
+
+    float scale = 1.0;
+    if(std::abs(scaling.x - scaling.y) <= epsilon && std::abs(scaling.x - scaling.z) <= epsilon && std::abs(scaling.y - scaling.z) <= epsilon) {
+        scale = (float) ((((double) scaling.x) + ((double) scaling.y) + ((double) scaling.z)) / 3.0);
+    } else {
+        add_root_node = true;
+    }
+
+    std::string up_axis = "Y_UP";
+    if(rotation.Equal(x_rot, epsilon)) {
+        up_axis = "X_UP";
+    } else if(rotation.Equal(y_rot, epsilon)) {
+        up_axis = "Y_UP";
+    } else if(rotation.Equal(z_rot, epsilon)) {
+        up_axis = "Z_UP";
+    } else {
+        add_root_node = true;
+    }
+
+    if(! position.Equal(aiVector3D(0, 0, 0))) {
+        add_root_node = true;
+    }
+
+    if(mScene->mRootNode->mNumChildren == 0) {
+        add_root_node = true;
+    }
+
+    if(add_root_node) {
+        aiScene* scene;
+        SceneCombiner::CopyScene(&scene, mScene);
+
+        aiNode* root = new aiNode("Scene");
+
+        root->mNumChildren = 1;
+        root->mChildren = new aiNode*[root->mNumChildren];
+
+        root->mChildren[0] = scene->mRootNode;
+        scene->mRootNode->mParent = root;
+        scene->mRootNode = root;
+
+        mScene = scene;
+        mSceneOwned = true;
+
+        up_axis = "Y_UP";
+        scale = 1.0;
+    }
+
+    mOutput << startstr << "<asset>" << endstr;
+    PushTag();
+    mOutput << startstr << "<contributor>" << endstr;
+    PushTag();
+
+    aiMetadata* meta = mScene->mRootNode->mMetaData;
+    aiString value;
+    if (!meta || !meta->Get("Author", value))
+        mOutput << startstr << "<author>" << "Assimp" << "</author>" << endstr;
+    else
+        mOutput << startstr << "<author>" << XMLEscape(value.C_Str()) << "</author>" << endstr;
+
+    if (!meta || !meta->Get("AuthoringTool", value))
+        mOutput << startstr << "<authoring_tool>" << "Assimp Exporter" << "</authoring_tool>" << endstr;
+    else
+        mOutput << startstr << "<authoring_tool>" << XMLEscape(value.C_Str()) << "</authoring_tool>" << endstr;
+
+    //mOutput << startstr << "<author>" << mScene->author.C_Str() << "</author>" << endstr;
+    //mOutput << startstr << "<authoring_tool>" << mScene->authoringTool.C_Str() << "</authoring_tool>" << endstr;
+
+    PopTag();
+    mOutput << startstr << "</contributor>" << endstr;
+    mOutput << startstr << "<created>" << date_str << "</created>" << endstr;
+    mOutput << startstr << "<modified>" << date_str << "</modified>" << endstr;
+    mOutput << startstr << "<unit name=\"meter\" meter=\"" << scale << "\" />" << endstr;
+    mOutput << startstr << "<up_axis>" << up_axis << "</up_axis>" << endstr;
+    PopTag();
+    mOutput << startstr << "</asset>" << endstr;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Write the embedded textures
 void ColladaExporter::WriteTextures() {
-	static const unsigned int buffer_size = 1024;
-	char str[buffer_size];
+    static const unsigned int buffer_size = 1024;
+    char str[buffer_size];
+
+    if(mScene->HasTextures()) {
+        for(unsigned int i = 0; i < mScene->mNumTextures; i++) {
+            // It would be great to be able to create a directory in portable standard C++, but it's not the case,
+            // so we just write the textures in the current directory.
+
+            aiTexture* texture = mScene->mTextures[i];
+
+            ASSIMP_itoa10(str, buffer_size, i + 1);
+
+            std::string name = mFile + "_texture_" + (i < 1000 ? "0" : "") + (i < 100 ? "0" : "") + (i < 10 ? "0" : "") + str + "." + ((const char*) texture->achFormatHint);
+
+            boost::scoped_ptr<IOStream> outfile(mIOSystem->Open(mPath + name, "wb"));
+            if(outfile == NULL) {
+                throw DeadlyExportError("could not open output texture file: " + mPath + name);
+            }
+
+            if(texture->mHeight == 0) {
+                outfile->Write((void*) texture->pcData, texture->mWidth, 1);
+            } else {
+                Bitmap::Save(texture, outfile.get());
+            }
+
+            outfile->Flush();
+
+            textures.insert(std::make_pair(i, name));
+        }
+    }
+}
 
-	if(mScene->HasTextures()) {
-		for(unsigned int i = 0; i < mScene->mNumTextures; i++) {
-			// It would be great to be able to create a directory in portable standard C++, but it's not the case,
-			// so we just write the textures in the current directory.
+// ------------------------------------------------------------------------------------------------
+// Write the embedded textures
+void ColladaExporter::WriteCamerasLibrary() {
+    if(mScene->HasCameras()) {
 
-			aiTexture* texture = mScene->mTextures[i];
+        mOutput << startstr << "<library_cameras>" << endstr;
+        PushTag();
 
-			ASSIMP_itoa10(str, buffer_size, i + 1);
+        for( size_t a = 0; a < mScene->mNumCameras; ++a)
+            WriteCamera( a);
 
-			std::string name = mFile + "_texture_" + (i < 1000 ? "0" : "") + (i < 100 ? "0" : "") + (i < 10 ? "0" : "") + str + "." + ((const char*) texture->achFormatHint);
+        PopTag();
+        mOutput << startstr << "</library_cameras>" << endstr;
 
-			boost::scoped_ptr<IOStream> outfile(mIOSystem->Open(mPath + name, "wb"));
-			if(outfile == NULL) {
-				throw DeadlyExportError("could not open output texture file: " + mPath + name);
-			}
+    }
+}
 
-			if(texture->mHeight == 0) {
-				outfile->Write((void*) texture->pcData, texture->mWidth, 1);
-			} else {
-				Bitmap::Save(texture, outfile.get());
-			}
+void ColladaExporter::WriteCamera(size_t pIndex){
 
-			outfile->Flush();
+    const aiCamera *cam = mScene->mCameras[pIndex];
+    const std::string idstrEscaped = XMLEscape(cam->mName.C_Str());
+
+    mOutput << startstr << "<camera id=\"" << idstrEscaped << "-camera\" name=\"" << idstrEscaped << "_name\" >" << endstr;
+    PushTag();
+    mOutput << startstr << "<optics>" << endstr;
+    PushTag();
+    mOutput << startstr << "<technique_common>" << endstr;
+    PushTag();
+    //assimp doesn't support the import of orthographic cameras! se we write
+    //always perspective
+    mOutput << startstr << "<perspective>" << endstr;
+    PushTag();
+    mOutput << startstr << "<xfov sid=\"xfov\">"<<
+                                AI_RAD_TO_DEG(cam->mHorizontalFOV)
+                        <<"</xfov>" << endstr;
+    mOutput << startstr << "<aspect_ratio>"
+                        <<      cam->mAspect
+                        << "</aspect_ratio>" << endstr;
+    mOutput << startstr << "<znear sid=\"znear\">"
+                        <<      cam->mClipPlaneNear
+                        <<  "</znear>" << endstr;
+    mOutput << startstr << "<zfar sid=\"zfar\">"
+                        <<      cam->mClipPlaneFar
+                        << "</zfar>" << endstr;
+    PopTag();
+    mOutput << startstr << "</perspective>" << endstr;
+    PopTag();
+    mOutput << startstr << "</technique_common>" << endstr;
+    PopTag();
+    mOutput << startstr << "</optics>" << endstr;
+    PopTag();
+    mOutput << startstr << "</camera>" << endstr;
 
-			textures.insert(std::make_pair(i, name));
-		}
-	}
+}
+
+
+// ------------------------------------------------------------------------------------------------
+// Write the embedded textures
+void ColladaExporter::WriteLightsLibrary() {
+    if(mScene->HasLights()) {
+
+        mOutput << startstr << "<library_lights>" << endstr;
+        PushTag();
+
+        for( size_t a = 0; a < mScene->mNumLights; ++a)
+            WriteLight( a);
+
+        PopTag();
+        mOutput << startstr << "</library_lights>" << endstr;
+
+    }
+}
+
+void ColladaExporter::WriteLight(size_t pIndex){
+
+    const aiLight *light = mScene->mLights[pIndex];
+    const std::string idstrEscaped = XMLEscape(light->mName.C_Str());
+
+    mOutput << startstr << "<light id=\"" << idstrEscaped << "-light\" name=\""
+            << idstrEscaped << "_name\" >" << endstr;
+    PushTag();
+    mOutput << startstr << "<technique_common>" << endstr;
+    PushTag();
+    switch(light->mType){
+        case aiLightSource_AMBIENT:
+            WriteAmbienttLight(light);
+            break;
+        case aiLightSource_DIRECTIONAL:
+            WriteDirectionalLight(light);
+            break;
+        case aiLightSource_POINT:
+            WritePointLight(light);
+            break;
+        case aiLightSource_SPOT:
+            WriteSpotLight(light);
+            break;
+        case aiLightSource_UNDEFINED:
+        case _aiLightSource_Force32Bit:
+            break;
+    }
+    PopTag();
+    mOutput << startstr << "</technique_common>" << endstr;
+
+    PopTag();
+    mOutput << startstr << "</light>" << endstr;
+
+}
+
+void ColladaExporter::WritePointLight(const aiLight *const light){
+    const aiColor3D &color=  light->mColorDiffuse;
+    mOutput << startstr << "<point>" << endstr;
+    PushTag();
+    mOutput << startstr << "<color sid=\"color\">"
+                            << color.r<<" "<<color.g<<" "<<color.b
+                        <<"</color>" << endstr;
+    mOutput << startstr << "<constant_attenuation>"
+                            << light->mAttenuationConstant
+                        <<"</constant_attenuation>" << endstr;
+    mOutput << startstr << "<linear_attenuation>"
+                            << light->mAttenuationLinear
+                        <<"</linear_attenuation>" << endstr;
+    mOutput << startstr << "<quadratic_attenuation>"
+                            << light->mAttenuationQuadratic
+                        <<"</quadratic_attenuation>" << endstr;
+
+    PopTag();
+    mOutput << startstr << "</point>" << endstr;
+
+}
+void ColladaExporter::WriteDirectionalLight(const aiLight *const light){
+    const aiColor3D &color=  light->mColorDiffuse;
+    mOutput << startstr << "<directional>" << endstr;
+    PushTag();
+    mOutput << startstr << "<color sid=\"color\">"
+                            << color.r<<" "<<color.g<<" "<<color.b
+                        <<"</color>" << endstr;
+
+    PopTag();
+    mOutput << startstr << "</directional>" << endstr;
+
+}
+void ColladaExporter::WriteSpotLight(const aiLight *const light){
+
+    const aiColor3D &color=  light->mColorDiffuse;
+    mOutput << startstr << "<spot>" << endstr;
+    PushTag();
+    mOutput << startstr << "<color sid=\"color\">"
+                            << color.r<<" "<<color.g<<" "<<color.b
+                        <<"</color>" << endstr;
+    mOutput << startstr << "<constant_attenuation>"
+                                << light->mAttenuationConstant
+                            <<"</constant_attenuation>" << endstr;
+    mOutput << startstr << "<linear_attenuation>"
+                            << light->mAttenuationLinear
+                        <<"</linear_attenuation>" << endstr;
+    mOutput << startstr << "<quadratic_attenuation>"
+                            << light->mAttenuationQuadratic
+                        <<"</quadratic_attenuation>" << endstr;
+    /*
+    out->mAngleOuterCone = AI_DEG_TO_RAD (std::acos(std::pow(0.1f,1.f/srcLight->mFalloffExponent))+
+                            srcLight->mFalloffAngle);
+    */
+
+    const float fallOffAngle = AI_RAD_TO_DEG(light->mAngleInnerCone);
+    mOutput << startstr <<"<falloff_angle sid=\"fall_off_angle\">"
+                                << fallOffAngle
+                        <<"</falloff_angle>" << endstr;
+    double temp = light->mAngleOuterCone-light->mAngleInnerCone;
+
+    temp = std::cos(temp);
+    temp = std::log(temp)/std::log(0.1);
+    temp = 1/temp;
+    mOutput << startstr << "<falloff_exponent sid=\"fall_off_exponent\">"
+                            << temp
+                        <<"</falloff_exponent>" << endstr;
+
+
+    PopTag();
+    mOutput << startstr << "</spot>" << endstr;
+
+}
+
+void ColladaExporter::WriteAmbienttLight(const aiLight *const light){
+
+    const aiColor3D &color=  light->mColorAmbient;
+    mOutput << startstr << "<ambient>" << endstr;
+    PushTag();
+    mOutput << startstr << "<color sid=\"color\">"
+                            << color.r<<" "<<color.g<<" "<<color.b
+                        <<"</color>" << endstr;
+
+    PopTag();
+    mOutput << startstr << "</ambient>" << endstr;
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -290,30 +495,30 @@ void ColladaExporter::ReadMaterialSurface( Surface& poSurface, const aiMaterial*
 
     if(index_str.size() != 0 && index_str[0] == '*')
     {
-		unsigned int index;
+        unsigned int index;
 
-    	index_str = index_str.substr(1, std::string::npos);
+        index_str = index_str.substr(1, std::string::npos);
 
-    	try {
-    		index = (unsigned int) strtoul10_64(index_str.c_str());
-    	} catch(std::exception& error) {
-    		throw DeadlyExportError(error.what());
-    	}
+        try {
+            index = (unsigned int) strtoul10_64(index_str.c_str());
+        } catch(std::exception& error) {
+            throw DeadlyExportError(error.what());
+        }
 
-    	std::map<unsigned int, std::string>::const_iterator name = textures.find(index);
+        std::map<unsigned int, std::string>::const_iterator name = textures.find(index);
 
-    	if(name != textures.end()) {
-    		poSurface.texture = name->second;
-    	} else {
-    		throw DeadlyExportError("could not find embedded texture at index " + index_str);
-    	}
+        if(name != textures.end()) {
+            poSurface.texture = name->second;
+        } else {
+            throw DeadlyExportError("could not find embedded texture at index " + index_str);
+        }
     } else
     {
-		poSurface.texture = texfile.C_Str();
+        poSurface.texture = texfile.C_Str();
     }
 
     poSurface.channel = uvChannel;
-	poSurface.exist = true;
+    poSurface.exist = true;
   } else
   {
     if( pKey )
@@ -327,16 +532,20 @@ void ColladaExporter::WriteImageEntry( const Surface& pSurface, const std::strin
 {
   if( !pSurface.texture.empty() )
   {
-    mOutput << startstr << "<image id=\"" << pNameAdd << "\">" << endstr;
-    PushTag(); 
+    mOutput << startstr << "<image id=\"" << XMLEscape(pNameAdd) << "\">" << endstr;
+    PushTag();
     mOutput << startstr << "<init_from>";
+
+    // URL encode image file name first, then XML encode on top
+    std::stringstream imageUrlEncoded;
     for( std::string::const_iterator it = pSurface.texture.begin(); it != pSurface.texture.end(); ++it )
     {
       if( isalnum( *it) || *it == '_' || *it == '.' || *it == '/' || *it == '\\' )
-        mOutput << *it;
+        imageUrlEncoded << *it;
       else
-        mOutput << '%' << std::hex << size_t( (unsigned char) *it) << std::dec;
+        imageUrlEncoded << '%' << std::hex << size_t( (unsigned char) *it) << std::dec;
     }
+    mOutput << XMLEscape(imageUrlEncoded.str());
     mOutput << "</init_from>" << endstr;
     PopTag();
     mOutput << startstr << "</image>" << endstr;
@@ -353,9 +562,10 @@ void ColladaExporter::WriteTextureColorEntry( const Surface& pSurface, const std
     if( pSurface.texture.empty() )
     {
       mOutput << startstr << "<color sid=\"" << pTypeName << "\">" << pSurface.color.r << "   " << pSurface.color.g << "   " << pSurface.color.b << "   " << pSurface.color.a << "</color>" << endstr;
-    } else
+    }
+    else
     {
-      mOutput << startstr << "<texture texture=\"" << pImageName << "\" texcoord=\"CHANNEL" << pSurface.channel << "\" />" << endstr;
+      mOutput << startstr << "<texture texture=\"" << XMLEscape(pImageName) << "\" texcoord=\"CHANNEL" << pSurface.channel << "\" />" << endstr;
     }
     PopTag();
     mOutput << startstr << "</" << pTypeName << ">" << endstr;
@@ -369,21 +579,21 @@ void ColladaExporter::WriteTextureParamEntry( const Surface& pSurface, const std
   // if surface is a texture, write out the sampler and the surface parameters necessary to reference the texture
   if( !pSurface.texture.empty() )
   {
-    mOutput << startstr << "<newparam sid=\"" << pMatName << "-" << pTypeName << "-surface\">" << endstr;
+    mOutput << startstr << "<newparam sid=\"" << XMLEscape(pMatName) << "-" << pTypeName << "-surface\">" << endstr;
     PushTag();
     mOutput << startstr << "<surface type=\"2D\">" << endstr;
     PushTag();
-    mOutput << startstr << "<init_from>" << pMatName << "-" << pTypeName << "-image</init_from>" << endstr;
+    mOutput << startstr << "<init_from>" << XMLEscape(pMatName) << "-" << pTypeName << "-image</init_from>" << endstr;
     PopTag();
     mOutput << startstr << "</surface>" << endstr;
     PopTag();
     mOutput << startstr << "</newparam>" << endstr;
 
-    mOutput << startstr << "<newparam sid=\"" << pMatName << "-" << pTypeName << "-sampler\">" << endstr;
+    mOutput << startstr << "<newparam sid=\"" << XMLEscape(pMatName) << "-" << pTypeName << "-sampler\">" << endstr;
     PushTag();
     mOutput << startstr << "<sampler2D>" << endstr;
     PushTag();
-    mOutput << startstr << "<source>" << pMatName << "-" << pTypeName << "-surface</source>" << endstr;
+    mOutput << startstr << "<source>" << XMLEscape(pMatName) << "-" << pTypeName << "-surface</source>" << endstr;
     PopTag();
     mOutput << startstr << "</sampler2D>" << endstr;
     PopTag();
@@ -395,13 +605,13 @@ void ColladaExporter::WriteTextureParamEntry( const Surface& pSurface, const std
 // Writes a scalar property
 void ColladaExporter::WriteFloatEntry( const Property& pProperty, const std::string& pTypeName)
 {
-	if(pProperty.exist) {
-		mOutput << startstr << "<" << pTypeName << ">" << endstr;
-		PushTag();
-		mOutput << startstr << "<float sid=\"" << pTypeName << "\">" << pProperty.value << "</float>" << endstr;
-		PopTag();
-		mOutput << startstr << "</" << pTypeName << ">" << endstr;
-	}
+    if(pProperty.exist) {
+        mOutput << startstr << "<" << pTypeName << ">" << endstr;
+        PushTag();
+        mOutput << startstr << "<float sid=\"" << pTypeName << "\">" << pProperty.value << "</float>" << endstr;
+        PopTag();
+        mOutput << startstr << "</" << pTypeName << ">" << endstr;
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -410,8 +620,6 @@ void ColladaExporter::WriteMaterials()
 {
   materials.resize( mScene->mNumMaterials);
 
-  std::set<std::string> material_names;
-
   /// collect all materials from the scene
   size_t numTextures = 0;
   for( size_t a = 0; a < mScene->mNumMaterials; ++a )
@@ -423,26 +631,26 @@ void ColladaExporter::WriteMaterials()
       name = "mat";
     materials[a].name = std::string( "m") + boost::lexical_cast<std::string> (a) + name.C_Str();
     for( std::string::iterator it = materials[a].name.begin(); it != materials[a].name.end(); ++it ) {
-		// isalnum on MSVC asserts for code points in [0,255]. Thus prevent unwanted promotion
-		// of char to signed int and take the unsigned char value.
+        // isalnum on MSVC asserts for code points outside [0,255]. Thus prevent unwanted promotion
+        // of char to signed int and take the unsigned char value.
       if( !isalnum( static_cast<uint8_t>(*it) ) ) {
         *it = '_';
-	  }
-	}
-
-	aiShadingMode shading;
-	materials[a].shading_model = "phong";
-	if(mat->Get( AI_MATKEY_SHADING_MODEL, shading) == aiReturn_SUCCESS) {
-		if(shading == aiShadingMode_Phong) {
-			materials[a].shading_model = "phong";
-		} else if(shading == aiShadingMode_Blinn) {
-			materials[a].shading_model = "blinn";
-		} else if(shading == aiShadingMode_NoShading) {
-			materials[a].shading_model = "constant";
-		} else if(shading == aiShadingMode_Gouraud) {
-			materials[a].shading_model = "lambert";
-		}
-	}
+      }
+    }
+
+    aiShadingMode shading = aiShadingMode_Flat;
+    materials[a].shading_model = "phong";
+    if(mat->Get( AI_MATKEY_SHADING_MODEL, shading) == aiReturn_SUCCESS) {
+        if(shading == aiShadingMode_Phong) {
+            materials[a].shading_model = "phong";
+        } else if(shading == aiShadingMode_Blinn) {
+            materials[a].shading_model = "blinn";
+        } else if(shading == aiShadingMode_NoShading) {
+            materials[a].shading_model = "constant";
+        } else if(shading == aiShadingMode_Gouraud) {
+            materials[a].shading_model = "lambert";
+        }
+    }
 
     ReadMaterialSurface( materials[a].ambient, mat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT);
     if( !materials[a].ambient.texture.empty() ) numTextures++;
@@ -454,31 +662,31 @@ void ColladaExporter::WriteMaterials()
     if( !materials[a].emissive.texture.empty() ) numTextures++;
     ReadMaterialSurface( materials[a].reflective, mat, aiTextureType_REFLECTION, AI_MATKEY_COLOR_REFLECTIVE);
     if( !materials[a].reflective.texture.empty() ) numTextures++;
-	ReadMaterialSurface( materials[a].transparent, mat, aiTextureType_OPACITY, AI_MATKEY_COLOR_TRANSPARENT);
+    ReadMaterialSurface( materials[a].transparent, mat, aiTextureType_OPACITY, AI_MATKEY_COLOR_TRANSPARENT);
     if( !materials[a].transparent.texture.empty() ) numTextures++;
     ReadMaterialSurface( materials[a].normal, mat, aiTextureType_NORMALS, NULL, 0, 0);
     if( !materials[a].normal.texture.empty() ) numTextures++;
 
-	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 = 1 - materials[a].transparency.value;
-	materials[a].index_refraction.exist = mat->Get( AI_MATKEY_REFRACTI, materials[a].index_refraction.value) == aiReturn_SUCCESS;
+    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 = 1 - materials[a].transparency.value;
+    materials[a].index_refraction.exist = mat->Get( AI_MATKEY_REFRACTI, materials[a].index_refraction.value) == aiReturn_SUCCESS;
   }
 
   // output textures if present
   if( numTextures > 0 )
   {
-    mOutput << startstr << "<library_images>" << endstr; 
+    mOutput << startstr << "<library_images>" << endstr;
     PushTag();
     for( std::vector<Material>::const_iterator it = materials.begin(); it != materials.end(); ++it )
-    { 
+    {
       const Material& mat = *it;
       WriteImageEntry( mat.ambient, mat.name + "-ambient-image");
       WriteImageEntry( mat.diffuse, mat.name + "-diffuse-image");
       WriteImageEntry( mat.specular, mat.name + "-specular-image");
       WriteImageEntry( mat.emissive, mat.name + "-emission-image");
       WriteImageEntry( mat.reflective, mat.name + "-reflective-image");
-	  WriteImageEntry( mat.transparent, mat.name + "-transparent-image");
+      WriteImageEntry( mat.transparent, mat.name + "-transparent-image");
       WriteImageEntry( mat.normal, mat.name + "-normal-image");
     }
     PopTag();
@@ -494,7 +702,7 @@ void ColladaExporter::WriteMaterials()
     {
       const Material& mat = *it;
       // this is so ridiculous it must be right
-      mOutput << startstr << "<effect id=\"" << mat.name << "-fx\" name=\"" << mat.name << "\">" << endstr;
+      mOutput << startstr << "<effect id=\"" << XMLEscape(mat.name) << "-fx\" name=\"" << XMLEscape(mat.name) << "\">" << endstr;
       PushTag();
       mOutput << startstr << "<profile_COMMON>" << endstr;
       PushTag();
@@ -505,27 +713,27 @@ void ColladaExporter::WriteMaterials()
       WriteTextureParamEntry( mat.diffuse, "diffuse", mat.name);
       WriteTextureParamEntry( mat.specular, "specular", mat.name);
       WriteTextureParamEntry( mat.reflective, "reflective", mat.name);
-	  WriteTextureParamEntry( mat.transparent, "transparent", mat.name);
-	  WriteTextureParamEntry( mat.normal, "normal", mat.name);
+      WriteTextureParamEntry( mat.transparent, "transparent", mat.name);
+      WriteTextureParamEntry( mat.normal, "normal", mat.name);
 
       mOutput << startstr << "<technique sid=\"standard\">" << endstr;
       PushTag();
-	  mOutput << startstr << "<" << mat.shading_model << ">" << endstr;
+      mOutput << startstr << "<" << mat.shading_model << ">" << endstr;
       PushTag();
 
       WriteTextureColorEntry( mat.emissive, "emission", mat.name + "-emission-sampler");
       WriteTextureColorEntry( mat.ambient, "ambient", mat.name + "-ambient-sampler");
       WriteTextureColorEntry( mat.diffuse, "diffuse", mat.name + "-diffuse-sampler");
       WriteTextureColorEntry( mat.specular, "specular", mat.name + "-specular-sampler");
-	  WriteFloatEntry(mat.shininess, "shininess");
+      WriteFloatEntry(mat.shininess, "shininess");
       WriteTextureColorEntry( mat.reflective, "reflective", mat.name + "-reflective-sampler");
-	  WriteTextureColorEntry( mat.transparent, "transparent", mat.name + "-transparent-sampler");
-	  WriteFloatEntry(mat.transparency, "transparency");
-	  WriteFloatEntry(mat.index_refraction, "index_of_refraction");
+      WriteTextureColorEntry( mat.transparent, "transparent", mat.name + "-transparent-sampler");
+      WriteFloatEntry(mat.transparency, "transparency");
+      WriteFloatEntry(mat.index_refraction, "index_of_refraction");
 
-	  if(! mat.normal.texture.empty()) {
-		WriteTextureColorEntry( mat.normal, "bump", mat.name + "-normal-sampler");
-	  }
+      if(! mat.normal.texture.empty()) {
+        WriteTextureColorEntry( mat.normal, "bump", mat.name + "-normal-sampler");
+      }
 
       PopTag();
       mOutput << startstr << "</" << mat.shading_model << ">" << endstr;
@@ -545,9 +753,9 @@ void ColladaExporter::WriteMaterials()
     for( std::vector<Material>::const_iterator it = materials.begin(); it != materials.end(); ++it )
     {
       const Material& mat = *it;
-      mOutput << startstr << "<material id=\"" << mat.name << "\" name=\"" << mat.name << "\">" << endstr;
+      mOutput << startstr << "<material id=\"" << XMLEscape(mat.name) << "\" name=\"" << mat.name << "\">" << endstr;
       PushTag();
-      mOutput << startstr << "<instance_effect url=\"#" << mat.name << "-fx\"/>" << endstr;
+      mOutput << startstr << "<instance_effect url=\"#" << XMLEscape(mat.name) << "-fx\"/>" << endstr;
       PopTag();
       mOutput << startstr << "</material>" << endstr;
     }
@@ -560,262 +768,324 @@ void ColladaExporter::WriteMaterials()
 // Writes the geometry library
 void ColladaExporter::WriteGeometryLibrary()
 {
-	mOutput << startstr << "<library_geometries>" << endstr;
-	PushTag();
+    mOutput << startstr << "<library_geometries>" << endstr;
+    PushTag();
 
-	for( size_t a = 0; a < mScene->mNumMeshes; ++a)
-		WriteGeometry( a);
+    for( size_t a = 0; a < mScene->mNumMeshes; ++a)
+        WriteGeometry( a);
 
-	PopTag();
-	mOutput << startstr << "</library_geometries>" << endstr;
+    PopTag();
+    mOutput << startstr << "</library_geometries>" << endstr;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Writes the given mesh
 void ColladaExporter::WriteGeometry( size_t pIndex)
 {
-	const aiMesh* mesh = mScene->mMeshes[pIndex];
-	std::string idstr = GetMeshId( 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;
 
-	// opening tag
-	mOutput << startstr << "<geometry id=\"" << idstr << "\" name=\"" << idstr << "_name\" >" << endstr;
-	PushTag();
-
-	mOutput << startstr << "<mesh>" << endstr;
-	PushTag();
-
-	// Positions
-	WriteFloatArray( idstr + "-positions", FloatType_Vector, (float*) mesh->mVertices, mesh->mNumVertices);
-	// Normals, if any
-	if( mesh->HasNormals() )
-		WriteFloatArray( idstr + "-normals", FloatType_Vector, (float*) mesh->mNormals, mesh->mNumVertices);
-
-	// texture coords
-	for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a)
-	{
-		if( mesh->HasTextureCoords( a) )
-		{
-			WriteFloatArray( idstr + "-tex" + boost::lexical_cast<std::string> (a), mesh->mNumUVComponents[a] == 3 ? FloatType_TexCoord3 : FloatType_TexCoord2,
-				(float*) mesh->mTextureCoords[a], mesh->mNumVertices);
-		}
-	}
-
-	// vertex colors
-	for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a)
-	{
-		if( mesh->HasVertexColors( a) )
-			WriteFloatArray( idstr + "-color" + boost::lexical_cast<std::string> (a), FloatType_Color, (float*) mesh->mColors[a], mesh->mNumVertices);
-	}
-
-	// assemble vertex structure
-	mOutput << startstr << "<vertices id=\"" << idstr << "-vertices" << "\">" << endstr;
-	PushTag();
-	mOutput << startstr << "<input semantic=\"POSITION\" source=\"#" << idstr << "-positions\" />" << endstr;
-	if( mesh->HasNormals() )
-		mOutput << startstr << "<input semantic=\"NORMAL\" source=\"#" << idstr << "-normals\" />" << endstr;
-	for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a )
-	{
-		if( mesh->HasTextureCoords( a) )
-			mOutput << startstr << "<input semantic=\"TEXCOORD\" source=\"#" << idstr << "-tex" << a << "\" " /*<< "set=\"" << a << "\"" */ << " />" << endstr;
-	}
-	for( size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a )
-	{
-		if( mesh->HasVertexColors( a) )
-			mOutput << startstr << "<input semantic=\"COLOR\" source=\"#" << idstr << "-color" << a << "\" " /*<< set=\"" << a << "\"" */ << " />" << endstr;
-	}
-	
-	PopTag();
-	mOutput << startstr << "</vertices>" << endstr;
-
-	// write face setup
-	mOutput << startstr << "<polylist count=\"" << mesh->mNumFaces << "\" material=\"theresonlyone\">" << endstr;
-	PushTag();
-	mOutput << startstr << "<input offset=\"0\" semantic=\"VERTEX\" source=\"#" << idstr << "-vertices\" />" << endstr;
-	
-	mOutput << startstr << "<vcount>";
-	for( size_t a = 0; a < mesh->mNumFaces; ++a )
-		mOutput << mesh->mFaces[a].mNumIndices << " ";
-	mOutput << "</vcount>" << endstr;
-	
-	mOutput << startstr << "<p>";
-	for( size_t a = 0; a < mesh->mNumFaces; ++a )
-	{
-		const aiFace& face = mesh->mFaces[a];
-		for( size_t b = 0; b < face.mNumIndices; ++b )
-			mOutput << face.mIndices[b] << " ";
-	}
-	mOutput << "</p>" << endstr;
-	PopTag();
-	mOutput << startstr << "</polylist>" << endstr;
-
-	// closing tags
-	PopTag();
-	mOutput << startstr << "</mesh>" << endstr;
-	PopTag();
-	mOutput << startstr << "</geometry>" << endstr;
+    // opening tag
+    mOutput << startstr << "<geometry id=\"" << idstrEscaped << "\" name=\"" << idstrEscaped << "_name\" >" << endstr;
+    PushTag();
+
+    mOutput << startstr << "<mesh>" << endstr;
+    PushTag();
+
+    // Positions
+    WriteFloatArray( idstr + "-positions", FloatType_Vector, (float*) mesh->mVertices, mesh->mNumVertices);
+    // Normals, if any
+    if( mesh->HasNormals() )
+        WriteFloatArray( idstr + "-normals", FloatType_Vector, (float*) mesh->mNormals, mesh->mNumVertices);
+
+    // texture coords
+    for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a)
+    {
+        if( mesh->HasTextureCoords( a) )
+        {
+            WriteFloatArray( idstr + "-tex" + boost::lexical_cast<std::string> (a), mesh->mNumUVComponents[a] == 3 ? FloatType_TexCoord3 : FloatType_TexCoord2,
+                (float*) mesh->mTextureCoords[a], mesh->mNumVertices);
+        }
+    }
+
+    // vertex colors
+    for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a)
+    {
+        if( mesh->HasVertexColors( a) )
+            WriteFloatArray( idstr + "-color" + boost::lexical_cast<std::string> (a), FloatType_Color, (float*) mesh->mColors[a], mesh->mNumVertices);
+    }
+
+    // assemble vertex structure
+    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( 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( a) )
+            mOutput << startstr << "<input semantic=\"COLOR\" source=\"#" << idstrEscaped << "-color" << a << "\" " /*<< set=\"" << a << "\"" */ << " />" << endstr;
+    }
+
+    PopTag();
+    mOutput << startstr << "</vertices>" << endstr;
+
+    // count the number of lines, triangles and polygon meshes
+    int countLines = 0;
+    int countPoly = 0;
+    for( size_t a = 0; a < mesh->mNumFaces; ++a )
+    {
+        if (mesh->mFaces[a].mNumIndices == 2) countLines++;
+        else if (mesh->mFaces[a].mNumIndices >= 3) countPoly++;
+    }
+
+    // lines
+    if (countLines)
+    {
+        mOutput << startstr << "<lines count=\"" << countLines << "\" material=\"defaultMaterial\">" << endstr;
+        PushTag();
+        mOutput << startstr << "<input offset=\"0\" semantic=\"VERTEX\" source=\"#" << idstrEscaped << "-vertices\" />" << endstr;
+        mOutput << startstr << "<p>";
+        for( size_t a = 0; a < mesh->mNumFaces; ++a )
+        {
+            const aiFace& face = mesh->mFaces[a];
+            if (face.mNumIndices != 2) continue;
+            for( size_t b = 0; b < face.mNumIndices; ++b )
+                mOutput << face.mIndices[b] << " ";
+        }
+        mOutput << "</p>" << endstr;
+        PopTag();
+        mOutput << startstr << "</lines>" << endstr;
+    }
+
+    // triangle - dont use it, because compatibility problems
+
+    // polygons
+    if (countPoly)
+    {
+        mOutput << startstr << "<polylist count=\"" << countPoly << "\" material=\"defaultMaterial\">" << endstr;
+        PushTag();
+        mOutput << startstr << "<input offset=\"0\" semantic=\"VERTEX\" source=\"#" << idstrEscaped << "-vertices\" />" << endstr;
+
+        mOutput << startstr << "<vcount>";
+        for( size_t a = 0; a < mesh->mNumFaces; ++a )
+        {
+            if (mesh->mFaces[a].mNumIndices < 3) continue;
+            mOutput << mesh->mFaces[a].mNumIndices << " ";
+        }
+        mOutput << "</vcount>" << endstr;
+
+        mOutput << startstr << "<p>";
+        for( size_t a = 0; a < mesh->mNumFaces; ++a )
+        {
+            const aiFace& face = mesh->mFaces[a];
+            if (face.mNumIndices < 3) continue;
+            for( size_t b = 0; b < face.mNumIndices; ++b )
+                mOutput << face.mIndices[b] << " ";
+        }
+        mOutput << "</p>" << endstr;
+        PopTag();
+        mOutput << startstr << "</polylist>" << endstr;
+    }
+
+    // closing tags
+    PopTag();
+    mOutput << startstr << "</mesh>" << endstr;
+    PopTag();
+    mOutput << startstr << "</geometry>" << endstr;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Writes a float array of the given type
 void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataType pType, const float* pData, size_t pElementCount)
 {
-	size_t floatsPerElement = 0;
-	switch( pType )
-	{
-		case FloatType_Vector: floatsPerElement = 3; break;
-		case FloatType_TexCoord2: floatsPerElement = 2; break;
-		case FloatType_TexCoord3: floatsPerElement = 3; break;
-		case FloatType_Color: floatsPerElement = 3; break;
-		default:
-			return;
-	}
-
-	std::string arrayId = pIdString + "-array";
-
-	mOutput << startstr << "<source id=\"" << pIdString << "\" name=\"" << pIdString << "\">" << endstr;
-	PushTag();
-
-	// source array
-	mOutput << startstr << "<float_array id=\"" << arrayId << "\" count=\"" << pElementCount * floatsPerElement << "\"> ";
-	PushTag();
-
-	if( pType == FloatType_TexCoord2 )
-	{
-		for( size_t a = 0; a < pElementCount; ++a )
-		{
-			mOutput << pData[a*3+0] << " ";
-			mOutput << pData[a*3+1] << " ";
-		}
-	} 
-	else if( pType == FloatType_Color )
-	{
-		for( size_t a = 0; a < pElementCount; ++a )
-		{
-			mOutput << pData[a*4+0] << " ";
-			mOutput << pData[a*4+1] << " ";
-			mOutput << pData[a*4+2] << " ";
-		}
-	}
-	else
-	{
-		for( size_t a = 0; a < pElementCount * floatsPerElement; ++a )
-			mOutput << pData[a] << " ";
-	}
-	mOutput << "</float_array>" << endstr; 
-	PopTag();
-
-	// the usual Collada fun. Let's bloat it even more!
-	mOutput << startstr << "<technique_common>" << endstr;
-	PushTag();
-	mOutput << startstr << "<accessor count=\"" << pElementCount << "\" offset=\"0\" source=\"#" << arrayId << "\" stride=\"" << floatsPerElement << "\">" << endstr;
-	PushTag();
-
-	switch( pType )
-	{
-		case FloatType_Vector:
-			mOutput << startstr << "<param name=\"X\" type=\"float\" />" << endstr;
-			mOutput << startstr << "<param name=\"Y\" type=\"float\" />" << endstr;
-			mOutput << startstr << "<param name=\"Z\" type=\"float\" />" << endstr;
-			break;
-
-		case FloatType_TexCoord2:
-			mOutput << startstr << "<param name=\"S\" type=\"float\" />" << endstr;
-			mOutput << startstr << "<param name=\"T\" type=\"float\" />" << endstr;
-			break;
-
-		case FloatType_TexCoord3:
-			mOutput << startstr << "<param name=\"S\" type=\"float\" />" << endstr;
-			mOutput << startstr << "<param name=\"T\" type=\"float\" />" << endstr;
-			mOutput << startstr << "<param name=\"P\" type=\"float\" />" << endstr;
-			break;
-
-		case FloatType_Color:
-			mOutput << startstr << "<param name=\"R\" type=\"float\" />" << endstr;
-			mOutput << startstr << "<param name=\"G\" type=\"float\" />" << endstr;
-			mOutput << startstr << "<param name=\"B\" type=\"float\" />" << endstr;
-			break;
-	}
-
-	PopTag();
-	mOutput << startstr << "</accessor>" << endstr;
-	PopTag();
-	mOutput << startstr << "</technique_common>" << endstr;
-	PopTag();
-	mOutput << startstr << "</source>" << endstr;
+    size_t floatsPerElement = 0;
+    switch( pType )
+    {
+        case FloatType_Vector: floatsPerElement = 3; break;
+        case FloatType_TexCoord2: floatsPerElement = 2; break;
+        case FloatType_TexCoord3: floatsPerElement = 3; break;
+        case FloatType_Color: floatsPerElement = 3; break;
+        default:
+            return;
+    }
+
+    std::string arrayId = pIdString + "-array";
+
+    mOutput << startstr << "<source id=\"" << XMLEscape(pIdString) << "\" name=\"" << XMLEscape(pIdString) << "\">" << endstr;
+    PushTag();
+
+    // source array
+    mOutput << startstr << "<float_array id=\"" << XMLEscape(arrayId) << "\" count=\"" << pElementCount * floatsPerElement << "\"> ";
+    PushTag();
+
+    if( pType == FloatType_TexCoord2 )
+    {
+        for( size_t a = 0; a < pElementCount; ++a )
+        {
+            mOutput << pData[a*3+0] << " ";
+            mOutput << pData[a*3+1] << " ";
+        }
+    }
+    else if( pType == FloatType_Color )
+    {
+        for( size_t a = 0; a < pElementCount; ++a )
+        {
+            mOutput << pData[a*4+0] << " ";
+            mOutput << pData[a*4+1] << " ";
+            mOutput << pData[a*4+2] << " ";
+        }
+    }
+    else
+    {
+        for( size_t a = 0; a < pElementCount * floatsPerElement; ++a )
+            mOutput << pData[a] << " ";
+    }
+    mOutput << "</float_array>" << endstr;
+    PopTag();
+
+    // the usual Collada fun. Let's bloat it even more!
+    mOutput << startstr << "<technique_common>" << endstr;
+    PushTag();
+    mOutput << startstr << "<accessor count=\"" << pElementCount << "\" offset=\"0\" source=\"#" << arrayId << "\" stride=\"" << floatsPerElement << "\">" << endstr;
+    PushTag();
+
+    switch( pType )
+    {
+        case FloatType_Vector:
+            mOutput << startstr << "<param name=\"X\" type=\"float\" />" << endstr;
+            mOutput << startstr << "<param name=\"Y\" type=\"float\" />" << endstr;
+            mOutput << startstr << "<param name=\"Z\" type=\"float\" />" << endstr;
+            break;
+
+        case FloatType_TexCoord2:
+            mOutput << startstr << "<param name=\"S\" type=\"float\" />" << endstr;
+            mOutput << startstr << "<param name=\"T\" type=\"float\" />" << endstr;
+            break;
+
+        case FloatType_TexCoord3:
+            mOutput << startstr << "<param name=\"S\" type=\"float\" />" << endstr;
+            mOutput << startstr << "<param name=\"T\" type=\"float\" />" << endstr;
+            mOutput << startstr << "<param name=\"P\" type=\"float\" />" << endstr;
+            break;
+
+        case FloatType_Color:
+            mOutput << startstr << "<param name=\"R\" type=\"float\" />" << endstr;
+            mOutput << startstr << "<param name=\"G\" type=\"float\" />" << endstr;
+            mOutput << startstr << "<param name=\"B\" type=\"float\" />" << endstr;
+            break;
+    }
+
+    PopTag();
+    mOutput << startstr << "</accessor>" << endstr;
+    PopTag();
+    mOutput << startstr << "</technique_common>" << endstr;
+    PopTag();
+    mOutput << startstr << "</source>" << endstr;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Writes the scene library
 void ColladaExporter::WriteSceneLibrary()
 {
-	std::string scene_name = mScene->mRootNode->mName.C_Str();
+    const std::string scene_name_escaped = XMLEscape(mScene->mRootNode->mName.C_Str());
 
-	mOutput << startstr << "<library_visual_scenes>" << endstr;
-	PushTag();
-	mOutput << startstr << "<visual_scene id=\"" + scene_name + "\" name=\"" + scene_name + "\">" << endstr;
-	PushTag();
+    mOutput << startstr << "<library_visual_scenes>" << endstr;
+    PushTag();
+    mOutput << startstr << "<visual_scene id=\"" + scene_name_escaped + "\" name=\"" + scene_name_escaped + "\">" << endstr;
+    PushTag();
 
-	// start recursive write at the root node
-	for( size_t a = 0; a < mScene->mRootNode->mNumChildren; ++a )
-		WriteNode( mScene->mRootNode->mChildren[a]);
+    // start recursive write at the root node
+    for( size_t a = 0; a < mScene->mRootNode->mNumChildren; ++a )
+        WriteNode( mScene->mRootNode->mChildren[a]);
 
-	PopTag();
-	mOutput << startstr << "</visual_scene>" << endstr;
-	PopTag();
-	mOutput << startstr << "</library_visual_scenes>" << endstr;
+    PopTag();
+    mOutput << startstr << "</visual_scene>" << endstr;
+    PopTag();
+    mOutput << startstr << "</library_visual_scenes>" << endstr;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Recursively writes the given node
-void ColladaExporter::WriteNode( const aiNode* pNode)
+void ColladaExporter::WriteNode(aiNode* pNode)
 {
-	mOutput << startstr << "<node id=\"" << pNode->mName.data << "\" name=\"" << pNode->mName.data << "\">" << endstr;
-	PushTag();
-
-	// write transformation - we can directly put the matrix there
-	// TODO: (thom) decompose into scale - rot - quad to allow adressing it by animations afterwards
-	const aiMatrix4x4& mat = pNode->mTransformation;
-	mOutput << startstr << "<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 << " ";
-	mOutput << mat.d1 << " " << mat.d2 << " " << mat.d3 << " " << mat.d4;
-	mOutput << "</matrix>" << endstr;
-
-	// instance every geometry
-	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=\"#" << GetMeshId( pNode->mMeshes[a]) << "\">" << endstr;
-		PushTag();
-	mOutput << startstr << "<bind_material>" << endstr;
-	PushTag();
-	mOutput << startstr << "<technique_common>" << endstr;
-	PushTag();
-	mOutput << startstr << "<instance_material symbol=\"theresonlyone\" target=\"#" << materials[mesh->mMaterialIndex].name << "\" />" << endstr;
-		PopTag();
-	mOutput << startstr << "</technique_common>" << endstr;
-	PopTag();
-	mOutput << startstr << "</bind_material>" << endstr;
-	PopTag();
-		mOutput << startstr << "</instance_geometry>" << endstr;
-	}
-
-	// recurse into subnodes
-	for( size_t a = 0; a < pNode->mNumChildren; ++a )
-		WriteNode( pNode->mChildren[a]);
-
-	PopTag();
-	mOutput << startstr << "</node>" << endstr;
+    // the must have a name
+    if (pNode->mName.length == 0)
+    {
+        std::stringstream ss;
+        ss << "Node_" << pNode;
+        pNode->mName.Set(ss.str());
+    }
+
+    const std::string node_name_escaped = XMLEscape(pNode->mName.data);
+    mOutput << startstr << "<node id=\"" << node_name_escaped << "\" name=\"" << node_name_escaped << "\">" << endstr;
+    PushTag();
+
+    // write transformation - we can directly put the matrix there
+    // TODO: (thom) decompose into scale - rot - quad to allow adressing it by animations afterwards
+    const aiMatrix4x4& mat = pNode->mTransformation;
+    mOutput << startstr << "<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 << " ";
+    mOutput << mat.d1 << " " << mat.d2 << " " << mat.d3 << " " << mat.d4;
+    mOutput << "</matrix>" << endstr;
+
+    if(pNode->mNumMeshes==0){
+        //check if it is a camera node
+        for(size_t i=0; i<mScene->mNumCameras; i++){
+            if(mScene->mCameras[i]->mName == pNode->mName){
+                mOutput << startstr <<"<instance_camera url=\"#" << node_name_escaped << "-camera\"/>" << endstr;
+                break;
+            }
+        }
+        //check if it is a light node
+        for(size_t i=0; i<mScene->mNumLights; i++){
+            if(mScene->mLights[i]->mName == pNode->mName){
+                mOutput << startstr <<"<instance_light url=\"#" << node_name_escaped << "-light\"/>" << endstr;
+                break;
+            }
+        }
+
+    }else
+    // instance every geometry
+    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;
+        PopTag();
+    mOutput << startstr << "</technique_common>" << endstr;
+    PopTag();
+    mOutput << startstr << "</bind_material>" << endstr;
+    PopTag();
+        mOutput << startstr << "</instance_geometry>" << endstr;
+    }
+
+    // recurse into subnodes
+    for( size_t a = 0; a < pNode->mNumChildren; ++a )
+        WriteNode( pNode->mChildren[a]);
+
+    PopTag();
+    mOutput << startstr << "</node>" << endstr;
 }
 
 #endif
 #endif
-

+ 90 - 64
assimplib.mod/assimp/code/ColladaExporter.h

@@ -2,11 +2,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -23,16 +23,16 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -45,12 +45,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define AI_COLLADAEXPORTER_H_INC
 
 #include "../include/assimp/ai_assert.h"
+#include "../include/assimp/material.h"
+#include "../include/assimp/mesh.h"
+#include "../include/assimp/light.h"
+#include "../include/assimp/Exporter.hpp"
 #include <sstream>
+#include <vector>
+#include <map>
+#include <boost/lexical_cast.hpp>
 
 struct aiScene;
 struct aiNode;
 
-namespace Assimp	
+namespace Assimp
 {
 
 /// Helper class to export a given scene to a Collada file. Just for my personal
@@ -58,97 +65,116 @@ namespace Assimp
 class ColladaExporter
 {
 public:
-	/// Constructor for a specific scene to export
-	ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file);
+    /// Constructor for a specific scene to export
+    ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file);
 
-	/// Destructor
-	virtual ~ColladaExporter();
+    /// Destructor
+    virtual ~ColladaExporter();
 
 protected:
-	/// Starts writing the contents
-	void WriteFile();
+    /// Starts writing the contents
+    void WriteFile();
 
-	/// Writes the asset header
-	void WriteHeader();
+    /// Writes the asset header
+    void WriteHeader();
 
-	/// Writes the embedded textures
-	void WriteTextures();
+    /// Writes the embedded textures
+    void WriteTextures();
 
-	/// Writes the material setup
-	void WriteMaterials();
+    /// Writes the material setup
+    void WriteMaterials();
 
-	/// Writes the geometry library
-	void WriteGeometryLibrary();
+    /// Writes the cameras library
+    void WriteCamerasLibrary();
 
-	/// Writes the given mesh
-	void WriteGeometry( size_t pIndex);
+    // Write a camera entry
+    void WriteCamera(size_t pIndex);
 
-	enum FloatDataType { FloatType_Vector, FloatType_TexCoord2, FloatType_TexCoord3, FloatType_Color };
+    /// Writes the cameras library
+    void WriteLightsLibrary();
 
-	/// Writes a float array of the given type
-	void WriteFloatArray( const std::string& pIdString, FloatDataType pType, const float* pData, size_t pElementCount);
+    // Write a camera entry
+    void WriteLight(size_t pIndex);
+    void WritePointLight(const aiLight *const light);
+    void WriteDirectionalLight(const aiLight *const light);
+    void WriteSpotLight(const aiLight *const light);
+    void WriteAmbienttLight(const aiLight *const light);
 
-	/// Writes the scene library
-	void WriteSceneLibrary();
+    /// Writes the geometry library
+    void WriteGeometryLibrary();
 
-	/// Recursively writes the given node
-	void WriteNode( const aiNode* pNode);
+    /// Writes the given mesh
+    void WriteGeometry( size_t pIndex);
 
-	/// 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); }
+    enum FloatDataType { FloatType_Vector, FloatType_TexCoord2, FloatType_TexCoord3, FloatType_Color };
 
-	/// Creates a mesh ID for the given mesh
-	std::string GetMeshId( size_t pIndex) const { return std::string( "meshId" ) + boost::lexical_cast<std::string> (pIndex); }
+    /// Writes a float array of the given type
+    void WriteFloatArray( const std::string& pIdString, FloatDataType pType, const float* pData, size_t pElementCount);
+
+    /// Writes the scene library
+    void WriteSceneLibrary();
+
+    /// Recursively writes the given node
+    void WriteNode( 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); }
+
+    /// Creates a mesh ID for the given mesh
+    std::string GetMeshId( size_t pIndex) const { return std::string( "meshId" ) + boost::lexical_cast<std::string> (pIndex); }
 
 public:
-	/// Stringstream to write all output into
-	std::stringstream mOutput;
+    /// Stringstream to write all output into
+    std::stringstream mOutput;
 
 protected:
-	/// The IOSystem for output
-	IOSystem* mIOSystem;
+    /// The IOSystem for output
+    IOSystem* mIOSystem;
 
-	/// Path of the directory where the scene will be exported
-	const std::string mPath;
+    /// Path of the directory where the scene will be exported
+    const std::string mPath;
 
-	/// Name of the file (without extension) where the scene will be exported
-	const std::string mFile;
+    /// Name of the file (without extension) where the scene will be exported
+    const std::string mFile;
 
-	/// The scene to be written
-	const aiScene* mScene;
-	bool mSceneOwned;
+    /// The scene to be written
+    const aiScene* mScene;
+    bool mSceneOwned;
 
-	/// current line start string, contains the current indentation for simple stream insertion
-	std::string startstr;
-	/// current line end string for simple stream insertion
-	std::string endstr;
+    /// current line start string, contains the current indentation for simple stream insertion
+    std::string startstr;
+    /// current line end string for simple stream insertion
+    std::string endstr;
 
   // pair of color and texture - texture precedences color
-  struct Surface 
-  { 
+  struct Surface
+  {
     bool exist;
-    aiColor4D color; 
-    std::string texture; 
-    size_t channel; 
+    aiColor4D color;
+    std::string texture;
+    size_t channel;
     Surface() { exist = false; channel = 0; }
   };
 
   struct Property
   {
     bool exist;
-	float value;
-	Property() { exist = false; }
+     float value;
+     Property()
+         : exist(false)
+         , value(0.0f)
+     {}
   };
 
-  // summarize a material in an convinient way. 
+  // summarize a material in an convinient way.
   struct Material
   {
     std::string name;
     std::string shading_model;
     Surface ambient, diffuse, specular, emissive, reflective, transparent, normal;
-   	Property shininess, transparency, index_refraction;
+    Property shininess, transparency, index_refraction;
 
     Material() {}
   };

+ 395 - 371
assimplib.mod/assimp/code/ColladaHelper.h

@@ -4,11 +4,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -25,16 +25,16 @@ 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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -43,149 +43,160 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_COLLADAHELPER_H_INC
 #define AI_COLLADAHELPER_H_INC
 
-namespace Assimp	{
-namespace Collada		{
+#include <string>
+#include <map>
+#include <vector>
+#include <stdint.h>
+#include "../include/assimp/light.h"
+#include "../include/assimp/mesh.h"
+#include "../include/assimp/material.h"
+
+struct aiMaterial;
+
+namespace Assimp    {
+namespace Collada       {
 
 /** Collada file versions which evolved during the years ... */
 enum FormatVersion
 {
-	FV_1_5_n,
-	FV_1_4_n,
-	FV_1_3_n
+    FV_1_5_n,
+    FV_1_4_n,
+    FV_1_3_n
 };
 
 
 /** Transformation types that can be applied to a node */
 enum TransformType
 {
-	TF_LOOKAT,
-	TF_ROTATE,
-	TF_TRANSLATE,
-	TF_SCALE,
-	TF_SKEW,
-	TF_MATRIX
+    TF_LOOKAT,
+    TF_ROTATE,
+    TF_TRANSLATE,
+    TF_SCALE,
+    TF_SKEW,
+    TF_MATRIX
 };
 
 /** Different types of input data to a vertex or face */
 enum InputType
 {
-	IT_Invalid,
-	IT_Vertex,  // special type for per-index data referring to the <vertices> element carrying the per-vertex data.
-	IT_Position,
-	IT_Normal,
-	IT_Texcoord,
-	IT_Color,
-	IT_Tangent,
-	IT_Bitangent
+    IT_Invalid,
+    IT_Vertex,  // special type for per-index data referring to the <vertices> element carrying the per-vertex data.
+    IT_Position,
+    IT_Normal,
+    IT_Texcoord,
+    IT_Color,
+    IT_Tangent,
+    IT_Bitangent
 };
 
 /** Contains all data for one of the different transformation types */
 struct Transform
 {
-	std::string mID;  ///< SID of the transform step, by which anim channels address their target node
-	TransformType mType;
-	float f[16]; ///< Interpretation of data depends on the type of the transformation 
+    std::string mID;  ///< SID of the transform step, by which anim channels address their target node
+    TransformType mType;
+    float f[16]; ///< Interpretation of data depends on the type of the transformation
 };
 
 /** A collada camera. */
 struct Camera
 {
-	Camera()
-		:	mOrtho  (false)
-		,	mHorFov (10e10f)
-		,	mVerFov (10e10f)
-		,	mAspect (10e10f)
-		,	mZNear  (0.1f)
-		,	mZFar   (1000.f)
-	{}
-
-	// Name of camera
-	std::string mName;
+    Camera()
+        :   mOrtho  (false)
+        ,   mHorFov (10e10f)
+        ,   mVerFov (10e10f)
+        ,   mAspect (10e10f)
+        ,   mZNear  (0.1f)
+        ,   mZFar   (1000.f)
+    {}
+
+    // Name of camera
+    std::string mName;
 
-	// True if it is an orthografic camera
-	bool mOrtho;
+    // True if it is an orthografic camera
+    bool mOrtho;
 
-	//! Horizontal field of view in degrees
-	float mHorFov;
+    //! Horizontal field of view in degrees
+    float mHorFov;
 
-	//! Vertical field of view in degrees
-	float mVerFov;
+    //! Vertical field of view in degrees
+    float mVerFov;
 
-	//! Screen aspect
-	float mAspect;
+    //! Screen aspect
+    float mAspect;
 
-	//! Near& far z
-	float mZNear, mZFar;
+    //! Near& far z
+    float mZNear, mZFar;
 };
 
-#define aiLightSource_AMBIENT 0xdeaddead
 #define ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET 1e9f
 
 /** A collada light source. */
 struct Light
-{	
-	Light()
-		:	mAttConstant     (1.f)
-		,	mAttLinear       (0.f)
-		,	mAttQuadratic    (0.f)
-		,	mFalloffAngle    (180.f)
-		,	mFalloffExponent (0.f)
-		,	mPenumbraAngle	 (ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET)
-		,	mOuterAngle		 (ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET)
-		,	mIntensity		 (1.f)
-	{}
-
-	//! Type of the light source aiLightSourceType + ambient
-	unsigned int mType;
-
-	//! Color of the light
-	aiColor3D mColor;
-
-	//! Light attenuation
-	float mAttConstant,mAttLinear,mAttQuadratic;
-
-	//! Spot light falloff
-	float mFalloffAngle;
-	float mFalloffExponent;
-
-	// -----------------------------------------------------
-	// FCOLLADA extension from here
-
-	//! ... related stuff from maja and max extensions
-	float mPenumbraAngle;
-	float mOuterAngle;
-
-	//! Common light intensity
-	float mIntensity;
+{
+    Light()
+        :   mType            (aiLightSource_UNDEFINED)
+        ,   mAttConstant     (1.f)
+        ,   mAttLinear       (0.f)
+        ,   mAttQuadratic    (0.f)
+        ,   mFalloffAngle    (180.f)
+        ,   mFalloffExponent (0.f)
+        ,   mPenumbraAngle   (ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET)
+        ,   mOuterAngle      (ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET)
+        ,   mIntensity       (1.f)
+    {}
+
+    //! Type of the light source aiLightSourceType + ambient
+    unsigned int mType;
+
+    //! Color of the light
+    aiColor3D mColor;
+
+    //! Light attenuation
+    float mAttConstant,mAttLinear,mAttQuadratic;
+
+    //! Spot light falloff
+    float mFalloffAngle;
+    float mFalloffExponent;
+
+    // -----------------------------------------------------
+    // FCOLLADA extension from here
+
+    //! ... related stuff from maja and max extensions
+    float mPenumbraAngle;
+    float mOuterAngle;
+
+    //! Common light intensity
+    float mIntensity;
 };
 
 /** Short vertex index description */
 struct InputSemanticMapEntry
 {
-	InputSemanticMapEntry()
-		:	mSet	(0)
-	{}
+    InputSemanticMapEntry()
+        :   mSet(0)
+        ,   mType(IT_Invalid)
+    {}
 
-	//! Index of set, optional
-	unsigned int mSet;
+    //! Index of set, optional
+    unsigned int mSet;
 
-	//! Name of referenced vertex input
-	InputType mType;
+    //! Type of referenced vertex input
+    InputType mType;
 };
 
 /** Table to map from effect to vertex input semantics */
 struct SemanticMappingTable
 {
-	//! Name of material
-	std::string mMatName;
+    //! Name of material
+    std::string mMatName;
 
-	//! List of semantic map commands, grouped by effect semantic name
-	std::map<std::string, InputSemanticMapEntry> mMap;
+    //! List of semantic map commands, grouped by effect semantic name
+    std::map<std::string, InputSemanticMapEntry> mMap;
 
-	//! For std::find
-	bool operator == (const std::string& s) const {
-		return s == mMatName;
-	}
+    //! For std::find
+    bool operator == (const std::string& s) const {
+        return s == mMatName;
+    }
 };
 
 /** A reference to a mesh inside a node, including materials assigned to the various subgroups.
@@ -193,409 +204,422 @@ struct SemanticMappingTable
  */
 struct MeshInstance
 {
-	///< ID of the mesh or controller to be instanced
-	std::string mMeshOrController;
+    ///< ID of the mesh or controller to be instanced
+    std::string mMeshOrController;
 
-	///< Map of materials by the subgroup ID they're applied to
-	std::map<std::string, SemanticMappingTable> mMaterials;
+    ///< Map of materials by the subgroup ID they're applied to
+    std::map<std::string, SemanticMappingTable> mMaterials;
 };
 
 /** A reference to a camera inside a node*/
 struct CameraInstance
 {
-	 ///< ID of the camera
-	std::string mCamera;
+     ///< ID of the camera
+    std::string mCamera;
 };
 
 /** A reference to a light inside a node*/
 struct LightInstance
 {
-	 ///< ID of the camera
-	std::string mLight;
+     ///< ID of the camera
+    std::string mLight;
 };
 
 /** A reference to a node inside a node*/
 struct NodeInstance
 {
-	 ///< ID of the node
-	std::string mNode;
+     ///< ID of the node
+    std::string mNode;
 };
 
 /** A node in a scene hierarchy */
 struct Node
 {
-	std::string mName;
-	std::string mID;
-  std::string mSID;
-	Node* mParent;
-	std::vector<Node*> mChildren;
+    std::string mName;
+    std::string mID;
+    std::string mSID;
+    Node* mParent;
+    std::vector<Node*> mChildren;
 
-	/** Operations in order to calculate the resulting transformation to parent. */
-	std::vector<Transform> mTransforms;
+    /** Operations in order to calculate the resulting transformation to parent. */
+    std::vector<Transform> mTransforms;
 
-	/** Meshes at this node */
-	std::vector<MeshInstance> mMeshes;    
+    /** Meshes at this node */
+    std::vector<MeshInstance> mMeshes;
 
-	/** Lights at this node */
-	std::vector<LightInstance> mLights;  
+    /** Lights at this node */
+    std::vector<LightInstance> mLights;
 
-	/** Cameras at this node */
-	std::vector<CameraInstance> mCameras; 
+    /** Cameras at this node */
+    std::vector<CameraInstance> mCameras;
 
-	/** Node instances at this node */
-	std::vector<NodeInstance> mNodeInstances;
+    /** Node instances at this node */
+    std::vector<NodeInstance> mNodeInstances;
 
-	/** Rootnodes: Name of primary camera, if any */
-	std::string mPrimaryCamera;
+    /** Rootnodes: Name of primary camera, if any */
+    std::string mPrimaryCamera;
 
-	//! Constructor. Begin with a zero parent
-	Node() { 
-		mParent = NULL;
-	}
+    //! Constructor. Begin with a zero parent
+    Node() {
+        mParent = NULL;
+    }
 
-	//! Destructor: delete all children subsequently
-	~Node() { 
-		for( std::vector<Node*>::iterator it = mChildren.begin(); it != mChildren.end(); ++it) 
-			delete *it; 
-	}
+    //! Destructor: delete all children subsequently
+    ~Node() {
+        for( std::vector<Node*>::iterator it = mChildren.begin(); it != mChildren.end(); ++it)
+            delete *it;
+    }
 };
 
 /** Data source array: either floats or strings */
 struct Data
 {
-	bool mIsStringArray;
-	std::vector<float> mValues;
-	std::vector<std::string> mStrings;
+    bool mIsStringArray;
+    std::vector<float> mValues;
+    std::vector<std::string> mStrings;
 };
 
 /** Accessor to a data array */
 struct Accessor
 {
-	size_t mCount;   // in number of objects
-	size_t mSize;    // size of an object, in elements (floats or strings, mostly 1)
-	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.
-						  // 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
-
-	Accessor() 
-	{ 
-		mCount = 0; mSize = 0; mOffset = 0; mStride = 0; mData = NULL; 
-		mSubOffset[0] = mSubOffset[1] = mSubOffset[2] = mSubOffset[3] = 0;
-	}
+    size_t mCount;   // in number of objects
+    size_t mSize;    // size of an object, in elements (floats or strings, mostly 1)
+    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.
+                          // 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
+
+    Accessor()
+    {
+        mCount = 0; mSize = 0; mOffset = 0; mStride = 0; mData = NULL;
+        mSubOffset[0] = mSubOffset[1] = mSubOffset[2] = mSubOffset[3] = 0;
+    }
 };
 
 /** A single face in a mesh */
 struct Face
 {
-	std::vector<size_t> mIndices;
+    std::vector<size_t> mIndices;
 };
 
 /** An input channel for mesh data, referring to a single accessor */
 struct InputChannel
 {
-	InputType mType;      // Type of the data
-	size_t mIndex;		  // Optional index, if multiple sets of the same data type are given
-	size_t mOffset;       // Index offset in the indices array of per-face indices. Don't ask, can't explain that any better.
-	std::string mAccessor; // ID of the accessor where to read the actual values from.
-	mutable const Accessor* mResolved; // Pointer to the accessor, if resolved. NULL else
+    InputType mType;      // Type of the data
+    size_t mIndex;        // Optional index, if multiple sets of the same data type are given
+    size_t mOffset;       // Index offset in the indices array of per-face indices. Don't ask, can't explain that any better.
+    std::string mAccessor; // ID of the accessor where to read the actual values from.
+    mutable const Accessor* mResolved; // Pointer to the accessor, if resolved. NULL else
 
-	InputChannel() { mType = IT_Invalid; mIndex = 0; mOffset = 0; mResolved = NULL; }
+    InputChannel() { mType = IT_Invalid; mIndex = 0; mOffset = 0; mResolved = NULL; }
 };
 
 /** Subset of a mesh with a certain material */
 struct SubMesh
 {
-	std::string mMaterial; ///< subgroup identifier
-	size_t mNumFaces; ///< number of faces in this submesh
+    std::string mMaterial; ///< subgroup identifier
+    size_t mNumFaces; ///< number of faces in this submesh
 };
 
 /** Contains data for a single mesh */
 struct Mesh
 {
-	Mesh()
-	{
-		for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
-			mNumUVComponents[i] = 2;
-	}
-    
+    Mesh()
+    {
+        for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
+            mNumUVComponents[i] = 2;
+    }
+
     std::string mName;
 
-	// just to check if there's some sophisticated addressing involved...
-	// which we don't support, and therefore should warn about.
-	std::string mVertexID; 
-
-	// Vertex data addressed by vertex indices
-	std::vector<InputChannel> mPerVertexData; 
-
-	// actual mesh data, assembled on encounter of a <p> element. Verbose format, not indexed
-	std::vector<aiVector3D> mPositions;
-	std::vector<aiVector3D> mNormals;
-	std::vector<aiVector3D> mTangents;
-	std::vector<aiVector3D> mBitangents;
-	std::vector<aiVector3D> mTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
-	std::vector<aiColor4D>  mColors[AI_MAX_NUMBER_OF_COLOR_SETS];
-
-	unsigned int mNumUVComponents[AI_MAX_NUMBER_OF_TEXTURECOORDS];
-
-	// Faces. Stored are only the number of vertices for each face.
-	// 1 == point, 2 == line, 3 == triangle, 4+ == poly
-	std::vector<size_t> mFaceSize;
-	
-	// Position indices for all faces in the sequence given in mFaceSize - 
-	// necessary for bone weight assignment
-	std::vector<size_t> mFacePosIndices;
-
-	// Submeshes in this mesh, each with a given material
-	std::vector<SubMesh> mSubMeshes;
+    // just to check if there's some sophisticated addressing involved...
+    // which we don't support, and therefore should warn about.
+    std::string mVertexID;
+
+    // Vertex data addressed by vertex indices
+    std::vector<InputChannel> mPerVertexData;
+
+    // actual mesh data, assembled on encounter of a <p> element. Verbose format, not indexed
+    std::vector<aiVector3D> mPositions;
+    std::vector<aiVector3D> mNormals;
+    std::vector<aiVector3D> mTangents;
+    std::vector<aiVector3D> mBitangents;
+    std::vector<aiVector3D> mTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+    std::vector<aiColor4D>  mColors[AI_MAX_NUMBER_OF_COLOR_SETS];
+
+    unsigned int mNumUVComponents[AI_MAX_NUMBER_OF_TEXTURECOORDS];
+
+    // Faces. Stored are only the number of vertices for each face.
+    // 1 == point, 2 == line, 3 == triangle, 4+ == poly
+    std::vector<size_t> mFaceSize;
+
+    // Position indices for all faces in the sequence given in mFaceSize -
+    // necessary for bone weight assignment
+    std::vector<size_t> mFacePosIndices;
+
+    // Submeshes in this mesh, each with a given material
+    std::vector<SubMesh> mSubMeshes;
 };
 
 /** Which type of primitives the ReadPrimitives() function is going to read */
 enum PrimitiveType
 {
-	Prim_Invalid,
-	Prim_Lines,
-	Prim_LineStrip,
-	Prim_Triangles,
-	Prim_TriStrips,
-	Prim_TriFans,
-	Prim_Polylist,
-	Prim_Polygon
+    Prim_Invalid,
+    Prim_Lines,
+    Prim_LineStrip,
+    Prim_Triangles,
+    Prim_TriStrips,
+    Prim_TriFans,
+    Prim_Polylist,
+    Prim_Polygon
 };
 
 /** A skeleton controller to deform a mesh with the use of joints */
 struct Controller
 {
-	// the URL of the mesh deformed by the controller.
-	std::string mMeshId; 
+    // the URL of the mesh deformed by the controller.
+    std::string mMeshId;
 
-	// accessor URL of the joint names
-	std::string mJointNameSource;
+    // accessor URL of the joint names
+    std::string mJointNameSource;
 
-  ///< The bind shape matrix, as array of floats. I'm not sure what this matrix actually describes, but it can't be ignored in all cases
-  float mBindShapeMatrix[16];
+    ///< The bind shape matrix, as array of floats. I'm not sure what this matrix actually describes, but it can't be ignored in all cases
+    float mBindShapeMatrix[16];
 
-	// accessor URL of the joint inverse bind matrices
-	std::string mJointOffsetMatrixSource;
+    // accessor URL of the joint inverse bind matrices
+    std::string mJointOffsetMatrixSource;
 
-	// input channel: joint names. 
-	InputChannel mWeightInputJoints;
-	// input channel: joint weights
-	InputChannel mWeightInputWeights;
+    // input channel: joint names.
+    InputChannel mWeightInputJoints;
+    // input channel: joint weights
+    InputChannel mWeightInputWeights;
 
-	// Number of weights per vertex.
-	std::vector<size_t> mWeightCounts;
+    // Number of weights per vertex.
+    std::vector<size_t> mWeightCounts;
 
-	// JointIndex-WeightIndex pairs for all vertices
-	std::vector< std::pair<size_t, size_t> > mWeights;
+    // JointIndex-WeightIndex pairs for all vertices
+    std::vector< std::pair<size_t, size_t> > mWeights;
 };
 
 /** A collada material. Pretty much the only member is a reference to an effect. */
 struct Material
 {
-	std::string mEffect;
+    std::string mName;
+    std::string mEffect;
 };
 
 /** Type of the effect param */
 enum ParamType
 {
-	Param_Sampler,
-	Param_Surface
+    Param_Sampler,
+    Param_Surface
 };
 
 /** A param for an effect. Might be of several types, but they all just refer to each other, so I summarize them */
 struct EffectParam
 {
-	ParamType mType;
-	std::string mReference; // to which other thing the param is referring to. 
+    ParamType mType;
+    std::string mReference; // to which other thing the param is referring to.
 };
 
 /** Shading type supported by the standard effect spec of Collada */
 enum ShadeType
 {
-	Shade_Invalid,
-	Shade_Constant,
-	Shade_Lambert,
-	Shade_Phong,
-	Shade_Blinn
+    Shade_Invalid,
+    Shade_Constant,
+    Shade_Lambert,
+    Shade_Phong,
+    Shade_Blinn
 };
 
 /** Represents a texture sampler in collada */
 struct Sampler
 {
-	Sampler()
-		:	mWrapU		(true)
-		,	mWrapV		(true)
-		,	mMirrorU	()
-		,	mMirrorV	()
-		,	mOp			(aiTextureOp_Multiply)
-		,	mUVId		(UINT_MAX)
-		,	mWeighting  (1.f)
-		,	mMixWithPrevious (1.f)
-	{}
-
-	/** Name of image reference
-	 */
-	std::string mName;
-
-	/** Wrap U?
-	 */
-	bool mWrapU;
-
-	/** Wrap V?
-	 */
-	bool mWrapV;
-
-	/** Mirror U?
-	 */
-	bool mMirrorU;
-
-	/** Mirror V?
-	 */
-	bool mMirrorV;
-
-	/** Blend mode
-	 */
-	aiTextureOp mOp;
-
-	/** UV transformation
-	 */
-	aiUVTransform mTransform;
-
-	/** Name of source UV channel
-	 */
-	std::string mUVChannel;
-
-	/** Resolved UV channel index or UINT_MAX if not known
-	 */
-	unsigned int mUVId;
-
-	// OKINO/MAX3D extensions from here
-	// -------------------------------------------------------
-
-	/** Weighting factor
-	 */
-	float mWeighting;
-
-	/** Mixing factor from OKINO
-	 */
-	float mMixWithPrevious;
+    Sampler()
+        :   mWrapU      (true)
+        ,   mWrapV      (true)
+        ,   mMirrorU    ()
+        ,   mMirrorV    ()
+        ,   mOp         (aiTextureOp_Multiply)
+        ,   mUVId       (UINT_MAX)
+        ,   mWeighting  (1.f)
+        ,   mMixWithPrevious (1.f)
+    {}
+
+    /** Name of image reference
+     */
+    std::string mName;
+
+    /** Wrap U?
+     */
+    bool mWrapU;
+
+    /** Wrap V?
+     */
+    bool mWrapV;
+
+    /** Mirror U?
+     */
+    bool mMirrorU;
+
+    /** Mirror V?
+     */
+    bool mMirrorV;
+
+    /** Blend mode
+     */
+    aiTextureOp mOp;
+
+    /** UV transformation
+     */
+    aiUVTransform mTransform;
+
+    /** Name of source UV channel
+     */
+    std::string mUVChannel;
+
+    /** Resolved UV channel index or UINT_MAX if not known
+     */
+    unsigned int mUVId;
+
+    // OKINO/MAX3D extensions from here
+    // -------------------------------------------------------
+
+    /** Weighting factor
+     */
+    float mWeighting;
+
+    /** Mixing factor from OKINO
+     */
+    float mMixWithPrevious;
 };
 
 /** A collada effect. Can contain about anything according to the Collada spec,
     but we limit our version to a reasonable subset. */
 struct Effect
 {
-	// Shading mode
-	ShadeType mShadeType;
-
-	// Colors
-	aiColor4D mEmissive, mAmbient, mDiffuse, mSpecular,
-		mTransparent, mReflective;
-
-	// Textures
-	Sampler mTexEmissive, mTexAmbient, mTexDiffuse, mTexSpecular,
-		mTexTransparent, mTexBump, mTexReflective;
-
-	// Scalar factory
-	float mShininess, mRefractIndex, mReflectivity;
-	float mTransparency;
-
-	// local params referring to each other by their SID
-	typedef std::map<std::string, Collada::EffectParam> ParamLibrary;
-	ParamLibrary mParams;
-
-	// MAX3D extensions
-	// ---------------------------------------------------------
-	// Double-sided?
-	bool mDoubleSided, mWireframe, mFaceted;
-	
-	Effect()
-		: mShadeType    (Shade_Phong)
-		, mEmissive		( 0, 0, 0, 1)
-		, mAmbient		( 0.1f, 0.1f, 0.1f, 1)
-		, mDiffuse		( 0.6f, 0.6f, 0.6f, 1)
-		, mSpecular		( 0.4f, 0.4f, 0.4f, 1)
-		, mTransparent	( 0, 0, 0, 1)
-		, mShininess    (10.0f)
-		, mRefractIndex (1.f)
-		, mReflectivity (1.f)
-		, mTransparency (0.f)
-		, mDoubleSided	(false)
-		, mWireframe    (false)
-		, mFaceted      (false)
-	{ 
-	}
+    // Shading mode
+    ShadeType mShadeType;
+
+    // Colors
+    aiColor4D mEmissive, mAmbient, mDiffuse, mSpecular,
+        mTransparent, mReflective;
+
+    // Textures
+    Sampler mTexEmissive, mTexAmbient, mTexDiffuse, mTexSpecular,
+        mTexTransparent, mTexBump, mTexReflective;
+
+    // Scalar factory
+    float mShininess, mRefractIndex, mReflectivity;
+    float mTransparency;
+    bool mHasTransparency;
+    bool mRGBTransparency;
+
+    // local params referring to each other by their SID
+    typedef std::map<std::string, Collada::EffectParam> ParamLibrary;
+    ParamLibrary mParams;
+
+    // MAX3D extensions
+    // ---------------------------------------------------------
+    // Double-sided?
+    bool mDoubleSided, mWireframe, mFaceted;
+
+    Effect()
+        : mShadeType    (Shade_Phong)
+        , mEmissive     ( 0, 0, 0, 1)
+        , mAmbient      ( 0.1f, 0.1f, 0.1f, 1)
+        , mDiffuse      ( 0.6f, 0.6f, 0.6f, 1)
+        , mSpecular     ( 0.4f, 0.4f, 0.4f, 1)
+        , mTransparent  ( 0, 0, 0, 1)
+        , mShininess    (10.0f)
+        , mRefractIndex (1.f)
+        , mReflectivity (1.f)
+        , mTransparency (1.f)
+        , mHasTransparency (false)
+        , mRGBTransparency(false)
+        , mDoubleSided  (false)
+        , mWireframe    (false)
+        , mFaceted      (false)
+    {
+    }
 };
 
 /** An image, meaning texture */
 struct Image
 {
-	std::string mFileName;
+    std::string mFileName;
 
-	/** If image file name is zero, embedded image data
-	 */
-	std::vector<uint8_t> mImageData;
+    /** If image file name is zero, embedded image data
+     */
+    std::vector<uint8_t> mImageData;
 
-	/** If image file name is zero, file format of
-	 *  embedded image data.
-	 */
-	std::string mEmbeddedFormat;
+    /** If image file name is zero, file format of
+     *  embedded image data.
+     */
+    std::string mEmbeddedFormat;
 
 };
 
 /** An animation channel. */
 struct AnimationChannel
 {
-	/** URL of the data to animate. Could be about anything, but we support only the 
-	 * "NodeID/TransformID.SubElement" notation 
-	 */
-	std::string mTarget;
-
-	/** Source URL of the time values. Collada calls them "input". Meh. */
-	std::string mSourceTimes;
-	/** Source URL of the value values. Collada calls them "output". */
-	std::string mSourceValues;
+    /** URL of the data to animate. Could be about anything, but we support only the
+     * "NodeID/TransformID.SubElement" notation
+     */
+    std::string mTarget;
+
+    /** Source URL of the time values. Collada calls them "input". Meh. */
+    std::string mSourceTimes;
+    /** Source URL of the value values. Collada calls them "output". */
+    std::string mSourceValues;
 };
 
 /** An animation. Container for 0-x animation channels or 0-x animations */
 struct Animation
 {
-	/** Anim name */
-	std::string mName;
+    /** Anim name */
+    std::string mName;
 
-	/** the animation channels, if any */
-	std::vector<AnimationChannel> mChannels;
+    /** the animation channels, if any */
+    std::vector<AnimationChannel> mChannels;
 
-	/** the sub-animations, if any */
-	std::vector<Animation*> mSubAnims;
+    /** the sub-animations, if any */
+    std::vector<Animation*> mSubAnims;
 
-	/** Destructor */
-	~Animation()
-	{
-		for( std::vector<Animation*>::iterator it = mSubAnims.begin(); it != mSubAnims.end(); ++it)
-			delete *it;
-	}
+    /** Destructor */
+    ~Animation()
+    {
+        for( std::vector<Animation*>::iterator it = mSubAnims.begin(); it != mSubAnims.end(); ++it)
+            delete *it;
+    }
 };
 
 /** Description of a collada animation channel which has been determined to affect the current node */
 struct ChannelEntry
 {
-	const Collada::AnimationChannel* mChannel; ///> the source channel
-	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
-
-	// resolved data references
-	const Collada::Accessor* mTimeAccessor; ///> Collada accessor to the time values
-	const Collada::Data* mTimeData; ///> Source data array for the time values
-	const Collada::Accessor* mValueAccessor; ///> Collada accessor to the key value values
-	const Collada::Data* mValueData; ///> Source datat array for the key value values
-
-	ChannelEntry() { mChannel = NULL; mSubElement = 0; }
+    const Collada::AnimationChannel* mChannel; ///> the source channel
+    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
+
+    // resolved data references
+    const Collada::Accessor* mTimeAccessor; ///> Collada accessor to the time values
+    const Collada::Data* mTimeData; ///> Source data array for the time values
+    const Collada::Accessor* mValueAccessor; ///> Collada accessor to the key value values
+    const Collada::Data* mValueData; ///> Source datat array for the key value values
+
+    ChannelEntry()
+      : mChannel()
+      , mTransformIndex()
+      , mSubElement()
+      , mTimeAccessor()
+      , mTimeData()
+      , mValueAccessor()
+      , mValueData()
+   {}
 };
 
 } // end of namespace Collada

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1259 - 1188
assimplib.mod/assimp/code/ColladaLoader.cpp


+ 181 - 171
assimplib.mod/assimp/code/ColladaLoader.h

@@ -4,11 +4,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -25,16 +25,16 @@ 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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -46,195 +46,205 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "BaseImporter.h"
 #include "ColladaParser.h"
 
+struct aiNode;
+struct aiCamera;
+struct aiLight;
+struct aiTexture;
+struct aiAnimation;
+
 namespace Assimp
 {
 
 struct ColladaMeshIndex
 {
-	std::string mMeshID;
-	size_t mSubMesh;
-	std::string mMaterial;
-	ColladaMeshIndex( const std::string& pMeshID, size_t pSubMesh, const std::string& pMaterial) 
-		: mMeshID( pMeshID), mSubMesh( pSubMesh), mMaterial( pMaterial)
-	{   }
-
-	bool operator < (const ColladaMeshIndex& p) const
-	{
-		if( mMeshID == p.mMeshID) 
-		{
-			if( mSubMesh == p.mSubMesh)
-				return mMaterial < p.mMaterial;
-			else 
-				return mSubMesh < p.mSubMesh;
-		} else
-		{
-			return mMeshID < p.mMeshID;
-		}
-	}
+    std::string mMeshID;
+    size_t mSubMesh;
+    std::string mMaterial;
+    ColladaMeshIndex( const std::string& pMeshID, size_t pSubMesh, const std::string& pMaterial)
+        : mMeshID( pMeshID), mSubMesh( pSubMesh), mMaterial( pMaterial)
+    {   }
+
+    bool operator < (const ColladaMeshIndex& p) const
+    {
+        if( mMeshID == p.mMeshID)
+        {
+            if( mSubMesh == p.mSubMesh)
+                return mMaterial < p.mMaterial;
+            else
+                return mSubMesh < p.mSubMesh;
+        } else
+        {
+            return mMeshID < p.mMeshID;
+        }
+    }
 };
 
 /** Loader class to read Collada scenes. Collada is over-engineered to death, with every new iteration bringing
- * more useless stuff, so I limited the data to what I think is useful for games. 
+ * more useless stuff, so I limited the data to what I think is useful for games.
 */
 class ColladaLoader : public BaseImporter
 {
 public:
-	ColladaLoader();
-	~ColladaLoader();
+    ColladaLoader();
+    ~ColladaLoader();
 
 
 public:
-	/** Returns whether the class can handle the format of the given file. 
-	 * See BaseImporter::CanRead() for details.	*/
-	bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
+    /** Returns whether the class can handle the format of the given file.
+     * See BaseImporter::CanRead() for details. */
+    bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
 
 protected:
-	/** Return importer meta information.
-	 * See #BaseImporter::GetInfo for the details
-	 */
-	const aiImporterDesc* GetInfo () const;
-
-	void SetupProperties(const Importer* pImp);
-
-	/** Imports the given file into the given scene structure. 
-	 * See BaseImporter::InternReadFile() for details
-	 */
-	void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
-
-	/** Recursively constructs a scene node for the given parser node and returns it. */
-	aiNode* BuildHierarchy( const ColladaParser& pParser, const Collada::Node* pNode);
-
-	/** Resolve node instances */
-	void ResolveNodeInstances( const ColladaParser& pParser, const Collada::Node* pNode,
-		std::vector<const Collada::Node*>& resolved);
-
-	/** Builds meshes for the given node and references them */
-	void BuildMeshesForNode( const ColladaParser& pParser, const Collada::Node* pNode, 
-		aiNode* pTarget);
-
-	/** 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, 
-		const Collada::Controller* pSrcController, size_t pStartVertex, size_t pStartFace);
-
-	/** Builds cameras for the given node and references them */
-	void BuildCamerasForNode( const ColladaParser& pParser, const Collada::Node* pNode, 
-		aiNode* pTarget);
-
-	/** Builds lights for the given node and references them */
-	void BuildLightsForNode( const ColladaParser& pParser, const Collada::Node* pNode, 
-		aiNode* pTarget);
-
-	/** Stores all meshes in the given scene */
-	void StoreSceneMeshes( aiScene* pScene);
-
-	/** Stores all materials in the given scene */
-	void StoreSceneMaterials( aiScene* pScene);
-
-	/** Stores all lights in the given scene */
-	void StoreSceneLights( aiScene* pScene);
-
-	/** Stores all cameras in the given scene */
-	void StoreSceneCameras( aiScene* pScene);
-
-	/** Stores all textures in the given scene */
-	void StoreSceneTextures( aiScene* pScene);
-
-	/** Stores all animations 
-	 * @param pScene target scene to store the anims
-	 */
-	void StoreAnimations( aiScene* pScene, const ColladaParser& pParser);
-
-	/** Stores all animations for the given source anim and its nested child animations
-	 * @param pScene target scene to store the anims
-	 * @param pSrcAnim the source animation to process
-	 * @param pPrefix Prefix to the name in case of nested animations
-	 */
-	void StoreAnimations( aiScene* pScene, const ColladaParser& pParser, const Collada::Animation* pSrcAnim, const std::string pPrefix);
-
-	/** Constructs the animation for the given source anim */
-	void CreateAnimation( aiScene* pScene, const ColladaParser& pParser, const Collada::Animation* pSrcAnim, const std::string& pName);
-	
-	/** Constructs materials from the collada material definitions */
-	void BuildMaterials( ColladaParser& pParser, aiScene* pScene);
-
-	/** Fill materials from the collada material definitions */
-	void FillMaterials( const ColladaParser& pParser, aiScene* pScene);
-
-	/** Resolve UV channel mappings*/
-	void ApplyVertexToEffectSemanticMapping(Collada::Sampler& sampler,
-		const Collada::SemanticMappingTable& table);
-
-	/** Add a texture and all of its sampling properties to a material*/
-	void AddTexture ( aiMaterial& mat, const ColladaParser& pParser,
-		const Collada::Effect& effect,
-		const Collada::Sampler& sampler,
-		aiTextureType type, unsigned int idx = 0);
-
-	/** Resolves the texture name for the given effect texture entry */
-	aiString FindFilenameForEffectTexture( const ColladaParser& pParser, 
-		const Collada::Effect& pEffect, const std::string& pName);
-
-	/** Converts a path read from a collada file to the usual representation */
-	void ConvertPath( aiString& ss);
-
-	/** Reads a float value from an accessor and its data array.
-	 * @param pAccessor The accessor to use for reading
-	 * @param pData The data array to read from
-	 * @param pIndex The index of the element to retrieve
-	 * @param pOffset Offset into the element, for multipart elements such as vectors or matrices
-	 * @return the specified value
-	 */
-	float ReadFloat( const Collada::Accessor& pAccessor, const Collada::Data& pData, size_t pIndex, size_t pOffset) const;
-
-	/** Reads a string value from an accessor and its data array.
-	 * @param pAccessor The accessor to use for reading
-	 * @param pData The data array to read from
-	 * @param pIndex The index of the element to retrieve
-	 * @return the specified value
-	 */
-	const std::string& ReadString( const Collada::Accessor& pAccessor, const Collada::Data& pData, size_t pIndex) const;
-
-	/** Recursively collects all nodes into the given array */
-	void CollectNodes( const aiNode* pNode, std::vector<const aiNode*>& poNodes) const;
-
-	/** Finds a node in the collada scene by the given name */
-	const Collada::Node* FindNode( const Collada::Node* pNode, const std::string& pName) const;
-	/** Finds a node in the collada scene by the given SID */
-	const Collada::Node* FindNodeBySID( const Collada::Node* pNode, const std::string& pSID) const;
-
-	/** Finds a proper name for a node derived from the collada-node's properties */
-	std::string FindNameForNode( const Collada::Node* pNode) const;
+    /** Return importer meta information.
+     * See #BaseImporter::GetInfo for the details
+     */
+    const aiImporterDesc* GetInfo () const;
+
+    void SetupProperties(const Importer* pImp);
+
+    /** Imports the given file into the given scene structure.
+     * See BaseImporter::InternReadFile() for details
+     */
+    void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
+
+    /** Recursively constructs a scene node for the given parser node and returns it. */
+    aiNode* BuildHierarchy( const ColladaParser& pParser, const Collada::Node* pNode);
+
+    /** Resolve node instances */
+    void ResolveNodeInstances( const ColladaParser& pParser, const Collada::Node* pNode,
+        std::vector<const Collada::Node*>& resolved);
+
+    /** Builds meshes for the given node and references them */
+    void BuildMeshesForNode( const ColladaParser& pParser, const Collada::Node* pNode,
+        aiNode* pTarget);
+
+    /** 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,
+        const Collada::Controller* pSrcController, size_t pStartVertex, size_t pStartFace);
+
+    /** Builds cameras for the given node and references them */
+    void BuildCamerasForNode( const ColladaParser& pParser, const Collada::Node* pNode,
+        aiNode* pTarget);
+
+    /** Builds lights for the given node and references them */
+    void BuildLightsForNode( const ColladaParser& pParser, const Collada::Node* pNode,
+        aiNode* pTarget);
+
+    /** Stores all meshes in the given scene */
+    void StoreSceneMeshes( aiScene* pScene);
+
+    /** Stores all materials in the given scene */
+    void StoreSceneMaterials( aiScene* pScene);
+
+    /** Stores all lights in the given scene */
+    void StoreSceneLights( aiScene* pScene);
+
+    /** Stores all cameras in the given scene */
+    void StoreSceneCameras( aiScene* pScene);
+
+    /** Stores all textures in the given scene */
+    void StoreSceneTextures( aiScene* pScene);
+
+    /** Stores all animations
+     * @param pScene target scene to store the anims
+     */
+    void StoreAnimations( aiScene* pScene, const ColladaParser& pParser);
+
+    /** Stores all animations for the given source anim and its nested child animations
+     * @param pScene target scene to store the anims
+     * @param pSrcAnim the source animation to process
+     * @param pPrefix Prefix to the name in case of nested animations
+     */
+    void StoreAnimations( aiScene* pScene, const ColladaParser& pParser, const Collada::Animation* pSrcAnim, const std::string& pPrefix);
+
+    /** Constructs the animation for the given source anim */
+    void CreateAnimation( aiScene* pScene, const ColladaParser& pParser, const Collada::Animation* pSrcAnim, const std::string& pName);
+
+    /** Constructs materials from the collada material definitions */
+    void BuildMaterials( ColladaParser& pParser, aiScene* pScene);
+
+    /** Fill materials from the collada material definitions */
+    void FillMaterials( const ColladaParser& pParser, aiScene* pScene);
+
+    /** Resolve UV channel mappings*/
+    void ApplyVertexToEffectSemanticMapping(Collada::Sampler& sampler,
+        const Collada::SemanticMappingTable& table);
+
+    /** Add a texture and all of its sampling properties to a material*/
+    void AddTexture ( aiMaterial& mat, const ColladaParser& pParser,
+        const Collada::Effect& effect,
+        const Collada::Sampler& sampler,
+        aiTextureType type, unsigned int idx = 0);
+
+    /** Resolves the texture name for the given effect texture entry */
+    aiString FindFilenameForEffectTexture( const ColladaParser& pParser,
+        const Collada::Effect& pEffect, const std::string& pName);
+
+    /** Converts a path read from a collada file to the usual representation */
+    void ConvertPath( aiString& ss);
+
+    /** Reads a float value from an accessor and its data array.
+     * @param pAccessor The accessor to use for reading
+     * @param pData The data array to read from
+     * @param pIndex The index of the element to retrieve
+     * @param pOffset Offset into the element, for multipart elements such as vectors or matrices
+     * @return the specified value
+     */
+    float ReadFloat( const Collada::Accessor& pAccessor, const Collada::Data& pData, size_t pIndex, size_t pOffset) const;
+
+    /** Reads a string value from an accessor and its data array.
+     * @param pAccessor The accessor to use for reading
+     * @param pData The data array to read from
+     * @param pIndex The index of the element to retrieve
+     * @return the specified value
+     */
+    const std::string& ReadString( const Collada::Accessor& pAccessor, const Collada::Data& pData, size_t pIndex) const;
+
+    /** Recursively collects all nodes into the given array */
+    void CollectNodes( const aiNode* pNode, std::vector<const aiNode*>& poNodes) const;
+
+    /** Finds a node in the collada scene by the given name */
+    const Collada::Node* FindNode( const Collada::Node* pNode, const std::string& pName) const;
+    /** Finds a node in the collada scene by the given SID */
+    const Collada::Node* FindNodeBySID( const Collada::Node* pNode, const std::string& pSID) const;
+
+    /** Finds a proper name for a node derived from the collada-node's properties */
+    std::string FindNameForNode( const Collada::Node* pNode);
 
 protected:
-	/** Filename, for a verbose error message */
-	std::string mFileName;
+    /** Filename, for a verbose error message */
+    std::string mFileName;
+
+    /** Which mesh-material compound was stored under which mesh ID */
+    std::map<ColladaMeshIndex, size_t> mMeshIndexByID;
 
-	/** Which mesh-material compound was stored under which mesh ID */
-	std::map<ColladaMeshIndex, size_t> mMeshIndexByID;
+    /** Which material was stored under which index in the scene */
+    std::map<std::string, size_t> mMaterialIndexByName;
 
-	/** Which material was stored under which index in the scene */
-	std::map<std::string, size_t> mMaterialIndexByName;
+    /** Accumulated meshes for the target scene */
+    std::vector<aiMesh*> mMeshes;
 
-	/** Accumulated meshes for the target scene */
-	std::vector<aiMesh*> mMeshes;
+    /** Temporary material list */
+    std::vector<std::pair<Collada::Effect*, aiMaterial*> > newMats;
 
-	/** Temporary material list */
-	std::vector<std::pair<Collada::Effect*, aiMaterial*> > newMats;
+    /** Temporary camera list */
+    std::vector<aiCamera*> mCameras;
 
-	/** Temporary camera list */
-	std::vector<aiCamera*> mCameras;
+    /** Temporary light list */
+    std::vector<aiLight*> mLights;
 
-	/** Temporary light list */
-	std::vector<aiLight*> mLights;
+    /** Temporary texture list */
+    std::vector<aiTexture*> mTextures;
 
-	/** Temporary texture list */
-	std::vector<aiTexture*> mTextures;
+    /** Accumulated animations for the target scene */
+    std::vector<aiAnimation*> mAnims;
 
-	/** Accumulated animations for the target scene */
-	std::vector<aiAnimation*> mAnims;
+    bool noSkeletonMesh;
+    bool ignoreUpDirection;
+    bool invertTransparency;
 
-	bool noSkeletonMesh;
-	bool ignoreUpDirection;
+    /** Used by FindNameForNode() to generate unique node names */
+    unsigned int mNodeNameCounter;
 };
 
 } // end of namespace Assimp

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 1316 - 1253
assimplib.mod/assimp/code/ColladaParser.cpp


+ 337 - 325
assimplib.mod/assimp/code/ColladaParser.h

@@ -1,45 +1,45 @@
 /*
-Open Asset Import Library (assimp)
-----------------------------------------------------------------------
-
-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.
-
-----------------------------------------------------------------------
-*/
+ Open Asset Import Library (assimp)
+ ----------------------------------------------------------------------
+ 
+ Copyright (c) 2006-2015, 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 ColladaParser.h
- *  @brief Defines the parser helper class for the collada loader 
+ *  @brief Defines the parser helper class for the collada loader
  */
 
 #ifndef AI_COLLADAPARSER_H_INC
@@ -47,295 +47,307 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include "irrXMLWrapper.h"
 #include "ColladaHelper.h"
+#include "../include/assimp/ai_assert.h"
+#include <boost/format.hpp>
 
 namespace Assimp
 {
-
-// ------------------------------------------------------------------------------------------
-/** Parser helper class for the Collada loader. 
- *
- *  Does all the XML reading and builds internal data structures from it, 
- *  but leaves the resolving of all the references to the loader.
-*/
-class ColladaParser
-{
-	friend class ColladaLoader;
-
-protected:
-	/** Constructor from XML file */
-	ColladaParser( IOSystem* pIOHandler, const std::string& pFile);
-
-	/** Destructor */
-	~ColladaParser();
-
-	/** Reads the contents of the file */
-	void ReadContents();
-
-	/** Reads the structure of the file */
-	void ReadStructure();
-
-	/** Reads asset informations such as coordinate system informations and legal blah */
-	void ReadAssetInfo();
-
-	/** Reads the animation library */
-	void ReadAnimationLibrary();
-
-	/** Reads an animation into the given parent structure */
-	void ReadAnimation( Collada::Animation* pParent);
-
-	/** Reads an animation sampler into the given anim channel */
-	void ReadAnimationSampler( Collada::AnimationChannel& pChannel);
-
-	/** Reads the skeleton controller library */
-	void ReadControllerLibrary();
-
-	/** Reads a controller into the given mesh structure */
-	void ReadController( Collada::Controller& pController);
-
-	/** Reads the joint definitions for the given controller */
-	void ReadControllerJoints( Collada::Controller& pController);
-
-	/** Reads the joint weights for the given controller */
-	void ReadControllerWeights( Collada::Controller& pController);
-
-	/** Reads the image library contents */
-	void ReadImageLibrary();
-
-	/** Reads an image entry into the given image */
-	void ReadImage( Collada::Image& pImage);
-
-	/** Reads the material library */
-	void ReadMaterialLibrary();
-
-	/** Reads a material entry into the given material */
-	void ReadMaterial( Collada::Material& pMaterial);
-
-	/** Reads the camera library */
-	void ReadCameraLibrary();
-
-	/** Reads a camera entry into the given camera */
-	void ReadCamera( Collada::Camera& pCamera);
-
-	/** Reads the light library */
-	void ReadLightLibrary();
-
-	/** Reads a light entry into the given light */
-	void ReadLight( Collada::Light& pLight);
-
-	/** Reads the effect library */
-	void ReadEffectLibrary();
-
-	/** Reads an effect entry into the given effect*/
-	void ReadEffect( Collada::Effect& pEffect);
-
-	/** Reads an COMMON effect profile */
-	void ReadEffectProfileCommon( Collada::Effect& pEffect);
-
-	/** Read sampler properties */
-	void ReadSamplerProperties( Collada::Sampler& pSampler);
-
-	/** Reads an effect entry containing a color or a texture defining that color */
-	void ReadEffectColor( aiColor4D& pColor, Collada::Sampler& pSampler);
-
-	/** Reads an effect entry containing a float */
-	void ReadEffectFloat( float& pFloat);
-
-	/** Reads an effect parameter specification of any kind */
-	void ReadEffectParam( Collada::EffectParam& pParam);
-
-	/** Reads the geometry library contents */
-	void ReadGeometryLibrary();
-
-	/** Reads a geometry from the geometry library. */
-	void ReadGeometry( Collada::Mesh* pMesh);
-
-	/** Reads a mesh from the geometry library */
-	void ReadMesh( Collada::Mesh* pMesh);
-
-	/** Reads a source element - a combination of raw data and an accessor defining 
-	 * things that should not be redefinable. Yes, that's another rant.
-	 */
-	void ReadSource();
-
-	/** Reads a data array holding a number of elements, and stores it in the global library.
-	 * Currently supported are array of floats and arrays of strings.
-	 */
-	void ReadDataArray();
-
-	/** Reads an accessor and stores it in the global library under the given ID - 
-	 * accessors use the ID of the parent <source> element
-	 */
-	void ReadAccessor( const std::string& pID);
-
-	/** Reads input declarations of per-vertex mesh data into the given mesh */
-	void ReadVertexData( Collada::Mesh* pMesh);
-
-	/** Reads input declarations of per-index mesh data into the given mesh */
-	void ReadIndexData( Collada::Mesh* pMesh);
-
-	/** Reads a single input channel element and stores it in the given array, if valid */
-	void ReadInputChannel( std::vector<Collada::InputChannel>& poChannels);
-
-	/** Reads a <p> primitive index list and assembles the mesh data into the given mesh */
-	void ReadPrimitives( Collada::Mesh* pMesh, std::vector<Collada::InputChannel>& pPerIndexChannels, 
-		size_t pNumPrimitives, const std::vector<size_t>& pVCount, Collada::PrimitiveType pPrimType);
-
-	/** Extracts a single object from an input channel and stores it in the appropriate mesh data array */
-	void ExtractDataObjectFromChannel( const Collada::InputChannel& pInput, size_t pLocalIndex, Collada::Mesh* pMesh);
-
-	/** Reads the library of node hierarchies and scene parts */
-	void ReadSceneLibrary();
-
-	/** Reads a scene node's contents including children and stores it in the given node */
-	void ReadSceneNode( Collada::Node* pNode);
-
-	/** Reads a node transformation entry of the given type and adds it to the given node's transformation list. */
-	void ReadNodeTransformation( Collada::Node* pNode, Collada::TransformType pType);
-
-	/** Reads a mesh reference in a node and adds it to the node's mesh list */
-	void ReadNodeGeometry( Collada::Node* pNode);
-
-	/** Reads the collada scene */
-	void ReadScene();
-
-	// Processes bind_vertex_input and bind elements
-	void ReadMaterialVertexInputBinding( Collada::SemanticMappingTable& tbl);
-
-protected:
-	/** Aborts the file reading with an exception */
-	void ThrowException( const std::string& pError) const;
-
-	/** Skips all data until the end node of the current element */
-	void SkipElement();
-
-	/** Skips all data until the end node of the given element */
-	void SkipElement( const char* pElement);
-
-	/** Compares the current xml element name to the given string and returns true if equal */
-	bool IsElement( const char* pName) const;
-
-	/** Tests for the opening tag of the given element, throws an exception if not found */
-	void TestOpening( const char* pName);
-
-	/** Tests for the closing tag of the given element, throws an exception if not found */
-	void TestClosing( const char* pName);
-
-	/** Checks the present element for the presence of the attribute, returns its index 
-	    or throws an exception if not found */
-	int GetAttribute( const char* pAttr) const;
-
-	/** Returns the index of the named attribute or -1 if not found. Does not throw,
-	    therefore useful for optional attributes */
-	int TestAttribute( const char* pAttr) const;
-
-	/** Reads the text contents of an element, throws an exception if not given. 
-	    Skips leading whitespace. */
-	const char* GetTextContent();
-
-	/** Reads the text contents of an element, returns NULL if not given.
-	    Skips leading whitespace. */
-	const char* TestTextContent();
-
-	/** Reads a single bool from current text content */
-	bool ReadBoolFromTextContent();
-
-	/** Reads a single float from current text content */
-	float ReadFloatFromTextContent();
-
-	/** Calculates the resulting transformation from all the given transform steps */
-	aiMatrix4x4 CalculateResultTransform( const std::vector<Collada::Transform>& pTransforms) const;
-
-	/** Determines the input data type for the given semantic string */
-	Collada::InputType GetTypeForSemantic( const std::string& pSemantic);
-
-	/** Finds the item in the given library by its reference, throws if not found */
-	template <typename Type> const Type& ResolveLibraryReference(
-		const std::map<std::string, Type>& pLibrary, const std::string& pURL) const;
-
-protected:
-	/** Filename, for a verbose error message */
-	std::string mFileName;
-
-	/** XML reader, member for everyday use */
-	irr::io::IrrXMLReader* mReader;
-
-	/** All data arrays found in the file by ID. Might be referred to by actually 
-	    everyone. Collada, you are a steaming pile of indirection. */
-	typedef std::map<std::string, Collada::Data> DataLibrary;
-	DataLibrary mDataLibrary;
-
-	/** Same for accessors which define how the data in a data array is accessed. */
-	typedef std::map<std::string, Collada::Accessor> AccessorLibrary;
-	AccessorLibrary mAccessorLibrary;
-
-	/** Mesh library: mesh by ID */
-	typedef std::map<std::string, Collada::Mesh*> MeshLibrary;
-	MeshLibrary mMeshLibrary;
-
-	/** node library: root node of the hierarchy part by ID */
-	typedef std::map<std::string, Collada::Node*> NodeLibrary;
-	NodeLibrary mNodeLibrary;
-
-	/** Image library: stores texture properties by ID */
-	typedef std::map<std::string, Collada::Image> ImageLibrary;
-	ImageLibrary mImageLibrary;
-
-	/** Effect library: surface attributes by ID */
-	typedef std::map<std::string, Collada::Effect> EffectLibrary;
-	EffectLibrary mEffectLibrary;
-
-	/** Material library: surface material by ID */
-	typedef std::map<std::string, Collada::Material> MaterialLibrary;
-	MaterialLibrary mMaterialLibrary;
-
-	/** Light library: surface light by ID */
-	typedef std::map<std::string, Collada::Light> LightLibrary;
-	LightLibrary mLightLibrary;
-
-	/** Camera library: surface material by ID */
-	typedef std::map<std::string, Collada::Camera> CameraLibrary;
-	CameraLibrary mCameraLibrary;
-
-	/** Controller library: joint controllers by ID */
-	typedef std::map<std::string, Collada::Controller> ControllerLibrary;
-	ControllerLibrary mControllerLibrary;
-
-	/** Pointer to the root node. Don't delete, it just points to one of 
-	    the nodes in the node library. */
-	Collada::Node* mRootNode;
-
-	/** Root animation container */
-	Collada::Animation mAnims;
-
-	/** Size unit: how large compared to a meter */
-	float mUnitSize;
-
-	/** Which is the up vector */
-	enum { UP_X, UP_Y, UP_Z } mUpDirection;
-
-	/** Collada file format version */
-	Collada::FormatVersion mFormat;
-};
-
-// ------------------------------------------------------------------------------------------------
-// Check for element match
-inline bool ColladaParser::IsElement( const char* pName) const
-{
-	ai_assert( mReader->getNodeType() == irr::io::EXN_ELEMENT); 
-	return ::strcmp( mReader->getNodeName(), pName) == 0; 
-}
-
-// ------------------------------------------------------------------------------------------------
-// Finds the item in the given library by its reference, throws if not found
-template <typename Type> 
-const Type& ColladaParser::ResolveLibraryReference( const std::map<std::string, Type>& pLibrary, const std::string& pURL) const
-{
-	typename std::map<std::string, Type>::const_iterator it = pLibrary.find( pURL);
-	if( it == pLibrary.end())
-		ThrowException( boost::str( boost::format( "Unable to resolve library reference \"%s\".") % pURL));
-	return it->second;
-}
-
+    
+    // ------------------------------------------------------------------------------------------
+    /** Parser helper class for the Collada loader.
+     *
+     *  Does all the XML reading and builds internal data structures from it,
+     *  but leaves the resolving of all the references to the loader.
+     */
+    class ColladaParser
+    {
+        friend class ColladaLoader;
+        
+    protected:
+        /** Constructor from XML file */
+        ColladaParser( IOSystem* pIOHandler, const std::string& pFile);
+        
+        /** Destructor */
+        ~ColladaParser();
+        
+        /** Reads the contents of the file */
+        void ReadContents();
+        
+        /** Reads the structure of the file */
+        void ReadStructure();
+        
+        /** Reads asset informations such as coordinate system informations and legal blah */
+        void ReadAssetInfo();
+        
+        /** Reads the animation library */
+        void ReadAnimationLibrary();
+        
+        /** Reads an animation into the given parent structure */
+        void ReadAnimation( Collada::Animation* pParent);
+        
+        /** Reads an animation sampler into the given anim channel */
+        void ReadAnimationSampler( Collada::AnimationChannel& pChannel);
+        
+        /** Reads the skeleton controller library */
+        void ReadControllerLibrary();
+        
+        /** Reads a controller into the given mesh structure */
+        void ReadController( Collada::Controller& pController);
+        
+        /** Reads the joint definitions for the given controller */
+        void ReadControllerJoints( Collada::Controller& pController);
+        
+        /** Reads the joint weights for the given controller */
+        void ReadControllerWeights( Collada::Controller& pController);
+        
+        /** Reads the image library contents */
+        void ReadImageLibrary();
+        
+        /** Reads an image entry into the given image */
+        void ReadImage( Collada::Image& pImage);
+        
+        /** Reads the material library */
+        void ReadMaterialLibrary();
+        
+        /** Reads a material entry into the given material */
+        void ReadMaterial( Collada::Material& pMaterial);
+        
+        /** Reads the camera library */
+        void ReadCameraLibrary();
+        
+        /** Reads a camera entry into the given camera */
+        void ReadCamera( Collada::Camera& pCamera);
+        
+        /** Reads the light library */
+        void ReadLightLibrary();
+        
+        /** Reads a light entry into the given light */
+        void ReadLight( Collada::Light& pLight);
+        
+        /** Reads the effect library */
+        void ReadEffectLibrary();
+        
+        /** Reads an effect entry into the given effect*/
+        void ReadEffect( Collada::Effect& pEffect);
+        
+        /** Reads an COMMON effect profile */
+        void ReadEffectProfileCommon( Collada::Effect& pEffect);
+        
+        /** Read sampler properties */
+        void ReadSamplerProperties( Collada::Sampler& pSampler);
+        
+        /** Reads an effect entry containing a color or a texture defining that color */
+        void ReadEffectColor( aiColor4D& pColor, Collada::Sampler& pSampler);
+        
+        /** Reads an effect entry containing a float */
+        void ReadEffectFloat( float& pFloat);
+        
+        /** Reads an effect parameter specification of any kind */
+        void ReadEffectParam( Collada::EffectParam& pParam);
+        
+        /** Reads the geometry library contents */
+        void ReadGeometryLibrary();
+        
+        /** Reads a geometry from the geometry library. */
+        void ReadGeometry( Collada::Mesh* pMesh);
+        
+        /** Reads a mesh from the geometry library */
+        void ReadMesh( Collada::Mesh* pMesh);
+        
+        /** Reads a source element - a combination of raw data and an accessor defining
+         * things that should not be redefinable. Yes, that's another rant.
+         */
+        void ReadSource();
+        
+        /** Reads a data array holding a number of elements, and stores it in the global library.
+         * Currently supported are array of floats and arrays of strings.
+         */
+        void ReadDataArray();
+        
+        /** Reads an accessor and stores it in the global library under the given ID -
+         * accessors use the ID of the parent <source> element
+         */
+        void ReadAccessor( const std::string& pID);
+        
+        /** Reads input declarations of per-vertex mesh data into the given mesh */
+        void ReadVertexData( Collada::Mesh* pMesh);
+        
+        /** Reads input declarations of per-index mesh data into the given mesh */
+        void ReadIndexData( Collada::Mesh* pMesh);
+        
+        /** Reads a single input channel element and stores it in the given array, if valid */
+        void ReadInputChannel( std::vector<Collada::InputChannel>& poChannels);
+        
+        /** Reads a <p> primitive index list and assembles the mesh data into the given mesh */
+        size_t ReadPrimitives( Collada::Mesh* pMesh, std::vector<Collada::InputChannel>& pPerIndexChannels,
+                              size_t pNumPrimitives, const std::vector<size_t>& pVCount, Collada::PrimitiveType pPrimType);
+        
+        /** Copies the data for a single primitive into the mesh, based on the InputChannels */
+        void CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset,
+                        Collada::Mesh* pMesh, std::vector<Collada::InputChannel>& pPerIndexChannels,
+                        size_t currentPrimitive, const std::vector<size_t>& indices);
+        
+        /** Reads one triangle of a tristrip into the mesh */
+        void ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, Collada::Mesh* pMesh,
+                               std::vector<Collada::InputChannel>& pPerIndexChannels, size_t currentPrimitive, const std::vector<size_t>& indices);
+        
+        /** Extracts a single object from an input channel and stores it in the appropriate mesh data array */
+        void ExtractDataObjectFromChannel( const Collada::InputChannel& pInput, size_t pLocalIndex, Collada::Mesh* pMesh);
+        
+        /** Reads the library of node hierarchies and scene parts */
+        void ReadSceneLibrary();
+        
+        /** Reads a scene node's contents including children and stores it in the given node */
+        void ReadSceneNode( Collada::Node* pNode);
+        
+        /** Reads a node transformation entry of the given type and adds it to the given node's transformation list. */
+        void ReadNodeTransformation( Collada::Node* pNode, Collada::TransformType pType);
+        
+        /** Reads a mesh reference in a node and adds it to the node's mesh list */
+        void ReadNodeGeometry( Collada::Node* pNode);
+        
+        /** Reads the collada scene */
+        void ReadScene();
+        
+        // Processes bind_vertex_input and bind elements
+        void ReadMaterialVertexInputBinding( Collada::SemanticMappingTable& tbl);
+        
+    protected:
+        /** Aborts the file reading with an exception */
+        AI_WONT_RETURN void ThrowException( const std::string& pError) const AI_WONT_RETURN_SUFFIX;
+        void ReportWarning(const char* msg,...);
+
+        /** Skips all data until the end node of the current element */
+        void SkipElement();
+        
+        /** Skips all data until the end node of the given element */
+        void SkipElement( const char* pElement);
+        
+        /** Compares the current xml element name to the given string and returns true if equal */
+        bool IsElement( const char* pName) const;
+        
+        /** Tests for the opening tag of the given element, throws an exception if not found */
+        void TestOpening( const char* pName);
+        
+        /** Tests for the closing tag of the given element, throws an exception if not found */
+        void TestClosing( const char* pName);
+        
+        /** Checks the present element for the presence of the attribute, returns its index
+         or throws an exception if not found */
+        int GetAttribute( const char* pAttr) const;
+        
+        /** Returns the index of the named attribute or -1 if not found. Does not throw,
+         therefore useful for optional attributes */
+        int TestAttribute( const char* pAttr) const;
+        
+        /** Reads the text contents of an element, throws an exception if not given.
+         Skips leading whitespace. */
+        const char* GetTextContent();
+        
+        /** Reads the text contents of an element, returns NULL if not given.
+         Skips leading whitespace. */
+        const char* TestTextContent();
+        
+        /** Reads a single bool from current text content */
+        bool ReadBoolFromTextContent();
+        
+        /** Reads a single float from current text content */
+        float ReadFloatFromTextContent();
+        
+        /** Calculates the resulting transformation from all the given transform steps */
+        aiMatrix4x4 CalculateResultTransform( const std::vector<Collada::Transform>& pTransforms) const;
+        
+        /** Determines the input data type for the given semantic string */
+        Collada::InputType GetTypeForSemantic( const std::string& pSemantic);
+        
+        /** Finds the item in the given library by its reference, throws if not found */
+        template <typename Type> const Type& ResolveLibraryReference(
+                                                                     const std::map<std::string, Type>& pLibrary, const std::string& pURL) const;
+        
+    protected:
+        /** Filename, for a verbose error message */
+        std::string mFileName;
+        
+        /** XML reader, member for everyday use */
+        irr::io::IrrXMLReader* mReader;
+        
+        /** All data arrays found in the file by ID. Might be referred to by actually
+         everyone. Collada, you are a steaming pile of indirection. */
+        typedef std::map<std::string, Collada::Data> DataLibrary;
+        DataLibrary mDataLibrary;
+        
+        /** Same for accessors which define how the data in a data array is accessed. */
+        typedef std::map<std::string, Collada::Accessor> AccessorLibrary;
+        AccessorLibrary mAccessorLibrary;
+        
+        /** Mesh library: mesh by ID */
+        typedef std::map<std::string, Collada::Mesh*> MeshLibrary;
+        MeshLibrary mMeshLibrary;
+        
+        /** node library: root node of the hierarchy part by ID */
+        typedef std::map<std::string, Collada::Node*> NodeLibrary;
+        NodeLibrary mNodeLibrary;
+        
+        /** Image library: stores texture properties by ID */
+        typedef std::map<std::string, Collada::Image> ImageLibrary;
+        ImageLibrary mImageLibrary;
+        
+        /** Effect library: surface attributes by ID */
+        typedef std::map<std::string, Collada::Effect> EffectLibrary;
+        EffectLibrary mEffectLibrary;
+        
+        /** Material library: surface material by ID */
+        typedef std::map<std::string, Collada::Material> MaterialLibrary;
+        MaterialLibrary mMaterialLibrary;
+        
+        /** Light library: surface light by ID */
+        typedef std::map<std::string, Collada::Light> LightLibrary;
+        LightLibrary mLightLibrary;
+        
+        /** Camera library: surface material by ID */
+        typedef std::map<std::string, Collada::Camera> CameraLibrary;
+        CameraLibrary mCameraLibrary;
+        
+        /** Controller library: joint controllers by ID */
+        typedef std::map<std::string, Collada::Controller> ControllerLibrary;
+        ControllerLibrary mControllerLibrary;
+        
+        /** Pointer to the root node. Don't delete, it just points to one of
+         the nodes in the node library. */
+        Collada::Node* mRootNode;
+        
+        /** Root animation container */
+        Collada::Animation mAnims;
+        
+        /** Size unit: how large compared to a meter */
+        float mUnitSize;
+        
+        /** Which is the up vector */
+        enum { UP_X, UP_Y, UP_Z } mUpDirection;
+        
+        /** Collada file format version */
+        Collada::FormatVersion mFormat;
+    };
+    
+    // ------------------------------------------------------------------------------------------------
+    // Check for element match
+    inline bool ColladaParser::IsElement( const char* pName) const
+    {
+        ai_assert( mReader->getNodeType() == irr::io::EXN_ELEMENT);
+        return ::strcmp( mReader->getNodeName(), pName) == 0;
+    }
+    
+    // ------------------------------------------------------------------------------------------------
+    // Finds the item in the given library by its reference, throws if not found
+    template <typename Type>
+    const Type& ColladaParser::ResolveLibraryReference( const std::map<std::string, Type>& pLibrary, const std::string& pURL) const
+    {
+        typename std::map<std::string, Type>::const_iterator it = pLibrary.find( pURL);
+        if( it == pLibrary.end())
+            ThrowException( boost::str( boost::format( "Unable to resolve library reference \"%s\".") % pURL));
+        return it->second;
+    }
+    
 } // end of namespace Assimp
 
 #endif // AI_COLLADAPARSER_H_INC

+ 399 - 399
assimplib.mod/assimp/code/ComputeUVMappingProcess.cpp

@@ -2,11 +2,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -23,16 +23,16 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -41,50 +41,50 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 /** @file GenUVCoords step */
 
 
-#include "AssimpPCH.h"
 #include "ComputeUVMappingProcess.h"
 #include "ProcessHelper.h"
+#include "Exceptional.h"
 
 using namespace Assimp;
 
 namespace {
 
-	const static aiVector3D base_axis_y(0.f,1.f,0.f);
-	const static aiVector3D base_axis_x(1.f,0.f,0.f);
-	const static aiVector3D base_axis_z(0.f,0.f,1.f);
-	const static float angle_epsilon = 0.95f;
+    const static aiVector3D base_axis_y(0.f,1.f,0.f);
+    const static aiVector3D base_axis_x(1.f,0.f,0.f);
+    const static aiVector3D base_axis_z(0.f,0.f,1.f);
+    const static float angle_epsilon = 0.95f;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 ComputeUVMappingProcess::ComputeUVMappingProcess()
 {
-	// nothing to do here
+    // nothing to do here
 }
 
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 ComputeUVMappingProcess::~ComputeUVMappingProcess()
 {
-	// nothing to do here
+    // nothing to do here
 }
 
 // ------------------------------------------------------------------------------------------------
 // Returns whether the processing step is present in the given flag field.
 bool ComputeUVMappingProcess::IsActive( unsigned int pFlags) const
 {
-	return	(pFlags & aiProcess_GenUVCoords) != 0;
+    return  (pFlags & aiProcess_GenUVCoords) != 0;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Check whether a ray intersects a plane and find the intersection point
 inline bool PlaneIntersect(const aiRay& ray, const aiVector3D& planePos,
-	const aiVector3D& planeNormal, aiVector3D& pos)
+    const aiVector3D& planeNormal, aiVector3D& pos)
 {
-	const float b = planeNormal * (planePos - ray.pos);
-	float h = ray.dir * planeNormal;
+    const float b = planeNormal * (planePos - ray.pos);
+    float h = ray.dir * planeNormal;
     if ((h < 10e-5f && h > -10e-5f) || (h = b/h) < 0)
-		return false;
+        return false;
 
     pos = ray.pos + (ray.dir * h);
     return true;
@@ -94,411 +94,411 @@ inline bool PlaneIntersect(const aiRay& ray, const aiVector3D& planePos,
 // Find the first empty UV channel in a mesh
 inline unsigned int FindEmptyUVChannel (aiMesh* mesh)
 {
-	for (unsigned int m = 0; m < AI_MAX_NUMBER_OF_TEXTURECOORDS;++m)
-		if (!mesh->mTextureCoords[m])return m;
-	
-	DefaultLogger::get()->error("Unable to compute UV coordinates, no free UV slot found");
-	return UINT_MAX;
+    for (unsigned int m = 0; m < AI_MAX_NUMBER_OF_TEXTURECOORDS;++m)
+        if (!mesh->mTextureCoords[m])return m;
+
+    DefaultLogger::get()->error("Unable to compute UV coordinates, no free UV slot found");
+    return UINT_MAX;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Try to remove UV seams
 void RemoveUVSeams (aiMesh* mesh, aiVector3D* out)
 {
-	// TODO: just a very rough algorithm. I think it could be done
-	// much easier, but I don't know how and am currently too tired to 
-	// to think about a better solution. 
-
-	const static float LOWER_LIMIT = 0.1f;
-	const static float UPPER_LIMIT = 0.9f;
-
-	const static float LOWER_EPSILON = 10e-3f;
-	const static float UPPER_EPSILON = 1.f-10e-3f;
-
-	for (unsigned int fidx = 0; fidx < mesh->mNumFaces;++fidx)
-	{
-		const aiFace& face = mesh->mFaces[fidx];
-		if (face.mNumIndices < 3) continue; // triangles and polygons only, please
-
-		unsigned int small = face.mNumIndices, large = small;
-		bool zero = false, one = false, round_to_zero = false;
-
-		// Check whether this face lies on a UV seam. We can just guess,
-		// but the assumption that a face with at least one very small
-		// on the one side and one very large U coord on the other side 
-		// lies on a UV seam should work for most cases.
-		for (unsigned int n = 0; n < face.mNumIndices;++n)
-		{
-			if (out[face.mIndices[n]].x < LOWER_LIMIT)
-			{
-				small = n;
-
-				// If we have a U value very close to 0 we can't
-				// round the others to 0, too.
-				if (out[face.mIndices[n]].x <= LOWER_EPSILON)
-					zero = true;
-				else round_to_zero = true;
-			}
-			if (out[face.mIndices[n]].x > UPPER_LIMIT)
-			{
-				large = n;
-
-				// If we have a U value very close to 1 we can't
-				// round the others to 1, too.
-				if (out[face.mIndices[n]].x >= UPPER_EPSILON)
-					one = true;
-			}
-		}
-		if (small != face.mNumIndices && large != face.mNumIndices)
-		{
-			for (unsigned int n = 0; n < face.mNumIndices;++n)
-			{
-				// If the u value is over the upper limit and no other u 
-				// value of that face is 0, round it to 0
-				if (out[face.mIndices[n]].x > UPPER_LIMIT && !zero)
-					out[face.mIndices[n]].x = 0.f;
-
-				// If the u value is below the lower limit and no other u 
-				// value of that face is 1, round it to 1
-				else if (out[face.mIndices[n]].x < LOWER_LIMIT && !one)
-					out[face.mIndices[n]].x = 1.f;
-
-				// The face contains both 0 and 1 as UV coords. This can occur
-				// for faces which have an edge that lies directly on the seam.
-				// Due to numerical inaccuracies one U coord becomes 0, the
-				// other 1. But we do still have a third UV coord to determine 
-				// to which side we must round to.
-				else if (one && zero)
-				{
-					if (round_to_zero && out[face.mIndices[n]].x >=  UPPER_EPSILON)
-						out[face.mIndices[n]].x = 0.f;
-					else if (!round_to_zero && out[face.mIndices[n]].x <= LOWER_EPSILON)
-						out[face.mIndices[n]].x = 1.f;
-				}
-			}
-		}
-	}
+    // TODO: just a very rough algorithm. I think it could be done
+    // much easier, but I don't know how and am currently too tired to
+    // to think about a better solution.
+
+    const static float LOWER_LIMIT = 0.1f;
+    const static float UPPER_LIMIT = 0.9f;
+
+    const static float LOWER_EPSILON = 10e-3f;
+    const static float UPPER_EPSILON = 1.f-10e-3f;
+
+    for (unsigned int fidx = 0; fidx < mesh->mNumFaces;++fidx)
+    {
+        const aiFace& face = mesh->mFaces[fidx];
+        if (face.mNumIndices < 3) continue; // triangles and polygons only, please
+
+        unsigned int small = face.mNumIndices, large = small;
+        bool zero = false, one = false, round_to_zero = false;
+
+        // Check whether this face lies on a UV seam. We can just guess,
+        // but the assumption that a face with at least one very small
+        // on the one side and one very large U coord on the other side
+        // lies on a UV seam should work for most cases.
+        for (unsigned int n = 0; n < face.mNumIndices;++n)
+        {
+            if (out[face.mIndices[n]].x < LOWER_LIMIT)
+            {
+                small = n;
+
+                // If we have a U value very close to 0 we can't
+                // round the others to 0, too.
+                if (out[face.mIndices[n]].x <= LOWER_EPSILON)
+                    zero = true;
+                else round_to_zero = true;
+            }
+            if (out[face.mIndices[n]].x > UPPER_LIMIT)
+            {
+                large = n;
+
+                // If we have a U value very close to 1 we can't
+                // round the others to 1, too.
+                if (out[face.mIndices[n]].x >= UPPER_EPSILON)
+                    one = true;
+            }
+        }
+        if (small != face.mNumIndices && large != face.mNumIndices)
+        {
+            for (unsigned int n = 0; n < face.mNumIndices;++n)
+            {
+                // If the u value is over the upper limit and no other u
+                // value of that face is 0, round it to 0
+                if (out[face.mIndices[n]].x > UPPER_LIMIT && !zero)
+                    out[face.mIndices[n]].x = 0.f;
+
+                // If the u value is below the lower limit and no other u
+                // value of that face is 1, round it to 1
+                else if (out[face.mIndices[n]].x < LOWER_LIMIT && !one)
+                    out[face.mIndices[n]].x = 1.f;
+
+                // The face contains both 0 and 1 as UV coords. This can occur
+                // for faces which have an edge that lies directly on the seam.
+                // Due to numerical inaccuracies one U coord becomes 0, the
+                // other 1. But we do still have a third UV coord to determine
+                // to which side we must round to.
+                else if (one && zero)
+                {
+                    if (round_to_zero && out[face.mIndices[n]].x >=  UPPER_EPSILON)
+                        out[face.mIndices[n]].x = 0.f;
+                    else if (!round_to_zero && out[face.mIndices[n]].x <= LOWER_EPSILON)
+                        out[face.mIndices[n]].x = 1.f;
+                }
+            }
+        }
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 void ComputeUVMappingProcess::ComputeSphereMapping(aiMesh* mesh,const aiVector3D& axis, aiVector3D* out)
 {
-	aiVector3D center, min, max;
-	FindMeshCenter(mesh, center, min, max);
-
-	// If the axis is one of x,y,z run a faster code path. It's worth the extra effort ...
-	// currently the mapping axis will always be one of x,y,z, except if the
-	// PretransformVertices step is used (it transforms the meshes into worldspace, 
-	// thus changing the mapping axis)
-	if (axis * base_axis_x >= angle_epsilon)	{
-
-		// For each point get a normalized projection vector in the sphere,
-		// get its longitude and latitude and map them to their respective
-		// UV axes. Problems occur around the poles ... unsolvable.
-		//
-		// The spherical coordinate system looks like this:
-		// x = cos(lon)*cos(lat)
-		// y = sin(lon)*cos(lat)
-		// z = sin(lat)
-		// 
-		// Thus we can derive:
-		// lat  = arcsin (z)
-		// lon  = arctan (y/x)
-		for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)	{
-			const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize();
-			out[pnt] = aiVector3D((atan2 (diff.z, diff.y) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
-				(asin  (diff.x) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f);
-		}
-	}
-	else if (axis * base_axis_y >= angle_epsilon)	{
-		// ... just the same again
-		for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)	{
-			const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize();
-			out[pnt] = aiVector3D((atan2 (diff.x, diff.z) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
-				(asin  (diff.y) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f);
-		}
-	}
-	else if (axis * base_axis_z >= angle_epsilon)	{
-		// ... just the same again
-		for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)	{
-			const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize();
-			out[pnt] = aiVector3D((atan2 (diff.y, diff.x) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
-				(asin  (diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f);
-		}
-	}
-	// slower code path in case the mapping axis is not one of the coordinate system axes
-	else	{
-		aiMatrix4x4 mTrafo;
-		aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo);
-
-		// again the same, except we're applying a transformation now
-		for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)	{
-			const aiVector3D diff = ((mTrafo*mesh->mVertices[pnt])-center).Normalize();
-			out[pnt] = aiVector3D((atan2 (diff.y, diff.x) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
-				(asin  (diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f);
-		}
-	}
-	
-	
-	// Now find and remove UV seams. A seam occurs if a face has a tcoord
-	// close to zero on the one side, and a tcoord close to one on the
-	// other side.
-	RemoveUVSeams(mesh,out);
+    aiVector3D center, min, max;
+    FindMeshCenter(mesh, center, min, max);
+
+    // If the axis is one of x,y,z run a faster code path. It's worth the extra effort ...
+    // currently the mapping axis will always be one of x,y,z, except if the
+    // PretransformVertices step is used (it transforms the meshes into worldspace,
+    // thus changing the mapping axis)
+    if (axis * base_axis_x >= angle_epsilon)    {
+
+        // For each point get a normalized projection vector in the sphere,
+        // get its longitude and latitude and map them to their respective
+        // UV axes. Problems occur around the poles ... unsolvable.
+        //
+        // The spherical coordinate system looks like this:
+        // x = cos(lon)*cos(lat)
+        // y = sin(lon)*cos(lat)
+        // z = sin(lat)
+        //
+        // Thus we can derive:
+        // lat  = arcsin (z)
+        // lon  = arctan (y/x)
+        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
+            const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize();
+            out[pnt] = aiVector3D((atan2 (diff.z, diff.y) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
+                (std::asin  (diff.x) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f);
+        }
+    }
+    else if (axis * base_axis_y >= angle_epsilon)   {
+        // ... just the same again
+        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
+            const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize();
+            out[pnt] = aiVector3D((atan2 (diff.x, diff.z) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
+                (std::asin  (diff.y) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f);
+        }
+    }
+    else if (axis * base_axis_z >= angle_epsilon)   {
+        // ... just the same again
+        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
+            const aiVector3D diff = (mesh->mVertices[pnt]-center).Normalize();
+            out[pnt] = aiVector3D((atan2 (diff.y, diff.x) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
+                (std::asin  (diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f);
+        }
+    }
+    // slower code path in case the mapping axis is not one of the coordinate system axes
+    else    {
+        aiMatrix4x4 mTrafo;
+        aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo);
+
+        // again the same, except we're applying a transformation now
+        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
+            const aiVector3D diff = ((mTrafo*mesh->mVertices[pnt])-center).Normalize();
+            out[pnt] = aiVector3D((atan2 (diff.y, diff.x) + AI_MATH_PI_F ) / AI_MATH_TWO_PI_F,
+                (asin  (diff.z) + AI_MATH_HALF_PI_F) / AI_MATH_PI_F, 0.f);
+        }
+    }
+
+
+    // Now find and remove UV seams. A seam occurs if a face has a tcoord
+    // close to zero on the one side, and a tcoord close to one on the
+    // other side.
+    RemoveUVSeams(mesh,out);
 }
 
 // ------------------------------------------------------------------------------------------------
 void ComputeUVMappingProcess::ComputeCylinderMapping(aiMesh* mesh,const aiVector3D& axis, aiVector3D* out)
 {
-	aiVector3D center, min, max;
-
-	// If the axis is one of x,y,z run a faster code path. It's worth the extra effort ...
-	// currently the mapping axis will always be one of x,y,z, except if the
-	// PretransformVertices step is used (it transforms the meshes into worldspace, 
-	// thus changing the mapping axis)
-	if (axis * base_axis_x >= angle_epsilon)	{
-		FindMeshCenter(mesh, center, min, max);
-		const float diff = max.x - min.x;
-
-		// If the main axis is 'z', the z coordinate of a point 'p' is mapped 
-		// directly to the texture V axis. The other axis is derived from
-		// the angle between ( p.x - c.x, p.y - c.y ) and (1,0), where
-		// 'c' is the center point of the mesh.
-		for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)	{
-			const aiVector3D& pos = mesh->mVertices[pnt];
-			aiVector3D& uv  = out[pnt];
-
-			uv.y = (pos.x - min.x) / diff;
-			uv.x = (atan2 ( pos.z - center.z, pos.y - center.y) +(float)AI_MATH_PI ) / (float)AI_MATH_TWO_PI;
-		}
-	}
-	else if (axis * base_axis_y >= angle_epsilon)	{
-		FindMeshCenter(mesh, center, min, max);
-		const float diff = max.y - min.y;
-
-		// just the same ...
-		for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)	{
-			const aiVector3D& pos = mesh->mVertices[pnt];
-			aiVector3D& uv  = out[pnt];
-
-			uv.y = (pos.y - min.y) / diff;
-			uv.x = (atan2 ( pos.x - center.x, pos.z - center.z) +(float)AI_MATH_PI ) / (float)AI_MATH_TWO_PI;
-		}
-	}
-	else if (axis * base_axis_z >= angle_epsilon)	{
-		FindMeshCenter(mesh, center, min, max);
-		const float diff = max.z - min.z;
-
-		// just the same ...
-		for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)	{
-			const aiVector3D& pos = mesh->mVertices[pnt];
-			aiVector3D& uv  = out[pnt];
-
-			uv.y = (pos.z - min.z) / diff;
-			uv.x = (atan2 ( pos.y - center.y, pos.x - center.x) +(float)AI_MATH_PI ) / (float)AI_MATH_TWO_PI;
-		}
-	}
-	// slower code path in case the mapping axis is not one of the coordinate system axes
-	else {
-		aiMatrix4x4 mTrafo;
-		aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo);
-		FindMeshCenterTransformed(mesh, center, min, max,mTrafo);
-		const float diff = max.y - min.y;
-
-		// again the same, except we're applying a transformation now
-		for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt){
-			const aiVector3D pos = mTrafo* mesh->mVertices[pnt];
-			aiVector3D& uv  = out[pnt];
-
-			uv.y = (pos.y - min.y) / diff;
-			uv.x = (atan2 ( pos.x - center.x, pos.z - center.z) +(float)AI_MATH_PI ) / (float)AI_MATH_TWO_PI;
-		}
-	}
-
-	// Now find and remove UV seams. A seam occurs if a face has a tcoord
-	// close to zero on the one side, and a tcoord close to one on the
-	// other side.
-	RemoveUVSeams(mesh,out);
+    aiVector3D center, min, max;
+
+    // If the axis is one of x,y,z run a faster code path. It's worth the extra effort ...
+    // currently the mapping axis will always be one of x,y,z, except if the
+    // PretransformVertices step is used (it transforms the meshes into worldspace,
+    // thus changing the mapping axis)
+    if (axis * base_axis_x >= angle_epsilon)    {
+        FindMeshCenter(mesh, center, min, max);
+        const float diff = max.x - min.x;
+
+        // If the main axis is 'z', the z coordinate of a point 'p' is mapped
+        // directly to the texture V axis. The other axis is derived from
+        // the angle between ( p.x - c.x, p.y - c.y ) and (1,0), where
+        // 'c' is the center point of the mesh.
+        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
+            const aiVector3D& pos = mesh->mVertices[pnt];
+            aiVector3D& uv  = out[pnt];
+
+            uv.y = (pos.x - min.x) / diff;
+            uv.x = (atan2 ( pos.z - center.z, pos.y - center.y) +(float)AI_MATH_PI ) / (float)AI_MATH_TWO_PI;
+        }
+    }
+    else if (axis * base_axis_y >= angle_epsilon)   {
+        FindMeshCenter(mesh, center, min, max);
+        const float diff = max.y - min.y;
+
+        // just the same ...
+        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
+            const aiVector3D& pos = mesh->mVertices[pnt];
+            aiVector3D& uv  = out[pnt];
+
+            uv.y = (pos.y - min.y) / diff;
+            uv.x = (atan2 ( pos.x - center.x, pos.z - center.z) +(float)AI_MATH_PI ) / (float)AI_MATH_TWO_PI;
+        }
+    }
+    else if (axis * base_axis_z >= angle_epsilon)   {
+        FindMeshCenter(mesh, center, min, max);
+        const float diff = max.z - min.z;
+
+        // just the same ...
+        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
+            const aiVector3D& pos = mesh->mVertices[pnt];
+            aiVector3D& uv  = out[pnt];
+
+            uv.y = (pos.z - min.z) / diff;
+            uv.x = (atan2 ( pos.y - center.y, pos.x - center.x) +(float)AI_MATH_PI ) / (float)AI_MATH_TWO_PI;
+        }
+    }
+    // slower code path in case the mapping axis is not one of the coordinate system axes
+    else {
+        aiMatrix4x4 mTrafo;
+        aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo);
+        FindMeshCenterTransformed(mesh, center, min, max,mTrafo);
+        const float diff = max.y - min.y;
+
+        // again the same, except we're applying a transformation now
+        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt){
+            const aiVector3D pos = mTrafo* mesh->mVertices[pnt];
+            aiVector3D& uv  = out[pnt];
+
+            uv.y = (pos.y - min.y) / diff;
+            uv.x = (atan2 ( pos.x - center.x, pos.z - center.z) +(float)AI_MATH_PI ) / (float)AI_MATH_TWO_PI;
+        }
+    }
+
+    // Now find and remove UV seams. A seam occurs if a face has a tcoord
+    // close to zero on the one side, and a tcoord close to one on the
+    // other side.
+    RemoveUVSeams(mesh,out);
 }
 
 // ------------------------------------------------------------------------------------------------
 void ComputeUVMappingProcess::ComputePlaneMapping(aiMesh* mesh,const aiVector3D& axis, aiVector3D* out)
 {
-	float diffu,diffv;
-	aiVector3D center, min, max;
-
-	// If the axis is one of x,y,z run a faster code path. It's worth the extra effort ...
-	// currently the mapping axis will always be one of x,y,z, except if the
-	// PretransformVertices step is used (it transforms the meshes into worldspace, 
-	// thus changing the mapping axis)
-	if (axis * base_axis_x >= angle_epsilon)	{
-		FindMeshCenter(mesh, center, min, max);
-		diffu = max.z - min.z;
-		diffv = max.y - min.y;
-
-		for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)	{
-			const aiVector3D& pos = mesh->mVertices[pnt];
-			out[pnt].Set((pos.z - min.z) / diffu,(pos.y - min.y) / diffv,0.f);
-		}
-	}
-	else if (axis * base_axis_y >= angle_epsilon)	{
-		FindMeshCenter(mesh, center, min, max);
-		diffu = max.x - min.x;
-		diffv = max.z - min.z;
-
-		for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)	{
-			const aiVector3D& pos = mesh->mVertices[pnt];
-			out[pnt].Set((pos.x - min.x) / diffu,(pos.z - min.z) / diffv,0.f);
-		}
-	}
-	else if (axis * base_axis_z >= angle_epsilon)	{
-		FindMeshCenter(mesh, center, min, max);
-		diffu = max.y - min.y;
-		diffv = max.z - min.z;
-
-		for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)	{
-			const aiVector3D& pos = mesh->mVertices[pnt];
-			out[pnt].Set((pos.y - min.y) / diffu,(pos.x - min.x) / diffv,0.f);
-		}
-	}
-	// slower code path in case the mapping axis is not one of the coordinate system axes
-	else
-	{
-		aiMatrix4x4 mTrafo;
-		aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo);
-		FindMeshCenterTransformed(mesh, center, min, max,mTrafo);
-		diffu = max.x - min.x;
-		diffv = max.z - min.z;
-
-		// again the same, except we're applying a transformation now
-		for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)	{
-			const aiVector3D pos = mTrafo * mesh->mVertices[pnt];
-			out[pnt].Set((pos.x - min.x) / diffu,(pos.z - min.z) / diffv,0.f);
-		}
-	}
-
-	// shouldn't be necessary to remove UV seams ...
+    float diffu,diffv;
+    aiVector3D center, min, max;
+
+    // If the axis is one of x,y,z run a faster code path. It's worth the extra effort ...
+    // currently the mapping axis will always be one of x,y,z, except if the
+    // PretransformVertices step is used (it transforms the meshes into worldspace,
+    // thus changing the mapping axis)
+    if (axis * base_axis_x >= angle_epsilon)    {
+        FindMeshCenter(mesh, center, min, max);
+        diffu = max.z - min.z;
+        diffv = max.y - min.y;
+
+        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
+            const aiVector3D& pos = mesh->mVertices[pnt];
+            out[pnt].Set((pos.z - min.z) / diffu,(pos.y - min.y) / diffv,0.f);
+        }
+    }
+    else if (axis * base_axis_y >= angle_epsilon)   {
+        FindMeshCenter(mesh, center, min, max);
+        diffu = max.x - min.x;
+        diffv = max.z - min.z;
+
+        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
+            const aiVector3D& pos = mesh->mVertices[pnt];
+            out[pnt].Set((pos.x - min.x) / diffu,(pos.z - min.z) / diffv,0.f);
+        }
+    }
+    else if (axis * base_axis_z >= angle_epsilon)   {
+        FindMeshCenter(mesh, center, min, max);
+        diffu = max.y - min.y;
+        diffv = max.z - min.z;
+
+        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
+            const aiVector3D& pos = mesh->mVertices[pnt];
+            out[pnt].Set((pos.y - min.y) / diffu,(pos.x - min.x) / diffv,0.f);
+        }
+    }
+    // slower code path in case the mapping axis is not one of the coordinate system axes
+    else
+    {
+        aiMatrix4x4 mTrafo;
+        aiMatrix4x4::FromToMatrix(axis,base_axis_y,mTrafo);
+        FindMeshCenterTransformed(mesh, center, min, max,mTrafo);
+        diffu = max.x - min.x;
+        diffv = max.z - min.z;
+
+        // again the same, except we're applying a transformation now
+        for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
+            const aiVector3D pos = mTrafo * mesh->mVertices[pnt];
+            out[pnt].Set((pos.x - min.x) / diffu,(pos.z - min.z) / diffv,0.f);
+        }
+    }
+
+    // shouldn't be necessary to remove UV seams ...
 }
 
 // ------------------------------------------------------------------------------------------------
 void ComputeUVMappingProcess::ComputeBoxMapping( aiMesh*, aiVector3D* )
 {
-	DefaultLogger::get()->error("Mapping type currently not implemented");
+    DefaultLogger::get()->error("Mapping type currently not implemented");
 }
 
 // ------------------------------------------------------------------------------------------------
-void ComputeUVMappingProcess::Execute( aiScene* pScene) 
+void ComputeUVMappingProcess::Execute( aiScene* pScene)
 {
-	DefaultLogger::get()->debug("GenUVCoordsProcess begin");
-	char buffer[1024];
-
-	if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT)
-		throw DeadlyImportError("Post-processing order mismatch: expecting pseudo-indexed (\"verbose\") vertices here");
-
-	std::list<MappingInfo> mappingStack;
-
-	/*  Iterate through all materials and search for non-UV mapped textures
-	 */
-	for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
-	{
-		mappingStack.clear();
-		aiMaterial* mat = pScene->mMaterials[i];
-		for (unsigned int a = 0; a < mat->mNumProperties;++a)
-		{
-			aiMaterialProperty* prop = mat->mProperties[a];
-			if (!::strcmp( prop->mKey.data, "$tex.mapping"))
-			{
-				aiTextureMapping& mapping = *((aiTextureMapping*)prop->mData);
-				if (aiTextureMapping_UV != mapping)
-				{
-					if (!DefaultLogger::isNullLogger())
-					{
-						sprintf(buffer, "Found non-UV mapped texture (%s,%i). Mapping type: %s",
-							TextureTypeToString((aiTextureType)prop->mSemantic),prop->mIndex,
-							MappingTypeToString(mapping));
-
-						DefaultLogger::get()->info(buffer);
-					}
-
-					if (aiTextureMapping_OTHER == mapping)
-						continue;
-
-					MappingInfo info (mapping);
-
-					// Get further properties - currently only the major axis
-					for (unsigned int a2 = 0; a2 < mat->mNumProperties;++a2)
-					{
-						aiMaterialProperty* prop2 = mat->mProperties[a2];
-						if (prop2->mSemantic != prop->mSemantic || prop2->mIndex != prop->mIndex)
-							continue;
-
-						if ( !::strcmp( prop2->mKey.data, "$tex.mapaxis"))	{
-							info.axis = *((aiVector3D*)prop2->mData);
-							break;
-						}
-					}
-
-					unsigned int idx;
-
-					// Check whether we have this mapping mode already
-					std::list<MappingInfo>::iterator it = std::find (mappingStack.begin(),mappingStack.end(), info);
-					if (mappingStack.end() != it)
-					{
-						idx = (*it).uv;
-					}
-					else
-					{
-						/*  We have found a non-UV mapped texture. Now
-						*   we need to find all meshes using this material
-						*   that we can compute UV channels for them.
-						*/
-						for (unsigned int m = 0; m < pScene->mNumMeshes;++m)
-						{
-							aiMesh* mesh = pScene->mMeshes[m];
-							unsigned int outIdx;
-							if ( mesh->mMaterialIndex != i || ( outIdx = FindEmptyUVChannel(mesh) ) == UINT_MAX ||
-								!mesh->mNumVertices)
-							{
-								continue;
-							}
-
-							// Allocate output storage
-							aiVector3D* p = mesh->mTextureCoords[outIdx] = new aiVector3D[mesh->mNumVertices];
-
-							switch (mapping)
-							{
-							case aiTextureMapping_SPHERE:
-								ComputeSphereMapping(mesh,info.axis,p);
-								break;
-							case aiTextureMapping_CYLINDER:
-								ComputeCylinderMapping(mesh,info.axis,p);
-								break;
-							case aiTextureMapping_PLANE:
-								ComputePlaneMapping(mesh,info.axis,p);
-								break;
-							case aiTextureMapping_BOX:
-								ComputeBoxMapping(mesh,p);
-								break;
-							default:
-								ai_assert(false);
-							}
-							if (m && idx != outIdx)
-							{
-								DefaultLogger::get()->warn("UV index mismatch. Not all meshes assigned to "
-									"this material have equal numbers of UV channels. The UV index stored in  "
-									"the material structure does therefore not apply for all meshes. ");
-							}
-							idx = outIdx;
-						}
-						info.uv = idx;
-						mappingStack.push_back(info);
-					}
-
-					// Update the material property list
-					mapping = aiTextureMapping_UV;
-					((aiMaterial*)mat)->AddProperty(&idx,1,AI_MATKEY_UVWSRC(prop->mSemantic,prop->mIndex));
-				}
-			}
-		}
-	}
-	DefaultLogger::get()->debug("GenUVCoordsProcess finished");
+    DefaultLogger::get()->debug("GenUVCoordsProcess begin");
+    char buffer[1024];
+
+    if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT)
+        throw DeadlyImportError("Post-processing order mismatch: expecting pseudo-indexed (\"verbose\") vertices here");
+
+    std::list<MappingInfo> mappingStack;
+
+    /*  Iterate through all materials and search for non-UV mapped textures
+     */
+    for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
+    {
+        mappingStack.clear();
+        aiMaterial* mat = pScene->mMaterials[i];
+        for (unsigned int a = 0; a < mat->mNumProperties;++a)
+        {
+            aiMaterialProperty* prop = mat->mProperties[a];
+            if (!::strcmp( prop->mKey.data, "$tex.mapping"))
+            {
+                aiTextureMapping& mapping = *((aiTextureMapping*)prop->mData);
+                if (aiTextureMapping_UV != mapping)
+                {
+                    if (!DefaultLogger::isNullLogger())
+                    {
+                        sprintf(buffer, "Found non-UV mapped texture (%s,%u). Mapping type: %s",
+                            TextureTypeToString((aiTextureType)prop->mSemantic),prop->mIndex,
+                            MappingTypeToString(mapping));
+
+                        DefaultLogger::get()->info(buffer);
+                    }
+
+                    if (aiTextureMapping_OTHER == mapping)
+                        continue;
+
+                    MappingInfo info (mapping);
+
+                    // Get further properties - currently only the major axis
+                    for (unsigned int a2 = 0; a2 < mat->mNumProperties;++a2)
+                    {
+                        aiMaterialProperty* prop2 = mat->mProperties[a2];
+                        if (prop2->mSemantic != prop->mSemantic || prop2->mIndex != prop->mIndex)
+                            continue;
+
+                        if ( !::strcmp( prop2->mKey.data, "$tex.mapaxis"))  {
+                            info.axis = *((aiVector3D*)prop2->mData);
+                            break;
+                        }
+                    }
+
+                    unsigned int idx;
+
+                    // Check whether we have this mapping mode already
+                    std::list<MappingInfo>::iterator it = std::find (mappingStack.begin(),mappingStack.end(), info);
+                    if (mappingStack.end() != it)
+                    {
+                        idx = (*it).uv;
+                    }
+                    else
+                    {
+                        /*  We have found a non-UV mapped texture. Now
+                        *   we need to find all meshes using this material
+                        *   that we can compute UV channels for them.
+                        */
+                        for (unsigned int m = 0; m < pScene->mNumMeshes;++m)
+                        {
+                            aiMesh* mesh = pScene->mMeshes[m];
+                            unsigned int outIdx = 0;
+                            if ( mesh->mMaterialIndex != i || ( outIdx = FindEmptyUVChannel(mesh) ) == UINT_MAX ||
+                                !mesh->mNumVertices)
+                            {
+                                continue;
+                            }
+
+                            // Allocate output storage
+                            aiVector3D* p = mesh->mTextureCoords[outIdx] = new aiVector3D[mesh->mNumVertices];
+
+                            switch (mapping)
+                            {
+                            case aiTextureMapping_SPHERE:
+                                ComputeSphereMapping(mesh,info.axis,p);
+                                break;
+                            case aiTextureMapping_CYLINDER:
+                                ComputeCylinderMapping(mesh,info.axis,p);
+                                break;
+                            case aiTextureMapping_PLANE:
+                                ComputePlaneMapping(mesh,info.axis,p);
+                                break;
+                            case aiTextureMapping_BOX:
+                                ComputeBoxMapping(mesh,p);
+                                break;
+                            default:
+                                ai_assert(false);
+                            }
+                            if (m && idx != outIdx)
+                            {
+                                DefaultLogger::get()->warn("UV index mismatch. Not all meshes assigned to "
+                                    "this material have equal numbers of UV channels. The UV index stored in  "
+                                    "the material structure does therefore not apply for all meshes. ");
+                            }
+                            idx = outIdx;
+                        }
+                        info.uv = idx;
+                        mappingStack.push_back(info);
+                    }
+
+                    // Update the material property list
+                    mapping = aiTextureMapping_UV;
+                    ((aiMaterial*)mat)->AddProperty(&idx,1,AI_MATKEY_UVWSRC(prop->mSemantic,prop->mIndex));
+                }
+            }
+        }
+    }
+    DefaultLogger::get()->debug("GenUVCoordsProcess finished");
 }

+ 85 - 82
assimplib.mod/assimp/code/ComputeUVMappingProcess.h

@@ -2,11 +2,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -23,16 +23,16 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -45,10 +45,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include "BaseProcess.h"
 #include "../include/assimp/mesh.h"
+#include "../include/assimp/material.h"
+#include "../include/assimp/types.h"
 
 class ComputeUVMappingTest;
+
 namespace Assimp
-	{
+    {
 
 // ---------------------------------------------------------------------------
 /** ComputeUVMappingProcess - converts special mappings, such as spherical,
@@ -57,86 +60,86 @@ namespace Assimp
 class ComputeUVMappingProcess : public BaseProcess
 {
 public:
-	ComputeUVMappingProcess();
-	~ComputeUVMappingProcess();
+    ComputeUVMappingProcess();
+    ~ComputeUVMappingProcess();
 
 public:
 
-	// -------------------------------------------------------------------
-	/** Returns whether the processing step is present in the given flag field.
-	* @param pFlags The processing flags the importer was called with. A bitwise
-	*   combination of #aiPostProcessSteps.
-	* @return true if the process is present in this flag fields, false if not.
-	*/
-	bool IsActive( unsigned int pFlags) const;
-
-	// -------------------------------------------------------------------
-	/** Executes the post processing step on the given imported data.
-	* At the moment a process is not supposed to fail.
-	* @param pScene The imported data to work at.
-	*/
-	void Execute( aiScene* pScene);
+    // -------------------------------------------------------------------
+    /** Returns whether the processing step is present in the given flag field.
+    * @param pFlags The processing flags the importer was called with. A bitwise
+    *   combination of #aiPostProcessSteps.
+    * @return true if the process is present in this flag fields, false if not.
+    */
+    bool IsActive( unsigned int pFlags) const;
+
+    // -------------------------------------------------------------------
+    /** Executes the post processing step on the given imported data.
+    * At the moment a process is not supposed to fail.
+    * @param pScene The imported data to work at.
+    */
+    void Execute( aiScene* pScene);
 
 protected:
 
-	// -------------------------------------------------------------------
-	/** Computes spherical UV coordinates for a mesh
-	 *
-	 *  @param mesh Mesh to be processed
-	 *  @param axis Main axis
-	 *  @param out Receives output UV coordinates
-	*/
-	void ComputeSphereMapping(aiMesh* mesh,const aiVector3D& axis,
-		aiVector3D* out);
-
-	// -------------------------------------------------------------------
-	/** Computes cylindrical UV coordinates for a mesh
-	 *
-	 *  @param mesh Mesh to be processed
-	 *  @param axis Main axis
-	 *  @param out Receives output UV coordinates
-	*/
-	void ComputeCylinderMapping(aiMesh* mesh,const aiVector3D& axis,
-		aiVector3D* out);
-
-	// -------------------------------------------------------------------
-	/** Computes planar UV coordinates for a mesh
-	 *
-	 *  @param mesh Mesh to be processed
-	 *  @param axis Main axis
-	 *  @param out Receives output UV coordinates
-	*/
-	void ComputePlaneMapping(aiMesh* mesh,const aiVector3D& axis, 
-		aiVector3D* out);
-
-	// -------------------------------------------------------------------
-	/** Computes cubic UV coordinates for a mesh
-	 *
-	 *  @param mesh Mesh to be processed
-	 *  @param out Receives output UV coordinates
-	*/
-	void ComputeBoxMapping(aiMesh* mesh, aiVector3D* out);
+    // -------------------------------------------------------------------
+    /** Computes spherical UV coordinates for a mesh
+     *
+     *  @param mesh Mesh to be processed
+     *  @param axis Main axis
+     *  @param out Receives output UV coordinates
+    */
+    void ComputeSphereMapping(aiMesh* mesh,const aiVector3D& axis,
+        aiVector3D* out);
+
+    // -------------------------------------------------------------------
+    /** Computes cylindrical UV coordinates for a mesh
+     *
+     *  @param mesh Mesh to be processed
+     *  @param axis Main axis
+     *  @param out Receives output UV coordinates
+    */
+    void ComputeCylinderMapping(aiMesh* mesh,const aiVector3D& axis,
+        aiVector3D* out);
+
+    // -------------------------------------------------------------------
+    /** Computes planar UV coordinates for a mesh
+     *
+     *  @param mesh Mesh to be processed
+     *  @param axis Main axis
+     *  @param out Receives output UV coordinates
+    */
+    void ComputePlaneMapping(aiMesh* mesh,const aiVector3D& axis,
+        aiVector3D* out);
+
+    // -------------------------------------------------------------------
+    /** Computes cubic UV coordinates for a mesh
+     *
+     *  @param mesh Mesh to be processed
+     *  @param out Receives output UV coordinates
+    */
+    void ComputeBoxMapping(aiMesh* mesh, aiVector3D* out);
 
 private:
 
-	// temporary structure to describe a mapping
-	struct MappingInfo
-	{
-		MappingInfo(aiTextureMapping _type)
-			: type	(_type)
-			, axis	(0.f,1.f,0.f)
-			, uv	(0u)
-		{}
-
-		aiTextureMapping type;
-		aiVector3D axis;
-		unsigned int uv;
-
-		bool operator== (const MappingInfo& other)
-		{
-			return type == other.type && axis == other.axis;
-		}
-	};
+    // temporary structure to describe a mapping
+    struct MappingInfo
+    {
+        explicit MappingInfo(aiTextureMapping _type)
+            : type  (_type)
+            , axis  (0.f,1.f,0.f)
+            , uv    (0u)
+        {}
+
+        aiTextureMapping type;
+        aiVector3D axis;
+        unsigned int uv;
+
+        bool operator== (const MappingInfo& other)
+        {
+            return type == other.type && axis == other.axis;
+        }
+    };
 };
 
 } // end of namespace Assimp

+ 180 - 167
assimplib.mod/assimp/code/ConvertToLHProcess.cpp

@@ -3,12 +3,12 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -25,16 +25,16 @@ conditions are met:
   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 
+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 
+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 
+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 
+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.
 ---------------------------------------------------------------------------
 */
@@ -47,8 +47,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *  better location.
  */
 
-#include "AssimpPCH.h"
+
 #include "ConvertToLHProcess.h"
+#include "../include/assimp/scene.h"
+#include "../include/assimp/postprocess.h"
+#include "../include/assimp/DefaultLogger.hpp"
 
 using namespace Assimp;
 
@@ -57,151 +60,155 @@ using namespace Assimp;
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 MakeLeftHandedProcess::MakeLeftHandedProcess()
-{}
+: BaseProcess() {
+    // empty
+}
 
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
-MakeLeftHandedProcess::~MakeLeftHandedProcess()
-{}
+MakeLeftHandedProcess::~MakeLeftHandedProcess() {
+    // empty
+}
 
 // ------------------------------------------------------------------------------------------------
 // Returns whether the processing step is present in the given flag field.
 bool MakeLeftHandedProcess::IsActive( unsigned int pFlags) const
 {
-	return 0 != (pFlags & aiProcess_MakeLeftHanded);
+    return 0 != (pFlags & aiProcess_MakeLeftHanded);
 }
 
 // ------------------------------------------------------------------------------------------------
 // Executes the post processing step on the given imported data.
 void MakeLeftHandedProcess::Execute( aiScene* pScene)
 {
-	// Check for an existent root node to proceed
-	ai_assert(pScene->mRootNode != NULL);
-	DefaultLogger::get()->debug("MakeLeftHandedProcess begin");
-
-	// recursively convert all the nodes 
-	ProcessNode( pScene->mRootNode, aiMatrix4x4());
-
-	// process the meshes accordingly
-	for( unsigned int a = 0; a < pScene->mNumMeshes; ++a)
-		ProcessMesh( pScene->mMeshes[a]);
-
-	// process the materials accordingly
-	for( unsigned int a = 0; a < pScene->mNumMaterials; ++a)
-		ProcessMaterial( pScene->mMaterials[a]);
-
-	// transform all animation channels as well
-	for( unsigned int a = 0; a < pScene->mNumAnimations; a++)
-	{
-		aiAnimation* anim = pScene->mAnimations[a];
-		for( unsigned int b = 0; b < anim->mNumChannels; b++)
-		{
-			aiNodeAnim* nodeAnim = anim->mChannels[b];
-			ProcessAnimation( nodeAnim);
-		}
-	}
-	DefaultLogger::get()->debug("MakeLeftHandedProcess finished");
+    // Check for an existent root node to proceed
+    ai_assert(pScene->mRootNode != NULL);
+    DefaultLogger::get()->debug("MakeLeftHandedProcess begin");
+
+    // recursively convert all the nodes
+    ProcessNode( pScene->mRootNode, aiMatrix4x4());
+
+    // process the meshes accordingly
+    for( unsigned int a = 0; a < pScene->mNumMeshes; ++a)
+        ProcessMesh( pScene->mMeshes[a]);
+
+    // process the materials accordingly
+    for( unsigned int a = 0; a < pScene->mNumMaterials; ++a)
+        ProcessMaterial( pScene->mMaterials[a]);
+
+    // transform all animation channels as well
+    for( unsigned int a = 0; a < pScene->mNumAnimations; a++)
+    {
+        aiAnimation* anim = pScene->mAnimations[a];
+        for( unsigned int b = 0; b < anim->mNumChannels; b++)
+        {
+            aiNodeAnim* nodeAnim = anim->mChannels[b];
+            ProcessAnimation( nodeAnim);
+        }
+    }
+    DefaultLogger::get()->debug("MakeLeftHandedProcess finished");
 }
 
 // ------------------------------------------------------------------------------------------------
 // Recursively converts a node, all of its children and all of its meshes
 void MakeLeftHandedProcess::ProcessNode( aiNode* pNode, const aiMatrix4x4& pParentGlobalRotation)
 {
-	// mirror all base vectors at the local Z axis
-	pNode->mTransformation.c1 = -pNode->mTransformation.c1;
-	pNode->mTransformation.c2 = -pNode->mTransformation.c2;
-	pNode->mTransformation.c3 = -pNode->mTransformation.c3;
-	pNode->mTransformation.c4 = -pNode->mTransformation.c4;
-
-	// now invert the Z axis again to keep the matrix determinant positive.
-	// The local meshes will be inverted accordingly so that the result should look just fine again.
-	pNode->mTransformation.a3 = -pNode->mTransformation.a3;
-	pNode->mTransformation.b3 = -pNode->mTransformation.b3;
-	pNode->mTransformation.c3 = -pNode->mTransformation.c3;
-	pNode->mTransformation.d3 = -pNode->mTransformation.d3; // useless, but anyways...
-
-	// continue for all children
-	for( size_t a = 0; a < pNode->mNumChildren; ++a)
-		ProcessNode( pNode->mChildren[a], pParentGlobalRotation * pNode->mTransformation);
+    // mirror all base vectors at the local Z axis
+    pNode->mTransformation.c1 = -pNode->mTransformation.c1;
+    pNode->mTransformation.c2 = -pNode->mTransformation.c2;
+    pNode->mTransformation.c3 = -pNode->mTransformation.c3;
+    pNode->mTransformation.c4 = -pNode->mTransformation.c4;
+
+    // now invert the Z axis again to keep the matrix determinant positive.
+    // The local meshes will be inverted accordingly so that the result should look just fine again.
+    pNode->mTransformation.a3 = -pNode->mTransformation.a3;
+    pNode->mTransformation.b3 = -pNode->mTransformation.b3;
+    pNode->mTransformation.c3 = -pNode->mTransformation.c3;
+    pNode->mTransformation.d3 = -pNode->mTransformation.d3; // useless, but anyways...
+
+    // continue for all children
+    for( size_t a = 0; a < pNode->mNumChildren; ++a ) {
+        ProcessNode( pNode->mChildren[ a ], pParentGlobalRotation * pNode->mTransformation );
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
-// Converts a single mesh to left handed coordinates. 
+// Converts a single mesh to left handed coordinates.
 void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh)
 {
-	// mirror positions, normals and stuff along the Z axis
-	for( size_t a = 0; a < pMesh->mNumVertices; ++a)
-	{
-		pMesh->mVertices[a].z *= -1.0f;
-		if( pMesh->HasNormals())
-			pMesh->mNormals[a].z *= -1.0f;
-		if( pMesh->HasTangentsAndBitangents())
-		{
-			pMesh->mTangents[a].z *= -1.0f;
-			pMesh->mBitangents[a].z *= -1.0f;
-		}
-	}
-
-	// mirror offset matrices of all bones
-	for( size_t a = 0; a < pMesh->mNumBones; ++a)
-	{
-		aiBone* bone = pMesh->mBones[a];
-		bone->mOffsetMatrix.a3 = -bone->mOffsetMatrix.a3;
-		bone->mOffsetMatrix.b3 = -bone->mOffsetMatrix.b3;
-		bone->mOffsetMatrix.d3 = -bone->mOffsetMatrix.d3;
-		bone->mOffsetMatrix.c1 = -bone->mOffsetMatrix.c1;
-		bone->mOffsetMatrix.c2 = -bone->mOffsetMatrix.c2;
-		bone->mOffsetMatrix.c4 = -bone->mOffsetMatrix.c4;
-	}
-
-	// mirror bitangents as well as they're derived from the texture coords
-	if( pMesh->HasTangentsAndBitangents())
-	{
-		for( unsigned int a = 0; a < pMesh->mNumVertices; a++)
-			pMesh->mBitangents[a] *= -1.0f;
-	}
+    // mirror positions, normals and stuff along the Z axis
+    for( size_t a = 0; a < pMesh->mNumVertices; ++a)
+    {
+        pMesh->mVertices[a].z *= -1.0f;
+        if( pMesh->HasNormals())
+            pMesh->mNormals[a].z *= -1.0f;
+        if( pMesh->HasTangentsAndBitangents())
+        {
+            pMesh->mTangents[a].z *= -1.0f;
+            pMesh->mBitangents[a].z *= -1.0f;
+        }
+    }
+
+    // mirror offset matrices of all bones
+    for( size_t a = 0; a < pMesh->mNumBones; ++a)
+    {
+        aiBone* bone = pMesh->mBones[a];
+        bone->mOffsetMatrix.a3 = -bone->mOffsetMatrix.a3;
+        bone->mOffsetMatrix.b3 = -bone->mOffsetMatrix.b3;
+        bone->mOffsetMatrix.d3 = -bone->mOffsetMatrix.d3;
+        bone->mOffsetMatrix.c1 = -bone->mOffsetMatrix.c1;
+        bone->mOffsetMatrix.c2 = -bone->mOffsetMatrix.c2;
+        bone->mOffsetMatrix.c4 = -bone->mOffsetMatrix.c4;
+    }
+
+    // mirror bitangents as well as they're derived from the texture coords
+    if( pMesh->HasTangentsAndBitangents())
+    {
+        for( unsigned int a = 0; a < pMesh->mNumVertices; a++)
+            pMesh->mBitangents[a] *= -1.0f;
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
-// Converts a single material to left handed coordinates. 
+// Converts a single material to left handed coordinates.
 void MakeLeftHandedProcess::ProcessMaterial( aiMaterial* _mat)
 {
-	aiMaterial* mat = (aiMaterial*)_mat;
-	for (unsigned int a = 0; a < mat->mNumProperties;++a)	{
-		aiMaterialProperty* prop = mat->mProperties[a];
-
-		// Mapping axis for UV mappings?
-		if (!::strcmp( prop->mKey.data, "$tex.mapaxis"))	{
-			ai_assert( prop->mDataLength >= sizeof(aiVector3D)); /* something is wrong with the validation if we end up here */ 
-			aiVector3D* pff = (aiVector3D*)prop->mData;
-
-			pff->z *= -1.f;
-		}
-	}
+    aiMaterial* mat = (aiMaterial*)_mat;
+    for (unsigned int a = 0; a < mat->mNumProperties;++a)   {
+        aiMaterialProperty* prop = mat->mProperties[a];
+
+        // Mapping axis for UV mappings?
+        if (!::strcmp( prop->mKey.data, "$tex.mapaxis"))    {
+            ai_assert( prop->mDataLength >= sizeof(aiVector3D)); /* something is wrong with the validation if we end up here */
+            aiVector3D* pff = (aiVector3D*)prop->mData;
+
+            pff->z *= -1.f;
+        }
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
-// Converts the given animation to LH coordinates. 
-void MakeLeftHandedProcess::ProcessAnimation( aiNodeAnim* pAnim) 
-{ 
-	// position keys 
-	for( unsigned int a = 0; a < pAnim->mNumPositionKeys; a++) 
-		pAnim->mPositionKeys[a].mValue.z *= -1.0f; 
-
-	// rotation keys 
-	for( unsigned int a = 0; a < pAnim->mNumRotationKeys; a++) 
-	{ 
-		/* That's the safe version, but the float errors add up. So we try the short version instead 
-		aiMatrix3x3 rotmat = pAnim->mRotationKeys[a].mValue.GetMatrix(); 
-		rotmat.a3 = -rotmat.a3; rotmat.b3 = -rotmat.b3; 
-		rotmat.c1 = -rotmat.c1; rotmat.c2 = -rotmat.c2; 
-		aiQuaternion rotquat( rotmat); 
-		pAnim->mRotationKeys[a].mValue = rotquat; 
-		*/ 
-		pAnim->mRotationKeys[a].mValue.x *= -1.0f; 
-		pAnim->mRotationKeys[a].mValue.y *= -1.0f; 
-	} 
-} 
+// Converts the given animation to LH coordinates.
+void MakeLeftHandedProcess::ProcessAnimation( aiNodeAnim* pAnim)
+{
+    // position keys
+    for( unsigned int a = 0; a < pAnim->mNumPositionKeys; a++)
+        pAnim->mPositionKeys[a].mValue.z *= -1.0f;
+
+    // rotation keys
+    for( unsigned int a = 0; a < pAnim->mNumRotationKeys; a++)
+    {
+        /* That's the safe version, but the float errors add up. So we try the short version instead
+        aiMatrix3x3 rotmat = pAnim->mRotationKeys[a].mValue.GetMatrix();
+        rotmat.a3 = -rotmat.a3; rotmat.b3 = -rotmat.b3;
+        rotmat.c1 = -rotmat.c1; rotmat.c2 = -rotmat.c2;
+        aiQuaternion rotquat( rotmat);
+        pAnim->mRotationKeys[a].mValue = rotquat;
+        */
+        pAnim->mRotationKeys[a].mValue.x *= -1.0f;
+        pAnim->mRotationKeys[a].mValue.y *= -1.0f;
+    }
+}
 
 #endif // !!  ASSIMP_BUILD_NO_MAKELEFTHANDED_PROCESS
 #ifndef  ASSIMP_BUILD_NO_FLIPUVS_PROCESS
@@ -221,54 +228,60 @@ FlipUVsProcess::~FlipUVsProcess()
 // Returns whether the processing step is present in the given flag field.
 bool FlipUVsProcess::IsActive( unsigned int pFlags) const
 {
-	return 0 != (pFlags & aiProcess_FlipUVs);
+    return 0 != (pFlags & aiProcess_FlipUVs);
 }
 
 // ------------------------------------------------------------------------------------------------
 // Executes the post processing step on the given imported data.
 void FlipUVsProcess::Execute( aiScene* pScene)
 {
-	DefaultLogger::get()->debug("FlipUVsProcess begin");
-	for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
-		ProcessMesh(pScene->mMeshes[i]);
+    DefaultLogger::get()->debug("FlipUVsProcess begin");
+    for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
+        ProcessMesh(pScene->mMeshes[i]);
 
-	for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
-		ProcessMaterial(pScene->mMaterials[i]);
-	DefaultLogger::get()->debug("FlipUVsProcess finished");
+    for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
+        ProcessMaterial(pScene->mMaterials[i]);
+    DefaultLogger::get()->debug("FlipUVsProcess finished");
 }
 
 // ------------------------------------------------------------------------------------------------
-// Converts a single material 
+// Converts a single material
 void FlipUVsProcess::ProcessMaterial (aiMaterial* _mat)
 {
-	aiMaterial* mat = (aiMaterial*)_mat;
-	for (unsigned int a = 0; a < mat->mNumProperties;++a)	{
-		aiMaterialProperty* prop = mat->mProperties[a];
-
-		// UV transformation key?
-		if (!::strcmp( prop->mKey.data, "$tex.uvtrafo"))	{
-			ai_assert( prop->mDataLength >= sizeof(aiUVTransform));  /* something is wrong with the validation if we end up here */
-			aiUVTransform* uv = (aiUVTransform*)prop->mData;
-
-			// just flip it, that's everything
-			uv->mTranslation.y *= -1.f;
-			uv->mRotation *= -1.f;
-		}
-	}
+    aiMaterial* mat = (aiMaterial*)_mat;
+    for (unsigned int a = 0; a < mat->mNumProperties;++a)   {
+        aiMaterialProperty* prop = mat->mProperties[a];
+        if( !prop ) {
+            DefaultLogger::get()->debug( "Property is null" );
+            continue;
+        }
+
+        // UV transformation key?
+        if (!::strcmp( prop->mKey.data, "$tex.uvtrafo"))    {
+            ai_assert( prop->mDataLength >= sizeof(aiUVTransform));  /* something is wrong with the validation if we end up here */
+            aiUVTransform* uv = (aiUVTransform*)prop->mData;
+
+            // just flip it, that's everything
+            uv->mTranslation.y *= -1.f;
+            uv->mRotation *= -1.f;
+        }
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
-// Converts a single mesh 
+// Converts a single mesh
 void FlipUVsProcess::ProcessMesh( aiMesh* pMesh)
 {
-	// mirror texture y coordinate
-	for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++)	{
-		if( !pMesh->HasTextureCoords( a))
-			break;
-
-		for( unsigned int b = 0; b < pMesh->mNumVertices; b++)
-			pMesh->mTextureCoords[a][b].y = 1.0f - pMesh->mTextureCoords[a][b].y;
-	}
+    // mirror texture y coordinate
+    for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; a++)   {
+        if( !pMesh->HasTextureCoords( a ) ) {
+            break;
+        }
+
+        for( unsigned int b = 0; b < pMesh->mNumVertices; b++ ) {
+            pMesh->mTextureCoords[ a ][ b ].y = 1.0f - pMesh->mTextureCoords[ a ][ b ].y;
+        }
+    }
 }
 
 #endif // !ASSIMP_BUILD_NO_FLIPUVS_PROCESS
@@ -289,30 +302,30 @@ FlipWindingOrderProcess::~FlipWindingOrderProcess()
 // Returns whether the processing step is present in the given flag field.
 bool FlipWindingOrderProcess::IsActive( unsigned int pFlags) const
 {
-	return 0 != (pFlags & aiProcess_FlipWindingOrder);
+    return 0 != (pFlags & aiProcess_FlipWindingOrder);
 }
 
 // ------------------------------------------------------------------------------------------------
 // Executes the post processing step on the given imported data.
 void FlipWindingOrderProcess::Execute( aiScene* pScene)
 {
-	DefaultLogger::get()->debug("FlipWindingOrderProcess begin");
-	for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
-		ProcessMesh(pScene->mMeshes[i]);
-	DefaultLogger::get()->debug("FlipWindingOrderProcess finished");
+    DefaultLogger::get()->debug("FlipWindingOrderProcess begin");
+    for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
+        ProcessMesh(pScene->mMeshes[i]);
+    DefaultLogger::get()->debug("FlipWindingOrderProcess finished");
 }
 
 // ------------------------------------------------------------------------------------------------
-// Converts a single mesh 
+// Converts a single mesh
 void FlipWindingOrderProcess::ProcessMesh( aiMesh* pMesh)
 {
-	// invert the order of all faces in this mesh
-	for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
-	{
-		aiFace& face = pMesh->mFaces[a];
-		for( unsigned int b = 0; b < face.mNumIndices / 2; b++)
-			std::swap( face.mIndices[b], face.mIndices[ face.mNumIndices - 1 - b]);
-	}
+    // invert the order of all faces in this mesh
+    for( unsigned int a = 0; a < pMesh->mNumFaces; a++)
+    {
+        aiFace& face = pMesh->mFaces[a];
+        for( unsigned int b = 0; b < face.mNumIndices / 2; b++)
+            std::swap( face.mIndices[b], face.mIndices[ face.mNumIndices - 1 - b]);
+    }
 }
 
 #endif // !! ASSIMP_BUILD_NO_FLIPWINDING_PROCESS

+ 70 - 68
assimplib.mod/assimp/code/ConvertToLHProcess.h

@@ -2,11 +2,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -23,16 +23,16 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -44,7 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  *  - LH to RH
  *  - UV origin upper-left to lower-left
- *  - face order cw to ccw 
+ *  - face order cw to ccw
  */
 #ifndef AI_CONVERTTOLHPROCESS_H_INC
 #define AI_CONVERTTOLHPROCESS_H_INC
@@ -54,14 +54,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 struct aiMesh;
 struct aiNodeAnim;
+struct aiNode;
+struct aiMaterial;
 
-namespace Assimp	{
+namespace Assimp    {
 
 // -----------------------------------------------------------------------------------
 /** @brief The MakeLeftHandedProcess converts all imported data to a left-handed
- *   coordinate system. 
+ *   coordinate system.
  *
- * This implies a mirroring of the Z axis of the coordinate system. But to keep 
+ * This implies a mirroring of the Z axis of the coordinate system. But to keep
  * transformation matrices free from reflections we shift the reflection to other
  * places. We mirror the meshes and adapt the rotations.
  *
@@ -69,46 +71,46 @@ namespace Assimp	{
  */
 class MakeLeftHandedProcess : public BaseProcess
 {
-	
+
 
 public:
-	MakeLeftHandedProcess();
-	~MakeLeftHandedProcess();
+    MakeLeftHandedProcess();
+    ~MakeLeftHandedProcess();
 
-	// -------------------------------------------------------------------
-	bool IsActive( unsigned int pFlags) const;
+    // -------------------------------------------------------------------
+    bool IsActive( unsigned int pFlags) const;
 
-	// -------------------------------------------------------------------
-	void Execute( aiScene* pScene);
+    // -------------------------------------------------------------------
+    void Execute( aiScene* pScene);
 
 protected:
 
-	// -------------------------------------------------------------------
-	/** Recursively converts a node and all of its children
-	 */
-	void ProcessNode( aiNode* pNode, const aiMatrix4x4& pParentGlobalRotation);
-
-	// -------------------------------------------------------------------
-	/** Converts a single mesh to left handed coordinates. 
-	 * This means that positions, normals and tangents are mirrored at
-	 * the local Z axis and the order of all faces are inverted.
-	 * @param pMesh The mesh to convert.
-	 */
-	void ProcessMesh( aiMesh* pMesh);
-
-	// -------------------------------------------------------------------
-	/** Converts a single material to left-handed coordinates
-	 * @param pMat Material to convert
-	 */
-	void ProcessMaterial( aiMaterial* pMat);
-
-	// -------------------------------------------------------------------
-	/** Converts the given animation to LH coordinates. 
-	 * The rotation and translation keys are transformed, the scale keys
-	 * work in local space and can therefore be left untouched.
-	 * @param pAnim The bone animation to transform
-	 */
-	void ProcessAnimation( aiNodeAnim* pAnim);
+    // -------------------------------------------------------------------
+    /** Recursively converts a node and all of its children
+     */
+    void ProcessNode( aiNode* pNode, const aiMatrix4x4& pParentGlobalRotation);
+
+    // -------------------------------------------------------------------
+    /** Converts a single mesh to left handed coordinates.
+     * This means that positions, normals and tangents are mirrored at
+     * the local Z axis and the order of all faces are inverted.
+     * @param pMesh The mesh to convert.
+     */
+    void ProcessMesh( aiMesh* pMesh);
+
+    // -------------------------------------------------------------------
+    /** Converts a single material to left-handed coordinates
+     * @param pMat Material to convert
+     */
+    void ProcessMaterial( aiMaterial* pMat);
+
+    // -------------------------------------------------------------------
+    /** Converts the given animation to LH coordinates.
+     * The rotation and translation keys are transformed, the scale keys
+     * work in local space and can therefore be left untouched.
+     * @param pAnim The bone animation to transform
+     */
+    void ProcessAnimation( aiNodeAnim* pAnim);
 };
 
 
@@ -117,23 +119,23 @@ protected:
  */
 class FlipWindingOrderProcess : public BaseProcess
 {
-	friend class Importer;
+    friend class Importer;
 
 public:
-	/** Constructor to be privately used by Importer */
-	FlipWindingOrderProcess();
+    /** Constructor to be privately used by Importer */
+    FlipWindingOrderProcess();
 
-	/** Destructor, private as well */
-	~FlipWindingOrderProcess();
+    /** Destructor, private as well */
+    ~FlipWindingOrderProcess();
 
-	// -------------------------------------------------------------------
-	bool IsActive( unsigned int pFlags) const;
+    // -------------------------------------------------------------------
+    bool IsActive( unsigned int pFlags) const;
 
-	// -------------------------------------------------------------------
-	void Execute( aiScene* pScene);
+    // -------------------------------------------------------------------
+    void Execute( aiScene* pScene);
 
 protected:
-	void ProcessMesh( aiMesh* pMesh);
+    void ProcessMesh( aiMesh* pMesh);
 };
 
 // ---------------------------------------------------------------------------
@@ -141,24 +143,24 @@ protected:
  */
 class FlipUVsProcess : public BaseProcess
 {
-	friend class Importer;
+    friend class Importer;
 
 public:
-	/** Constructor to be privately used by Importer */
-	FlipUVsProcess();
+    /** Constructor to be privately used by Importer */
+    FlipUVsProcess();
 
-	/** Destructor, private as well */
-	~FlipUVsProcess();
+    /** Destructor, private as well */
+    ~FlipUVsProcess();
 
-	// -------------------------------------------------------------------
-	bool IsActive( unsigned int pFlags) const;
+    // -------------------------------------------------------------------
+    bool IsActive( unsigned int pFlags) const;
 
-	// -------------------------------------------------------------------
-	void Execute( aiScene* pScene);
+    // -------------------------------------------------------------------
+    void Execute( aiScene* pScene);
 
 protected:
-	void ProcessMesh( aiMesh* pMesh);
-	void ProcessMaterial( aiMaterial* mat);
+    void ProcessMesh( aiMesh* pMesh);
+    void ProcessMaterial( aiMaterial* mat);
 };
 
 } // end of namespace Assimp

+ 129 - 126
assimplib.mod/assimp/code/DXFHelper.h

@@ -2,11 +2,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -23,22 +23,22 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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  DXFHelper.h 
+/** @file  DXFHelper.h
  *  @brief Internal utilities for the DXF loader.
  */
 
@@ -48,9 +48,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "LineSplitter.h"
 #include "TinyFormatter.h"
 #include "StreamReader.h"
+#include "fast_atof.h"
+#include <vector>
+#include "../include/assimp/DefaultLogger.hpp"
 
 namespace Assimp {
-	namespace DXF {
+    namespace DXF {
 
 
 // read pairs of lines, parse group code and value and provide utilities
@@ -60,113 +63,113 @@ class LineReader
 
 public:
 
-	LineReader(StreamReaderLE& reader)
-		 // do NOT skip empty lines. In DXF files, they count as valid data.
-		: splitter(reader,false,true)
-		, end()
-	{
-	}
+    LineReader(StreamReaderLE& reader)
+         // do NOT skip empty lines. In DXF files, they count as valid data.
+        : splitter(reader,false,true)
+        , end()
+    {
+    }
 
 public:
 
 
-	// -----------------------------------------
-	bool Is(int gc, const char* what) const {
-		return groupcode == gc && !strcmp(what,value.c_str());
-	}
+    // -----------------------------------------
+    bool Is(int gc, const char* what) const {
+        return groupcode == gc && !strcmp(what,value.c_str());
+    }
 
-	// -----------------------------------------
-	bool Is(int gc) const {
-		return groupcode == gc;
-	}
+    // -----------------------------------------
+    bool Is(int gc) const {
+        return groupcode == gc;
+    }
 
-	// -----------------------------------------
-	int GroupCode() const {
-		return groupcode;
-	}
+    // -----------------------------------------
+    int GroupCode() const {
+        return groupcode;
+    }
 
-	// -----------------------------------------
-	const std::string& Value() const {
-		return value;
-	}
+    // -----------------------------------------
+    const std::string& Value() const {
+        return value;
+    }
 
-	// -----------------------------------------
-	bool End() const {
-		return !((bool)*this);
-	}
+    // -----------------------------------------
+    bool End() const {
+        return !((bool)*this);
+    }
 
 public:
 
-	// -----------------------------------------
-	unsigned int ValueAsUnsignedInt() const {
-		return strtoul10(value.c_str());
-	}
+    // -----------------------------------------
+    unsigned int ValueAsUnsignedInt() const {
+        return strtoul10(value.c_str());
+    }
 
-	// -----------------------------------------
-	int ValueAsSignedInt() const {
-		return strtol10(value.c_str());
-	}
+    // -----------------------------------------
+    int ValueAsSignedInt() const {
+        return strtol10(value.c_str());
+    }
 
-	// -----------------------------------------
-	float ValueAsFloat() const {
-		return fast_atof(value.c_str());
-	}
+    // -----------------------------------------
+    float ValueAsFloat() const {
+        return fast_atof(value.c_str());
+    }
 
 public:
 
-	// -----------------------------------------
-	/** pseudo-iterator increment to advance to the next (groupcode/value) pair */
-	LineReader& operator++() {
-		if (end) {
-			if (end == 1) {
-				++end;
-			}
-			return *this;
-		}
-
-		try {
-			groupcode = strtol10(splitter->c_str());
-			splitter++;
-
-			value = *splitter;
-			splitter++;
-
-			// automatically skip over {} meta blocks (these are for application use
-			// and currently not relevant for Assimp).
-			if (value.length() && value[0] == '{') {
-
-				size_t cnt = 0;
-				for(;splitter->length() && splitter->at(0) != '}'; splitter++, cnt++);
-
-				splitter++;
-				DefaultLogger::get()->debug((Formatter::format("DXF: skipped over control group ("),cnt," lines)"));
-			}
-		} catch(std::logic_error&) {
-			ai_assert(!splitter);
-		}
-		if (!splitter) {
-			end = 1;
-		}
-		return *this;
-	}
-
-	// -----------------------------------------
-	LineReader& operator++(int) {
-		return ++(*this);
-	}
-
-
-	// -----------------------------------------
-	operator bool() const {
-		return end <= 1;
-	}
+    // -----------------------------------------
+    /** pseudo-iterator increment to advance to the next (groupcode/value) pair */
+    LineReader& operator++() {
+        if (end) {
+            if (end == 1) {
+                ++end;
+            }
+            return *this;
+        }
+
+        try {
+            groupcode = strtol10(splitter->c_str());
+            splitter++;
+
+            value = *splitter;
+            splitter++;
+
+            // automatically skip over {} meta blocks (these are for application use
+            // and currently not relevant for Assimp).
+            if (value.length() && value[0] == '{') {
+
+                size_t cnt = 0;
+                for(;splitter->length() && splitter->at(0) != '}'; splitter++, cnt++);
+
+                splitter++;
+                DefaultLogger::get()->debug((Formatter::format("DXF: skipped over control group ("),cnt," lines)"));
+            }
+        } catch(std::logic_error&) {
+            ai_assert(!splitter);
+        }
+        if (!splitter) {
+            end = 1;
+        }
+        return *this;
+    }
+
+    // -----------------------------------------
+    LineReader& operator++(int) {
+        return ++(*this);
+    }
+
+
+    // -----------------------------------------
+    operator bool() const {
+        return end <= 1;
+    }
 
 private:
 
-	LineSplitter splitter;
-	int groupcode;
-	std::string value;
-	int end;
+    LineSplitter splitter;
+    int groupcode;
+    std::string value;
+    int end;
 };
 
 
@@ -174,52 +177,52 @@ private:
 // represents a POLYLINE or a LWPOLYLINE. or even a 3DFACE The data is converted as needed.
 struct PolyLine
 {
-	PolyLine()
-		: flags()
-	{}
-	
-	std::vector<aiVector3D> positions;
-	std::vector<aiColor4D>  colors;
-	std::vector<unsigned int> indices;
-	std::vector<unsigned int> counts;
-	unsigned int flags;
-
-	std::string layer;
-	std::string desc;
+    PolyLine()
+        : flags()
+    {}
+
+    std::vector<aiVector3D> positions;
+    std::vector<aiColor4D>  colors;
+    std::vector<unsigned int> indices;
+    std::vector<unsigned int> counts;
+    unsigned int flags;
+
+    std::string layer;
+    std::string desc;
 };
 
 
 // reference to a BLOCK. Specifies its own coordinate system.
 struct InsertBlock
 {
-	InsertBlock()
-		: scale(1.f,1.f,1.f)
-		, angle()
-	{}
+    InsertBlock()
+        : scale(1.f,1.f,1.f)
+        , angle()
+    {}
 
-	aiVector3D pos;
-	aiVector3D scale;
-	float angle;
+    aiVector3D pos;
+    aiVector3D scale;
+    float angle;
 
-	std::string name;
+    std::string name;
 };
 
 
 // keeps track of all geometry in a single BLOCK.
 struct Block
 {
-	std::vector< boost::shared_ptr<PolyLine> > lines;
-	std::vector<InsertBlock> insertions;
+    std::vector< boost::shared_ptr<PolyLine> > lines;
+    std::vector<InsertBlock> insertions;
 
-	std::string name;
-	aiVector3D base;
+    std::string name;
+    aiVector3D base;
 };
 
 
 struct FileData
 {
-	// note: the LAST block always contains the stuff from ENTITIES.
-	std::vector<Block> blocks;
+    // note: the LAST block always contains the stuff from ENTITIES.
+    std::vector<Block> blocks;
 };
 
 

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 570 - 566
assimplib.mod/assimp/code/DXFLoader.cpp


+ 76 - 76
assimplib.mod/assimp/code/DXFLoader.h

@@ -2,11 +2,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -23,22 +23,22 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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  DXFLoader.h 
+/** @file  DXFLoader.h
  *  @brief Declaration of the .dxf importer class.
  */
 #ifndef AI_DXFLOADER_H_INCLUDED
@@ -46,17 +46,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include "BaseImporter.h"
 
-namespace Assimp	{
-	namespace DXF {
-	
-		class LineReader;
-		struct FileData;
-		struct PolyLine;
-		struct Block;
-		struct InsertBlock;
+namespace Assimp    {
+    namespace DXF {
 
-		typedef std::map<std::string, const DXF::Block*> BlockMap;
-	}
+        class LineReader;
+        struct FileData;
+        struct PolyLine;
+        struct Block;
+        struct InsertBlock;
+
+        typedef std::map<std::string, const DXF::Block*> BlockMap;
+    }
 
 
 // ---------------------------------------------------------------------------
@@ -66,85 +66,85 @@ namespace Assimp	{
 class DXFImporter : public BaseImporter
 {
 public:
-	DXFImporter();
-	~DXFImporter();
+    DXFImporter();
+    ~DXFImporter();
 
 
 
 public:
 
-	// -------------------------------------------------------------------
-	/** Returns whether the class can handle the format of the given file. 
-	* See BaseImporter::CanRead() for details.	*/
-	bool CanRead( const std::string& pFile, IOSystem* pIOHandler, 
-		bool checkSig) const;
+    // -------------------------------------------------------------------
+    /** Returns whether the class can handle the format of the given file.
+    * See BaseImporter::CanRead() for details.  */
+    bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
+        bool checkSig) const;
 
 protected:
 
-	// -------------------------------------------------------------------
-	/** Return importer meta information.
-	 * See #BaseImporter::GetInfo for the details*/
-	const aiImporterDesc* GetInfo () const;
+    // -------------------------------------------------------------------
+    /** Return importer meta information.
+     * See #BaseImporter::GetInfo for the details*/
+    const aiImporterDesc* GetInfo () const;
 
-	// -------------------------------------------------------------------
-	/** Imports the given file into the given scene structure. 
-	 * See BaseImporter::InternReadFile() for details */
-	void InternReadFile( const std::string& pFile, 
-		aiScene* pScene, 
-		IOSystem* pIOHandler);
+    // -------------------------------------------------------------------
+    /** Imports the given file into the given scene structure.
+     * See BaseImporter::InternReadFile() for details */
+    void InternReadFile( const std::string& pFile,
+        aiScene* pScene,
+        IOSystem* pIOHandler);
 
 private:
 
-	// -----------------------------------------------------
-	void SkipSection(DXF::LineReader& reader);
+    // -----------------------------------------------------
+    void SkipSection(DXF::LineReader& reader);
 
-	// -----------------------------------------------------
-	void ParseHeader(DXF::LineReader& reader,
-		DXF::FileData& output);
+    // -----------------------------------------------------
+    void ParseHeader(DXF::LineReader& reader,
+        DXF::FileData& output);
 
-	// -----------------------------------------------------
-	void ParseEntities(DXF::LineReader& reader,
-		DXF::FileData& output);
+    // -----------------------------------------------------
+    void ParseEntities(DXF::LineReader& reader,
+        DXF::FileData& output);
 
-	// -----------------------------------------------------
-	void ParseBlocks(DXF::LineReader& reader, 
-		DXF::FileData& output);
+    // -----------------------------------------------------
+    void ParseBlocks(DXF::LineReader& reader,
+        DXF::FileData& output);
 
-	// -----------------------------------------------------
-	void ParseBlock(DXF::LineReader& reader, 
-		DXF::FileData& output);
+    // -----------------------------------------------------
+    void ParseBlock(DXF::LineReader& reader,
+        DXF::FileData& output);
 
-	// -----------------------------------------------------
-	void ParseInsertion(DXF::LineReader& reader, 
-		DXF::FileData& output);
+    // -----------------------------------------------------
+    void ParseInsertion(DXF::LineReader& reader,
+        DXF::FileData& output);
 
-	// -----------------------------------------------------
-	void ParsePolyLine(DXF::LineReader& reader, 
-		DXF::FileData& output);
+    // -----------------------------------------------------
+    void ParsePolyLine(DXF::LineReader& reader,
+        DXF::FileData& output);
 
-	// -----------------------------------------------------
-	void ParsePolyLineVertex(DXF::LineReader& reader, 
-		DXF::PolyLine& line);
+    // -----------------------------------------------------
+    void ParsePolyLineVertex(DXF::LineReader& reader,
+        DXF::PolyLine& line);
 
-	// -----------------------------------------------------
-	void Parse3DFace(DXF::LineReader& reader, 
-		DXF::FileData& output);
+    // -----------------------------------------------------
+    void Parse3DFace(DXF::LineReader& reader,
+        DXF::FileData& output);
 
-	// -----------------------------------------------------
-	void ConvertMeshes(aiScene* pScene, 
-		DXF::FileData& output);
+    // -----------------------------------------------------
+    void ConvertMeshes(aiScene* pScene,
+        DXF::FileData& output);
 
-	// -----------------------------------------------------
-	void GenerateHierarchy(aiScene* pScene, 
-		DXF::FileData& output);
+    // -----------------------------------------------------
+    void GenerateHierarchy(aiScene* pScene,
+        DXF::FileData& output);
 
-	// -----------------------------------------------------
-	void GenerateMaterials(aiScene* pScene, 
-		DXF::FileData& output);
+    // -----------------------------------------------------
+    void GenerateMaterials(aiScene* pScene,
+        DXF::FileData& output);
 
-	// -----------------------------------------------------
-	void ExpandBlockReferences(DXF::Block& bl,
-		const DXF::BlockMap& blocks_by_name);
+    // -----------------------------------------------------
+    void ExpandBlockReferences(DXF::Block& bl,
+        const DXF::BlockMap& blocks_by_name);
 };
 
 } // end of namespace Assimp

+ 372 - 371
assimplib.mod/assimp/code/DeboneProcess.cpp

@@ -1,12 +1,12 @@
-									 /*
+/*
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -23,16 +23,16 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -41,11 +41,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 /// @file DeboneProcess.cpp
 /** Implementation of the DeboneProcess post processing step */
 
-#include "AssimpPCH.h"
+
 
 // internal headers of the post-processing framework
 #include "ProcessHelper.h"
 #include "DeboneProcess.h"
+#include <stdio.h>
 
 
 using namespace Assimp;
@@ -54,411 +55,411 @@ using namespace Assimp;
 // Constructor to be privately used by Importer
 DeboneProcess::DeboneProcess()
 {
-	mNumBones = 0;
-	mNumBonesCanDoWithout = 0;
+    mNumBones = 0;
+    mNumBonesCanDoWithout = 0;
 
-	mThreshold = AI_DEBONE_THRESHOLD;
-	mAllOrNone = false;
+    mThreshold = AI_DEBONE_THRESHOLD;
+    mAllOrNone = false;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 DeboneProcess::~DeboneProcess()
 {
-	// nothing to do here
+    // nothing to do here
 }
 
 // ------------------------------------------------------------------------------------------------
 // Returns whether the processing step is present in the given flag field.
 bool DeboneProcess::IsActive( unsigned int pFlags) const
 {
-	return (pFlags & aiProcess_Debone) != 0;
+    return (pFlags & aiProcess_Debone) != 0;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Executes the post processing step on the given imported data.
 void DeboneProcess::SetupProperties(const Importer* pImp)
-{	
-	// get the current value of the property
-	mAllOrNone = pImp->GetPropertyInteger(AI_CONFIG_PP_DB_ALL_OR_NONE,0)?true:false;
-	mThreshold = pImp->GetPropertyFloat(AI_CONFIG_PP_DB_THRESHOLD,AI_DEBONE_THRESHOLD);
+{
+    // get the current value of the property
+    mAllOrNone = pImp->GetPropertyInteger(AI_CONFIG_PP_DB_ALL_OR_NONE,0)?true:false;
+    mThreshold = pImp->GetPropertyFloat(AI_CONFIG_PP_DB_THRESHOLD,AI_DEBONE_THRESHOLD);
 }
 
 // ------------------------------------------------------------------------------------------------
 // Executes the post processing step on the given imported data.
 void DeboneProcess::Execute( aiScene* pScene)
 {
-	DefaultLogger::get()->debug("DeboneProcess begin");
-
-	if(!pScene->mNumMeshes) {
-		return;
-	}
-
-	std::vector<bool> splitList(pScene->mNumMeshes); 
-	for( unsigned int a = 0; a < pScene->mNumMeshes; a++) {
-		splitList[a] = ConsiderMesh( pScene->mMeshes[a] );
-	}
-
-	int numSplits = 0; 
-
-	if(!!mNumBonesCanDoWithout && (!mAllOrNone||mNumBonesCanDoWithout==mNumBones))	{
-		for(unsigned int a = 0; a < pScene->mNumMeshes; a++)	{
-			if(splitList[a]) {
-				numSplits++;
-			}
-		}
-	}
-
-	if(numSplits)	{
-		// we need to do something. Let's go.
-		mSubMeshIndices.clear();
-		mSubMeshIndices.resize(pScene->mNumMeshes);
-
-		// build a new array of meshes for the scene
-		std::vector<aiMesh*> meshes;
-
-		for(unsigned int a=0;a<pScene->mNumMeshes;a++)
-		{
-			aiMesh* srcMesh = pScene->mMeshes[a];
-
-			std::vector<std::pair<aiMesh*,const aiBone*> > newMeshes;
-
-			if(splitList[a]) { 
-				SplitMesh(srcMesh,newMeshes);
-			}
-
-			// mesh was split
-			if(!newMeshes.empty())	{				
-				unsigned int out = 0, in = srcMesh->mNumBones;				
-
-				// store new meshes and indices of the new meshes
-				for(unsigned int b=0;b<newMeshes.size();b++)	{						
-					const aiString *find = newMeshes[b].second?&newMeshes[b].second->mName:0;
-
-					aiNode *theNode = find?pScene->mRootNode->FindNode(*find):0;
-					std::pair<unsigned int,aiNode*> push_pair(meshes.size(),theNode);
-
-					mSubMeshIndices[a].push_back(push_pair);
-					meshes.push_back(newMeshes[b].first);
-
-					out+=newMeshes[b].first->mNumBones;
-				}
-						   
-				if(!DefaultLogger::isNullLogger()) {
-					char buffer[1024];
-					::sprintf(buffer,"Removed %i bones. Input bones: %i. Output bones: %i",in-out,in,out);
-					DefaultLogger::get()->info(buffer);
-				}
-
-				// and destroy the source mesh. It should be completely contained inside the new submeshes
-				delete srcMesh;
-			}
-			else	{
-				// Mesh is kept unchanged - store it's new place in the mesh array
-				mSubMeshIndices[a].push_back(std::pair<unsigned int,aiNode*>(meshes.size(),(aiNode*)0));
-				meshes.push_back(srcMesh);
-			}
-		}	
-			
-		// rebuild the scene's mesh array
-		pScene->mNumMeshes = meshes.size();
-		delete [] pScene->mMeshes;
-		pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
-		std::copy( meshes.begin(), meshes.end(), pScene->mMeshes);
-
-		// recurse through all nodes and translate the node's mesh indices to fit the new mesh array
-		UpdateNode( pScene->mRootNode);
-	}
-
-	DefaultLogger::get()->debug("DeboneProcess end");
+    DefaultLogger::get()->debug("DeboneProcess begin");
+
+    if(!pScene->mNumMeshes) {
+        return;
+    }
+
+    std::vector<bool> splitList(pScene->mNumMeshes);
+    for( unsigned int a = 0; a < pScene->mNumMeshes; a++) {
+        splitList[a] = ConsiderMesh( pScene->mMeshes[a] );
+    }
+
+    int numSplits = 0;
+
+    if(!!mNumBonesCanDoWithout && (!mAllOrNone||mNumBonesCanDoWithout==mNumBones))  {
+        for(unsigned int a = 0; a < pScene->mNumMeshes; a++)    {
+            if(splitList[a]) {
+                numSplits++;
+            }
+        }
+    }
+
+    if(numSplits)   {
+        // we need to do something. Let's go.
+        //mSubMeshIndices.clear();                  // really needed?
+        mSubMeshIndices.resize(pScene->mNumMeshes); // because we're doing it here anyway
+
+        // build a new array of meshes for the scene
+        std::vector<aiMesh*> meshes;
+
+        for(unsigned int a=0;a<pScene->mNumMeshes;a++)
+        {
+            aiMesh* srcMesh = pScene->mMeshes[a];
+
+            std::vector<std::pair<aiMesh*,const aiBone*> > newMeshes;
+
+            if(splitList[a]) {
+                SplitMesh(srcMesh,newMeshes);
+            }
+
+            // mesh was split
+            if(!newMeshes.empty())  {
+                unsigned int out = 0, in = srcMesh->mNumBones;
+
+                // store new meshes and indices of the new meshes
+                for(unsigned int b=0;b<newMeshes.size();b++)    {
+                    const aiString *find = newMeshes[b].second?&newMeshes[b].second->mName:0;
+
+                    aiNode *theNode = find?pScene->mRootNode->FindNode(*find):0;
+                    std::pair<unsigned int,aiNode*> push_pair(meshes.size(),theNode);
+
+                    mSubMeshIndices[a].push_back(push_pair);
+                    meshes.push_back(newMeshes[b].first);
+
+                    out+=newMeshes[b].first->mNumBones;
+                }
+
+                if(!DefaultLogger::isNullLogger()) {
+                    char buffer[1024];
+                    ::sprintf(buffer,"Removed %u bones. Input bones: %u. Output bones: %u",in-out,in,out);
+                    DefaultLogger::get()->info(buffer);
+                }
+
+                // and destroy the source mesh. It should be completely contained inside the new submeshes
+                delete srcMesh;
+            }
+            else    {
+                // Mesh is kept unchanged - store it's new place in the mesh array
+                mSubMeshIndices[a].push_back(std::pair<unsigned int,aiNode*>(meshes.size(),(aiNode*)0));
+                meshes.push_back(srcMesh);
+            }
+        }
+
+        // rebuild the scene's mesh array
+        pScene->mNumMeshes = meshes.size();
+        delete [] pScene->mMeshes;
+        pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
+        std::copy( meshes.begin(), meshes.end(), pScene->mMeshes);
+
+        // recurse through all nodes and translate the node's mesh indices to fit the new mesh array
+        UpdateNode( pScene->mRootNode);
+    }
+
+    DefaultLogger::get()->debug("DeboneProcess end");
 }
 
 // ------------------------------------------------------------------------------------------------
 // Counts bones total/removable in a given mesh.
 bool DeboneProcess::ConsiderMesh(const aiMesh* pMesh)
 {
-	if(!pMesh->HasBones()) {
-		return false;
-	}
-
-	bool split = false;
-
-	//interstitial faces not permitted
-	bool isInterstitialRequired = false;
-
-	std::vector<bool> isBoneNecessary(pMesh->mNumBones,false);
-	std::vector<unsigned int> vertexBones(pMesh->mNumVertices,UINT_MAX);
-
-	const unsigned int cUnowned = UINT_MAX;
-	const unsigned int cCoowned = UINT_MAX-1;
-
-	for(unsigned int i=0;i<pMesh->mNumBones;i++)	{
-		for(unsigned int j=0;j<pMesh->mBones[i]->mNumWeights;j++)	{
-			float w = pMesh->mBones[i]->mWeights[j].mWeight;
-
-			if(w==0.0f) {
-				continue;
-			}
-
-			unsigned int vid = pMesh->mBones[i]->mWeights[j].mVertexId;
-			if(w>=mThreshold)	{
-
-				if(vertexBones[vid]!=cUnowned)	{
-					if(vertexBones[vid]==i) //double entry
-					{
-						DefaultLogger::get()->warn("Encountered double entry in bone weights");					
-					}
-					else //TODO: track attraction in order to break tie
-					{
-						vertexBones[vid] = cCoowned;
-					}
-				}
-				else vertexBones[vid] = i;			
-			}
-
-			if(!isBoneNecessary[i]) {
-				isBoneNecessary[i] = w<mThreshold;
-			}
-		}
-
-		if(!isBoneNecessary[i])  {
-			isInterstitialRequired = true;
-		}
-	}
-
-	if(isInterstitialRequired) {
-		for(unsigned int i=0;i<pMesh->mNumFaces;i++) {
-			unsigned int v = vertexBones[pMesh->mFaces[i].mIndices[0]];
-
-			for(unsigned int j=1;j<pMesh->mFaces[i].mNumIndices;j++) {
-				unsigned int w = vertexBones[pMesh->mFaces[i].mIndices[j]];
-
-				if(v!=w)	{
-					if(v<pMesh->mNumBones) isBoneNecessary[v] = true; 
-					if(w<pMesh->mNumBones) isBoneNecessary[w] = true; 
-				}
-			}
-		}
-	}
-
-	for(unsigned int i=0;i<pMesh->mNumBones;i++)	{
-		if(!isBoneNecessary[i])	{
-			mNumBonesCanDoWithout++; 
-			split = true;
-		}
-		
-		mNumBones++;
-	}
-	return split;
+    if(!pMesh->HasBones()) {
+        return false;
+    }
+
+    bool split = false;
+
+    //interstitial faces not permitted
+    bool isInterstitialRequired = false;
+
+    std::vector<bool> isBoneNecessary(pMesh->mNumBones,false);
+    std::vector<unsigned int> vertexBones(pMesh->mNumVertices,UINT_MAX);
+
+    const unsigned int cUnowned = UINT_MAX;
+    const unsigned int cCoowned = UINT_MAX-1;
+
+    for(unsigned int i=0;i<pMesh->mNumBones;i++)    {
+        for(unsigned int j=0;j<pMesh->mBones[i]->mNumWeights;j++)   {
+            float w = pMesh->mBones[i]->mWeights[j].mWeight;
+
+            if(w==0.0f) {
+                continue;
+            }
+
+            unsigned int vid = pMesh->mBones[i]->mWeights[j].mVertexId;
+            if(w>=mThreshold)   {
+
+                if(vertexBones[vid]!=cUnowned)  {
+                    if(vertexBones[vid]==i) //double entry
+                    {
+                        DefaultLogger::get()->warn("Encountered double entry in bone weights");
+                    }
+                    else //TODO: track attraction in order to break tie
+                    {
+                        vertexBones[vid] = cCoowned;
+                    }
+                }
+                else vertexBones[vid] = i;
+            }
+
+            if(!isBoneNecessary[i]) {
+                isBoneNecessary[i] = w<mThreshold;
+            }
+        }
+
+        if(!isBoneNecessary[i])  {
+            isInterstitialRequired = true;
+        }
+    }
+
+    if(isInterstitialRequired) {
+        for(unsigned int i=0;i<pMesh->mNumFaces;i++) {
+            unsigned int v = vertexBones[pMesh->mFaces[i].mIndices[0]];
+
+            for(unsigned int j=1;j<pMesh->mFaces[i].mNumIndices;j++) {
+                unsigned int w = vertexBones[pMesh->mFaces[i].mIndices[j]];
+
+                if(v!=w)    {
+                    if(v<pMesh->mNumBones) isBoneNecessary[v] = true;
+                    if(w<pMesh->mNumBones) isBoneNecessary[w] = true;
+                }
+            }
+        }
+    }
+
+    for(unsigned int i=0;i<pMesh->mNumBones;i++)    {
+        if(!isBoneNecessary[i]) {
+            mNumBonesCanDoWithout++;
+            split = true;
+        }
+
+        mNumBones++;
+    }
+    return split;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Splits the given mesh by bone count.
 void DeboneProcess::SplitMesh( const aiMesh* pMesh, std::vector< std::pair< aiMesh*,const aiBone* > >& poNewMeshes) const
 {
-	// same deal here as ConsiderMesh basically
-
-	std::vector<bool> isBoneNecessary(pMesh->mNumBones,false);
-	std::vector<unsigned int> vertexBones(pMesh->mNumVertices,UINT_MAX);
-
-	const unsigned int cUnowned = UINT_MAX;
-	const unsigned int cCoowned = UINT_MAX-1;
-
-	for(unsigned int i=0;i<pMesh->mNumBones;i++)	{
-		for(unsigned int j=0;j<pMesh->mBones[i]->mNumWeights;j++)	{
-			float w = pMesh->mBones[i]->mWeights[j].mWeight;
-
-			if(w==0.0f) {
-				continue;
-			}
-
-			unsigned int vid = pMesh->mBones[i]->mWeights[j].mVertexId;
-
-			if(w>=mThreshold) {
-				if(vertexBones[vid]!=cUnowned)  {
-					if(vertexBones[vid]==i) //double entry
-					{
-						//DefaultLogger::get()->warn("Encountered double entry in bone weights");					
-					}
-					else //TODO: track attraction in order to break tie
-					{
-						vertexBones[vid] = cCoowned;
-					}
-				}
-				else vertexBones[vid] = i;			
-			}
-
-			if(!isBoneNecessary[i]) {
-				isBoneNecessary[i] = w<mThreshold;
-			}
-		}
-	}
-
-	unsigned int nFacesUnowned = 0;
-
-	std::vector<unsigned int> faceBones(pMesh->mNumFaces,UINT_MAX);
-	std::vector<unsigned int> facesPerBone(pMesh->mNumBones,0);
-
-	for(unsigned int i=0;i<pMesh->mNumFaces;i++) {
-		unsigned int nInterstitial = 1;
-
-		unsigned int v = vertexBones[pMesh->mFaces[i].mIndices[0]];
-
-		for(unsigned int j=1;j<pMesh->mFaces[i].mNumIndices;j++) {
-			unsigned int w = vertexBones[pMesh->mFaces[i].mIndices[j]];
-
-			if(v!=w)	{
-				if(v<pMesh->mNumBones) isBoneNecessary[v] = true; 
-				if(w<pMesh->mNumBones) isBoneNecessary[w] = true; 
-			}
-			else nInterstitial++;
-		}
-
-		if(v<pMesh->mNumBones &&nInterstitial==pMesh->mFaces[i].mNumIndices)	{				
-			faceBones[i] = v; //primitive belongs to bone #v
-			facesPerBone[v]++;
-		}
-		else nFacesUnowned++; 
-	}
-
-	// invalidate any "cojoined" faces
-	for(unsigned int i=0;i<pMesh->mNumFaces;i++) {
-		if(faceBones[i]<pMesh->mNumBones&&isBoneNecessary[faceBones[i]]) 
-		{
-			ai_assert(facesPerBone[faceBones[i]]>0);
-			facesPerBone[faceBones[i]]--; 
-			
-			nFacesUnowned++; 
-			faceBones[i] = cUnowned; 
-		}
-	}
-
-	if(nFacesUnowned) {	 	
-		std::vector<unsigned int> subFaces;
-
-		for(unsigned int i=0;i<pMesh->mNumFaces;i++)	{
-			if(faceBones[i]==cUnowned) {
-				subFaces.push_back(i);
-			}
-		}
-
-		aiMesh *baseMesh = MakeSubmesh(pMesh,subFaces,0);
-		std::pair<aiMesh*,const aiBone*> push_pair(baseMesh,(const aiBone*)0);
-
-		poNewMeshes.push_back(push_pair);
-	}
-
-	for(unsigned int i=0;i<pMesh->mNumBones;i++) {			
-
-		if(!isBoneNecessary[i]&&facesPerBone[i]>0)	{				
-			std::vector<unsigned int> subFaces;
-
-			for(unsigned int j=0;j<pMesh->mNumFaces;j++)	{
-				if(faceBones[j]==i) {
-					subFaces.push_back(j);
-				}
-			}
-
-			unsigned int f = AI_SUBMESH_FLAGS_SANS_BONES;
-			aiMesh *subMesh =MakeSubmesh(pMesh,subFaces,f);
-
-			//Lifted from PretransformVertices.cpp
-			ApplyTransform(subMesh,pMesh->mBones[i]->mOffsetMatrix);
-			std::pair<aiMesh*,const aiBone*> push_pair(subMesh,pMesh->mBones[i]);
-
-			poNewMeshes.push_back(push_pair);		
-		}
-	}
+    // same deal here as ConsiderMesh basically
+
+    std::vector<bool> isBoneNecessary(pMesh->mNumBones,false);
+    std::vector<unsigned int> vertexBones(pMesh->mNumVertices,UINT_MAX);
+
+    const unsigned int cUnowned = UINT_MAX;
+    const unsigned int cCoowned = UINT_MAX-1;
+
+    for(unsigned int i=0;i<pMesh->mNumBones;i++)    {
+        for(unsigned int j=0;j<pMesh->mBones[i]->mNumWeights;j++)   {
+            float w = pMesh->mBones[i]->mWeights[j].mWeight;
+
+            if(w==0.0f) {
+                continue;
+            }
+
+            unsigned int vid = pMesh->mBones[i]->mWeights[j].mVertexId;
+
+            if(w>=mThreshold) {
+                if(vertexBones[vid]!=cUnowned)  {
+                    if(vertexBones[vid]==i) //double entry
+                    {
+                        //DefaultLogger::get()->warn("Encountered double entry in bone weights");
+                    }
+                    else //TODO: track attraction in order to break tie
+                    {
+                        vertexBones[vid] = cCoowned;
+                    }
+                }
+                else vertexBones[vid] = i;
+            }
+
+            if(!isBoneNecessary[i]) {
+                isBoneNecessary[i] = w<mThreshold;
+            }
+        }
+    }
+
+    unsigned int nFacesUnowned = 0;
+
+    std::vector<unsigned int> faceBones(pMesh->mNumFaces,UINT_MAX);
+    std::vector<unsigned int> facesPerBone(pMesh->mNumBones,0);
+
+    for(unsigned int i=0;i<pMesh->mNumFaces;i++) {
+        unsigned int nInterstitial = 1;
+
+        unsigned int v = vertexBones[pMesh->mFaces[i].mIndices[0]];
+
+        for(unsigned int j=1;j<pMesh->mFaces[i].mNumIndices;j++) {
+            unsigned int w = vertexBones[pMesh->mFaces[i].mIndices[j]];
+
+            if(v!=w)    {
+                if(v<pMesh->mNumBones) isBoneNecessary[v] = true;
+                if(w<pMesh->mNumBones) isBoneNecessary[w] = true;
+            }
+            else nInterstitial++;
+        }
+
+        if(v<pMesh->mNumBones &&nInterstitial==pMesh->mFaces[i].mNumIndices)    {
+            faceBones[i] = v; //primitive belongs to bone #v
+            facesPerBone[v]++;
+        }
+        else nFacesUnowned++;
+    }
+
+    // invalidate any "cojoined" faces
+    for(unsigned int i=0;i<pMesh->mNumFaces;i++) {
+        if(faceBones[i]<pMesh->mNumBones&&isBoneNecessary[faceBones[i]])
+        {
+            ai_assert(facesPerBone[faceBones[i]]>0);
+            facesPerBone[faceBones[i]]--;
+
+            nFacesUnowned++;
+            faceBones[i] = cUnowned;
+        }
+    }
+
+    if(nFacesUnowned) {
+        std::vector<unsigned int> subFaces;
+
+        for(unsigned int i=0;i<pMesh->mNumFaces;i++)    {
+            if(faceBones[i]==cUnowned) {
+                subFaces.push_back(i);
+            }
+        }
+
+        aiMesh *baseMesh = MakeSubmesh(pMesh,subFaces,0);
+        std::pair<aiMesh*,const aiBone*> push_pair(baseMesh,(const aiBone*)0);
+
+        poNewMeshes.push_back(push_pair);
+    }
+
+    for(unsigned int i=0;i<pMesh->mNumBones;i++) {
+
+        if(!isBoneNecessary[i]&&facesPerBone[i]>0)  {
+            std::vector<unsigned int> subFaces;
+
+            for(unsigned int j=0;j<pMesh->mNumFaces;j++)    {
+                if(faceBones[j]==i) {
+                    subFaces.push_back(j);
+                }
+            }
+
+            unsigned int f = AI_SUBMESH_FLAGS_SANS_BONES;
+            aiMesh *subMesh =MakeSubmesh(pMesh,subFaces,f);
+
+            //Lifted from PretransformVertices.cpp
+            ApplyTransform(subMesh,pMesh->mBones[i]->mOffsetMatrix);
+            std::pair<aiMesh*,const aiBone*> push_pair(subMesh,pMesh->mBones[i]);
+
+            poNewMeshes.push_back(push_pair);
+        }
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 // Recursively updates the node's mesh list to account for the changed mesh list
 void DeboneProcess::UpdateNode(aiNode* pNode) const
 {
-	// rebuild the node's mesh index list
-	
-	std::vector<unsigned int> newMeshList;
-
-	// this will require two passes
-
-	unsigned int m = pNode->mNumMeshes, n = mSubMeshIndices.size();
-	
-	// first pass, look for meshes which have not moved
-
-	for(unsigned int a=0;a<m;a++)	{
-
-		unsigned int srcIndex = pNode->mMeshes[a];
-		const std::vector< std::pair< unsigned int,aiNode* > > &subMeshes = mSubMeshIndices[srcIndex];
-		unsigned int nSubmeshes = subMeshes.size();
-
-		for(unsigned int b=0;b<nSubmeshes;b++) {
-			if(!subMeshes[b].second) {
-				newMeshList.push_back(subMeshes[b].first);
-			}
-		}
-	}
-
-	// second pass, collect deboned meshes 
-
-	for(unsigned int a=0;a<n;a++)
-	{
-		const std::vector< std::pair< unsigned int,aiNode* > > &subMeshes = mSubMeshIndices[a];
-		unsigned int nSubmeshes = subMeshes.size();
-
-		for(unsigned int b=0;b<nSubmeshes;b++) {
-			if(subMeshes[b].second == pNode)	{
-				newMeshList.push_back(subMeshes[b].first);
-			}
-		}
-	}
-
-	if( pNode->mNumMeshes > 0 )	{
-		delete [] pNode->mMeshes; pNode->mMeshes = NULL;
-	}
-
-	pNode->mNumMeshes = newMeshList.size();
-
-	if(pNode->mNumMeshes)	{
-		pNode->mMeshes = new unsigned int[pNode->mNumMeshes];
-		std::copy( newMeshList.begin(), newMeshList.end(), pNode->mMeshes);
-	}
-
-	// do that also recursively for all children
-	for( unsigned int a = 0; a < pNode->mNumChildren; ++a )	{
-		UpdateNode( pNode->mChildren[a]);
-	}
+    // rebuild the node's mesh index list
+
+    std::vector<unsigned int> newMeshList;
+
+    // this will require two passes
+
+    unsigned int m = pNode->mNumMeshes, n = mSubMeshIndices.size();
+
+    // first pass, look for meshes which have not moved
+
+    for(unsigned int a=0;a<m;a++)   {
+
+        unsigned int srcIndex = pNode->mMeshes[a];
+        const std::vector< std::pair< unsigned int,aiNode* > > &subMeshes = mSubMeshIndices[srcIndex];
+        unsigned int nSubmeshes = subMeshes.size();
+
+        for(unsigned int b=0;b<nSubmeshes;b++) {
+            if(!subMeshes[b].second) {
+                newMeshList.push_back(subMeshes[b].first);
+            }
+        }
+    }
+
+    // second pass, collect deboned meshes
+
+    for(unsigned int a=0;a<n;a++)
+    {
+        const std::vector< std::pair< unsigned int,aiNode* > > &subMeshes = mSubMeshIndices[a];
+        unsigned int nSubmeshes = subMeshes.size();
+
+        for(unsigned int b=0;b<nSubmeshes;b++) {
+            if(subMeshes[b].second == pNode)    {
+                newMeshList.push_back(subMeshes[b].first);
+            }
+        }
+    }
+
+    if( pNode->mNumMeshes > 0 ) {
+        delete [] pNode->mMeshes; pNode->mMeshes = NULL;
+    }
+
+    pNode->mNumMeshes = newMeshList.size();
+
+    if(pNode->mNumMeshes)   {
+        pNode->mMeshes = new unsigned int[pNode->mNumMeshes];
+        std::copy( newMeshList.begin(), newMeshList.end(), pNode->mMeshes);
+    }
+
+    // do that also recursively for all children
+    for( unsigned int a = 0; a < pNode->mNumChildren; ++a ) {
+        UpdateNode( pNode->mChildren[a]);
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 // Apply the node transformation to a mesh
 void DeboneProcess::ApplyTransform(aiMesh* mesh, const aiMatrix4x4& mat)const
 {
-	// Check whether we need to transform the coordinates at all
-	if (!mat.IsIdentity()) {
-		
-		if (mesh->HasPositions()) {
-			for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
-				mesh->mVertices[i] = mat * mesh->mVertices[i];
-			}
-		}
-		if (mesh->HasNormals() || mesh->HasTangentsAndBitangents()) {
-			aiMatrix4x4 mWorldIT = mat;
-			mWorldIT.Inverse().Transpose();
-
-			// TODO: implement Inverse() for aiMatrix3x3
-			aiMatrix3x3 m = aiMatrix3x3(mWorldIT);
-
-			if (mesh->HasNormals()) {
-				for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
-					mesh->mNormals[i] = (m * mesh->mNormals[i]).Normalize();
-				}
-			}
-			if (mesh->HasTangentsAndBitangents()) {
-				for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
-					mesh->mTangents[i]   = (m * mesh->mTangents[i]).Normalize();
-					mesh->mBitangents[i] = (m * mesh->mBitangents[i]).Normalize();
-				}
-			}
-		}
-	}
+    // Check whether we need to transform the coordinates at all
+    if (!mat.IsIdentity()) {
+
+        if (mesh->HasPositions()) {
+            for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
+                mesh->mVertices[i] = mat * mesh->mVertices[i];
+            }
+        }
+        if (mesh->HasNormals() || mesh->HasTangentsAndBitangents()) {
+            aiMatrix4x4 mWorldIT = mat;
+            mWorldIT.Inverse().Transpose();
+
+            // TODO: implement Inverse() for aiMatrix3x3
+            aiMatrix3x3 m = aiMatrix3x3(mWorldIT);
+
+            if (mesh->HasNormals()) {
+                for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
+                    mesh->mNormals[i] = (m * mesh->mNormals[i]).Normalize();
+                }
+            }
+            if (mesh->HasTangentsAndBitangents()) {
+                for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
+                    mesh->mTangents[i]   = (m * mesh->mTangents[i]).Normalize();
+                    mesh->mBitangents[i] = (m * mesh->mBitangents[i]).Normalize();
+                }
+            }
+        }
+    }
 }

+ 63 - 63
assimplib.mod/assimp/code/DeboneProcess.h

@@ -1,12 +1,12 @@
-				   /*
+                   /*
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -23,16 +23,16 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -55,76 +55,76 @@ namespace Assimp
 {
 
 #if (!defined AI_DEBONE_THRESHOLD)
-#	define AI_DEBONE_THRESHOLD	1.0f
+#   define AI_DEBONE_THRESHOLD  1.0f
 #endif // !! AI_DEBONE_THRESHOLD
 
 // ---------------------------------------------------------------------------
-/** This post processing step removes bones nearly losslessly or according to 
+/** This post processing step removes bones nearly losslessly or according to
 * a configured threshold. In order to remove the bone, the primitives affected by
-* the bone are split from the mesh. The split off (new) mesh is boneless. At any 
+* the bone are split from the mesh. The split off (new) mesh is boneless. At any
 * point in time, bones without affect upon a given mesh are to be removed.
 */
 class DeboneProcess : public BaseProcess
 {
 public:
 
-	DeboneProcess();
-	~DeboneProcess();
+    DeboneProcess();
+    ~DeboneProcess();
 
 public:
-	// -------------------------------------------------------------------
-	/** Returns whether the processing step is present in the given flag.
-	* @param pFlags The processing flags the importer was called with. 
-	*   A bitwise combination of #aiPostProcessSteps.
-	* @return true if the process is present in this flag fields, 
-	*   false if not.
-	*/
-	bool IsActive( unsigned int pFlags) const;
-
-	// -------------------------------------------------------------------
-	/** Called prior to ExecuteOnScene().
-	* The function is a request to the process to update its configuration
-	* basing on the Importer's configuration property list.
-	*/
-	void SetupProperties(const Importer* pImp);
+    // -------------------------------------------------------------------
+    /** Returns whether the processing step is present in the given flag.
+    * @param pFlags The processing flags the importer was called with.
+    *   A bitwise combination of #aiPostProcessSteps.
+    * @return true if the process is present in this flag fields,
+    *   false if not.
+    */
+    bool IsActive( unsigned int pFlags) const;
+
+    // -------------------------------------------------------------------
+    /** Called prior to ExecuteOnScene().
+    * The function is a request to the process to update its configuration
+    * basing on the Importer's configuration property list.
+    */
+    void SetupProperties(const Importer* pImp);
 
 protected:
-		
-	// -------------------------------------------------------------------
-	/** Executes the post processing step on the given imported data.
-	* At the moment a process is not supposed to fail.
-	* @param pScene The imported data to work at.
-	*/
-	void Execute( aiScene* pScene);
-
-	// -------------------------------------------------------------------
-	/** Counts bones total/removable in a given mesh.
-	* @param pMesh The mesh to process.
-	*/
-	bool ConsiderMesh( const aiMesh* pMesh);
-
-	/// Splits the given mesh by bone count.
-	/// @param pMesh the Mesh to split. Is not changed at all, but might be superfluous in case it was split.
-	/// @param poNewMeshes Array of submeshes created in the process. Empty if splitting was not necessary.
-	void SplitMesh(const aiMesh* pMesh, std::vector< std::pair< aiMesh*,const aiBone* > >& poNewMeshes) const;
-
-	/// Recursively updates the node's mesh list to account for the changed mesh list
-	void UpdateNode(aiNode* pNode) const;
-
-	// -------------------------------------------------------------------
-	// Apply transformation to a mesh 
-	void ApplyTransform(aiMesh* mesh, const aiMatrix4x4& mat)const;
+
+    // -------------------------------------------------------------------
+    /** Executes the post processing step on the given imported data.
+    * At the moment a process is not supposed to fail.
+    * @param pScene The imported data to work at.
+    */
+    void Execute( aiScene* pScene);
+
+    // -------------------------------------------------------------------
+    /** Counts bones total/removable in a given mesh.
+    * @param pMesh The mesh to process.
+    */
+    bool ConsiderMesh( const aiMesh* pMesh);
+
+    /// Splits the given mesh by bone count.
+    /// @param pMesh the Mesh to split. Is not changed at all, but might be superfluous in case it was split.
+    /// @param poNewMeshes Array of submeshes created in the process. Empty if splitting was not necessary.
+    void SplitMesh(const aiMesh* pMesh, std::vector< std::pair< aiMesh*,const aiBone* > >& poNewMeshes) const;
+
+    /// Recursively updates the node's mesh list to account for the changed mesh list
+    void UpdateNode(aiNode* pNode) const;
+
+    // -------------------------------------------------------------------
+    // Apply transformation to a mesh
+    void ApplyTransform(aiMesh* mesh, const aiMatrix4x4& mat)const;
 
 public:
-	/** Number of bones present in the scene. */
-	unsigned int mNumBones;
-	unsigned int mNumBonesCanDoWithout;
+    /** Number of bones present in the scene. */
+    unsigned int mNumBones;
+    unsigned int mNumBonesCanDoWithout;
 
-	float mThreshold;
-	bool mAllOrNone;
+    float mThreshold;
+    bool mAllOrNone;
 
-	/// Per mesh index: Array of indices of the new submeshes.
-	std::vector< std::vector< std::pair< unsigned int,aiNode* > > > mSubMeshIndices;
+    /// Per mesh index: Array of indices of the new submeshes.
+    std::vector< std::vector< std::pair< unsigned int,aiNode* > > > mSubMeshIndices;
 };
 
 } // end of namespace Assimp

+ 61 - 60
assimplib.mod/assimp/code/DefaultIOStream.cpp

@@ -3,12 +3,12 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -25,90 +25,91 @@ conditions are met:
   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 
+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 
+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 
+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 
+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  DefaultIOStream.cpp
- *  @brief Default File I/O implementation for #Importer 
+ *  @brief Default File I/O implementation for #Importer
  */
 
-#include "AssimpPCH.h"
 
+#include "../include/assimp/ai_assert.h"
 #include "DefaultIOStream.h"
-#include <sys/types.h> 
-#include <sys/stat.h> 
+#include <boost/static_assert.hpp>
+#include <sys/types.h>
+#include <sys/stat.h>
 
 using namespace Assimp;
 
 // ----------------------------------------------------------------------------------
 DefaultIOStream::~DefaultIOStream()
 {
-	if (mFile) {
-		::fclose(mFile);
-	}
+    if (mFile) {
+        ::fclose(mFile);
+    }
 }
 
 // ----------------------------------------------------------------------------------
-size_t DefaultIOStream::Read(void* pvBuffer, 
-	size_t pSize, 
-	size_t pCount)
+size_t DefaultIOStream::Read(void* pvBuffer,
+    size_t pSize,
+    size_t pCount)
 {
-	ai_assert(NULL != pvBuffer && 0 != pSize && 0 != pCount);
-	return (mFile ? ::fread(pvBuffer, pSize, pCount, mFile) : 0);
+    ai_assert(NULL != pvBuffer && 0 != pSize && 0 != pCount);
+    return (mFile ? ::fread(pvBuffer, pSize, pCount, mFile) : 0);
 }
 
 // ----------------------------------------------------------------------------------
-size_t DefaultIOStream::Write(const void* pvBuffer, 
-	size_t pSize,
-	size_t pCount)
+size_t DefaultIOStream::Write(const void* pvBuffer,
+    size_t pSize,
+    size_t pCount)
 {
-	ai_assert(NULL != pvBuffer && 0 != pSize && 0 != pCount);
-	return (mFile ? ::fwrite(pvBuffer, pSize, pCount, mFile) : 0);
+    ai_assert(NULL != pvBuffer && 0 != pSize && 0 != pCount);
+    return (mFile ? ::fwrite(pvBuffer, pSize, pCount, mFile) : 0);
 }
 
 // ----------------------------------------------------------------------------------
 aiReturn DefaultIOStream::Seek(size_t pOffset,
-	 aiOrigin pOrigin)
+     aiOrigin pOrigin)
 {
-	if (!mFile) {
-		return AI_FAILURE;
-	}
+    if (!mFile) {
+        return AI_FAILURE;
+    }
 
-	// Just to check whether our enum maps one to one with the CRT constants
-	BOOST_STATIC_ASSERT(aiOrigin_CUR == SEEK_CUR && 
-		aiOrigin_END == SEEK_END && aiOrigin_SET == SEEK_SET);
+    // Just to check whether our enum maps one to one with the CRT constants
+    BOOST_STATIC_ASSERT(aiOrigin_CUR == SEEK_CUR &&
+        aiOrigin_END == SEEK_END && aiOrigin_SET == SEEK_SET);
 
-	// do the seek
-	return (0 == ::fseek(mFile, (long)pOffset,(int)pOrigin) ? AI_SUCCESS : AI_FAILURE);
+    // do the seek
+    return (0 == ::fseek(mFile, (long)pOffset,(int)pOrigin) ? AI_SUCCESS : AI_FAILURE);
 }
 
 // ----------------------------------------------------------------------------------
 size_t DefaultIOStream::Tell() const
 {
-	if (!mFile) {
-		return 0;
-	}
-	return ::ftell(mFile);
+    if (!mFile) {
+        return 0;
+    }
+    return ::ftell(mFile);
 }
 
 // ----------------------------------------------------------------------------------
 size_t DefaultIOStream::FileSize() const
 {
-	if (! mFile || mFilename.empty()) {
-		return 0;
-	}
-	
-	if (SIZE_MAX == cachedSize) {
+    if (! mFile || mFilename.empty()) {
+        return 0;
+    }
+
+    if (SIZE_MAX == cachedSize) {
 
         // Although fseek/ftell would allow us to reuse the exising file handle here,
         // it is generally unsafe because:
@@ -119,28 +120,28 @@ size_t DefaultIOStream::FileSize() const
         // See here for details:
         // https://www.securecoding.cert.org/confluence/display/seccode/FIO19-C.+Do+not+use+fseek()+and+ftell()+to+compute+the+size+of+a+regular+file
 #if defined _WIN32 && !defined __GNUC__
-		struct __stat64 fileStat; 
-		int err = _stat64(  mFilename.c_str(), &fileStat ); 
-		if (0 != err) 
-			return 0; 
-		cachedSize = (size_t) (fileStat.st_size); 
+        struct __stat64 fileStat;
+        int err = _stat64(  mFilename.c_str(), &fileStat );
+        if (0 != err)
+            return 0;
+        cachedSize = (size_t) (fileStat.st_size);
 #else
-		struct stat fileStat; 
-		int err = stat(mFilename.c_str(), &fileStat ); 
-		if (0 != err) 
-			return 0; 
-		cachedSize = (size_t) (fileStat.st_size); 
+        struct stat fileStat;
+        int err = stat(mFilename.c_str(), &fileStat );
+        if (0 != err)
+            return 0;
+        cachedSize = (size_t) (fileStat.st_size);
 #endif
-	}
-	return cachedSize;
+    }
+    return cachedSize;
 }
 
 // ----------------------------------------------------------------------------------
 void DefaultIOStream::Flush()
 {
-	if (mFile) {
-		::fflush(mFile);
-	}
+    if (mFile) {
+        ::fflush(mFile);
+    }
 }
 
 // ----------------------------------------------------------------------------------

+ 66 - 57
assimplib.mod/assimp/code/DefaultIOStream.h

@@ -2,11 +2,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -23,16 +23,16 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -44,86 +44,95 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <stdio.h>
 #include "../include/assimp/IOStream.hpp"
+#include "../include/assimp/importerdesc.h"
+#include "Defines.h"
 
-namespace Assimp	{
+namespace Assimp    {
 
 // ----------------------------------------------------------------------------------
-//!	@class	DefaultIOStream
-//!	@brief	Default IO implementation, use standard IO operations
+//! @class  DefaultIOStream
+//! @brief  Default IO implementation, use standard IO operations
 //! @note   An instance of this class can exist without a valid file handle
 //!         attached to it. All calls fail, but the instance can nevertheless be
 //!         used with no restrictions.
 class DefaultIOStream : public IOStream
 {
-	friend class DefaultIOSystem;
+    friend class DefaultIOSystem;
+#if __ANDROID__
+#if __ANDROID_API__ > 9
+#if defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT)
+    friend class AndroidJNIIOSystem;
+#endif // defined(AI_CONFIG_ANDROID_JNI_ASSIMP_MANAGER_SUPPORT)
+#endif // __ANDROID_API__ > 9
+#endif // __ANDROID__
 
 protected:
-	DefaultIOStream ();
-	DefaultIOStream (FILE* pFile, const std::string &strFilename);
+    DefaultIOStream();
+    DefaultIOStream(FILE* pFile, const std::string &strFilename);
 
 public:
-	/** Destructor public to allow simple deletion to close the file. */
-	~DefaultIOStream ();
+    /** Destructor public to allow simple deletion to close the file. */
+    ~DefaultIOStream ();
 
-	// -------------------------------------------------------------------
-	// Read from stream
-    size_t Read(void* pvBuffer, 
-		size_t pSize, 
-		size_t pCount);
+    // -------------------------------------------------------------------
+    /// Read from stream
+    size_t Read(void* pvBuffer,
+        size_t pSize,
+        size_t pCount);
 
 
-	// -------------------------------------------------------------------
-	// Write to stream
-    size_t Write(const void* pvBuffer, 
-		size_t pSize,
-		size_t pCount);
+    // -------------------------------------------------------------------
+    /// Write to stream
+    size_t Write(const void* pvBuffer,
+        size_t pSize,
+        size_t pCount);
 
-	// -------------------------------------------------------------------
-	// Seek specific position
-	aiReturn Seek(size_t pOffset,
-		aiOrigin pOrigin);
+    // -------------------------------------------------------------------
+    /// Seek specific position
+    aiReturn Seek(size_t pOffset,
+        aiOrigin pOrigin);
 
-	// -------------------------------------------------------------------
-	// Get current seek position
+    // -------------------------------------------------------------------
+    /// Get current seek position
     size_t Tell() const;
 
-	// -------------------------------------------------------------------
-	// Get size of file
-	size_t FileSize() const;
+    // -------------------------------------------------------------------
+    /// Get size of file
+    size_t FileSize() const;
 
-	// -------------------------------------------------------------------
-	// Flush file contents
-	void Flush();
+    // -------------------------------------------------------------------
+    /// Flush file contents
+    void Flush();
 
 private:
-	//!	File datastructure, using clib
-	FILE* mFile;
-	//!	Filename
-	std::string	mFilename;
+    //  File datastructure, using clib
+    FILE* mFile;
+    //  Filename
+    std::string mFilename;
 
-	//! Cached file size
-	mutable size_t cachedSize;
+    // Cached file size
+    mutable size_t cachedSize;
 };
 
 
 // ----------------------------------------------------------------------------------
-inline DefaultIOStream::DefaultIOStream () : 
-	mFile		(NULL), 
-	mFilename	(""),
-	cachedSize	(SIZE_MAX)
+inline DefaultIOStream::DefaultIOStream () :
+    mFile       (NULL),
+    mFilename   (""),
+    cachedSize  (SIZE_MAX)
 {
-	// empty
+    // empty
 }
 
 
 // ----------------------------------------------------------------------------------
-inline DefaultIOStream::DefaultIOStream (FILE* pFile, 
-		const std::string &strFilename) :
-	mFile(pFile), 
-	mFilename(strFilename),
-	cachedSize	(SIZE_MAX)
+inline DefaultIOStream::DefaultIOStream (FILE* pFile,
+        const std::string &strFilename) :
+    mFile(pFile),
+    mFilename(strFilename),
+    cachedSize  (SIZE_MAX)
 {
-	// empty
+    // empty
 }
 // ----------------------------------------------------------------------------------
 

+ 93 - 60
assimplib.mod/assimp/code/DefaultIOSystem.cpp

@@ -3,12 +3,12 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -25,26 +25,29 @@ conditions are met:
   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 
+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 
+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 
+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 
+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 Default implementation of IOSystem using the standard C file functions */
 
-#include "AssimpPCH.h"
-
-#include <stdlib.h>
 #include "DefaultIOSystem.h"
 #include "DefaultIOStream.h"
+#include "StringComparison.h"
+
+#include "../include/assimp/DefaultLogger.hpp"
+#include "../include/assimp/ai_assert.h"
+#include <stdlib.h>
+
 
 #ifdef __unix__
 #include <sys/param.h>
@@ -54,50 +57,50 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 using namespace Assimp;
 
 // ------------------------------------------------------------------------------------------------
-// Constructor. 
+// Constructor.
 DefaultIOSystem::DefaultIOSystem()
 {
-	// nothing to do here
+    // nothing to do here
 }
 
 // ------------------------------------------------------------------------------------------------
-// Destructor. 
+// Destructor.
 DefaultIOSystem::~DefaultIOSystem()
 {
-	// nothing to do here
+    // nothing to do here
 }
 
 // ------------------------------------------------------------------------------------------------
 // Tests for the existence of a file at the given path.
 bool DefaultIOSystem::Exists( const char* pFile) const
 {
-	FILE* file = ::fopen( pFile, "rb");
-	if( !file)
-		return false;
+    FILE* file = ::fopen( pFile, "rb");
+    if( !file)
+        return false;
 
-	::fclose( file);
-	return true;
+    ::fclose( file);
+    return true;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Open a new file with a given path.
 IOStream* DefaultIOSystem::Open( const char* strFile, const char* strMode)
 {
-	ai_assert(NULL != strFile);
-	ai_assert(NULL != strMode);
+    ai_assert(NULL != strFile);
+    ai_assert(NULL != strMode);
 
-	FILE* file = ::fopen( strFile, strMode);
-	if( NULL == file) 
-		return NULL;
+    FILE* file = ::fopen( strFile, strMode);
+    if( NULL == file)
+        return NULL;
 
-	return new DefaultIOStream(file, (std::string) strFile);
+    return new DefaultIOStream(file, (std::string) strFile);
 }
 
 // ------------------------------------------------------------------------------------------------
 // Closes the given file and releases all resources associated with it.
 void DefaultIOSystem::Close( IOStream* pFile)
 {
-	delete pFile;
+    delete pFile;
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -105,9 +108,9 @@ void DefaultIOSystem::Close( IOStream* pFile)
 char DefaultIOSystem::getOsSeparator() const
 {
 #ifndef _WIN32
-	return '/';
+    return '/';
 #else
-	return '\\';
+    return '\\';
 #endif
 }
 
@@ -115,53 +118,83 @@ char DefaultIOSystem::getOsSeparator() const
 // IOSystem default implementation (ComparePaths isn't a pure virtual function)
 bool IOSystem::ComparePaths (const char* one, const char* second) const
 {
-	return !ASSIMP_stricmp(one,second);
+    return !ASSIMP_stricmp(one,second);
 }
 
 // maximum path length
-// XXX http://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html 
+// XXX http://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html
 #ifdef PATH_MAX
-#	define PATHLIMIT PATH_MAX
+#   define PATHLIMIT PATH_MAX
 #else
-#	define PATHLIMIT 4096
+#   define PATHLIMIT 4096
 #endif
 
 // ------------------------------------------------------------------------------------------------
 // Convert a relative path into an absolute path
 inline void MakeAbsolutePath (const char* in, char* _out)
 {
-	ai_assert(in && _out);
-	char* ret;
-#ifdef _WIN32
-	ret = ::_fullpath(_out, in,PATHLIMIT);
+    ai_assert(in && _out);
+    char* ret;
+#if defined( _MSC_VER ) || defined( __MINGW32__ )
+    ret = ::_fullpath( _out, in, PATHLIMIT );
 #else
-    	// use realpath
-    	ret = realpath(in, _out);
-#endif  
-	if(!ret) {
-		// preserve the input path, maybe someone else is able to fix
-		// the path before it is accessed (e.g. our file system filter)
-		DefaultLogger::get()->warn("Invalid path: "+std::string(in));
-		strcpy(_out,in);
-	}  
+    // use realpath
+    ret = realpath(in, _out);
+#endif
+    if(!ret) {
+        // preserve the input path, maybe someone else is able to fix
+        // the path before it is accessed (e.g. our file system filter)
+        DefaultLogger::get()->warn("Invalid path: "+std::string(in));
+        strcpy(_out,in);
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 // DefaultIOSystem's more specialized implementation
 bool DefaultIOSystem::ComparePaths (const char* one, const char* second) const
 {
-	// chances are quite good both paths are formatted identically,
-	// so we can hopefully return here already
-	if( !ASSIMP_stricmp(one,second) )
-		return true;
-
-	char temp1[PATHLIMIT];
-	char temp2[PATHLIMIT];
-	
-	MakeAbsolutePath (one, temp1);
-	MakeAbsolutePath (second, temp2);
-
-	return !ASSIMP_stricmp(temp1,temp2);
+    // chances are quite good both paths are formatted identically,
+    // so we can hopefully return here already
+    if( !ASSIMP_stricmp(one,second) )
+        return true;
+
+    char temp1[PATHLIMIT];
+    char temp2[PATHLIMIT];
+
+    MakeAbsolutePath (one, temp1);
+    MakeAbsolutePath (second, temp2);
+
+    return !ASSIMP_stricmp(temp1,temp2);
+}
+
+// ------------------------------------------------------------------------------------------------
+std::string DefaultIOSystem::fileName( const std::string &path )
+{
+    std::string ret = path;
+    std::size_t last = ret.find_last_of("\\/");
+    if (last != std::string::npos) ret = ret.substr(last + 1);
+    return ret;
+}
+
+
+// ------------------------------------------------------------------------------------------------
+std::string DefaultIOSystem::completeBaseName( const std::string &path )
+{
+    std::string ret = fileName(path);
+    std::size_t pos = ret.find_last_of('.');
+    if(pos != ret.npos) ret = ret.substr(0, pos);
+    return ret;
 }
 
+// ------------------------------------------------------------------------------------------------
+std::string DefaultIOSystem::absolutePath( const std::string &path )
+{
+    std::string ret = path;
+    std::size_t last = ret.find_last_of("\\/");
+    if (last != std::string::npos) ret = ret.substr(0, last);
+    return ret;
+}
+
+// ------------------------------------------------------------------------------------------------
+
 #undef PATHLIMIT

+ 44 - 29
assimplib.mod/assimp/code/DefaultIOSystem.h

@@ -2,11 +2,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -23,16 +23,16 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -44,38 +44,53 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include "../include/assimp/IOSystem.hpp"
 
-namespace Assimp	{
+namespace Assimp    {
 
 // ---------------------------------------------------------------------------
 /** Default implementation of IOSystem using the standard C file functions */
 class DefaultIOSystem : public IOSystem
 {
 public:
-	/** Constructor. */
+    /** Constructor. */
     DefaultIOSystem();
 
-	/** Destructor. */
-	~DefaultIOSystem();
+    /** Destructor. */
+    ~DefaultIOSystem();
 
-	// -------------------------------------------------------------------
-	/** Tests for the existence of a file at the given path. */
-	bool Exists( const char* pFile) const;
+    // -------------------------------------------------------------------
+    /** Tests for the existence of a file at the given path. */
+    bool Exists( const char* pFile) const;
 
-	// -------------------------------------------------------------------
-	/** Returns the directory separator. */
-	char getOsSeparator() const;
+    // -------------------------------------------------------------------
+    /** Returns the directory separator. */
+    char getOsSeparator() const;
 
-	// -------------------------------------------------------------------
-	/** Open a new file with a given path. */
-	IOStream* Open( const char* pFile, const char* pMode = "rb");
+    // -------------------------------------------------------------------
+    /** Open a new file with a given path. */
+    IOStream* Open( const char* pFile, const char* pMode = "rb");
 
-	// -------------------------------------------------------------------
-	/** Closes the given file and releases all resources associated with it. */
-	void Close( IOStream* pFile);
+    // -------------------------------------------------------------------
+    /** Closes the given file and releases all resources associated with it. */
+    void Close( IOStream* pFile);
 
-	// -------------------------------------------------------------------
-	/** Compare two paths */
-	bool ComparePaths (const char* one, const char* second) const;
+    // -------------------------------------------------------------------
+    /** Compare two paths */
+    bool ComparePaths (const char* one, const char* second) const;
+
+    /** @brief get the file name of a full filepath
+     * example: /tmp/archive.tar.gz -> archive.tar.gz
+     */
+    static std::string fileName( const std::string &path );
+
+    /** @brief get the complete base name of a full filepath
+     * example: /tmp/archive.tar.gz -> archive.tar
+     */
+    static std::string completeBaseName( const std::string &path);
+
+    /** @brief get the path of a full filepath
+     * example: /tmp/archive.tar.gz -> /tmp/
+     */
+    static std::string absolutePath( const std::string &path);
 };
 
 } //!ns Assimp

+ 243 - 243
assimplib.mod/assimp/code/DefaultLogger.cpp

@@ -3,12 +3,12 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -25,16 +25,16 @@ conditions are met:
   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 
+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 
+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 
+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 
+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.
 ---------------------------------------------------------------------------
 */
@@ -43,22 +43,26 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *  @brief Implementation of DefaultLogger (and Logger)
  */
 
-#include "AssimpPCH.h"
 #include "DefaultIOSystem.h"
 
 // Default log streams
 #include "Win32DebugLogStream.h"
 #include "StdOStreamLogStream.h"
 #include "FileLogStream.h"
+#include "../include/assimp/NullLogger.hpp"
+#include "../include/assimp/DefaultLogger.hpp"
+#include "../include/assimp/ai_assert.h"
+#include <iostream>
+#include <stdio.h>
 
 #ifndef ASSIMP_BUILD_SINGLETHREADED
-#	include <boost/thread/thread.hpp>
-#	include <boost/thread/mutex.hpp>
+#   include <boost/thread/thread.hpp>
+#   include <boost/thread/mutex.hpp>
 
 boost::mutex loggerMutex;
 #endif
 
-namespace Assimp	{
+namespace Assimp    {
 
 // ----------------------------------------------------------------------------------
 NullLogger DefaultLogger::s_pNullLogger;
@@ -70,351 +74,347 @@ static const unsigned int SeverityAll = Logger::Info | Logger::Err | Logger::War
 // Represents a log-stream + its error severity
 struct LogStreamInfo
 {
-	unsigned int m_uiErrorSeverity;
-	LogStream *m_pStream;
-
-	// Constructor
-	LogStreamInfo( unsigned int uiErrorSev, LogStream *pStream ) :
-		m_uiErrorSeverity( uiErrorSev ),
-		m_pStream( pStream )
-	{
-		// empty
-	}
-	
-	// Destructor
-	~LogStreamInfo()
-	{
-		delete m_pStream;
-	}
+    unsigned int m_uiErrorSeverity;
+    LogStream *m_pStream;
+
+    // Constructor
+    LogStreamInfo( unsigned int uiErrorSev, LogStream *pStream ) :
+        m_uiErrorSeverity( uiErrorSev ),
+        m_pStream( pStream )
+    {
+        // empty
+    }
+
+    // Destructor
+    ~LogStreamInfo()
+    {
+        delete m_pStream;
+    }
 };
 
 // ----------------------------------------------------------------------------------
 // Construct a default log stream
-LogStream* LogStream::createDefaultStream(aiDefaultLogStream	streams,
-	const char* name /*= "AssimpLog.txt"*/,
-	IOSystem* io		    /*= NULL*/)
+LogStream* LogStream::createDefaultStream(aiDefaultLogStream    streams,
+    const char* name /*= "AssimpLog.txt"*/,
+    IOSystem* io            /*= NULL*/)
 {
-	switch (streams)	
-	{
-		// This is a platform-specific feature
-	case aiDefaultLogStream_DEBUGGER:
+    switch (streams)
+    {
+        // This is a platform-specific feature
+    case aiDefaultLogStream_DEBUGGER:
 #ifdef WIN32
-		return new Win32DebugLogStream();
+        return new Win32DebugLogStream();
 #else
-		return NULL;
+        return NULL;
 #endif
 
-		// Platform-independent default streams
-	case aiDefaultLogStream_STDERR:
-		return new StdOStreamLogStream(std::cerr);
-	case aiDefaultLogStream_STDOUT:
-		return new StdOStreamLogStream(std::cout);
-	case aiDefaultLogStream_FILE:
-		return (name && *name ? new FileLogStream(name,io) : NULL);
-	default:
-		// We don't know this default log stream, so raise an assertion
-		ai_assert(false);
-
-	};
-
-	// For compilers without dead code path detection
-	return NULL;
+        // Platform-independent default streams
+    case aiDefaultLogStream_STDERR:
+        return new StdOStreamLogStream(std::cerr);
+    case aiDefaultLogStream_STDOUT:
+        return new StdOStreamLogStream(std::cout);
+    case aiDefaultLogStream_FILE:
+        return (name && *name ? new FileLogStream(name,io) : NULL);
+    default:
+        // We don't know this default log stream, so raise an assertion
+        ai_assert(false);
+
+    };
+
+    // For compilers without dead code path detection
+    return NULL;
 }
 
 // ----------------------------------------------------------------------------------
-//	Creates the only singleton instance
+//  Creates the only singleton instance
 Logger *DefaultLogger::create(const char* name /*= "AssimpLog.txt"*/,
-	LogSeverity severity                       /*= NORMAL*/,
-	unsigned int defStreams                    /*= aiDefaultLogStream_DEBUGGER | aiDefaultLogStream_FILE*/,
-	IOSystem* io		                       /*= NULL*/)
+    LogSeverity severity                       /*= NORMAL*/,
+    unsigned int defStreams                    /*= aiDefaultLogStream_DEBUGGER | aiDefaultLogStream_FILE*/,
+    IOSystem* io                               /*= NULL*/)
 {
-	// enter the mutex here to avoid concurrency problems
+    // enter the mutex here to avoid concurrency problems
 #ifndef ASSIMP_BUILD_SINGLETHREADED
-	boost::mutex::scoped_lock lock(loggerMutex);
+    boost::mutex::scoped_lock lock(loggerMutex);
 #endif
 
-	if (m_pLogger && !isNullLogger() )
-		delete m_pLogger;
+    if (m_pLogger && !isNullLogger() )
+        delete m_pLogger;
 
-	m_pLogger = new DefaultLogger( severity );
+    m_pLogger = new DefaultLogger( severity );
 
-	// Attach default log streams
-	// Stream the log to the MSVC debugger?
-	if (defStreams & aiDefaultLogStream_DEBUGGER)
-		m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_DEBUGGER));
+    // Attach default log streams
+    // Stream the log to the MSVC debugger?
+    if (defStreams & aiDefaultLogStream_DEBUGGER)
+        m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_DEBUGGER));
 
-	// Stream the log to COUT?
-	if (defStreams & aiDefaultLogStream_STDOUT)
-		m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_STDOUT));
+    // Stream the log to COUT?
+    if (defStreams & aiDefaultLogStream_STDOUT)
+        m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_STDOUT));
 
-	// Stream the log to CERR?
-	if (defStreams & aiDefaultLogStream_STDERR)
-		 m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_STDERR));
-	
-	// Stream the log to a file
-	if (defStreams & aiDefaultLogStream_FILE && name && *name)
-		m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_FILE,name,io));
+    // Stream the log to CERR?
+    if (defStreams & aiDefaultLogStream_STDERR)
+         m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_STDERR));
 
-	return m_pLogger;
+    // Stream the log to a file
+    if (defStreams & aiDefaultLogStream_FILE && name && *name)
+        m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_FILE,name,io));
+
+    return m_pLogger;
 }
 
 // ----------------------------------------------------------------------------------
-void Logger::debug(const char* message)	{
-
-	// SECURITY FIX: otherwise it's easy to produce overruns since
-	// sometimes importers will include data from the input file
-	// (i.e. node names) in their messages.
-	if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) {
-		ai_assert(false);
-		return;
-	}
-	return OnDebug(message);
+void Logger::debug(const char* message) {
+
+    // SECURITY FIX: otherwise it's easy to produce overruns since
+    // sometimes importers will include data from the input file
+    // (i.e. node names) in their messages.
+    if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) {
+        return;
+    }
+    return OnDebug(message);
 }
 
 // ----------------------------------------------------------------------------------
-void Logger::info(const char* message)	{
-	
-	// SECURITY FIX: see above
-	if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) {
-		ai_assert(false);
-		return;
-	}
-	return OnInfo(message);
+void Logger::info(const char* message)  {
+
+    // SECURITY FIX: see above
+    if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) {
+        return;
+    }
+    return OnInfo(message);
 }
-	
+
 // ----------------------------------------------------------------------------------
-void Logger::warn(const char* message)	{
-	
-	// SECURITY FIX: see above
-	if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) {
-		ai_assert(false);
-		return;
-	}
-	return OnWarn(message);
+void Logger::warn(const char* message)  {
+
+    // SECURITY FIX: see above
+    if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) {
+        return;
+    }
+    return OnWarn(message);
 }
 
 // ----------------------------------------------------------------------------------
-void Logger::error(const char* message)	{
-	
-	// SECURITY FIX: see above
-	if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) {
-		ai_assert(false);
-		return;
-	}
-	return OnError(message);
+void Logger::error(const char* message) {
+
+    // SECURITY FIX: see above
+    if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) {
+        return;
+    }
+    return OnError(message);
 }
 
 // ----------------------------------------------------------------------------------
 void DefaultLogger::set( Logger *logger )
 {
-	// enter the mutex here to avoid concurrency problems
+    // enter the mutex here to avoid concurrency problems
 #ifndef ASSIMP_BUILD_SINGLETHREADED
-	boost::mutex::scoped_lock lock(loggerMutex);
+    boost::mutex::scoped_lock lock(loggerMutex);
 #endif
 
-	if (!logger)logger = &s_pNullLogger;
-	if (m_pLogger && !isNullLogger() )
-		delete m_pLogger;
+    if (!logger)logger = &s_pNullLogger;
+    if (m_pLogger && !isNullLogger() )
+        delete m_pLogger;
 
-	DefaultLogger::m_pLogger = logger;
+    DefaultLogger::m_pLogger = logger;
 }
 
 // ----------------------------------------------------------------------------------
 bool DefaultLogger::isNullLogger()
 {
-	return m_pLogger == &s_pNullLogger;
+    return m_pLogger == &s_pNullLogger;
 }
 
 // ----------------------------------------------------------------------------------
-//	Singleton getter
+//  Singleton getter
 Logger *DefaultLogger::get()
 {
-	return m_pLogger;
+    return m_pLogger;
 }
 
 // ----------------------------------------------------------------------------------
-//	Kills the only instance
+//  Kills the only instance
 void DefaultLogger::kill()
 {
-	// enter the mutex here to avoid concurrency problems
+    // enter the mutex here to avoid concurrency problems
 #ifndef ASSIMP_BUILD_SINGLETHREADED
-	boost::mutex::scoped_lock lock(loggerMutex);
+    boost::mutex::scoped_lock lock(loggerMutex);
 #endif
 
-	if (m_pLogger == &s_pNullLogger)return;
-	delete m_pLogger;
-	m_pLogger = &s_pNullLogger;
+    if (m_pLogger == &s_pNullLogger)return;
+    delete m_pLogger;
+    m_pLogger = &s_pNullLogger;
 }
 
 // ----------------------------------------------------------------------------------
-//	Debug message
+//  Debug message
 void DefaultLogger::OnDebug( const char* message )
 {
-	if ( m_Severity == Logger::NORMAL )
-		return;
+    if ( m_Severity == Logger::NORMAL )
+        return;
 
-	char msg[MAX_LOG_MESSAGE_LENGTH + 16];
-	::sprintf(msg,"Debug, T%i: %s", GetThreadID(), message );
+    char msg[MAX_LOG_MESSAGE_LENGTH + 16];
+    ::sprintf(msg,"Debug, T%u: %s", GetThreadID(), message );
 
-	WriteToStreams( msg, Logger::Debugging );
+    WriteToStreams( msg, Logger::Debugging );
 }
 
 // ----------------------------------------------------------------------------------
-//	Logs an info
+//  Logs an info
 void DefaultLogger::OnInfo( const char* message )
 {
-	char msg[MAX_LOG_MESSAGE_LENGTH + 16];
-	::sprintf(msg,"Info,  T%i: %s", GetThreadID(), message );
+    char msg[MAX_LOG_MESSAGE_LENGTH + 16];
+    ::sprintf(msg,"Info,  T%u: %s", GetThreadID(), message );
 
-	WriteToStreams( msg , Logger::Info );
+    WriteToStreams( msg , Logger::Info );
 }
 
 // ----------------------------------------------------------------------------------
-//	Logs a warning
+//  Logs a warning
 void DefaultLogger::OnWarn( const char* message )
 {
-	char msg[MAX_LOG_MESSAGE_LENGTH + 16];
-	::sprintf(msg,"Warn,  T%i: %s", GetThreadID(), message );
+    char msg[MAX_LOG_MESSAGE_LENGTH + 16];
+    ::sprintf(msg,"Warn,  T%u: %s", GetThreadID(), message );
 
-	WriteToStreams( msg, Logger::Warn );
+    WriteToStreams( msg, Logger::Warn );
 }
 
 // ----------------------------------------------------------------------------------
-//	Logs an error
+//  Logs an error
 void DefaultLogger::OnError( const char* message )
 {
-	char msg[MAX_LOG_MESSAGE_LENGTH + 16];
-	::sprintf(msg,"Error, T%i: %s", GetThreadID(), message );
+    char msg[MAX_LOG_MESSAGE_LENGTH + 16];
+    ::sprintf(msg,"Error, T%u: %s", GetThreadID(), message );
 
-	WriteToStreams( msg, Logger::Err );
+    WriteToStreams( msg, Logger::Err );
 }
 
 // ----------------------------------------------------------------------------------
-//	Will attach a new stream
+//  Will attach a new stream
 bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity )
 {
-	if (!pStream)
-		return false;
-
-	if (0 == severity)	{
-		severity = Logger::Info | Logger::Err | Logger::Warn | Logger::Debugging;
-	}
-
-	for ( StreamIt it = m_StreamArray.begin();
-		it != m_StreamArray.end();
-		++it )
-	{
-		if ( (*it)->m_pStream == pStream )
-		{
-			(*it)->m_uiErrorSeverity |= severity;
-			return true;
-		}
-	}
-	
-	LogStreamInfo *pInfo = new LogStreamInfo( severity, pStream );
-	m_StreamArray.push_back( pInfo );
-	return true;
+    if (!pStream)
+        return false;
+
+    if (0 == severity)  {
+        severity = Logger::Info | Logger::Err | Logger::Warn | Logger::Debugging;
+    }
+
+    for ( StreamIt it = m_StreamArray.begin();
+        it != m_StreamArray.end();
+        ++it )
+    {
+        if ( (*it)->m_pStream == pStream )
+        {
+            (*it)->m_uiErrorSeverity |= severity;
+            return true;
+        }
+    }
+
+    LogStreamInfo *pInfo = new LogStreamInfo( severity, pStream );
+    m_StreamArray.push_back( pInfo );
+    return true;
 }
 
 // ----------------------------------------------------------------------------------
-//	Detatch a stream
+//  Detatch a stream
 bool DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity )
 {
-	if (!pStream)
-		return false;
-
-	if (0 == severity)	{
-		severity = SeverityAll;
-	}
-	
-	for ( StreamIt it = m_StreamArray.begin();
-		it != m_StreamArray.end();
-		++it )
-	{
-		if ( (*it)->m_pStream == pStream )
-		{
-			(*it)->m_uiErrorSeverity &= ~severity;
-			if ( (*it)->m_uiErrorSeverity == 0 )
-			{
-				// don't delete the underlying stream 'cause the caller gains ownership again
-				(**it).m_pStream = NULL;
-				delete *it;
-				m_StreamArray.erase( it );
-				break;
-			}
-			return true;
-		}
-	}
-	return false;
+    if (!pStream)
+        return false;
+
+    if (0 == severity)  {
+        severity = SeverityAll;
+    }
+
+    for ( StreamIt it = m_StreamArray.begin();
+        it != m_StreamArray.end();
+        ++it )
+    {
+        if ( (*it)->m_pStream == pStream )
+        {
+            (*it)->m_uiErrorSeverity &= ~severity;
+            if ( (*it)->m_uiErrorSeverity == 0 )
+            {
+                // don't delete the underlying stream 'cause the caller gains ownership again
+                (**it).m_pStream = NULL;
+                delete *it;
+                m_StreamArray.erase( it );
+                break;
+            }
+            return true;
+        }
+    }
+    return false;
 }
 
 // ----------------------------------------------------------------------------------
-//	Constructor
-DefaultLogger::DefaultLogger(LogSeverity severity) 
+//  Constructor
+DefaultLogger::DefaultLogger(LogSeverity severity)
 
-	:	Logger	( severity )
-	,	noRepeatMsg	(false)
-	,	lastLen( 0 )
+    :   Logger  ( severity )
+    ,   noRepeatMsg (false)
+    ,   lastLen( 0 )
 {
-	lastMsg[0] = '\0';
+    lastMsg[0] = '\0';
 }
 
 // ----------------------------------------------------------------------------------
-//	Destructor
+//  Destructor
 DefaultLogger::~DefaultLogger()
 {
-	for ( StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it ) {
-		// also frees the underlying stream, we are its owner.
-		delete *it;
-	}
+    for ( StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it ) {
+        // also frees the underlying stream, we are its owner.
+        delete *it;
+    }
 }
 
 // ----------------------------------------------------------------------------------
-//	Writes message to stream
-void DefaultLogger::WriteToStreams(const char *message, 
-	ErrorSeverity ErrorSev )
+//  Writes message to stream
+void DefaultLogger::WriteToStreams(const char *message,
+    ErrorSeverity ErrorSev )
 {
-	ai_assert(NULL != message);
-
-	// Check whether this is a repeated message
-	if (! ::strncmp( message,lastMsg, lastLen-1))
-	{
-		if (!noRepeatMsg)
-		{
-			noRepeatMsg = true;
-			message = "Skipping one or more lines with the same contents\n";
-		}
-		else return;
-	}
-	else
-	{
-		// append a new-line character to the message to be printed
-		lastLen = ::strlen(message);
-		::memcpy(lastMsg,message,lastLen+1);
-		::strcat(lastMsg+lastLen,"\n");
-
-		message = lastMsg;
-		noRepeatMsg = false;
-		++lastLen;
-	}
-	for ( ConstStreamIt it = m_StreamArray.begin();
-		it != m_StreamArray.end();
-		++it)
-	{
-		if ( ErrorSev & (*it)->m_uiErrorSeverity )
-			(*it)->m_pStream->write( message);
-	}
+    ai_assert(NULL != message);
+
+    // Check whether this is a repeated message
+    if (! ::strncmp( message,lastMsg, lastLen-1))
+    {
+        if (!noRepeatMsg)
+        {
+            noRepeatMsg = true;
+            message = "Skipping one or more lines with the same contents\n";
+        }
+        else return;
+    }
+    else
+    {
+        // append a new-line character to the message to be printed
+        lastLen = ::strlen(message);
+        ::memcpy(lastMsg,message,lastLen+1);
+        ::strcat(lastMsg+lastLen,"\n");
+
+        message = lastMsg;
+        noRepeatMsg = false;
+        ++lastLen;
+    }
+    for ( ConstStreamIt it = m_StreamArray.begin();
+        it != m_StreamArray.end();
+        ++it)
+    {
+        if ( ErrorSev & (*it)->m_uiErrorSeverity )
+            (*it)->m_pStream->write( message);
+    }
 }
 
 // ----------------------------------------------------------------------------------
-//	Returns thread id, if not supported only a zero will be returned.
+//  Returns thread id, if not supported only a zero will be returned.
 unsigned int DefaultLogger::GetThreadID()
 {
-	// fixme: we can get this value via boost::threads
+    // fixme: we can get this value via boost::threads
 #ifdef WIN32
-	return (unsigned int)::GetCurrentThreadId();
+    return (unsigned int)::GetCurrentThreadId();
 #else
-	return 0; // not supported
+    return 0; // not supported
 #endif
 }
 

+ 18 - 18
assimplib.mod/assimp/code/DefaultProgressHandler.h

@@ -2,11 +2,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -23,16 +23,16 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -45,20 +45,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define INCLUDED_AI_DEFAULTPROGRESSHANDLER_H
 
 #include "../include/assimp/ProgressHandler.hpp"
-namespace Assimp	{
+namespace Assimp    {
 
 // ------------------------------------------------------------------------------------
 /** @brief Internal default implementation of the #ProgressHandler interface. */
-class DefaultProgressHandler 
-	: public ProgressHandler	{
+class DefaultProgressHandler
+    : public ProgressHandler    {
 
-	
-	virtual bool Update(float /*percentage*/) {
-		return false;
-	}
 
+    virtual bool Update(float /*percentage*/) {
+        return false;
+    }
 
-}; // !class DefaultProgressHandler 
+
+}; // !class DefaultProgressHandler
 } // Namespace Assimp
 
 #endif

+ 49 - 0
assimplib.mod/assimp/code/Defines.h

@@ -0,0 +1,49 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+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.
+
+----------------------------------------------------------------------
+*/
+
+// We need those constants, workaround for any platforms where nobody defined them yet
+#if (!defined SIZE_MAX)
+#   define SIZE_MAX (~((size_t)0))
+#endif
+
+#if (!defined UINT_MAX)
+#   define UINT_MAX (~((unsigned int)0))
+#endif
+

+ 47 - 46
assimplib.mod/assimp/code/Exceptional.h

@@ -5,8 +5,8 @@ Open Asset Import Library (assimp)
 Copyright (c) 2006-2008, 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 
+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
@@ -23,16 +23,16 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -42,25 +42,26 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define INCLUDED_EXCEPTIONAL_H
 
 #include <stdexcept>
+#include "DefaultIOStream.h"
 using std::runtime_error;
 
 #ifdef _MSC_VER
-#	pragma warning(disable : 4275)
+#   pragma warning(disable : 4275)
 #endif
 
 // ---------------------------------------------------------------------------
-/** FOR IMPORTER PLUGINS ONLY: Simple exception class to be thrown if an 
+/** FOR IMPORTER PLUGINS ONLY: Simple exception class to be thrown if an
  *  unrecoverable error occurs while importing. Loading APIs return
  *  NULL instead of a valid aiScene then.  */
 class DeadlyImportError
-	: public runtime_error
+    : public runtime_error
 {
 public:
-	/** Constructor with arguments */
-	explicit DeadlyImportError( const std::string& pErrorText)
-		: runtime_error(pErrorText)
-	{
-	}
+    /** Constructor with arguments */
+    explicit DeadlyImportError( const std::string& pErrorText)
+        : runtime_error(pErrorText)
+    {
+    }
 
 private:
 };
@@ -68,57 +69,57 @@ private:
 typedef DeadlyImportError DeadlyExportError;
 
 #ifdef _MSC_VER
-#	pragma warning(default : 4275)
+#   pragma warning(default : 4275)
 #endif
 
 // ---------------------------------------------------------------------------
 template <typename T>
-struct ExceptionSwallower	{
-	T operator ()() const {
-		return T();
-	}
+struct ExceptionSwallower   {
+    T operator ()() const {
+        return T();
+    }
 };
 
 // ---------------------------------------------------------------------------
 template <typename T>
-struct ExceptionSwallower<T*>	{
-	T* operator ()() const {
-		return NULL;
-	}
+struct ExceptionSwallower<T*>   {
+    T* operator ()() const {
+        return NULL;
+    }
 };
 
 // ---------------------------------------------------------------------------
 template <>
-struct ExceptionSwallower<aiReturn>	{
-	aiReturn operator ()() const {
-		try {
-			throw;
-		}
-		catch (std::bad_alloc&) {
-			return aiReturn_OUTOFMEMORY;
-		}
-		catch (...) {
-			return aiReturn_FAILURE;
-		}
-	}
+struct ExceptionSwallower<aiReturn> {
+    aiReturn operator ()() const {
+        try {
+            throw;
+        }
+        catch (std::bad_alloc&) {
+            return aiReturn_OUTOFMEMORY;
+        }
+        catch (...) {
+            return aiReturn_FAILURE;
+        }
+    }
 };
 
 // ---------------------------------------------------------------------------
 template <>
-struct ExceptionSwallower<void>	{
-	void operator ()() const {
-		return;
-	}
+struct ExceptionSwallower<void> {
+    void operator ()() const {
+        return;
+    }
 };
 
 #define ASSIMP_BEGIN_EXCEPTION_REGION()\
 {\
-	try {
+    try {
 
 #define ASSIMP_END_EXCEPTION_REGION(type)\
-	} catch(...) {\
-		return ExceptionSwallower<type>()();\
-	}\
+    } catch(...) {\
+        return ExceptionSwallower<type>()();\
+    }\
 }
 
 #endif // INCLUDED_EXCEPTIONAL_H

+ 413 - 266
assimplib.mod/assimp/code/Exporter.cpp

@@ -3,12 +3,12 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -25,16 +25,16 @@ conditions are met:
   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 
+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 
+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 
+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 
+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.
 ---------------------------------------------------------------------------
 */
@@ -50,19 +50,25 @@ description strings.
 Here we implement only the C++ interface (Assimp::Exporter).
 */
 
-#include "AssimpPCH.h"
-
 #ifndef ASSIMP_BUILD_NO_EXPORT
 
 #include "DefaultIOSystem.h"
-#include "BlobIOSystem.h" 
-#include "SceneCombiner.h" 
-#include "BaseProcess.h" 
+#include "BlobIOSystem.h"
+#include "SceneCombiner.h"
+#include "BaseProcess.h"
 #include "Importer.h" // need this for GetPostProcessingStepInstanceList()
 
 #include "JoinVerticesProcess.h"
 #include "MakeVerboseFormat.h"
 #include "ConvertToLHProcess.h"
+#include "Exceptional.h"
+#include "ScenePrivate.h"
+#include <boost/shared_ptr.hpp>
+#include "../include/assimp/Exporter.hpp"
+#include "../include/assimp/mesh.h"
+#include "../include/assimp/postprocess.h"
+#include "../include/assimp/scene.h"
+#include <memory>
 
 namespace Assimp {
 
@@ -71,44 +77,71 @@ void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out);
 
 // ------------------------------------------------------------------------------------------------
 // Exporter worker function prototypes. Should not be necessary to #ifndef them, it's just a prototype
-void ExportSceneCollada(const char*,IOSystem*, const aiScene*);
-void ExportSceneObj(const char*,IOSystem*, const aiScene*);
-void ExportSceneSTL(const char*,IOSystem*, const aiScene*);
-void ExportSceneSTLBinary(const char*,IOSystem*, const aiScene*);
-void ExportScenePly(const char*,IOSystem*, const aiScene*);
-void ExportScene3DS(const char*, IOSystem*, const aiScene*) {}
+// do not use const, because some exporter need to convert the scene temporary
+void ExportSceneCollada(const char*,IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneXFile(const char*,IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneStep(const char*,IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneObj(const char*,IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneSTL(const char*,IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneSTLBinary(const char*,IOSystem*, const aiScene*, const ExportProperties*);
+void ExportScenePly(const char*,IOSystem*, const aiScene*, const ExportProperties*);
+void ExportScenePlyBinary(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+void ExportScene3DS(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneAssbin(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneAssxml(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 
 // ------------------------------------------------------------------------------------------------
 // global array of all export formats which Assimp supports in its current build
-Exporter::ExportFormatEntry gExporters[] = 
+Exporter::ExportFormatEntry gExporters[] =
 {
 #ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER
-	Exporter::ExportFormatEntry( "collada", "COLLADA - Digital Asset Exchange Schema", "dae", &ExportSceneCollada),
+    Exporter::ExportFormatEntry( "collada", "COLLADA - Digital Asset Exchange Schema", "dae", &ExportSceneCollada),
+#endif
+
+#ifndef ASSIMP_BUILD_NO_XFILE_EXPORTER
+    Exporter::ExportFormatEntry( "x", "X Files", "x", &ExportSceneXFile,
+        aiProcess_MakeLeftHanded | aiProcess_FlipWindingOrder | aiProcess_FlipUVs),
+#endif
+
+#ifndef ASSIMP_BUILD_NO_STEP_EXPORTER
+    Exporter::ExportFormatEntry( "stp", "Step Files", "stp", &ExportSceneStep, 0),
 #endif
 
 #ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER
-	Exporter::ExportFormatEntry( "obj", "Wavefront OBJ format", "obj", &ExportSceneObj, 
-		aiProcess_GenSmoothNormals /*| aiProcess_PreTransformVertices */),
+    Exporter::ExportFormatEntry( "obj", "Wavefront OBJ format", "obj", &ExportSceneObj,
+        aiProcess_GenSmoothNormals /*| aiProcess_PreTransformVertices */),
 #endif
 
 #ifndef ASSIMP_BUILD_NO_STL_EXPORTER
-	Exporter::ExportFormatEntry( "stl", "Stereolithography", "stl" , &ExportSceneSTL, 
-		aiProcess_Triangulate | aiProcess_GenNormals | aiProcess_PreTransformVertices
-	),
-	Exporter::ExportFormatEntry( "stlb", "Stereolithography (binary)", "stl" , &ExportSceneSTLBinary, 
-		aiProcess_Triangulate | aiProcess_GenNormals | aiProcess_PreTransformVertices
-	),
+    Exporter::ExportFormatEntry( "stl", "Stereolithography", "stl" , &ExportSceneSTL,
+        aiProcess_Triangulate | aiProcess_GenNormals | aiProcess_PreTransformVertices
+    ),
+    Exporter::ExportFormatEntry( "stlb", "Stereolithography (binary)", "stl" , &ExportSceneSTLBinary,
+        aiProcess_Triangulate | aiProcess_GenNormals | aiProcess_PreTransformVertices
+    ),
 #endif
 
 #ifndef ASSIMP_BUILD_NO_PLY_EXPORTER
-	Exporter::ExportFormatEntry( "ply", "Stanford Polygon Library", "ply" , &ExportScenePly, 
-		aiProcess_PreTransformVertices
-	),
+    Exporter::ExportFormatEntry( "ply", "Stanford Polygon Library", "ply" , &ExportScenePly,
+        aiProcess_PreTransformVertices
+    ),
+    Exporter::ExportFormatEntry( "plyb", "Stanford Polygon Library (binary)", "ply", &ExportScenePlyBinary,
+        aiProcess_PreTransformVertices
+    ),
 #endif
 
-//#ifndef ASSIMP_BUILD_NO_3DS_EXPORTER
-//	ExportFormatEntry( "3ds", "Autodesk 3DS (legacy format)", "3ds" , &ExportScene3DS),
-//#endif
+#ifndef ASSIMP_BUILD_NO_3DS_EXPORTER
+    Exporter::ExportFormatEntry( "3ds", "Autodesk 3DS (legacy)", "3ds" , &ExportScene3DS,
+        aiProcess_Triangulate | aiProcess_SortByPType | aiProcess_JoinIdenticalVertices),
+#endif
+
+#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER
+    Exporter::ExportFormatEntry( "assbin", "Assimp Binary", "assbin" , &ExportSceneAssbin, 0),
+#endif
+
+#ifndef ASSIMP_BUILD_NO_ASSXML_EXPORTER
+    Exporter::ExportFormatEntry( "assxml", "Assxml Document", "assxml" , &ExportSceneAssxml, 0),
+#endif
 };
 
 #define ASSIMP_NUM_EXPORTERS (sizeof(gExporters)/sizeof(gExporters[0]))
@@ -117,42 +150,42 @@ Exporter::ExportFormatEntry gExporters[] =
 class ExporterPimpl {
 public:
 
-	ExporterPimpl()
-		: blob()
-		, mIOSystem(new Assimp::DefaultIOSystem())
-		, mIsDefaultIOHandler(true)
-	{
-		GetPostProcessingStepInstanceList(mPostProcessingSteps);
+    ExporterPimpl()
+        : blob()
+        , mIOSystem(new Assimp::DefaultIOSystem())
+        , mIsDefaultIOHandler(true)
+    {
+        GetPostProcessingStepInstanceList(mPostProcessingSteps);
 
-		// grab all builtin exporters
-		mExporters.resize(ASSIMP_NUM_EXPORTERS);
-		std::copy(gExporters,gExporters+ASSIMP_NUM_EXPORTERS,mExporters.begin());
-	}
+        // grab all builtin exporters
+        mExporters.resize(ASSIMP_NUM_EXPORTERS);
+        std::copy(gExporters,gExporters+ASSIMP_NUM_EXPORTERS,mExporters.begin());
+    }
 
-	~ExporterPimpl() 
-	{
-		delete blob;
+    ~ExporterPimpl()
+    {
+        delete blob;
 
-		// Delete all post-processing plug-ins
-		for( unsigned int a = 0; a < mPostProcessingSteps.size(); a++) {
-			delete mPostProcessingSteps[a];
-		}
-	}
+        // Delete all post-processing plug-ins
+        for( unsigned int a = 0; a < mPostProcessingSteps.size(); a++) {
+            delete mPostProcessingSteps[a];
+        }
+    }
 
 public:
-		
-	aiExportDataBlob* blob;
-	boost::shared_ptr< Assimp::IOSystem > mIOSystem;
-	bool mIsDefaultIOHandler;
 
-	/** Post processing steps we can apply at the imported data. */
-	std::vector< BaseProcess* > mPostProcessingSteps;
+    aiExportDataBlob* blob;
+    boost::shared_ptr< Assimp::IOSystem > mIOSystem;
+    bool mIsDefaultIOHandler;
 
-	/** Last fatal export error */
-	std::string mError;
+    /** Post processing steps we can apply at the imported data. */
+    std::vector< BaseProcess* > mPostProcessingSteps;
 
-	/** Exporters, this includes those registered using #Assimp::Exporter::RegisterExporter */
-	std::vector<Exporter::ExportFormatEntry> mExporters;
+    /** Last fatal export error */
+    std::string mError;
+
+    /** Exporters, this includes those registered using #Assimp::Exporter::RegisterExporter */
+    std::vector<Exporter::ExportFormatEntry> mExporters;
 };
 
 
@@ -166,7 +199,7 @@ using namespace Assimp;
 
 
 // ------------------------------------------------------------------------------------------------
-Exporter :: Exporter() 
+Exporter :: Exporter()
 : pimpl(new ExporterPimpl())
 {
 }
@@ -175,294 +208,408 @@ Exporter :: Exporter()
 // ------------------------------------------------------------------------------------------------
 Exporter :: ~Exporter()
 {
-	FreeBlob();
+    FreeBlob();
 
-	delete pimpl;
+    delete pimpl;
 }
 
 
 // ------------------------------------------------------------------------------------------------
 void Exporter :: SetIOHandler( IOSystem* pIOHandler)
 {
-	pimpl->mIsDefaultIOHandler = !pIOHandler;
-	pimpl->mIOSystem.reset(pIOHandler);
+    pimpl->mIsDefaultIOHandler = !pIOHandler;
+    pimpl->mIOSystem.reset(pIOHandler);
 }
 
 
 // ------------------------------------------------------------------------------------------------
 IOSystem* Exporter :: GetIOHandler() const
 {
-	return pimpl->mIOSystem.get();
+    return pimpl->mIOSystem.get();
 }
 
 
 // ------------------------------------------------------------------------------------------------
 bool Exporter :: IsDefaultIOHandler() const
 {
-	return pimpl->mIsDefaultIOHandler;
+    return pimpl->mIsDefaultIOHandler;
 }
 
 
 // ------------------------------------------------------------------------------------------------
-const aiExportDataBlob* Exporter :: ExportToBlob(  const aiScene* pScene, const char* pFormatId, unsigned int )
+const aiExportDataBlob* Exporter :: ExportToBlob(  const aiScene* pScene, const char* pFormatId, unsigned int, const ExportProperties* pProperties)
 {
-	if (pimpl->blob) {
-		delete pimpl->blob;
-		pimpl->blob = NULL;
-	}
+    if (pimpl->blob) {
+        delete pimpl->blob;
+        pimpl->blob = NULL;
+    }
 
 
-	boost::shared_ptr<IOSystem> old = pimpl->mIOSystem;
+    boost::shared_ptr<IOSystem> old = pimpl->mIOSystem;
 
-	BlobIOSystem* blobio = new BlobIOSystem();
-	pimpl->mIOSystem = boost::shared_ptr<IOSystem>( blobio );
+    BlobIOSystem* blobio = new BlobIOSystem();
+    pimpl->mIOSystem = boost::shared_ptr<IOSystem>( blobio );
 
-	if (AI_SUCCESS != Export(pScene,pFormatId,blobio->GetMagicFileName())) {
-		pimpl->mIOSystem = old;
-		return NULL;
-	}
+    if (AI_SUCCESS != Export(pScene,pFormatId,blobio->GetMagicFileName())) {
+        pimpl->mIOSystem = old;
+        return NULL;
+    }
 
-	pimpl->blob = blobio->GetBlobChain();
-	pimpl->mIOSystem = old;
+    pimpl->blob = blobio->GetBlobChain();
+    pimpl->mIOSystem = old;
 
-	return pimpl->blob;
+    return pimpl->blob;
 }
 
 
 // ------------------------------------------------------------------------------------------------
-bool IsVerboseFormat(const aiMesh* mesh) 
+bool IsVerboseFormat(const aiMesh* mesh)
 {
-	// avoid slow vector<bool> specialization
-	std::vector<unsigned int> seen(mesh->mNumVertices,0);
-	for(unsigned int i = 0; i < mesh->mNumFaces; ++i) {
-		const aiFace& f = mesh->mFaces[i];
-		for(unsigned int j = 0; j < f.mNumIndices; ++j) {
-			if(++seen[f.mIndices[j]] == 2) {
-				// found a duplicate index
-				return false;
-			}
-		}
-	}
-	return true;
+    // avoid slow vector<bool> specialization
+    std::vector<unsigned int> seen(mesh->mNumVertices,0);
+    for(unsigned int i = 0; i < mesh->mNumFaces; ++i) {
+        const aiFace& f = mesh->mFaces[i];
+        for(unsigned int j = 0; j < f.mNumIndices; ++j) {
+            if(++seen[f.mIndices[j]] == 2) {
+                // found a duplicate index
+                return false;
+            }
+        }
+    }
+    return true;
 }
 
 
 // ------------------------------------------------------------------------------------------------
-bool IsVerboseFormat(const aiScene* pScene) 
+bool IsVerboseFormat(const aiScene* pScene)
 {
-	for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
-		if(!IsVerboseFormat(pScene->mMeshes[i])) {
-			return false;
-		}
-	}
-	return true;
+    for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
+        if(!IsVerboseFormat(pScene->mMeshes[i])) {
+            return false;
+        }
+    }
+    return true;
 }
 
 
 // ------------------------------------------------------------------------------------------------
-aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing )
-{
-	ASSIMP_BEGIN_EXCEPTION_REGION();
-
-	// when they create scenes from scratch, users will likely create them not in verbose
-	// format. They will likely not be aware that there is a flag in the scene to indicate
-	// this, however. To avoid surprises and bug reports, we check for duplicates in
-	// meshes upfront.
-	const bool is_verbose_format = !(pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) || IsVerboseFormat(pScene);
-
-	pimpl->mError = "";
-	for (size_t i = 0; i < pimpl->mExporters.size(); ++i) {
-		const Exporter::ExportFormatEntry& exp = pimpl->mExporters[i];
-		if (!strcmp(exp.mDescription.id,pFormatId)) {
-
-			try {
-
-				// Always create a full copy of the scene. We might optimize this one day, 
-				// but for now it is the most pragmatic way.
-				aiScene* scenecopy_tmp;
-				SceneCombiner::CopyScene(&scenecopy_tmp,pScene);
-
-				std::auto_ptr<aiScene> scenecopy(scenecopy_tmp);
-				const ScenePrivateData* const priv = ScenePriv(pScene);
-
-				// steps that are not idempotent, i.e. we might need to run them again, usually to get back to the
-				// original state before the step was applied first. When checking which steps we don't need
-				// to run, those are excluded.
-				const unsigned int nonIdempotentSteps = aiProcess_FlipWindingOrder | aiProcess_FlipUVs | aiProcess_MakeLeftHanded;
-
-				// Erase all pp steps that were already applied to this scene
-				const unsigned int pp = (exp.mEnforcePP | pPreprocessing) & ~(priv && !priv->mIsCopy
-					? (priv->mPPStepsApplied & ~nonIdempotentSteps)
-					: 0u);
-
-				// If no extra postprocessing was specified, and we obtained this scene from an
-				// Assimp importer, apply the reverse steps automatically.
-				// TODO: either drop this, or document it. Otherwise it is just a bad surprise.
-				//if (!pPreprocessing && priv) {
-				//	pp |= (nonIdempotentSteps & priv->mPPStepsApplied);
-				//}
-
-				// If the input scene is not in verbose format, but there is at least postprocessing step that relies on it,
-				// we need to run the MakeVerboseFormat step first.
-				bool must_join_again = false;
-				if (!is_verbose_format) {
-					
-					bool verbosify = false;
-					for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
-						BaseProcess* const p = pimpl->mPostProcessingSteps[a];
-
-						if (p->IsActive(pp) && p->RequireVerboseFormat()) {
-							verbosify = true;
-							break;
-						}
-					}
-
-					if (verbosify || (exp.mEnforcePP & aiProcess_JoinIdenticalVertices)) {
-						DefaultLogger::get()->debug("export: Scene data not in verbose format, applying MakeVerboseFormat step first");
-
-						MakeVerboseFormatProcess proc;
-						proc.Execute(scenecopy.get());
-
-						if(!(exp.mEnforcePP & aiProcess_JoinIdenticalVertices)) {
-							must_join_again = true;
-						}
-					}
-				}
-
-				if (pp) {
-					// the three 'conversion' steps need to be executed first because all other steps rely on the standard data layout
-					{
-						FlipWindingOrderProcess step;
-						if (step.IsActive(pp)) {
-							step.Execute(scenecopy.get());
-						}
-					}
-					
-					{
-						FlipUVsProcess step;
-						if (step.IsActive(pp)) {
-							step.Execute(scenecopy.get());
-						}
-					}
-
-					{
-						MakeLeftHandedProcess step;
-						if (step.IsActive(pp)) {
-							step.Execute(scenecopy.get());
-						}
-					}
-
-					// dispatch other processes
-					for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
-						BaseProcess* const p = pimpl->mPostProcessingSteps[a];
-
-						if (p->IsActive(pp) 
-							&& !dynamic_cast<FlipUVsProcess*>(p) 
-							&& !dynamic_cast<FlipWindingOrderProcess*>(p) 
-							&& !dynamic_cast<MakeLeftHandedProcess*>(p)) {
-
-							p->Execute(scenecopy.get());
-						}
-					}
-					ScenePrivateData* const privOut = ScenePriv(scenecopy.get());
-					ai_assert(privOut);
-
-					privOut->mPPStepsApplied |= pp;
-				}
-
-				if(must_join_again) {
-					JoinVerticesProcess proc;
-					proc.Execute(scenecopy.get());
-				}
-
-				exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get());
-			}
-			catch (DeadlyExportError& err) {
-				pimpl->mError = err.what();
-				return AI_FAILURE;
-			}
-			return AI_SUCCESS;
-		}
-	}
-
-	pimpl->mError = std::string("Found no exporter to handle this file format: ") + pFormatId;
-	ASSIMP_END_EXCEPTION_REGION(aiReturn);
-	return AI_FAILURE;
+aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing, const ExportProperties* pProperties)
+{
+    ASSIMP_BEGIN_EXCEPTION_REGION();
+
+    // when they create scenes from scratch, users will likely create them not in verbose
+    // format. They will likely not be aware that there is a flag in the scene to indicate
+    // this, however. To avoid surprises and bug reports, we check for duplicates in
+    // meshes upfront.
+    const bool is_verbose_format = !(pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) || IsVerboseFormat(pScene);
+
+    pimpl->mError = "";
+    for (size_t i = 0; i < pimpl->mExporters.size(); ++i) {
+        const Exporter::ExportFormatEntry& exp = pimpl->mExporters[i];
+        if (!strcmp(exp.mDescription.id,pFormatId)) {
+
+            try {
+
+                // Always create a full copy of the scene. We might optimize this one day,
+                // but for now it is the most pragmatic way.
+                aiScene* scenecopy_tmp;
+                SceneCombiner::CopyScene(&scenecopy_tmp,pScene);
+
+                std::auto_ptr<aiScene> scenecopy(scenecopy_tmp);
+                const ScenePrivateData* const priv = ScenePriv(pScene);
+
+                // steps that are not idempotent, i.e. we might need to run them again, usually to get back to the
+                // original state before the step was applied first. When checking which steps we don't need
+                // to run, those are excluded.
+                const unsigned int nonIdempotentSteps = aiProcess_FlipWindingOrder | aiProcess_FlipUVs | aiProcess_MakeLeftHanded;
+
+                // Erase all pp steps that were already applied to this scene
+                const unsigned int pp = (exp.mEnforcePP | pPreprocessing) & ~(priv && !priv->mIsCopy
+                    ? (priv->mPPStepsApplied & ~nonIdempotentSteps)
+                    : 0u);
+
+                // If no extra postprocessing was specified, and we obtained this scene from an
+                // Assimp importer, apply the reverse steps automatically.
+                // TODO: either drop this, or document it. Otherwise it is just a bad surprise.
+                //if (!pPreprocessing && priv) {
+                //  pp |= (nonIdempotentSteps & priv->mPPStepsApplied);
+                //}
+
+                // If the input scene is not in verbose format, but there is at least postprocessing step that relies on it,
+                // we need to run the MakeVerboseFormat step first.
+                bool must_join_again = false;
+                if (!is_verbose_format) {
+
+                    bool verbosify = false;
+                    for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
+                        BaseProcess* const p = pimpl->mPostProcessingSteps[a];
+
+                        if (p->IsActive(pp) && p->RequireVerboseFormat()) {
+                            verbosify = true;
+                            break;
+                        }
+                    }
+
+                    if (verbosify || (exp.mEnforcePP & aiProcess_JoinIdenticalVertices)) {
+                        DefaultLogger::get()->debug("export: Scene data not in verbose format, applying MakeVerboseFormat step first");
+
+                        MakeVerboseFormatProcess proc;
+                        proc.Execute(scenecopy.get());
+
+                        if(!(exp.mEnforcePP & aiProcess_JoinIdenticalVertices)) {
+                            must_join_again = true;
+                        }
+                    }
+                }
+
+                if (pp) {
+                    // the three 'conversion' steps need to be executed first because all other steps rely on the standard data layout
+                    {
+                        FlipWindingOrderProcess step;
+                        if (step.IsActive(pp)) {
+                            step.Execute(scenecopy.get());
+                        }
+                    }
+
+                    {
+                        FlipUVsProcess step;
+                        if (step.IsActive(pp)) {
+                            step.Execute(scenecopy.get());
+                        }
+                    }
+
+                    {
+                        MakeLeftHandedProcess step;
+                        if (step.IsActive(pp)) {
+                            step.Execute(scenecopy.get());
+                        }
+                    }
+
+                    // dispatch other processes
+                    for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
+                        BaseProcess* const p = pimpl->mPostProcessingSteps[a];
+
+                        if (p->IsActive(pp)
+                            && !dynamic_cast<FlipUVsProcess*>(p)
+                            && !dynamic_cast<FlipWindingOrderProcess*>(p)
+                            && !dynamic_cast<MakeLeftHandedProcess*>(p)) {
+
+                            p->Execute(scenecopy.get());
+                        }
+                    }
+                    ScenePrivateData* const privOut = ScenePriv(scenecopy.get());
+                    ai_assert(privOut);
+
+                    privOut->mPPStepsApplied |= pp;
+                }
+
+                if(must_join_again) {
+                    JoinVerticesProcess proc;
+                    proc.Execute(scenecopy.get());
+                }
+
+                ExportProperties emptyProperties;  // Never pass NULL ExportProperties so Exporters don't have to worry.
+                exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get(), pProperties ? pProperties : &emptyProperties);
+            }
+            catch (DeadlyExportError& err) {
+                pimpl->mError = err.what();
+                return AI_FAILURE;
+            }
+            return AI_SUCCESS;
+        }
+    }
+
+    pimpl->mError = std::string("Found no exporter to handle this file format: ") + pFormatId;
+    ASSIMP_END_EXCEPTION_REGION(aiReturn);
+    return AI_FAILURE;
 }
 
 
 // ------------------------------------------------------------------------------------------------
 const char* Exporter :: GetErrorString() const
 {
-	return pimpl->mError.c_str();
+    return pimpl->mError.c_str();
 }
 
 
 // ------------------------------------------------------------------------------------------------
 void Exporter :: FreeBlob( )
 {
-	delete pimpl->blob;
-	pimpl->blob = NULL;
+    delete pimpl->blob;
+    pimpl->blob = NULL;
 
-	pimpl->mError = "";
+    pimpl->mError = "";
 }
 
 
 // ------------------------------------------------------------------------------------------------
-const aiExportDataBlob* Exporter :: GetBlob() const 
+const aiExportDataBlob* Exporter :: GetBlob() const
 {
-	return pimpl->blob;
+    return pimpl->blob;
 }
 
 
 // ------------------------------------------------------------------------------------------------
-const aiExportDataBlob* Exporter :: GetOrphanedBlob() const 
+const aiExportDataBlob* Exporter :: GetOrphanedBlob() const
 {
-	const aiExportDataBlob* tmp = pimpl->blob;
-	pimpl->blob = NULL;
-	return tmp;
+    const aiExportDataBlob* tmp = pimpl->blob;
+    pimpl->blob = NULL;
+    return tmp;
 }
 
 
 // ------------------------------------------------------------------------------------------------
-size_t Exporter :: GetExportFormatCount() const 
+size_t Exporter :: GetExportFormatCount() const
 {
-	return pimpl->mExporters.size();
+    return pimpl->mExporters.size();
 }
 
 // ------------------------------------------------------------------------------------------------
-const aiExportFormatDesc* Exporter :: GetExportFormatDescription( size_t pIndex ) const 
+const aiExportFormatDesc* Exporter :: GetExportFormatDescription( size_t pIndex ) const
 {
-	if (pIndex >= GetExportFormatCount()) {
-		return NULL;
-	}
+    if (pIndex >= GetExportFormatCount()) {
+        return NULL;
+    }
+
+    // Return from static storage if the requested index is built-in.
+    if (pIndex < sizeof(gExporters) / sizeof(gExporters[0])) {
+        return &gExporters[pIndex].mDescription;
+    }
 
-	return &pimpl->mExporters[pIndex].mDescription;
+    return &pimpl->mExporters[pIndex].mDescription;
 }
 
 // ------------------------------------------------------------------------------------------------
 aiReturn Exporter :: RegisterExporter(const ExportFormatEntry& desc)
 {
-	BOOST_FOREACH(const ExportFormatEntry& e, pimpl->mExporters) {
-		if (!strcmp(e.mDescription.id,desc.mDescription.id)) {
-			return aiReturn_FAILURE;
-		}
-	}
-
-	pimpl->mExporters.push_back(desc);
-	return aiReturn_SUCCESS;
+    BOOST_FOREACH(const ExportFormatEntry& e, pimpl->mExporters) {
+        if (!strcmp(e.mDescription.id,desc.mDescription.id)) {
+            return aiReturn_FAILURE;
+        }
+    }
+
+    pimpl->mExporters.push_back(desc);
+    return aiReturn_SUCCESS;
 }
 
 
 // ------------------------------------------------------------------------------------------------
 void Exporter :: UnregisterExporter(const char* id)
 {
-	for(std::vector<ExportFormatEntry>::iterator it = pimpl->mExporters.begin(); it != pimpl->mExporters.end(); ++it) {
-		if (!strcmp((*it).mDescription.id,id)) {
-			pimpl->mExporters.erase(it);
-			break;
-		}
-	}
+    for(std::vector<ExportFormatEntry>::iterator it = pimpl->mExporters.begin(); it != pimpl->mExporters.end(); ++it) {
+        if (!strcmp((*it).mDescription.id,id)) {
+            pimpl->mExporters.erase(it);
+            break;
+        }
+    }
+}
+
+ExportProperties :: ExportProperties() {}
+
+ExportProperties::ExportProperties(const ExportProperties &other)
+     : mIntProperties(other.mIntProperties),
+   mFloatProperties(other.mFloatProperties),
+   mStringProperties(other.mStringProperties),
+   mMatrixProperties(other.mMatrixProperties)
+{
+
 }
 
+
+// ------------------------------------------------------------------------------------------------
+// Set a configuration property
+bool ExportProperties :: SetPropertyInteger(const char* szName, int iValue)
+{
+    return SetGenericProperty<int>(mIntProperties, szName,iValue);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Set a configuration property
+bool ExportProperties :: SetPropertyFloat(const char* szName, float iValue)
+{
+    return SetGenericProperty<float>(mFloatProperties, szName,iValue);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Set a configuration property
+bool ExportProperties :: SetPropertyString(const char* szName, const std::string& value)
+{
+    return SetGenericProperty<std::string>(mStringProperties, szName,value);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Set a configuration property
+bool ExportProperties :: SetPropertyMatrix(const char* szName, const aiMatrix4x4& value)
+{
+    return SetGenericProperty<aiMatrix4x4>(mMatrixProperties, szName,value);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get a configuration property
+int ExportProperties :: GetPropertyInteger(const char* szName,
+    int iErrorReturn /*= 0xffffffff*/) const
+{
+    return GetGenericProperty<int>(mIntProperties,szName,iErrorReturn);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get a configuration property
+float ExportProperties :: GetPropertyFloat(const char* szName,
+    float iErrorReturn /*= 10e10*/) const
+{
+    return GetGenericProperty<float>(mFloatProperties,szName,iErrorReturn);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Get a configuration property
+const std::string ExportProperties :: GetPropertyString(const char* szName,
+    const std::string& iErrorReturn /*= ""*/) const
+{
+    return GetGenericProperty<std::string>(mStringProperties,szName,iErrorReturn);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Has a configuration property
+const aiMatrix4x4 ExportProperties :: GetPropertyMatrix(const char* szName,
+    const aiMatrix4x4& iErrorReturn /*= aiMatrix4x4()*/) const
+{
+    return GetGenericProperty<aiMatrix4x4>(mMatrixProperties,szName,iErrorReturn);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Has a configuration property
+bool ExportProperties :: HasPropertyInteger(const char* szName) const
+{
+    return HasGenericProperty<int>(mIntProperties, szName);
+}
+
+// ------------------------------------------------------------------------------------------------
+// Has a configuration property
+bool ExportProperties :: HasPropertyBool(const char* szName) const
+{
+    return HasGenericProperty<int>(mIntProperties, szName);
+};
+
+// ------------------------------------------------------------------------------------------------
+// Has a configuration property
+bool ExportProperties :: HasPropertyFloat(const char* szName) const
+{
+    return HasGenericProperty<float>(mFloatProperties, szName);
+};
+
+// ------------------------------------------------------------------------------------------------
+// Has a configuration property
+bool ExportProperties :: HasPropertyString(const char* szName) const
+{
+    return HasGenericProperty<std::string>(mStringProperties, szName);
+};
+
+// ------------------------------------------------------------------------------------------------
+// Has a configuration property
+bool ExportProperties :: HasPropertyMatrix(const char* szName) const
+{
+    return HasGenericProperty<aiMatrix4x4>(mMatrixProperties, szName);
+};
+
+
 #endif // !ASSIMP_BUILD_NO_EXPORT

+ 196 - 196
assimplib.mod/assimp/code/FBXAnimation.cpp

@@ -2,11 +2,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -23,26 +23,25 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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  FBXAnimation.cpp
- *  @brief Assimp::FBX::AnimationCurve, Assimp::FBX::AnimationCurveNode, 
- *         Assimp::FBX::AnimationLayer, Assimp::FBX::AnimationStack 
+ *  @brief Assimp::FBX::AnimationCurve, Assimp::FBX::AnimationCurveNode,
+ *         Assimp::FBX::AnimationLayer, Assimp::FBX::AnimationStack
  */
-#include "AssimpPCH.h"
 
 #ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
 
@@ -52,41 +51,42 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "FBXImportSettings.h"
 #include "FBXDocumentUtil.h"
 #include "FBXProperties.h"
+#include <boost/foreach.hpp>
 
 namespace Assimp {
 namespace FBX {
 
-	using namespace Util;
+    using namespace Util;
 
 // ------------------------------------------------------------------------------------------------
-AnimationCurve::AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& doc)
+AnimationCurve::AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& /*doc*/)
 : Object(id, element, name)
 {
-	const Scope& sc = GetRequiredScope(element);
-	const Element& KeyTime = GetRequiredElement(sc,"KeyTime");
-	const Element& KeyValueFloat = GetRequiredElement(sc,"KeyValueFloat");
-
-	ParseVectorDataArray(keys, KeyTime);
-	ParseVectorDataArray(values, KeyValueFloat);
-
-	if(keys.size() != values.size()) {
-		DOMError("the number of key times does not match the number of keyframe values",&KeyTime);
-	}
-	
-	// check if the key times are well-ordered
-	if(!std::equal(keys.begin(), keys.end() - 1, keys.begin() + 1, std::less<KeyTimeList::value_type>())) {
-		DOMError("the keyframes are not in ascending order",&KeyTime);
-	}
-
-	const Element* KeyAttrDataFloat = sc["KeyAttrDataFloat"];
-	if(KeyAttrDataFloat) {
-		ParseVectorDataArray(attributes, *KeyAttrDataFloat);
-	}
-
-	const Element* KeyAttrFlags = sc["KeyAttrFlags"];
-	if(KeyAttrFlags) {
-		ParseVectorDataArray(flags, *KeyAttrFlags);
-	}
+    const Scope& sc = GetRequiredScope(element);
+    const Element& KeyTime = GetRequiredElement(sc,"KeyTime");
+    const Element& KeyValueFloat = GetRequiredElement(sc,"KeyValueFloat");
+
+    ParseVectorDataArray(keys, KeyTime);
+    ParseVectorDataArray(values, KeyValueFloat);
+
+    if(keys.size() != values.size()) {
+        DOMError("the number of key times does not match the number of keyframe values",&KeyTime);
+    }
+
+    // check if the key times are well-ordered
+    if(!std::equal(keys.begin(), keys.end() - 1, keys.begin() + 1, std::less<KeyTimeList::value_type>())) {
+        DOMError("the keyframes are not in ascending order",&KeyTime);
+    }
+
+    const Element* KeyAttrDataFloat = sc["KeyAttrDataFloat"];
+    if(KeyAttrDataFloat) {
+        ParseVectorDataArray(attributes, *KeyAttrDataFloat);
+    }
+
+    const Element* KeyAttrFlags = sc["KeyAttrFlags"];
+    if(KeyAttrFlags) {
+        ParseVectorDataArray(flags, *KeyAttrFlags);
+    }
 }
 
 
@@ -98,62 +98,62 @@ AnimationCurve::~AnimationCurve()
 
 
 // ------------------------------------------------------------------------------------------------
-AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc, 
-	const char* const * target_prop_whitelist /*= NULL*/, size_t whitelist_size /*= 0*/)
+AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc,
+    const char* const * target_prop_whitelist /*= NULL*/, size_t whitelist_size /*= 0*/)
 : Object(id, element, name)
 , target()
 , doc(doc)
 {
-	const Scope& sc = GetRequiredScope(element);
-	
-	// find target node
-	const char* whitelist[] = {"Model","NodeAttribute"};
-	const std::vector<const Connection*>& conns = doc.GetConnectionsBySourceSequenced(ID(),whitelist,2);
-
-	BOOST_FOREACH(const Connection* con, conns) {
-
-		// link should go for a property
-		if (!con->PropertyName().length()) {
-			continue;
-		}
-
-		if(target_prop_whitelist) {
-			const char* const s = con->PropertyName().c_str();
-			bool ok = false;
-			for (size_t i = 0; i < whitelist_size; ++i) {
-				if (!strcmp(s, target_prop_whitelist[i])) {
-					ok = true;
-					break;
-				}
-			}
-
-			if (!ok) {
-				throw std::range_error("AnimationCurveNode target property is not in whitelist");
-			}
-		}
-
-		const Object* const ob = con->DestinationObject();
-		if(!ob) {
-			DOMWarning("failed to read destination object for AnimationCurveNode->Model link, ignoring",&element);
-			continue;
-		}
-
-		// XXX support constraints as DOM class
-		//ai_assert(dynamic_cast<const Model*>(ob) || dynamic_cast<const NodeAttribute*>(ob));
-		target = ob; 
-		if(!target) {
-			continue;
-		}
-
-		prop = con->PropertyName();
-		break;
-	}
-
-	if(!target) {
-		DOMWarning("failed to resolve target Model/NodeAttribute/Constraint for AnimationCurveNode",&element);
-	}
-
-	props = GetPropertyTable(doc,"AnimationCurveNode.FbxAnimCurveNode",element,sc,false);
+    const Scope& sc = GetRequiredScope(element);
+
+    // find target node
+    const char* whitelist[] = {"Model","NodeAttribute"};
+    const std::vector<const Connection*>& conns = doc.GetConnectionsBySourceSequenced(ID(),whitelist,2);
+
+    BOOST_FOREACH(const Connection* con, conns) {
+
+        // link should go for a property
+        if (!con->PropertyName().length()) {
+            continue;
+        }
+
+        if(target_prop_whitelist) {
+            const char* const s = con->PropertyName().c_str();
+            bool ok = false;
+            for (size_t i = 0; i < whitelist_size; ++i) {
+                if (!strcmp(s, target_prop_whitelist[i])) {
+                    ok = true;
+                    break;
+                }
+            }
+
+            if (!ok) {
+                throw std::range_error("AnimationCurveNode target property is not in whitelist");
+            }
+        }
+
+        const Object* const ob = con->DestinationObject();
+        if(!ob) {
+            DOMWarning("failed to read destination object for AnimationCurveNode->Model link, ignoring",&element);
+            continue;
+        }
+
+        // XXX support constraints as DOM class
+        //ai_assert(dynamic_cast<const Model*>(ob) || dynamic_cast<const NodeAttribute*>(ob));
+        target = ob;
+        if(!target) {
+            continue;
+        }
+
+        prop = con->PropertyName();
+        break;
+    }
+
+    if(!target) {
+        DOMWarning("failed to resolve target Model/NodeAttribute/Constraint for AnimationCurveNode",&element);
+    }
+
+    props = GetPropertyTable(doc,"AnimationCurveNode.FbxAnimCurveNode",element,sc,false);
 }
 
 
@@ -167,34 +167,34 @@ AnimationCurveNode::~AnimationCurveNode()
 // ------------------------------------------------------------------------------------------------
 const AnimationCurveMap& AnimationCurveNode::Curves() const
 {
-	if(curves.empty()) {
-		// resolve attached animation curves
-		const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurve");
-
-		BOOST_FOREACH(const Connection* con, conns) {
-
-			// link should go for a property
-			if (!con->PropertyName().length()) {
-				continue;
-			}
-
-			const Object* const ob = con->SourceObject();
-			if(!ob) {
-				DOMWarning("failed to read source object for AnimationCurve->AnimationCurveNode link, ignoring",&element);
-				continue;
-			}
-
-			const AnimationCurve* const anim = dynamic_cast<const AnimationCurve*>(ob);
-			if(!anim) {
-				DOMWarning("source object for ->AnimationCurveNode link is not an AnimationCurve",&element);
-				continue;
-			}
-
-			curves[con->PropertyName()] = anim;
-		}
-	}
-
-	return curves;
+    if(curves.empty()) {
+        // resolve attached animation curves
+        const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurve");
+
+        BOOST_FOREACH(const Connection* con, conns) {
+
+            // link should go for a property
+            if (!con->PropertyName().length()) {
+                continue;
+            }
+
+            const Object* const ob = con->SourceObject();
+            if(!ob) {
+                DOMWarning("failed to read source object for AnimationCurve->AnimationCurveNode link, ignoring",&element);
+                continue;
+            }
+
+            const AnimationCurve* const anim = dynamic_cast<const AnimationCurve*>(ob);
+            if(!anim) {
+                DOMWarning("source object for ->AnimationCurveNode link is not an AnimationCurve",&element);
+                continue;
+            }
+
+            curves[con->PropertyName()] = anim;
+        }
+    }
+
+    return curves;
 }
 
 
@@ -203,10 +203,10 @@ AnimationLayer::AnimationLayer(uint64_t id, const Element& element, const std::s
 : Object(id, element, name)
 , doc(doc)
 {
-	const Scope& sc = GetRequiredScope(element);
+    const Scope& sc = GetRequiredScope(element);
 
-	// note: the props table here bears little importance and is usually absent
-	props = GetPropertyTable(doc,"AnimationLayer.FbxAnimLayer",element,sc, true);
+    // note: the props table here bears little importance and is usually absent
+    props = GetPropertyTable(doc,"AnimationLayer.FbxAnimLayer",element,sc, true);
 }
 
 
@@ -218,86 +218,86 @@ AnimationLayer::~AnimationLayer()
 
 
 // ------------------------------------------------------------------------------------------------
-AnimationCurveNodeList AnimationLayer::Nodes(const char* const * target_prop_whitelist /*= NULL*/, 
-	size_t whitelist_size /*= 0*/) const
+AnimationCurveNodeList AnimationLayer::Nodes(const char* const * target_prop_whitelist /*= NULL*/,
+    size_t whitelist_size /*= 0*/) const
 {
-	AnimationCurveNodeList nodes;
-
-	// resolve attached animation nodes
-	const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurveNode");
-	nodes.reserve(conns.size());
-
-	BOOST_FOREACH(const Connection* con, conns) {
-
-		// link should not go to a property
-		if (con->PropertyName().length()) {
-			continue;
-		}
-
-		const Object* const ob = con->SourceObject();
-		if(!ob) {
-			DOMWarning("failed to read source object for AnimationCurveNode->AnimationLayer link, ignoring",&element);
-			continue;
-		}
-
-		const AnimationCurveNode* const anim = dynamic_cast<const AnimationCurveNode*>(ob);
-		if(!anim) {
-			DOMWarning("source object for ->AnimationLayer link is not an AnimationCurveNode",&element);
-			continue;
-		}
-
-		if(target_prop_whitelist) {
-			const char* s = anim->TargetProperty().c_str();
-			bool ok = false;
-			for (size_t i = 0; i < whitelist_size; ++i) {
-				if (!strcmp(s, target_prop_whitelist[i])) {
-					ok = true;
-					break;
-				}
-			}
-			if(!ok) {
-				continue;
-			}
-		}
-		nodes.push_back(anim);
-	}
-
-	return nodes; // pray for NRVO
+    AnimationCurveNodeList nodes;
+
+    // resolve attached animation nodes
+    const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurveNode");
+    nodes.reserve(conns.size());
+
+    BOOST_FOREACH(const Connection* con, conns) {
+
+        // link should not go to a property
+        if (con->PropertyName().length()) {
+            continue;
+        }
+
+        const Object* const ob = con->SourceObject();
+        if(!ob) {
+            DOMWarning("failed to read source object for AnimationCurveNode->AnimationLayer link, ignoring",&element);
+            continue;
+        }
+
+        const AnimationCurveNode* const anim = dynamic_cast<const AnimationCurveNode*>(ob);
+        if(!anim) {
+            DOMWarning("source object for ->AnimationLayer link is not an AnimationCurveNode",&element);
+            continue;
+        }
+
+        if(target_prop_whitelist) {
+            const char* s = anim->TargetProperty().c_str();
+            bool ok = false;
+            for (size_t i = 0; i < whitelist_size; ++i) {
+                if (!strcmp(s, target_prop_whitelist[i])) {
+                    ok = true;
+                    break;
+                }
+            }
+            if(!ok) {
+                continue;
+            }
+        }
+        nodes.push_back(anim);
+    }
+
+    return nodes; // pray for NRVO
 }
 
 // ------------------------------------------------------------------------------------------------
 AnimationStack::AnimationStack(uint64_t id, const Element& element, const std::string& name, const Document& doc)
 : Object(id, element, name)
 {
-	const Scope& sc = GetRequiredScope(element);
-
-	// note: we don't currently use any of these properties so we shouldn't bother if it is missing
-	props = GetPropertyTable(doc,"AnimationStack.FbxAnimStack",element,sc, true);
-
-	// resolve attached animation layers
-	const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationLayer");
-	layers.reserve(conns.size());
-
-	BOOST_FOREACH(const Connection* con, conns) {
-
-		// link should not go to a property
-		if (con->PropertyName().length()) {
-			continue;
-		}
-
-		const Object* const ob = con->SourceObject();
-		if(!ob) {
-			DOMWarning("failed to read source object for AnimationLayer->AnimationStack link, ignoring",&element);
-			continue;
-		}
-
-		const AnimationLayer* const anim = dynamic_cast<const AnimationLayer*>(ob);
-		if(!anim) {
-			DOMWarning("source object for ->AnimationStack link is not an AnimationLayer",&element);
-			continue;
-		}
-		layers.push_back(anim);
-	}
+    const Scope& sc = GetRequiredScope(element);
+
+    // note: we don't currently use any of these properties so we shouldn't bother if it is missing
+    props = GetPropertyTable(doc,"AnimationStack.FbxAnimStack",element,sc, true);
+
+    // resolve attached animation layers
+    const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationLayer");
+    layers.reserve(conns.size());
+
+    BOOST_FOREACH(const Connection* con, conns) {
+
+        // link should not go to a property
+        if (con->PropertyName().length()) {
+            continue;
+        }
+
+        const Object* const ob = con->SourceObject();
+        if(!ob) {
+            DOMWarning("failed to read source object for AnimationLayer->AnimationStack link, ignoring",&element);
+            continue;
+        }
+
+        const AnimationLayer* const anim = dynamic_cast<const AnimationLayer*>(ob);
+        if(!anim) {
+            DOMWarning("source object for ->AnimationStack link is not an AnimationLayer",&element);
+            continue;
+        }
+        layers.push_back(anim);
+    }
 }
 
 

+ 266 - 261
assimplib.mod/assimp/code/FBXBinaryTokenizer.cpp

@@ -2,11 +2,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -23,16 +23,16 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -42,12 +42,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *    we emit tokens so the parser needs almost no special handling
  *    for binary files.
  */
-#include "AssimpPCH.h"
 
 #ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
 
 #include "FBXTokenizer.h"
 #include "FBXUtil.h"
+#include "../include/assimp/defs.h"
+#include <stdint.h>
+#include "Exceptional.h"
+#include "ByteSwapper.h"
 
 namespace Assimp {
 namespace FBX {
@@ -55,21 +58,22 @@ namespace FBX {
 
 // ------------------------------------------------------------------------------------------------
 Token::Token(const char* sbegin, const char* send, TokenType type, unsigned int offset)
-	: sbegin(sbegin)
-	, send(send)
-	, type(type)
-	, line(offset)
-	, column(BINARY_MARKER)
-#ifdef DEBUG
-	, contents(sbegin, static_cast<size_t>(send-sbegin))
-#endif
+    :
+    #ifdef DEBUG
+    contents(sbegin, static_cast<size_t>(send-sbegin)),
+    #endif
+    sbegin(sbegin)
+    , send(send)
+    , type(type)
+    , line(offset)
+    , column(BINARY_MARKER)
 {
-	ai_assert(sbegin);
-	ai_assert(send);
+    ai_assert(sbegin);
+    ai_assert(send);
 
-	// binary tokens may have zero length because they are sometimes dummies
-	// inserted by TokenizeBinary()
-	ai_assert(send >= sbegin);
+    // binary tokens may have zero length because they are sometimes dummies
+    // inserted by TokenizeBinary()
+    ai_assert(send >= sbegin);
 }
 
 
@@ -77,87 +81,88 @@ namespace {
 
 // ------------------------------------------------------------------------------------------------
 // signal tokenization error, this is always unrecoverable. Throws DeadlyImportError.
-void TokenizeError(const std::string& message, unsigned int offset)
+AI_WONT_RETURN void TokenizeError(const std::string& message, unsigned int offset) AI_WONT_RETURN_SUFFIX;
+AI_WONT_RETURN void TokenizeError(const std::string& message, unsigned int offset)
 {
-	throw DeadlyImportError(Util::AddOffset("FBX-Tokenize",message,offset));
+    throw DeadlyImportError(Util::AddOffset("FBX-Tokenize",message,offset));
 }
 
 
 // ------------------------------------------------------------------------------------------------
 uint32_t Offset(const char* begin, const char* cursor)
 {
-	ai_assert(begin <= cursor);
-	return static_cast<unsigned int>(cursor - begin);
+    ai_assert(begin <= cursor);
+    return static_cast<unsigned int>(cursor - begin);
 }
 
 
 // ------------------------------------------------------------------------------------------------
 void TokenizeError(const std::string& message, const char* begin, const char* cursor)
 {
-	TokenizeError(message, Offset(begin, cursor));
+    TokenizeError(message, Offset(begin, cursor));
 }
 
 
 // ------------------------------------------------------------------------------------------------
 uint32_t ReadWord(const char* input, const char*& cursor, const char* end)
 {
-	if(Offset(cursor, end) < 4) {
-		TokenizeError("cannot ReadWord, out of bounds",input, cursor);
-	} 
+    if(Offset(cursor, end) < 4) {
+        TokenizeError("cannot ReadWord, out of bounds",input, cursor);
+    }
 
-	uint32_t word = *reinterpret_cast<const uint32_t*>(cursor);
-	AI_SWAP4(word);
+    uint32_t word = *reinterpret_cast<const uint32_t*>(cursor);
+    AI_SWAP4(word);
 
-	cursor += 4;
+    cursor += 4;
 
-	return word;
+    return word;
 }
 
 
 // ------------------------------------------------------------------------------------------------
 uint8_t ReadByte(const char* input, const char*& cursor, const char* end)
 {
-	if(Offset(cursor, end) < 1) {
-		TokenizeError("cannot ReadByte, out of bounds",input, cursor);
-	} 
+    if(Offset(cursor, end) < 1) {
+        TokenizeError("cannot ReadByte, out of bounds",input, cursor);
+    }
 
-	uint8_t word = *reinterpret_cast<const uint8_t*>(cursor);
-	++cursor;
+    uint8_t word = *reinterpret_cast<const uint8_t*>(cursor);
+    ++cursor;
 
-	return word;
+    return word;
 }
 
 
 // ------------------------------------------------------------------------------------------------
-unsigned int ReadString(const char*& sbegin_out, const char*& send_out, const char* input, const char*& cursor, const char* end, 
-	bool long_length = false,
-	bool allow_null = false)
+unsigned int ReadString(const char*& sbegin_out, const char*& send_out, const char* input, const char*& cursor, const char* end,
+    bool long_length = false,
+    bool allow_null = false)
 {
-	const uint32_t len_len = long_length ? 4 : 1;
-	if(Offset(cursor, end) < len_len) {
-		TokenizeError("cannot ReadString, out of bounds reading length",input, cursor);
-	} 
+    const uint32_t len_len = long_length ? 4 : 1;
+    if(Offset(cursor, end) < len_len) {
+        TokenizeError("cannot ReadString, out of bounds reading length",input, cursor);
+    }
 
-	const uint32_t length = long_length ? ReadWord(input, cursor, end) : ReadByte(input, cursor, end);
+    const uint32_t length = long_length ? ReadWord(input, cursor, end) : ReadByte(input, cursor, end);
 
-	if (Offset(cursor, end) < length) {
-		TokenizeError("cannot ReadString, length is out of bounds",input, cursor);
-	}
+    if (Offset(cursor, end) < length) {
+        TokenizeError("cannot ReadString, length is out of bounds",input, cursor);
+    }
 
-	sbegin_out = cursor;
-	cursor += length;
+    sbegin_out = cursor;
+    cursor += length;
 
-	send_out = cursor;
+    send_out = cursor;
 
-	if(!allow_null) {
-		for (unsigned int i = 0; i < length; ++i) {
-			if(sbegin_out[i] == '\0') {
-				TokenizeError("failed ReadString, unexpected NUL character in string",input, cursor);
-			}
-		}
-	}
+    if(!allow_null) {
+        for (unsigned int i = 0; i < length; ++i) {
+            if(sbegin_out[i] == '\0') {
+                TokenizeError("failed ReadString, unexpected NUL character in string",input, cursor);
+            }
+        }
+    }
 
-	return length;
+    return length;
 }
 
 
@@ -165,203 +170,203 @@ unsigned int ReadString(const char*& sbegin_out, const char*& send_out, const ch
 // ------------------------------------------------------------------------------------------------
 void ReadData(const char*& sbegin_out, const char*& send_out, const char* input, const char*& cursor, const char* end)
 {
-	if(Offset(cursor, end) < 1) {
-		TokenizeError("cannot ReadData, out of bounds reading length",input, cursor);
-	} 
-
-	const char type = *cursor;
-	sbegin_out = cursor++;
-
-	switch(type)
-	{
-		// 16 bit int
-	case 'Y':
-		cursor += 2;
-		break;
-
-		// 1 bit bool flag (yes/no)
-	case 'C':
-		cursor += 1;
-		break;
-
-		// 32 bit int
-	case 'I':
-		// <- fall thru
-
-		// float
-	case 'F':
-		cursor += 4;
-		break;
-
-		// double
-	case 'D':
-		cursor += 8;
-		break;
-
-		// 64 bit int
-	case 'L':
-		cursor += 8;
-		break;
-
-		// note: do not write cursor += ReadWord(...cursor) as this would be UB
-
-		// raw binary data
-	case 'R':	
-	{
-		const uint32_t length = ReadWord(input, cursor, end);
-		cursor += length;
-		break;
-	}
-
-	case 'b': 
-		// TODO: what is the 'b' type code? Right now we just skip over it /
-		// take the full range we could get
-		cursor = end;
-		break;
-
-		// array of *
-	case 'f':
-	case 'd':
-	case 'l':
-	case 'i':	{
-	
-		const uint32_t length = ReadWord(input, cursor, end);
-		const uint32_t encoding = ReadWord(input, cursor, end);
-
-		const uint32_t comp_len = ReadWord(input, cursor, end);
-
-		// compute length based on type and check against the stored value
-		if(encoding == 0) {
-			uint32_t stride = 0;
-			switch(type)
-			{
-			case 'f':
-			case 'i':
-				stride = 4;
-				break;
-
-			case 'd':
-			case 'l':
-				stride = 8;
-				break;
-
-			default:
-				ai_assert(false);
-			};
+    if(Offset(cursor, end) < 1) {
+        TokenizeError("cannot ReadData, out of bounds reading length",input, cursor);
+    }
+
+    const char type = *cursor;
+    sbegin_out = cursor++;
+
+    switch(type)
+    {
+        // 16 bit int
+    case 'Y':
+        cursor += 2;
+        break;
+
+        // 1 bit bool flag (yes/no)
+    case 'C':
+        cursor += 1;
+        break;
+
+        // 32 bit int
+    case 'I':
+        // <- fall thru
+
+        // float
+    case 'F':
+        cursor += 4;
+        break;
+
+        // double
+    case 'D':
+        cursor += 8;
+        break;
+
+        // 64 bit int
+    case 'L':
+        cursor += 8;
+        break;
+
+        // note: do not write cursor += ReadWord(...cursor) as this would be UB
+
+        // raw binary data
+    case 'R':
+    {
+        const uint32_t length = ReadWord(input, cursor, end);
+        cursor += length;
+        break;
+    }
+
+    case 'b':
+        // TODO: what is the 'b' type code? Right now we just skip over it /
+        // take the full range we could get
+        cursor = end;
+        break;
+
+        // array of *
+    case 'f':
+    case 'd':
+    case 'l':
+    case 'i':   {
+
+        const uint32_t length = ReadWord(input, cursor, end);
+        const uint32_t encoding = ReadWord(input, cursor, end);
+
+        const uint32_t comp_len = ReadWord(input, cursor, end);
+
+        // compute length based on type and check against the stored value
+        if(encoding == 0) {
+            uint32_t stride = 0;
+            switch(type)
+            {
+            case 'f':
+            case 'i':
+                stride = 4;
+                break;
+
+            case 'd':
+            case 'l':
+                stride = 8;
+                break;
+
+            default:
+                ai_assert(false);
+            };
             ai_assert(stride > 0);
-			if(length * stride != comp_len) {
-				TokenizeError("cannot ReadData, calculated data stride differs from what the file claims",input, cursor);
-			}
-		}
-		// zip/deflate algorithm (encoding==1)? take given length. anything else? die
-		else if (encoding != 1) {			
-			TokenizeError("cannot ReadData, unknown encoding",input, cursor);
-		}
-		cursor += comp_len;
-		break;
-	}
-
-		// string
-	case 'S': {
-		const char* sb, *se;
-		// 0 characters can legally happen in such strings
-		ReadString(sb, se, input, cursor, end, true, true);
-		break;
-	}
-	default:
-		TokenizeError("cannot ReadData, unexpected type code: " + std::string(&type, 1),input, cursor);
-	}
-
-	if(cursor > end) {
-		TokenizeError("cannot ReadData, the remaining size is too small for the data type: " + std::string(&type, 1),input, cursor);
-	} 
-
-	// the type code is contained in the returned range
-	send_out = cursor;
+            if(length * stride != comp_len) {
+                TokenizeError("cannot ReadData, calculated data stride differs from what the file claims",input, cursor);
+            }
+        }
+        // zip/deflate algorithm (encoding==1)? take given length. anything else? die
+        else if (encoding != 1) {
+            TokenizeError("cannot ReadData, unknown encoding",input, cursor);
+        }
+        cursor += comp_len;
+        break;
+    }
+
+        // string
+    case 'S': {
+        const char* sb, *se;
+        // 0 characters can legally happen in such strings
+        ReadString(sb, se, input, cursor, end, true, true);
+        break;
+    }
+    default:
+        TokenizeError("cannot ReadData, unexpected type code: " + std::string(&type, 1),input, cursor);
+    }
+
+    if(cursor > end) {
+        TokenizeError("cannot ReadData, the remaining size is too small for the data type: " + std::string(&type, 1),input, cursor);
+    }
+
+    // the type code is contained in the returned range
+    send_out = cursor;
 }
 
 
 // ------------------------------------------------------------------------------------------------
 bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor, const char* end)
 {
-	// the first word contains the offset at which this block ends
-	const uint32_t end_offset = ReadWord(input, cursor, end);
-	
-	// we may get 0 if reading reached the end of the file -
-	// fbx files have a mysterious extra footer which I don't know 
-	// how to extract any information from, but at least it always 
-	// starts with a 0.
-	if(!end_offset) {
-		return false;
-	}
-
-	if(end_offset > Offset(input, end)) {
-		TokenizeError("block offset is out of range",input, cursor);
-	}
-	else if(end_offset < Offset(input, cursor)) {
-		TokenizeError("block offset is negative out of range",input, cursor);
-	}
-
-	// the second data word contains the number of properties in the scope
-	const uint32_t prop_count = ReadWord(input, cursor, end);
-
-	// the third data word contains the length of the property list
-	const uint32_t prop_length = ReadWord(input, cursor, end);
-
-	// now comes the name of the scope/key
-	const char* sbeg, *send;
-	ReadString(sbeg, send, input, cursor, end);
-
-	output_tokens.push_back(new_Token(sbeg, send, TokenType_KEY, Offset(input, cursor) ));
-
-	// now come the individual properties
-	const char* begin_cursor = cursor;
-	for (unsigned int i = 0; i < prop_count; ++i) {
-		ReadData(sbeg, send, input, cursor, begin_cursor + prop_length);
-
-		output_tokens.push_back(new_Token(sbeg, send, TokenType_DATA, Offset(input, cursor) ));
-
-		if(i != prop_count-1) {
-			output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_COMMA, Offset(input, cursor) ));
-		}
-	}
-
-	if (Offset(begin_cursor, cursor) != prop_length) {
-		TokenizeError("property length not reached, something is wrong",input, cursor);
-	}
-
-	// at the end of each nested block, there is a NUL record to indicate
-	// that the sub-scope exists (i.e. to distinguish between P: and P : {})
-	// this NUL record is 13 bytes long.
+    // the first word contains the offset at which this block ends
+    const uint32_t end_offset = ReadWord(input, cursor, end);
+
+    // we may get 0 if reading reached the end of the file -
+    // fbx files have a mysterious extra footer which I don't know
+    // how to extract any information from, but at least it always
+    // starts with a 0.
+    if(!end_offset) {
+        return false;
+    }
+
+    if(end_offset > Offset(input, end)) {
+        TokenizeError("block offset is out of range",input, cursor);
+    }
+    else if(end_offset < Offset(input, cursor)) {
+        TokenizeError("block offset is negative out of range",input, cursor);
+    }
+
+    // the second data word contains the number of properties in the scope
+    const uint32_t prop_count = ReadWord(input, cursor, end);
+
+    // the third data word contains the length of the property list
+    const uint32_t prop_length = ReadWord(input, cursor, end);
+
+    // now comes the name of the scope/key
+    const char* sbeg, *send;
+    ReadString(sbeg, send, input, cursor, end);
+
+    output_tokens.push_back(new_Token(sbeg, send, TokenType_KEY, Offset(input, cursor) ));
+
+    // now come the individual properties
+    const char* begin_cursor = cursor;
+    for (unsigned int i = 0; i < prop_count; ++i) {
+        ReadData(sbeg, send, input, cursor, begin_cursor + prop_length);
+
+        output_tokens.push_back(new_Token(sbeg, send, TokenType_DATA, Offset(input, cursor) ));
+
+        if(i != prop_count-1) {
+            output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_COMMA, Offset(input, cursor) ));
+        }
+    }
+
+    if (Offset(begin_cursor, cursor) != prop_length) {
+        TokenizeError("property length not reached, something is wrong",input, cursor);
+    }
+
+    // at the end of each nested block, there is a NUL record to indicate
+    // that the sub-scope exists (i.e. to distinguish between P: and P : {})
+    // this NUL record is 13 bytes long.
 #define BLOCK_SENTINEL_LENGTH 13
 
-	if (Offset(input, cursor) < end_offset) {
+    if (Offset(input, cursor) < end_offset) {
 
-		if (end_offset - Offset(input, cursor) < BLOCK_SENTINEL_LENGTH) {
-			TokenizeError("insufficient padding bytes at block end",input, cursor);
-		}
+        if (end_offset - Offset(input, cursor) < BLOCK_SENTINEL_LENGTH) {
+            TokenizeError("insufficient padding bytes at block end",input, cursor);
+        }
 
-		output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_OPEN_BRACKET, Offset(input, cursor) ));
+        output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_OPEN_BRACKET, Offset(input, cursor) ));
 
-		// XXX this is vulnerable to stack overflowing ..
-		while(Offset(input, cursor) < end_offset - BLOCK_SENTINEL_LENGTH) {
-			ReadScope(output_tokens, input, cursor, input + end_offset - BLOCK_SENTINEL_LENGTH);
-		}
-		output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_CLOSE_BRACKET, Offset(input, cursor) ));
+        // XXX this is vulnerable to stack overflowing ..
+        while(Offset(input, cursor) < end_offset - BLOCK_SENTINEL_LENGTH) {
+            ReadScope(output_tokens, input, cursor, input + end_offset - BLOCK_SENTINEL_LENGTH);
+        }
+        output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_CLOSE_BRACKET, Offset(input, cursor) ));
 
-		for (unsigned int i = 0; i < BLOCK_SENTINEL_LENGTH; ++i) {
-			if(cursor[i] != '\0') {
-				TokenizeError("failed to read nested block sentinel, expected all bytes to be 0",input, cursor);
-			}
-		}
-		cursor += BLOCK_SENTINEL_LENGTH;
-	}
+        for (unsigned int i = 0; i < BLOCK_SENTINEL_LENGTH; ++i) {
+            if(cursor[i] != '\0') {
+                TokenizeError("failed to read nested block sentinel, expected all bytes to be 0",input, cursor);
+            }
+        }
+        cursor += BLOCK_SENTINEL_LENGTH;
+    }
 
-	if (Offset(input, cursor) != end_offset) {
-		TokenizeError("scope length not reached, something is wrong",input, cursor);
-	}
+    if (Offset(input, cursor) != end_offset) {
+        TokenizeError("scope length not reached, something is wrong",input, cursor);
+    }
 
-	return true;
+    return true;
 }
 
 
@@ -370,29 +375,29 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor,
 // ------------------------------------------------------------------------------------------------
 void TokenizeBinary(TokenList& output_tokens, const char* input, unsigned int length)
 {
-	ai_assert(input);
+    ai_assert(input);
 
-	if(length < 0x1b) {
-		TokenizeError("file is too short",0);
-	}
+    if(length < 0x1b) {
+        TokenizeError("file is too short",0);
+    }
 
-	if (strncmp(input,"Kaydara FBX Binary",18)) {
-		TokenizeError("magic bytes not found",0);
-	}
+    if (strncmp(input,"Kaydara FBX Binary",18)) {
+        TokenizeError("magic bytes not found",0);
+    }
 
 
-	//uint32_t offset = 0x1b;
+    //uint32_t offset = 0x1b;
 
-	const char* cursor = input + 0x1b;
+    const char* cursor = input + 0x1b;
 
-	while (cursor < input + length) {
-		if(!ReadScope(output_tokens, input, cursor, input + length)) {
-			break;
-		}
-	}
+    while (cursor < input + length) {
+        if(!ReadScope(output_tokens, input, cursor, input + length)) {
+            break;
+        }
+    }
 }
 
 } // !FBX
 } // !Assimp
 
-#endif
+#endif

+ 22 - 22
assimplib.mod/assimp/code/FBXCompileConfig.h

@@ -2,11 +2,11 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2015, 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 
+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
@@ -23,16 +23,16 @@ following conditions are met:
   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 
+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 
+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 
+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 
+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.
 
 ----------------------------------------------------------------------
@@ -46,21 +46,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 //
 #if _MSC_VER > 1500 || (defined __GNUC___)
-#	define ASSIMP_FBX_USE_UNORDERED_MULTIMAP
-#	else
-#	define fbx_unordered_map map
-#	define fbx_unordered_multimap multimap
+#   define ASSIMP_FBX_USE_UNORDERED_MULTIMAP
+#   else
+#   define fbx_unordered_map map
+#   define fbx_unordered_multimap multimap
 #endif
 
 #ifdef ASSIMP_FBX_USE_UNORDERED_MULTIMAP
-#	include <unordered_map>
-#	if _MSC_VER > 1600
-#		define fbx_unordered_map unordered_map
-#		define fbx_unordered_multimap unordered_multimap
-#	else
-#		define fbx_unordered_map tr1::unordered_map
-#		define fbx_unordered_multimap tr1::unordered_multimap
-#	endif
+#   include <unordered_map>
+#   if _MSC_VER > 1600
+#       define fbx_unordered_map unordered_map
+#       define fbx_unordered_multimap unordered_multimap
+#   else
+#       define fbx_unordered_map tr1::unordered_map
+#       define fbx_unordered_multimap tr1::unordered_multimap
+#   endif
 #endif
 
 #endif

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 2930 - 2837
assimplib.mod/assimp/code/FBXConverter.cpp


برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است