Преглед на файлове

Merge remote-tracking branch 'upstream/master'

Sebastian Matusik преди 7 години
родител
ревизия
624e5b4d1a
променени са 100 файла, в които са добавени 1962 реда и са изтрити 1157 реда
  1. 3 0
      .gitignore
  2. 258 0
      CHANGES
  3. 2 27
      CMakeLists.txt
  4. 10 0
      CONTRIBUTING.md
  5. 3 0
      INSTALL
  6. 0 2
      Readme.md
  7. 4 0
      appveyor.yml
  8. 14 12
      code/3DSConverter.cpp
  9. 1 1
      code/3DSExporter.cpp
  10. 22 22
      code/3DSLoader.cpp
  11. 19 19
      code/ACLoader.cpp
  12. 1 1
      code/AMFImporter.cpp
  13. 0 12
      code/AMFImporter.hpp
  14. 4 4
      code/AMFImporter_Macro.hpp
  15. 1 1
      code/AMFImporter_Material.cpp
  16. 1 1
      code/AMFImporter_Postprocess.cpp
  17. 8 8
      code/ASELoader.cpp
  18. 14 12
      code/ASEParser.cpp
  19. 1 1
      code/ASEParser.h
  20. 1 1
      code/Assimp.cpp
  21. 1 1
      code/B3DImporter.cpp
  22. 31 27
      code/BaseImporter.cpp
  23. 1 1
      code/BaseProcess.cpp
  24. 185 0
      code/BlenderCustomData.cpp
  25. 89 0
      code/BlenderCustomData.h
  26. 5 6
      code/BlenderDNA.cpp
  27. 35 2
      code/BlenderDNA.h
  28. 103 3
      code/BlenderDNA.inl
  29. 69 10
      code/BlenderLoader.cpp
  30. 1 1
      code/BlenderModifier.h
  31. 44 0
      code/BlenderScene.cpp
  32. 79 1
      code/BlenderScene.h
  33. 11 0
      code/BlenderSceneGen.h
  34. 1 1
      code/BlenderTessellator.h
  35. 11 2
      code/CMakeLists.txt
  36. 23 77
      code/COBLoader.cpp
  37. 1 21
      code/COBLoader.h
  38. 1 1
      code/CSMLoader.cpp
  39. 6 6
      code/CalcTangentsProcess.cpp
  40. 1 1
      code/ColladaExporter.h
  41. 4 3
      code/ColladaHelper.h
  42. 58 60
      code/ColladaLoader.cpp
  43. 36 37
      code/ColladaParser.cpp
  44. 6 6
      code/ComputeUVMappingProcess.cpp
  45. 9 9
      code/ConvertToLHProcess.cpp
  46. 1 1
      code/D3MFExporter.cpp
  47. 3 3
      code/D3MFImporter.cpp
  48. 1 1
      code/D3MFOpcPackage.cpp
  49. 1 1
      code/DXFHelper.h
  50. 32 59
      code/DXFLoader.cpp
  51. 5 7
      code/DeboneProcess.cpp
  52. 7 7
      code/DefaultIOSystem.cpp
  53. 3 5
      code/EmbedTexturesProcess.cpp
  54. 18 11
      code/Exporter.cpp
  55. 2 2
      code/FBXBinaryTokenizer.cpp
  56. 58 49
      code/FBXConverter.cpp
  57. 9 5
      code/FBXConverter.h
  58. 4 4
      code/FBXDocument.cpp
  59. 3 3
      code/FBXDocumentUtil.cpp
  60. 25 21
      code/FBXExporter.cpp
  61. 1 1
      code/FBXExporter.h
  62. 1 1
      code/FBXMaterial.cpp
  63. 3 0
      code/FBXMeshGeometry.cpp
  64. 58 19
      code/FindDegenerates.cpp
  65. 2 1
      code/FindDegenerates.h
  66. 4 6
      code/FindInstancesProcess.cpp
  67. 7 7
      code/FindInvalidDataProcess.cpp
  68. 20 18
      code/FixNormalsStep.cpp
  69. 12 11
      code/GenFaceNormalsProcess.cpp
  70. 2 1
      code/GenFaceNormalsProcess.h
  71. 19 17
      code/GenVertexNormalsProcess.cpp
  72. 1 0
      code/GenVertexNormalsProcess.h
  73. 3 3
      code/HMPLoader.cpp
  74. 28 28
      code/IRRLoader.cpp
  75. 10 10
      code/IRRMeshLoader.cpp
  76. 10 15
      code/IRRShared.cpp
  77. 1 1
      code/IRRShared.h
  78. 60 67
      code/Importer.cpp
  79. 1 1
      code/Importer/IFC/IFCUtil.cpp
  80. 10 10
      code/Importer/IFC/STEPFileReader.cpp
  81. 7 15
      code/ImproveCacheLocality.cpp
  82. 113 118
      code/JoinVerticesProcess.cpp
  83. 20 16
      code/LWOBLoader.cpp
  84. 43 36
      code/LWOLoader.cpp
  85. 1 1
      code/LWOLoader.h
  86. 24 22
      code/LWOMaterial.cpp
  87. 23 23
      code/LWSLoader.cpp
  88. 7 9
      code/LimitBoneWeightsProcess.cpp
  89. 10 10
      code/MD2Loader.cpp
  90. 27 30
      code/MD3Loader.cpp
  91. 4 5
      code/MD5Loader.cpp
  92. 10 10
      code/MD5Parser.cpp
  93. 6 4
      code/MDCLoader.cpp
  94. 34 34
      code/MDLLoader.cpp
  95. 9 8
      code/MDLMaterialLoader.cpp
  96. 1 1
      code/MMDImporter.cpp
  97. 3 6
      code/MS3DLoader.cpp
  98. 7 4
      code/MakeVerboseFormat.cpp
  99. 6 5
      code/MaterialSystem.cpp
  100. 4 4
      code/NDOLoader.cpp

+ 3 - 0
.gitignore

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

+ 258 - 0
CHANGES

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

+ 2 - 27
CMakeLists.txt

@@ -152,7 +152,7 @@ EXECUTE_PROCESS(
 
 # Get the latest abbreviated commit hash of the working branch
 EXECUTE_PROCESS(
-  COMMAND git log -1 --format=%h
+  COMMAND git log -1 --format=%h --no-show-signature
   WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
   OUTPUT_VARIABLE GIT_COMMIT_HASH
   OUTPUT_STRIP_TRAILING_WHITESPACE
@@ -412,32 +412,7 @@ IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
   ENDIF ( WIN32 AND DirectX_D3DX9_LIBRARY )
 
   ADD_SUBDIRECTORY( tools/assimp_cmd/ )
-
-  # Check dependencies for assimp_qt_viewer.
-  # Why here? Maybe user do not want Qt viewer and have no Qt.
-  # Why assimp_qt_viewer/CMakeLists.txt still contain similar check?
-  # Because viewer can be build independently of Assimp.
-  FIND_PACKAGE(Qt5Widgets QUIET)
-  FIND_PACKAGE(DevIL QUIET)
-  FIND_PACKAGE(OpenGL QUIET)
-  IF ( Qt5Widgets_FOUND AND IL_FOUND AND OPENGL_FOUND)
-    ADD_SUBDIRECTORY( tools/assimp_qt_viewer/ )
-  ELSE()
-    SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "")
-    IF (NOT Qt5_FOUND)
-      SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} Qt5")
-    ENDIF (NOT Qt5_FOUND)
-
-    IF (NOT IL_FOUND)
-      SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} DevIL")
-    ENDIF (NOT IL_FOUND)
-
-    IF (NOT OPENGL_FOUND)
-      SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} OpengGL")
-    ENDIF (NOT OPENGL_FOUND)
-
-    MESSAGE (WARNING "Build of assimp_qt_viewer is disabled. Unsatisfied dendencies: ${ASSIMP_QT_VIEWER_DEPENDENCIES}")
-  ENDIF ( Qt5Widgets_FOUND AND IL_FOUND AND OPENGL_FOUND)
+  ADD_SUBDIRECTORY( tools/assimp_qt_viewer/ )
 ENDIF ( ASSIMP_BUILD_ASSIMP_TOOLS )
 
 IF ( ASSIMP_BUILD_SAMPLES)

+ 10 - 0
CONTRIBUTING.md

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

+ 3 - 0
INSTALL

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

+ 0 - 2
Readme.md

@@ -140,8 +140,6 @@ Open Asset Import Library is implemented in C++. The directory structure is:
 	/tools		Tools (old assimp viewer, command line `assimp`)
 	/samples	A small number of samples to illustrate possible
                         use cases for Assimp
-	/workspaces	Build environments for vc,xcode,... (deprecated,
-			CMake has superseeded all legacy build options!)
 
 
 ### Where to get help ###

+ 4 - 0
appveyor.yml

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

+ 14 - 12
code/3DSConverter.cpp

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

+ 1 - 1
code/3DSExporter.cpp

@@ -381,7 +381,7 @@ void Discreet3DSExporter::WriteTexture(const aiMaterial& mat, aiTextureType type
 
     // TODO: handle embedded textures properly
     if (path.data[0] == '*') {
-        DefaultLogger::get()->error("Ignoring embedded texture for export: " + std::string(path.C_Str()));
+        ASSIMP_LOG_ERROR("Ignoring embedded texture for export: " + std::string(path.C_Str()));
         return;
     }
 

+ 22 - 22
code/3DSLoader.cpp

@@ -71,7 +71,7 @@ static const aiImporterDesc desc = {
     0,
     0,
     0,
-    "3ds prj 3DS PRJ"
+	"3ds prj"
 };
 
 
@@ -127,7 +127,7 @@ Discreet3DSImporter::~Discreet3DSImporter() {
 // Returns whether the class can handle the format of the given file.
 bool Discreet3DSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const {
     std::string extension = GetExtension(pFile);
-    if(extension == "3ds" || extension == "3DS" || extension == "prj"|| extension == "PRJ" ) {
+	if(extension == "3ds" || extension == "prj") {
         return true;
     }
 
@@ -258,8 +258,9 @@ void Discreet3DSImporter::ReadChunk(Discreet3DS::Chunk* pcOut)
     if (pcOut->Size - sizeof(Discreet3DS::Chunk) > stream->GetRemainingSize())
         throw DeadlyImportError("Chunk is too large");
 
-    if (pcOut->Size - sizeof(Discreet3DS::Chunk) > stream->GetRemainingSizeToLimit())
-        DefaultLogger::get()->error("3DS: Chunk overflow");
+    if (pcOut->Size - sizeof(Discreet3DS::Chunk) > stream->GetRemainingSizeToLimit()) {
+        ASSIMP_LOG_ERROR("3DS: Chunk overflow");
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -320,7 +321,7 @@ void Discreet3DSImporter::ParseEditorChunk()
         // print the version number
         char buff[10];
         ASSIMP_itoa10(buff,stream->GetI2());
-        DefaultLogger::get()->info(std::string("3DS file format version: ") + buff);
+        ASSIMP_LOG_INFO_F(std::string("3DS file format version: "), buff);
         }
         break;
     };
@@ -361,7 +362,7 @@ void Discreet3DSImporter::ParseObjectChunk()
         if (is_qnan(mClrAmbient.r))
         {
             // We failed to read the ambient base color.
-            DefaultLogger::get()->error("3DS: Failed to read ambient base color");
+            ASSIMP_LOG_ERROR("3DS: Failed to read ambient base color");
             mClrAmbient.r = mClrAmbient.g = mClrAmbient.b = 0.0f;
         }
         break;
@@ -463,7 +464,7 @@ void Discreet3DSImporter::ParseChunk(const char* name, unsigned int num)
         if (len < 1e-5) {
 
             // There are some files with lookat == position. Don't know why or whether it's ok or not.
-            DefaultLogger::get()->error("3DS: Unable to read proper camera look-at vector");
+            ASSIMP_LOG_ERROR("3DS: Unable to read proper camera look-at vector");
             camera->mLookAt = aiVector3D(0.0,1.0,0.0);
 
         }
@@ -629,9 +630,9 @@ void Discreet3DSImporter::SkipTCBInfo()
     if (!flags) {
         // Currently we can't do anything with these values. They occur
         // quite rare, so it wouldn't be worth the effort implementing
-        // them. 3DS ist not really suitable for complex animations,
+        // them. 3DS is not really suitable for complex animations,
         // so full support is not required.
-        DefaultLogger::get()->warn("3DS: Skipping TCB animation info");
+        ASSIMP_LOG_WARN("3DS: Skipping TCB animation info");
     }
 
     if (flags & Discreet3DS::KEY_USE_TENS) {
@@ -732,7 +733,6 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
 
             // If object name is DUMMY, take this one instead
             if (mCurrentNode->mName == "$$$DUMMY")  {
-                //DefaultLogger::get()->warn("3DS: Skipping dummy object name for non-dummy object");
                 mCurrentNode->mName = std::string(sz);
                 break;
             }
@@ -743,7 +743,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
 
         if ( Discreet3DS::CHUNK_TRACKINFO != parent)
         {
-            DefaultLogger::get()->warn("3DS: Skipping pivot subchunk for non usual object");
+            ASSIMP_LOG_WARN("3DS: Skipping pivot subchunk for non usual object");
             break;
         }
 
@@ -805,7 +805,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
         {
         // roll keys are accepted for cameras only
         if (parent != Discreet3DS::CHUNK_TRACKCAMERA)   {
-            DefaultLogger::get()->warn("3DS: Ignoring roll track for non-camera object");
+            ASSIMP_LOG_WARN("3DS: Ignoring roll track for non-camera object");
             break;
         }
         bool sortKeys = false;
@@ -845,7 +845,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
         // CAMERA FOV KEYFRAME
     case Discreet3DS::CHUNK_TRACKFOV:
         {
-            DefaultLogger::get()->error("3DS: Skipping FOV animation track. "
+            ASSIMP_LOG_ERROR("3DS: Skipping FOV animation track. "
                 "This is not supported");
         }
         break;
@@ -985,7 +985,7 @@ void Discreet3DSImporter::ParseFaceChunk()
             }
         }
         if (0xcdcdcdcd == idx)  {
-            DefaultLogger::get()->error(std::string("3DS: Unknown material: ") + sz);
+            ASSIMP_LOG_ERROR_F( "3DS: Unknown material: ", sz);
         }
 
         // Now continue and read all material indices
@@ -995,7 +995,7 @@ void Discreet3DSImporter::ParseFaceChunk()
 
             // check range
             if (fidx >= mMesh.mFaceMaterials.size())    {
-                DefaultLogger::get()->error("3DS: Invalid face index in face material list");
+                ASSIMP_LOG_ERROR("3DS: Invalid face index in face material list");
             }
             else mMesh.mFaceMaterials[fidx] = idx;
         }}
@@ -1110,7 +1110,7 @@ void Discreet3DSImporter::ParseMaterialChunk()
 
         if (!cnt)   {
             // This may not be, we use the default name instead
-            DefaultLogger::get()->error("3DS: Empty material name");
+            ASSIMP_LOG_ERROR("3DS: Empty material name");
         }
         else mScene->mMaterials.back().mName = std::string(sz,cnt);
         }
@@ -1123,7 +1123,7 @@ void Discreet3DSImporter::ParseMaterialChunk()
         ParseColorChunk(pc);
         if (is_qnan(pc->r)) {
             // color chunk is invalid. Simply ignore it
-            DefaultLogger::get()->error("3DS: Unable to read DIFFUSE chunk");
+            ASSIMP_LOG_ERROR("3DS: Unable to read DIFFUSE chunk");
             pc->r = pc->g = pc->b = 1.0f;
         }}
         break;
@@ -1135,7 +1135,7 @@ void Discreet3DSImporter::ParseMaterialChunk()
         ParseColorChunk(pc);
         if (is_qnan(pc->r)) {
             // color chunk is invalid. Simply ignore it
-            DefaultLogger::get()->error("3DS: Unable to read SPECULAR chunk");
+            ASSIMP_LOG_ERROR("3DS: Unable to read SPECULAR chunk");
             pc->r = pc->g = pc->b = 1.0f;
         }}
         break;
@@ -1147,7 +1147,7 @@ void Discreet3DSImporter::ParseMaterialChunk()
         ParseColorChunk(pc);
         if (is_qnan(pc->r)) {
             // color chunk is invalid. Simply ignore it
-            DefaultLogger::get()->error("3DS: Unable to read AMBIENT chunk");
+            ASSIMP_LOG_ERROR("3DS: Unable to read AMBIENT chunk");
             pc->r = pc->g = pc->b = 0.0f;
         }}
         break;
@@ -1159,7 +1159,7 @@ void Discreet3DSImporter::ParseMaterialChunk()
         ParseColorChunk(pc);
         if (is_qnan(pc->r)) {
             // color chunk is invalid. Simply ignore it
-            DefaultLogger::get()->error("3DS: Unable to read EMISSIVE chunk");
+            ASSIMP_LOG_ERROR("3DS: Unable to read EMISSIVE chunk");
             pc->r = pc->g = pc->b = 0.0f;
         }}
         break;
@@ -1293,7 +1293,7 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut)
         pcOut->mScaleU = stream->GetF4();
         if (0.0f == pcOut->mScaleU)
         {
-            DefaultLogger::get()->warn("Texture coordinate scaling in the x direction is zero. Assuming 1.");
+            ASSIMP_LOG_WARN("Texture coordinate scaling in the x direction is zero. Assuming 1.");
             pcOut->mScaleU = 1.0f;
         }
         break;
@@ -1302,7 +1302,7 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut)
         pcOut->mScaleV = stream->GetF4();
         if (0.0f == pcOut->mScaleV)
         {
-            DefaultLogger::get()->warn("Texture coordinate scaling in the y direction is zero. Assuming 1.");
+            ASSIMP_LOG_WARN("Texture coordinate scaling in the y direction is zero. Assuming 1.");
             pcOut->mScaleV = 1.0f;
         }
         break;

+ 19 - 19
code/ACLoader.cpp

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

+ 1 - 1
code/AMFImporter.cpp

@@ -230,7 +230,7 @@ casu_cres:
 	if(!skipped_before[sk_idx])
 	{
 		skipped_before[sk_idx] = true;
-		LogWarning("Skipping node \"" + nn + "\" in " + pParentNodeName + ".");
+        ASSIMP_LOG_WARN_F("Skipping node \"", nn, "\" in ", pParentNodeName, ".");
 	}
 }
 

+ 0 - 12
code/AMFImporter.hpp

@@ -358,18 +358,6 @@ private:
 	/************** Functions: LOG set *************/
 	/***********************************************/
 
-	/// \fn void LogInfo(const std::string& pMessage)
-	/// Short variant for calling \ref DefaultLogger::get()->info()
-	void LogInfo(const std::string& pMessage) { DefaultLogger::get()->info(pMessage); }
-
-	/// \fn void LogWarning(const std::string& pMessage)
-	/// Short variant for calling \ref DefaultLogger::get()->warn()
-	void LogWarning(const std::string& pMessage) { DefaultLogger::get()->warn(pMessage); }
-
-	/// \fn void LogError(const std::string& pMessage)
-	/// Short variant for calling \ref DefaultLogger::get()->error()
-	void LogError(const std::string& pMessage) { DefaultLogger::get()->error(pMessage); }
-
 	/***********************************************/
 	/************** Functions: XML set *************/
 	/***********************************************/

+ 4 - 4
code/AMFImporter_Macro.hpp

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

+ 1 - 1
code/AMFImporter_Material.cpp

@@ -99,7 +99,7 @@ CAMFImporter_NodeElement* ne;
 		ParseHelper_Node_Exit();
 		// check that all components was defined
 		if(!(read_flag[0] && read_flag[1] && read_flag[2])) throw DeadlyImportError("Not all color components are defined.");
-		// check if <a> is absent. Then manualy add "a == 1".
+		// check if <a> is absent. Then manually add "a == 1".
 		if(!read_flag[3]) als.Color.a = 1;
 
 	}// if(!mReader->isEmptyElement())

+ 1 - 1
code/AMFImporter_Postprocess.cpp

@@ -770,7 +770,7 @@ std::list<aiNode*> ch_node;
 		// find referenced object
 		if(!Find_ConvertedNode(als.ObjectID, pNodeList, &found_node)) Throw_ID_NotFound(als.ObjectID);
 
-		// create node for apllying transformation
+		// create node for applying transformation
 		t_node = new aiNode;
 		t_node->mParent = con_node;
 		// apply transformation

+ 8 - 8
code/ASELoader.cpp

@@ -200,7 +200,7 @@ void ASEImporter::InternReadFile( const std::string& pFile,
             ConvertMeshes(*i,avOutMeshes);
         }
         if (tookNormals)    {
-            DefaultLogger::get()->debug("ASE: Taking normals from the file. Use "
+            ASSIMP_LOG_DEBUG("ASE: Taking normals from the file. Use "
                 "the AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS setting if you "
                 "experience problems");
         }
@@ -297,15 +297,15 @@ void ASEImporter::BuildAnimations(const std::vector<BaseNode*>& nodes)
 
         // TODO: Implement Bezier & TCB support
         if ((*i)->mAnim.mPositionType != ASE::Animation::TRACK) {
-            DefaultLogger::get()->warn("ASE: Position controller uses Bezier/TCB keys. "
+            ASSIMP_LOG_WARN("ASE: Position controller uses Bezier/TCB keys. "
                 "This is not supported.");
         }
         if ((*i)->mAnim.mRotationType != ASE::Animation::TRACK) {
-            DefaultLogger::get()->warn("ASE: Rotation controller uses Bezier/TCB keys. "
+            ASSIMP_LOG_WARN("ASE: Rotation controller uses Bezier/TCB keys. "
                 "This is not supported.");
         }
         if ((*i)->mAnim.mScalingType != ASE::Animation::TRACK)  {
-            DefaultLogger::get()->warn("ASE: Position controller uses Bezier/TCB keys. "
+            ASSIMP_LOG_WARN("ASE: Position controller uses Bezier/TCB keys. "
                 "This is not supported.");
         }
 
@@ -624,7 +624,7 @@ void ASEImporter::AddNodes (const std::vector<BaseNode*>& nodes,
             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+")");
+            ASSIMP_LOG_DEBUG("ASE: Generating separate target node ("+snode->mName+")");
         }
     }
 
@@ -947,7 +947,7 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMesh
     // validate the material index of the mesh
     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");
+        ASSIMP_LOG_WARN("Material index is out of range");
     }
 
     // If the material the mesh is assigned to is consisting of submeshes, split it
@@ -957,11 +957,11 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMesh
 
         std::vector<unsigned int>* aiSplit = new std::vector<unsigned int>[vSubMaterials.size()];
 
-        // build a list of all faces per submaterial
+        // build a list of all faces per sub-material
         for (unsigned int i = 0; i < mesh.mFaces.size();++i)    {
             // check range
             if (mesh.mFaces[i].iMaterial >= vSubMaterials.size()) {
-                DefaultLogger::get()->warn("Submaterial index is out of range");
+                ASSIMP_LOG_WARN("Submaterial index is out of range");
 
                 // use the last material instead
                 aiSplit[vSubMaterials.size()-1].push_back(i);

+ 14 - 12
code/ASEParser.cpp

@@ -151,7 +151,7 @@ void Parser::LogWarning(const char* szWarn)
 #endif
 
     // output the warning to the logger ...
-    DefaultLogger::get()->warn(szTemp);
+    ASSIMP_LOG_WARN(szTemp);
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -167,7 +167,7 @@ void Parser::LogInfo(const char* szWarn)
 #endif
 
     // output the information to the logger ...
-    DefaultLogger::get()->info(szTemp);
+    ASSIMP_LOG_INFO(szTemp);
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -758,7 +758,7 @@ void Parser::ParseLV3MapBlock(Texture& map)
                     SkipToNextToken();
                 if (temp != "Bitmap" && temp != "Normal Bump")
                 {
-                    DefaultLogger::get()->warn("ASE: Skipping unknown map type: " + temp);
+                    ASSIMP_LOG_WARN_F("ASE: Skipping unknown map type: ", temp);
                     parsePath = false;
                 }
                 continue;
@@ -773,7 +773,7 @@ void Parser::ParseLV3MapBlock(Texture& map)
                 {
                     // 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");
+                    ASSIMP_LOG_WARN("ASE: Skipping invalid map entry");
                     map.mMapName = "";
                 }
 
@@ -1072,7 +1072,7 @@ void Parser::ParseLV2AnimationBlock(ASE::BaseNode& mesh)
                         ( mesh.mType != BaseNode::Light  || ((ASE::Light&)mesh).mLightType   != ASE::Light::TARGET))
                     {
 
-                        DefaultLogger::get()->error("ASE: Found target animation channel "
+                        ASSIMP_LOG_ERROR("ASE: Found target animation channel "
                             "but the node is neither a camera nor a spot light");
                         anim = NULL;
                     }
@@ -1098,7 +1098,7 @@ void Parser::ParseLV2AnimationBlock(ASE::BaseNode& mesh)
                 if (!anim || anim == &mesh.mTargetAnim)
                 {
                     // Target animation channels may have no rotation channels
-                    DefaultLogger::get()->error("ASE: Ignoring scaling channel in target animation");
+                    ASSIMP_LOG_ERROR("ASE: Ignoring scaling channel in target animation");
                     SkipSection();
                 }
                 else ParseLV3ScaleAnimationBlock(*anim);
@@ -1112,7 +1112,7 @@ void Parser::ParseLV2AnimationBlock(ASE::BaseNode& mesh)
                 if (!anim || anim == &mesh.mTargetAnim)
                 {
                     // Target animation channels may have no rotation channels
-                    DefaultLogger::get()->error("ASE: Ignoring rotation channel in target animation");
+                    ASSIMP_LOG_ERROR("ASE: Ignoring rotation channel in target animation");
                     SkipSection();
                 }
                 else ParseLV3RotAnimationBlock(*anim);
@@ -1295,12 +1295,14 @@ void Parser::ParseLV2NodeTransformBlock(ASE::BaseNode& mesh)
                     {
                         mode = 2;
                     }
-                    else DefaultLogger::get()->error("ASE: Ignoring target transform, "
-                        "this is no spot light or target camera");
+                    else {
+                        ASSIMP_LOG_ERROR("ASE: Ignoring target transform, "
+                            "this is no spot light or target camera");
+                    }
                 }
                 else
                 {
-                    DefaultLogger::get()->error("ASE: Unknown node transformation: " + temp);
+                    ASSIMP_LOG_ERROR("ASE: Unknown node transformation: " + temp);
                     // mode = 0
                 }
                 continue;
@@ -1916,7 +1918,7 @@ void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh)
                 else if (index == face.mIndices[2])
                     index = 2;
                 else    {
-                    DefaultLogger::get()->error("ASE: Invalid vertex index in MESH_VERTEXNORMAL section");
+                    ASSIMP_LOG_ERROR("ASE: Invalid vertex index in MESH_VERTEXNORMAL section");
                     continue;
                 }
                 // We'll renormalize later
@@ -1928,7 +1930,7 @@ void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh)
                 ParseLV4MeshFloatTriple(&vNormal.x,faceIdx);
 
                 if (faceIdx >= sMesh.mFaces.size()) {
-                    DefaultLogger::get()->error("ASE: Invalid vertex index in MESH_FACENORMAL section");
+                    ASSIMP_LOG_ERROR("ASE: Invalid vertex index in MESH_FACENORMAL section");
                     continue;
                 }
 

+ 1 - 1
code/ASEParser.h

@@ -427,7 +427,7 @@ public:
 
     // -------------------------------------------------------------------
     //! Construct a parser from a given input file which is
-    //! guaranted to be terminated with zero.
+    //! guaranteed to be terminated with zero.
     //! @param szFile Input file
     //! @param fileFormatDefault Assumed file format version. If the
     //!   file format is specified in the file the new value replaces

+ 1 - 1
code/Assimp.cpp

@@ -146,7 +146,7 @@ private:
 
 // ------------------------------------------------------------------------------------------------
 void ReportSceneNotFoundError() {
-    DefaultLogger::get()->error("Unable to find the Assimp::Importer for this aiScene. "
+    ASSIMP_LOG_ERROR("Unable to find the Assimp::Importer for this aiScene. "
         "The C-API does not accept scenes produced by the C++ API and vice versa");
 
     ai_assert(false);

+ 1 - 1
code/B3DImporter.cpp

@@ -614,7 +614,7 @@ void B3DImporter::ReadBB3D( aiScene *scene ){
         if (!DefaultLogger::isNullLogger()) {
             char dmp[128];
             ai_snprintf(dmp, 128, "B3D file format version: %i",version);
-            DefaultLogger::get()->info(dmp);
+            ASSIMP_LOG_INFO(dmp);
         }
 
         while( ChunkSize() ){

+ 31 - 27
code/BaseImporter.cpp

@@ -64,23 +64,24 @@ using namespace Assimp;
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 BaseImporter::BaseImporter()
-: m_progress()
-{
+: m_progress() {
     // nothing to do here
 }
 
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
-BaseImporter::~BaseImporter()
-{
+BaseImporter::~BaseImporter() {
     // 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)
-{
+aiScene* BaseImporter::ReadFile(const Importer* pImp, const std::string& pFile, IOSystem* pIOHandler) {
     m_progress = pImp->GetProgressHandler();
+    if (nullptr == m_progress) {
+        return nullptr;
+    }
+
     ai_assert(m_progress);
 
     // Gather configuration properties for this run
@@ -100,8 +101,8 @@ aiScene* BaseImporter::ReadFile(const Importer* pImp, const std::string& pFile,
     } catch( const std::exception& err )    {
         // extract error description
         m_ErrorText = err.what();
-        DefaultLogger::get()->error(m_ErrorText);
-        return NULL;
+        ASSIMP_LOG_ERROR(m_ErrorText);
+        return nullptr;
     }
 
     // return what we gathered from the import.
@@ -142,7 +143,8 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions) {
     const char**        tokens,
     unsigned int        numTokens,
     unsigned int        searchBytes /* = 200 */,
-    bool                tokensSol /* false */)
+    bool                tokensSol /* false */,
+    bool                noAlphaBeforeTokens /* false */)
 {
     ai_assert( nullptr != tokens );
     ai_assert( 0 != numTokens );
@@ -192,10 +194,15 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions) {
             if( !r ) {
                 continue;
             }
+            // We need to make sure that we didn't accidentially identify the end of another token as our token,
+            // e.g. in a previous version the "gltf " present in some gltf files was detected as "f "
+            if (noAlphaBeforeTokens && (r != buffer && isalpha(r[-1]))) {
+                continue;
+            }
             // We got a match, either we don't care where it is, or it happens to
             // 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]);
+                ASSIMP_LOG_DEBUG_F( "Found positive match for header keyword: ", tokens[i] );
                 return true;
             }
         }
@@ -322,7 +329,7 @@ void BaseImporter::ConvertToUTF8(std::vector<char>& data)
 
     // 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 ...");
+        ASSIMP_LOG_DEBUG("Found UTF-8 BOM ...");
 
         std::copy(data.begin()+3,data.end(),data.begin());
         data.resize(data.size()-3);
@@ -341,7 +348,7 @@ void BaseImporter::ConvertToUTF8(std::vector<char>& data)
 
     // UTF 32 LE with BOM
     if(*((uint32_t*)&data.front()) == 0x0000FFFE) {
-        DefaultLogger::get()->debug("Found UTF-32 BOM ...");
+        ASSIMP_LOG_DEBUG("Found UTF-32 BOM ...");
 
         std::vector<char> output;
         int *ptr = (int*)&data[ 0 ];
@@ -361,7 +368,7 @@ void BaseImporter::ConvertToUTF8(std::vector<char>& data)
 
     // UTF 16 LE with BOM
     if(*((uint16_t*)&data.front()) == 0xFEFF) {
-        DefaultLogger::get()->debug("Found UTF-16 BOM ...");
+        ASSIMP_LOG_DEBUG("Found UTF-16 BOM ...");
 
         std::vector<unsigned char> output;
         utf8::utf16to8(data.begin(), data.end(), back_inserter(output));
@@ -386,16 +393,14 @@ void BaseImporter::ConvertUTF8toISO8859_1(std::string& data)
                 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.";
-
-                DefaultLogger::get()->error(stream.str());
+                ASSIMP_LOG_ERROR( stream.str() );
 
                 data[j++] = data[i++];
                 data[j] = data[i];
             }
         } else {
-            DefaultLogger::get()->error("UTF8 code but only one character remaining");
+            ASSIMP_LOG_ERROR("UTF8 code but only one character remaining");
 
             data[j] = data[i];
         }
@@ -411,7 +416,7 @@ void BaseImporter::TextFileToBuffer(IOStream* stream,
     std::vector<char>& data,
     TextFileMode mode)
 {
-    ai_assert(NULL != stream);
+    ai_assert(nullptr != stream);
 
     const size_t fileSize = stream->FileSize();
     if (mode == FORBID_EMPTY) {
@@ -472,14 +477,14 @@ struct Assimp::BatchData {
     , pImporter( nullptr )
     , next_id(0xffff)
     , validate( validate ) {
-        ai_assert( NULL != pIO );
+        ai_assert( nullptr != pIO );
         
         pImporter = new Importer();
         pImporter->SetIOHandler( pIO );
     }
 
     ~BatchData() {
-        pImporter->SetIOHandler( NULL ); /* get pointer back into our possession */
+        pImporter->SetIOHandler( nullptr ); /* get pointer back into our possession */
         delete pImporter;
     }
 
@@ -505,9 +510,8 @@ struct Assimp::BatchData {
 typedef std::list<LoadRequest>::iterator LoadReqIt;
 
 // ------------------------------------------------------------------------------------------------
-BatchLoader::BatchLoader(IOSystem* pIO, bool validate )
-{
-    ai_assert(NULL != pIO);
+BatchLoader::BatchLoader(IOSystem* pIO, bool validate ) {
+    ai_assert(nullptr != pIO);
 
     m_data = new BatchData( pIO, validate );
 }
@@ -573,7 +577,7 @@ aiScene* BatchLoader::GetImport( unsigned int which )
             return sc;
         }
     }
-    return NULL;
+    return nullptr;
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -596,13 +600,13 @@ void BatchLoader::LoadAll()
 
         if (!DefaultLogger::isNullLogger())
         {
-            DefaultLogger::get()->info("%%% BEGIN EXTERNAL FILE %%%");
-            DefaultLogger::get()->info("File: " + (*it).file);
+            ASSIMP_LOG_INFO("%%% BEGIN EXTERNAL FILE %%%");
+            ASSIMP_LOG_INFO_F("File: ", (*it).file);
         }
         m_data->pImporter->ReadFile((*it).file,pp);
         (*it).scene = m_data->pImporter->GetOrphanedScene();
         (*it).loaded = true;
 
-        DefaultLogger::get()->info("%%% END EXTERNAL FILE %%%");
+        ASSIMP_LOG_INFO("%%% END EXTERNAL FILE %%%");
     }
 }

+ 1 - 1
code/BaseProcess.cpp

@@ -85,7 +85,7 @@ void BaseProcess::ExecuteOnScene( Importer* pImp)
 
         // extract error description
         pImp->Pimpl()->mErrorString = err.what();
-        DefaultLogger::get()->error(pImp->Pimpl()->mErrorString);
+        ASSIMP_LOG_ERROR(pImp->Pimpl()->mErrorString);
 
         // and kill the partially imported data
         delete pImp->Pimpl()->mScene;

+ 185 - 0
code/BlenderCustomData.cpp

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

+ 89 - 0
code/BlenderCustomData.h

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

+ 5 - 6
code/BlenderDNA.cpp

@@ -210,8 +210,7 @@ void DNAParser::Parse ()
         s.size = offset;
     }
 
-    DefaultLogger::get()->debug((format(),"BlenderDNA: Got ",dna.structures.size(),
-        " structures with totally ",fields," fields"));
+    ASSIMP_LOG_DEBUG_F( "BlenderDNA: Got ", dna.structures.size()," structures with totally ",fields," fields");
 
 #ifdef ASSIMP_BUILD_BLENDER_DEBUG
     dna.DumpToFile();
@@ -228,12 +227,12 @@ void DNAParser::Parse ()
 // ------------------------------------------------------------------------------------------------
 void DNA :: DumpToFile()
 {
-    // we dont't bother using the VFS here for this is only for debugging.
+    // we don't bother using the VFS here for this is only for debugging.
     // (and all your bases are belong to us).
 
     std::ofstream f("dna.txt");
     if (f.fail()) {
-        DefaultLogger::get()->error("Could not dump dna to dna.txt");
+        ASSIMP_LOG_ERROR("Could not dump dna to dna.txt");
         return;
     }
     f << "Field format: type name offset size" << "\n";
@@ -248,7 +247,7 @@ void DNA :: DumpToFile()
     }
     f << std::flush;
 
-    DefaultLogger::get()->info("BlenderDNA: Dumped dna to dna.txt");
+    ASSIMP_LOG_INFO("BlenderDNA: Dumped dna to dna.txt");
 }
 #endif
 
@@ -367,7 +366,7 @@ void SectionParser :: Next()
     }
 
 #ifdef ASSIMP_BUILD_BLENDER_DEBUG
-    DefaultLogger::get()->debug(current.id);
+    ASSIMP_LOG_DEBUG(current.id);
 #endif
 }
 

+ 35 - 2
code/BlenderDNA.h

@@ -309,6 +309,28 @@ public:
     void ReadField(T& out, const char* name,
         const FileDatabase& db) const;
 
+    // --------------------------------------------------------
+    /**
+    *   @brief  field parsing for dynamic vectors
+    *   @param[in]  out vector of struct to be filled
+    *   @param[in]  name of field
+    *   @param[in]  db to access the file, dna, ...
+    *   @return true when read was successful
+    */
+    template <int error_policy, template <typename> class TOUT, typename T>
+    bool ReadFieldPtrVector(vector<TOUT<T>>&out, const char* name, const FileDatabase& db) const;
+
+    /**
+    *   @brief  parses raw customdata
+    *   @param[in]  out shared_ptr to be filled
+    *   @param[in]  cdtype customdata type to read
+    *   @param[in]  name of field ptr
+    *   @param[in]  db to access the file, dna, ...
+    *   @return true when read was successful
+    */
+    template <int error_policy>
+    bool ReadCustomDataPtr(std::shared_ptr<ElemBase>&out, int cdtype, const char* name, const FileDatabase& db) const;
+
 private:
 
     // --------------------------------------------------------
@@ -381,7 +403,7 @@ template <>  struct Structure :: _defaultInitializer<ErrorPolicy_Warn> {
 
     template <typename T>
     void operator ()(T& out, const char* reason = "<add reason>") {
-        DefaultLogger::get()->warn(reason);
+        ASSIMP_LOG_WARN(reason);
 
         // ... and let the show go on
         _defaultInitializer<0 /*ErrorPolicy_Igno*/>()(out);
@@ -663,7 +685,7 @@ 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.
+     *   cache doesn't know the item yet.
      *  @param ptr Item address to look for. */
     template <typename T> void get (
         const Structure& s,
@@ -803,6 +825,17 @@ private:
     FileDatabase& db;
 };
 
+/**
+*   @brief  read CustomData's data to ptr to mem
+*   @param[out] out memory ptr to set
+*   @param[in]  cdtype  to read
+*   @param[in]  cnt cnt of elements to read
+*   @param[in]  db to read elements from
+*   @return true when ok
+*/
+bool readCustomData(std::shared_ptr<ElemBase> &out, int cdtype, size_t cnt, const FileDatabase &db);
+
+
     } // end Blend
 } // end Assimp
 

+ 103 - 3
code/BlenderDNA.inl

@@ -307,6 +307,108 @@ void Structure :: ReadField(T& out, const char* name, const FileDatabase& db) co
 }
 
 
+//--------------------------------------------------------------------------------
+// field parsing for raw untyped data (like CustomDataLayer.data)
+template <int error_policy>
+bool Structure::ReadCustomDataPtr(std::shared_ptr<ElemBase>&out, int cdtype, const char* name, const FileDatabase& db) const {
+
+	const StreamReaderAny::pos old = db.reader->GetCurrentPos();
+
+	Pointer ptrval;
+	const Field* f;
+	try	{
+		f = &(*this)[name];
+
+		// sanity check, should never happen if the genblenddna script is right
+		if (!(f->flags & FieldFlag_Pointer)) {
+			throw Error((Formatter::format(), "Field `", name, "` of structure `",
+				this->name, "` ought to be a pointer"));
+		}
+
+		db.reader->IncPtr(f->offset);
+		Convert(ptrval, db);
+		// actually it is meaningless on which Structure the Convert is called
+		// because the `Pointer` argument triggers a special implementation.
+	}
+	catch (const Error& e) {
+		_defaultInitializer<error_policy>()(out, e.what());
+		out.reset();
+	}
+
+	bool readOk = true;
+	if (ptrval.val)	{
+		// get block for ptr
+		const FileBlockHead* block = LocateFileBlockForAddress(ptrval, db);
+		db.reader->SetCurrentPos(block->start + static_cast<size_t>((ptrval.val - block->address.val)));
+		// read block->num instances of given type to out
+		readOk = readCustomData(out, cdtype, block->num, db);
+	}
+
+	// and recover the previous stream position
+	db.reader->SetCurrentPos(old);
+
+#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
+	++db.stats().fields_read;
+#endif
+
+	return readOk;
+}
+
+//--------------------------------------------------------------------------------
+template <int error_policy, template <typename> class TOUT, typename T>
+bool Structure::ReadFieldPtrVector(vector<TOUT<T>>&out, const char* name, const FileDatabase& db) const {
+	out.clear();
+
+	const StreamReaderAny::pos old = db.reader->GetCurrentPos();
+
+	Pointer ptrval;
+	const Field* f;
+	try	{
+		f = &(*this)[name];
+
+		// sanity check, should never happen if the genblenddna script is right
+		if (!(f->flags & FieldFlag_Pointer)) {
+			throw Error((Formatter::format(), "Field `", name, "` of structure `",
+				this->name, "` ought to be a pointer"));
+		}
+
+		db.reader->IncPtr(f->offset);
+		Convert(ptrval, db);
+		// actually it is meaningless on which Structure the Convert is called
+		// because the `Pointer` argument triggers a special implementation.
+	}
+	catch (const Error& e) {
+		_defaultInitializer<error_policy>()(out, e.what());
+		out.clear();
+		return false;
+	}
+
+
+	if (ptrval.val)	{
+		// find the file block the pointer is pointing to
+		const FileBlockHead* block = LocateFileBlockForAddress(ptrval, db);
+		db.reader->SetCurrentPos(block->start + static_cast<size_t>((ptrval.val - block->address.val)));
+		// FIXME: basically, this could cause problems with 64 bit pointers on 32 bit systems.
+		// I really ought to improve StreamReader to work with 64 bit indices exclusively.
+
+		const Structure& s = db.dna[f->type];
+		for (size_t i = 0; i < block->num; ++i)	{
+			TOUT<T> p(new T);
+			s.Convert(*p, db);
+			out.push_back(p);
+		}
+	}
+
+	db.reader->SetCurrentPos(old);
+
+#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
+	++db.stats().fields_read;
+#endif
+
+	return false;
+}
+
+
 //--------------------------------------------------------------------------------
 template <template <typename> class TOUT, typename T>
 bool Structure :: ResolvePointer(TOUT<T>& out, const Pointer & ptrval, const FileDatabase& db,
@@ -468,9 +570,7 @@ template <> bool Structure :: ResolvePointer<std::shared_ptr,ElemBase>(std::shar
         // this might happen if DNA::RegisterConverters hasn't been called so far
         // 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"
-            ));
+        ASSIMP_LOG_WARN_F( "Failed to find a converter for the `",s.name,"` structure" );
         return false;
     }
 

+ 69 - 10
code/BlenderLoader.cpp

@@ -54,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "BlenderIntermediate.h"
 #include "BlenderModifier.h"
 #include "BlenderBMesh.h"
+#include "BlenderCustomData.h"
 #include <assimp/StringUtils.h>
 #include <assimp/scene.h>
 #include <assimp/importerdesc.h>
@@ -327,12 +328,12 @@ void BlenderImporter::ExtractScene(Scene& out, const FileDatabase& file)
     ss.Convert(out,file);
 
 #ifndef ASSIMP_BUILD_BLENDER_NO_STATS
-    DefaultLogger::get()->info((format(),
+    ASSIMP_LOG_INFO_F(
         "(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
 }
 
@@ -1021,6 +1022,34 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
         }
     }
 
+    // TODO should we create the TextureUVMapping map in Convert<Material> to prevent redundant processing?
+
+    // create texture <-> uvname mapping for all materials
+    // key is texture number, value is data *
+    typedef std::map<uint32_t, const MLoopUV *> TextureUVMapping;
+    // key is material number, value is the TextureUVMapping for the material
+    typedef std::map<uint32_t, TextureUVMapping> MaterialTextureUVMappings;
+    MaterialTextureUVMappings matTexUvMappings;
+    const uint32_t maxMat = static_cast<const uint32_t>(mesh->mat.size());
+    for (uint32_t m = 0; m < maxMat; ++m) {
+        // get material by index
+        const std::shared_ptr<Material> pMat = mesh->mat[m];
+        TextureUVMapping texuv;
+        const uint32_t maxTex = sizeof(pMat->mtex) / sizeof(pMat->mtex[0]);
+        for (uint32_t t = 0; t < maxTex; ++t) {
+            if (pMat->mtex[t] && pMat->mtex[t]->uvname[0]) {
+                // get the CustomData layer for given uvname and correct type
+                const ElemBase *pLoop = getCustomDataLayerData(mesh->ldata, CD_MLOOPUV, pMat->mtex[t]->uvname);
+                if (pLoop) {
+                    texuv.insert(std::make_pair(t, dynamic_cast<const MLoopUV *>(pLoop)));
+                }
+            }
+        }
+        if (texuv.size()) {
+            matTexUvMappings.insert(std::make_pair(m, texuv));
+        }
+    }
+
     // collect texture coordinates, they're stored in a separate per-face buffer
     if (mesh->mtface || mesh->mloopuv) {
         if (mesh->totface > static_cast<int> ( mesh->mtface.size())) {
@@ -1028,8 +1057,17 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
         }
         for (std::vector<aiMesh*>::iterator it = temp->begin()+old; it != temp->end(); ++it) {
             ai_assert((*it)->mNumVertices && (*it)->mNumFaces);
-
-            (*it)->mTextureCoords[0] = new aiVector3D[(*it)->mNumVertices];
+            const auto itMatTexUvMapping = matTexUvMappings.find((*it)->mMaterialIndex);
+            if (itMatTexUvMapping == matTexUvMappings.end()) {
+                // default behaviour like before
+                (*it)->mTextureCoords[0] = new aiVector3D[(*it)->mNumVertices];
+            }
+            else {
+                // create texture coords for every mapped tex
+                for (uint32_t i = 0; i < itMatTexUvMapping->second.size(); ++i) {
+                    (*it)->mTextureCoords[i] = new aiVector3D[(*it)->mNumVertices];
+                }
+            }
             (*it)->mNumFaces = (*it)->mNumVertices = 0;
         }
 
@@ -1051,13 +1089,34 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
             aiMesh* const out = temp[ mat_num_to_mesh_idx[ v.mat_nr ] ];
             const aiFace& f = out->mFaces[out->mNumFaces++];
 
-            aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices];
-            for (unsigned int j = 0; j < f.mNumIndices; ++j,++vo,++out->mNumVertices) {
-                const MLoopUV& uv = mesh->mloopuv[v.loopstart + j];
-                vo->x = uv.uv[0];
-                vo->y = uv.uv[1];
+            const auto itMatTexUvMapping = matTexUvMappings.find(v.mat_nr);
+            if (itMatTexUvMapping == matTexUvMappings.end()) {
+                // old behavior
+                aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices];
+                for (unsigned int j = 0; j < f.mNumIndices; ++j, ++vo, ++out->mNumVertices) {
+                    const MLoopUV& uv = mesh->mloopuv[v.loopstart + j];
+                    vo->x = uv.uv[0];
+                    vo->y = uv.uv[1];
+                }
+            }
+            else {
+                // create textureCoords for every mapped tex
+                for (uint32_t m = 0; m < itMatTexUvMapping->second.size(); ++m) {
+                    const MLoopUV *tm = itMatTexUvMapping->second[m];
+                    aiVector3D* vo = &out->mTextureCoords[m][out->mNumVertices];
+                    uint32_t j = 0;
+                    for (; j < f.mNumIndices; ++j, ++vo) {
+                        const MLoopUV& uv = tm[v.loopstart + j];
+                        vo->x = uv.uv[0];
+                        vo->y = uv.uv[1];
+                    }
+                    // only update written mNumVertices in last loop
+                    // TODO why must the numVertices be incremented here?
+                    if (m == itMatTexUvMapping->second.size() - 1) {
+                        out->mNumVertices += j;
+                    }
+                }
             }
-
         }
     }
 

+ 1 - 1
code/BlenderModifier.h

@@ -86,7 +86,7 @@ public:
         const Scene& /*in*/,
         const Object& /*orig_object*/
     ) {
-        DefaultLogger::get()->warn((Formatter::format("This modifier is not supported, skipping: "),orig_modifier.dna_type));
+        ASSIMP_LOG_INFO_F("This modifier is not supported, skipping: ",orig_modifier.dna_type );
         return;
     }
 };

+ 44 - 0
code/BlenderScene.cpp

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

+ 79 - 1
code/BlenderScene.h

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

+ 11 - 0
code/BlenderSceneGen.h

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

+ 1 - 1
code/BlenderTessellator.h

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

+ 11 - 2
code/CMakeLists.txt

@@ -208,8 +208,15 @@ OPTION(ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT "default value of all ASSIMP_BUILD_
 # macro to add the CMake Option ADD_ASSIMP_IMPORTER_<name> which enables compile of loader
 # 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" ${ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT})
-  IF(ASSIMP_BUILD_${name}_IMPORTER)
+  IF (ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT)
+    set(ASSIMP_IMPORTER_ENABLED TRUE)
+    IF (DEFINED ASSIMP_BUILD_${name}_IMPORTER AND NOT ASSIMP_BUILD_${name}_IMPORTER)
+      set(ASSIMP_IMPORTER_ENABLED FALSE)
+    ENDIF ()
+  ELSE ()
+    set(ASSIMP_IMPORTER_ENABLED ${ASSIMP_BUILD_${name}_IMPORTER})
+  ENDIF ()
+  IF (ASSIMP_IMPORTER_ENABLED)
     LIST(APPEND ASSIMP_LOADER_SRCS ${ARGN})
     SET(ASSIMP_IMPORTERS_ENABLED "${ASSIMP_IMPORTERS_ENABLED} ${name}")
     SET(${name}_SRCS ${ARGN})
@@ -462,6 +469,8 @@ ADD_ASSIMP_IMPORTER( BLEND
   BlenderBMesh.cpp
   BlenderTessellator.h
   BlenderTessellator.cpp
+  BlenderCustomData.h
+  BlenderCustomData.cpp
 )
 
 ADD_ASSIMP_IMPORTER( IFC

+ 23 - 77
code/COBLoader.cpp

@@ -150,7 +150,7 @@ void COBImporter::InternReadFile( const std::string& pFile,
         ThrowException("Could not found magic id: `Caligari`");
     }
 
-    DefaultLogger::get()->info("File format tag: "+std::string(head+9,6));
+    ASSIMP_LOG_INFO_F("File format tag: ",std::string(head+9,6));
     if (head[16]!='L') {
         ThrowException("File is big-endian, which is not supported");
     }
@@ -303,7 +303,7 @@ aiNode* COBImporter::BuildNodes(const Node& root,const Scene& scin,aiScene* fill
                     }
                     std::unique_ptr<const Material> defmat;
                     if(!min) {
-                        DefaultLogger::get()->debug(format()<<"Could not resolve material index "
+                        ASSIMP_LOG_DEBUG(format()<<"Could not resolve material index "
                             <<reflist.first<<" - creating default material for this slot");
 
                         defmat.reset(min=new Material());
@@ -475,7 +475,7 @@ void COBImporter::UnsupportedChunk_Ascii(LineSplitter& splitter, const ChunkInfo
 
     // we can recover if the chunk size was specified.
     if(nfo.size != static_cast<unsigned int>(-1)) {
-        DefaultLogger::get()->error(error);
+        ASSIMP_LOG_ERROR(error);
 
         // (HACK) - our current position in the stream is the beginning of the
         // head line of the next chunk. That's fine, but the caller is going
@@ -487,46 +487,6 @@ void COBImporter::UnsupportedChunk_Ascii(LineSplitter& splitter, const ChunkInfo
     else ThrowException(error);
 }
 
-// ------------------------------------------------------------------------------------------------
-void COBImporter::LogWarn_Ascii(const LineSplitter& splitter, const format& message)    {
-    LogWarn_Ascii(message << " [at line "<< splitter.get_index()<<"]");
-}
-
-// ------------------------------------------------------------------------------------------------
-void COBImporter::LogError_Ascii(const LineSplitter& splitter, const format& message)   {
-    LogError_Ascii(message << " [at line "<< splitter.get_index()<<"]");
-}
-
-// ------------------------------------------------------------------------------------------------
-void COBImporter::LogInfo_Ascii(const LineSplitter& splitter, const format& message)    {
-    LogInfo_Ascii(message << " [at line "<< splitter.get_index()<<"]");
-}
-
-// ------------------------------------------------------------------------------------------------
-void COBImporter::LogDebug_Ascii(const LineSplitter& splitter, const format& message)   {
-    LogDebug_Ascii(message << " [at line "<< splitter.get_index()<<"]");
-}
-
-// ------------------------------------------------------------------------------------------------
-void COBImporter::LogWarn_Ascii(const Formatter::format& message)   {
-    DefaultLogger::get()->warn(std::string("COB: ")+=message);
-}
-
-// ------------------------------------------------------------------------------------------------
-void COBImporter::LogError_Ascii(const Formatter::format& message)  {
-    DefaultLogger::get()->error(std::string("COB: ")+=message);
-}
-
-// ------------------------------------------------------------------------------------------------
-void COBImporter::LogInfo_Ascii(const Formatter::format& message)   {
-    DefaultLogger::get()->info(std::string("COB: ")+=message);
-}
-
-// ------------------------------------------------------------------------------------------------
-void COBImporter::LogDebug_Ascii(const Formatter::format& message)  {
-    DefaultLogger::get()->debug(std::string("COB: ")+=message);
-}
-
 // ------------------------------------------------------------------------------------------------
 void COBImporter::ReadBasicNodeInfo_Ascii(Node& msh, LineSplitter& splitter, const ChunkInfo& /*nfo*/)
 {
@@ -576,8 +536,7 @@ void COBImporter::ReadMat1_Ascii(Scene& out, LineSplitter& splitter, const Chunk
 
     ++splitter;
     if (!splitter.match_start("mat# ")) {
-        LogWarn_Ascii(splitter,format()<<
-            "Expected `mat#` line in `Mat1` chunk "<<nfo.id);
+        ASSIMP_LOG_WARN_F( "Expected `mat#` line in `Mat1` chunk ", nfo.id );
         return;
     }
 
@@ -589,8 +548,7 @@ void COBImporter::ReadMat1_Ascii(Scene& out, LineSplitter& splitter, const Chunk
     ++splitter;
 
     if (!splitter.match_start("shader: ")) {
-        LogWarn_Ascii(splitter,format()<<
-            "Expected `mat#` line in `Mat1` chunk "<<nfo.id);
+        ASSIMP_LOG_WARN_F( "Expected `mat#` line in `Mat1` chunk ", nfo.id);
         return;
     }
     std::string shader = std::string(splitter[1]);
@@ -603,14 +561,12 @@ void COBImporter::ReadMat1_Ascii(Scene& out, LineSplitter& splitter, const Chunk
         mat.shader = Material::PHONG;
     }
     else if (shader != "flat") {
-        LogWarn_Ascii(splitter,format()<<
-            "Unknown value for `shader` in `Mat1` chunk "<<nfo.id);
+        ASSIMP_LOG_WARN_F( "Unknown value for `shader` in `Mat1` chunk ", nfo.id );
     }
 
     ++splitter;
     if (!splitter.match_start("rgb ")) {
-        LogWarn_Ascii(splitter,format()<<
-            "Expected `rgb` line in `Mat1` chunk "<<nfo.id);
+        ASSIMP_LOG_WARN_F( "Expected `rgb` line in `Mat1` chunk ", nfo.id);
     }
 
     const char* rgb = splitter[1];
@@ -618,8 +574,7 @@ void COBImporter::ReadMat1_Ascii(Scene& out, LineSplitter& splitter, const Chunk
 
     ++splitter;
     if (!splitter.match_start("alpha ")) {
-        LogWarn_Ascii(splitter,format()<<
-            "Expected `alpha` line in `Mat1` chunk "<<nfo.id);
+        ASSIMP_LOG_WARN_F( "Expected `alpha` line in `Mat1` chunk ", nfo.id);
     }
 
     const char* tokens[10];
@@ -640,8 +595,7 @@ void COBImporter::ReadUnit_Ascii(Scene& out, LineSplitter& splitter, const Chunk
     }
     ++splitter;
     if (!splitter.match_start("Units ")) {
-        LogWarn_Ascii(splitter,format()<<
-            "Expected `Units` line in `Unit` chunk "<<nfo.id);
+        ASSIMP_LOG_WARN_F( "Expected `Units` line in `Unit` chunk ", nfo.id);
         return;
     }
 
@@ -652,13 +606,12 @@ void COBImporter::ReadUnit_Ascii(Scene& out, LineSplitter& splitter, const Chunk
             const unsigned int t=strtoul10(splitter[1]);
 
             nd->unit_scale = t>=sizeof(units)/sizeof(units[0])?(
-                LogWarn_Ascii(splitter,format()<<t<<" is not a valid value for `Units` attribute in `Unit chunk` "<<nfo.id)
+                ASSIMP_LOG_WARN_F(t, " is not a valid value for `Units` attribute in `Unit chunk` ", nfo.id)
                 ,1.f):units[t];
             return;
         }
     }
-    LogWarn_Ascii(splitter,format()<<"`Unit` chunk "<<nfo.id<<" is a child of "
-        <<nfo.parent_id<<" which does not exist");
+    ASSIMP_LOG_WARN_F( "`Unit` chunk ", nfo.id, " is a child of ", nfo.parent_id, " which does not exist");
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -692,15 +645,13 @@ void COBImporter::ReadLght_Ascii(Scene& out, LineSplitter& splitter, const Chunk
         msh.ltype = Light::SPOT;
     }
     else {
-        LogWarn_Ascii(splitter,format()<<
-            "Unknown kind of light source in `Lght` chunk "<<nfo.id<<" : "<<*splitter);
+        ASSIMP_LOG_WARN_F( "Unknown kind of light source in `Lght` chunk ", nfo.id, " : ", *splitter );
         msh.ltype = Light::SPOT;
     }
 
     ++splitter;
     if (!splitter.match_start("color ")) {
-        LogWarn_Ascii(splitter,format()<<
-            "Expected `color` line in `Lght` chunk "<<nfo.id);
+        ASSIMP_LOG_WARN_F( "Expected `color` line in `Lght` chunk ", nfo.id );
     }
 
     const char* rgb = splitter[1];
@@ -708,16 +659,14 @@ void COBImporter::ReadLght_Ascii(Scene& out, LineSplitter& splitter, const Chunk
 
     SkipSpaces(&rgb);
     if (strncmp(rgb,"cone angle",10)) {
-        LogWarn_Ascii(splitter,format()<<
-            "Expected `cone angle` entity in `color` line in `Lght` chunk "<<nfo.id);
+        ASSIMP_LOG_WARN_F( "Expected `cone angle` entity in `color` line in `Lght` chunk ", nfo.id );
     }
     SkipSpaces(rgb+10,&rgb);
     msh.angle = fast_atof(&rgb);
 
     SkipSpaces(&rgb);
     if (strncmp(rgb,"inner angle",11)) {
-        LogWarn_Ascii(splitter,format()<<
-            "Expected `inner angle` entity in `color` line in `Lght` chunk "<<nfo.id);
+        ASSIMP_LOG_WARN_F( "Expected `inner angle` entity in `color` line in `Lght` chunk ", nfo.id);
     }
     SkipSpaces(rgb+11,&rgb);
     msh.inner_angle = fast_atof(&rgb);
@@ -828,7 +777,7 @@ void COBImporter::ReadPolH_Ascii(Scene& out, LineSplitter& splitter, const Chunk
 
             for(unsigned int cur = 0; cur < cnt && ++splitter ;++cur) {
                 if (splitter.match_start("Hole")) {
-                    LogWarn_Ascii(splitter,"Skipping unsupported `Hole` line");
+                    ASSIMP_LOG_WARN( "Skipping unsupported `Hole` line" );
                     continue;
                 }
 
@@ -888,7 +837,7 @@ void COBImporter::ReadBitM_Ascii(Scene& /*out*/, LineSplitter& splitter, const C
 
     const unsigned int head = strtoul10((++splitter)[1]);
     if (head != sizeof(Bitmap::BitmapHeader)) {
-        LogWarn_Ascii(splitter,"Unexpected ThumbNailHdrSize, skipping this chunk");
+        ASSIMP_LOG_WARN("Unexpected ThumbNailHdrSize, skipping this chunk");
         return;
     }
 
@@ -935,7 +884,7 @@ void COBImporter::UnsupportedChunk_Binary( StreamReaderLE& reader, const ChunkIn
 
     // we can recover if the chunk size was specified.
     if(nfo.size != static_cast<unsigned int>(-1)) {
-        DefaultLogger::get()->error(error);
+        ASSIMP_LOG_ERROR(error);
         reader.IncPtr(nfo.size);
     }
     else ThrowException(error);
@@ -1142,7 +1091,7 @@ void COBImporter::ReadMat1_Binary(COB::Scene& out, StreamReaderLE& reader, const
             mat.type = Material::METAL;
             break;
         default:
-            LogError_Ascii(format("Unrecognized shader type in `Mat1` chunk with id ")<<nfo.id);
+            ASSIMP_LOG_ERROR_F( "Unrecognized shader type in `Mat1` chunk with id ", nfo.id );
             mat.type = Material::FLAT;
     }
 
@@ -1157,7 +1106,7 @@ void COBImporter::ReadMat1_Binary(COB::Scene& out, StreamReaderLE& reader, const
             mat.autofacet = Material::SMOOTH;
             break;
         default:
-            LogError_Ascii(format("Unrecognized faceting mode in `Mat1` chunk with id ")<<nfo.id);
+            ASSIMP_LOG_ERROR_F( "Unrecognized faceting mode in `Mat1` chunk with id ", nfo.id );
             mat.autofacet = Material::FACETED;
     }
     mat.autofacet_angle = static_cast<float>(reader.GetI1());
@@ -1289,16 +1238,13 @@ void COBImporter::ReadUnit_Binary(COB::Scene& out, StreamReaderLE& reader, const
         if (nd->id == nfo.parent_id) {
             const unsigned int t=reader.GetI2();
             nd->unit_scale = t>=sizeof(units)/sizeof(units[0])?(
-                LogWarn_Ascii(format()<<t<<" is not a valid value for `Units` attribute in `Unit chunk` "<<nfo.id)
+                ASSIMP_LOG_WARN_F(t," is not a valid value for `Units` attribute in `Unit chunk` ", nfo.id)
                 ,1.f):units[t];
 
             return;
         }
     }
-    LogWarn_Ascii(format()<<"`Unit` chunk "<<nfo.id<<" is a child of "
-        <<nfo.parent_id<<" which does not exist");
+    ASSIMP_LOG_WARN_F( "`Unit` chunk ", nfo.id, " is a child of ", nfo.parent_id, " which does not exist");
 }
 
-
-#endif
-
+#endif // ASSIMP_BUILD_NO_COB_IMPORTER

+ 1 - 21
code/COBLoader.h

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

+ 1 - 1
code/CSMLoader.cpp

@@ -233,7 +233,7 @@ void CSMImporter::InternReadFile( const std::string& pFile,
 
                         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)");
+                            ASSIMP_LOG_WARN("CSM: Encountered invalid marker data (DROPOUT)");
                         }
                         else    {
                             aiVectorKey* sub = s->mPositionKeys + s->mNumPositionKeys;

+ 6 - 6
code/CalcTangentsProcess.cpp

@@ -95,7 +95,7 @@ void CalcTangentsProcess::Execute( aiScene* pScene)
 {
     ai_assert( NULL != pScene );
 
-    DefaultLogger::get()->debug("CalcTangentsProcess begin");
+    ASSIMP_LOG_DEBUG("CalcTangentsProcess begin");
 
     bool bHas = false;
     for ( unsigned int a = 0; a < pScene->mNumMeshes; a++ ) {
@@ -103,9 +103,9 @@ void CalcTangentsProcess::Execute( aiScene* pScene)
     }
 
     if ( bHas ) {
-        DefaultLogger::get()->info("CalcTangentsProcess finished. Tangents have been calculated");
+        ASSIMP_LOG_INFO("CalcTangentsProcess finished. Tangents have been calculated");
     } else {
-        DefaultLogger::get()->debug("CalcTangentsProcess finished");
+        ASSIMP_LOG_DEBUG("CalcTangentsProcess finished");
     }
 }
 
@@ -126,19 +126,19 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
     // are undefined.
     if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON)))
     {
-        DefaultLogger::get()->info("Tangents are undefined for line and point meshes");
+        ASSIMP_LOG_INFO("Tangents are undefined for line and point meshes");
         return false;
     }
 
     // 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");
+        ASSIMP_LOG_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));
+        ASSIMP_LOG_ERROR((Formatter::format("Failed to compute tangents; need UV data in channel"),configSourceUV));
         return false;
     }
 

+ 1 - 1
code/ColladaExporter.h

@@ -189,7 +189,7 @@ protected:
      {}
   };
 
-  // summarize a material in an convinient way.
+  // summarize a material in an convenient way.
   struct Material
   {
     std::string name;

+ 4 - 3
code/ColladaHelper.h

@@ -272,12 +272,13 @@ struct Node
     /** Node instances at this node */
     std::vector<NodeInstance> mNodeInstances;
 
-    /** Rootnodes: Name of primary camera, if any */
+    /** Root-nodes: Name of primary camera, if any */
     std::string mPrimaryCamera;
 
     //! Constructor. Begin with a zero parent
-    Node() {
-        mParent = NULL;
+    Node()
+    : mParent( nullptr ){
+        // empty
     }
 
     //! Destructor: delete all children subsequently

+ 58 - 60
code/ColladaLoader.cpp

@@ -181,26 +181,27 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
     // ... then fill the materials with the now adjusted settings
     FillMaterials(parser, pScene);
 
-        // Apply unitsize scale calculation
-        pScene->mRootNode->mTransformation *= aiMatrix4x4(parser.mUnitSize, 0,  0,  0,
-                                                          0,  parser.mUnitSize,  0,  0,
-                                                          0,  0,  parser.mUnitSize,  0,
-                                                          0,  0,  0,  1);
-        if( !ignoreUpDirection ) {
-        // Convert to Y_UP, if different orientation
-        if( parser.mUpDirection == ColladaParser::UP_X)
-            pScene->mRootNode->mTransformation *= aiMatrix4x4(
-                 0, -1,  0,  0,
-                 1,  0,  0,  0,
-                 0,  0,  1,  0,
-                 0,  0,  0,  1);
-        else if( parser.mUpDirection == ColladaParser::UP_Z)
-            pScene->mRootNode->mTransformation *= aiMatrix4x4(
-                 1,  0,  0,  0,
-                 0,  0,  1,  0,
-                 0, -1,  0,  0,
-                 0,  0,  0,  1);
-        }
+    // Apply unitsize scale calculation
+    pScene->mRootNode->mTransformation *= aiMatrix4x4(parser.mUnitSize, 0,  0,  0,
+                                                        0,  parser.mUnitSize,  0,  0,
+                                                        0,  0,  parser.mUnitSize,  0,
+                                                        0,  0,  0,  1);
+    if( !ignoreUpDirection ) {
+    // Convert to Y_UP, if different orientation
+    if( parser.mUpDirection == ColladaParser::UP_X)
+        pScene->mRootNode->mTransformation *= aiMatrix4x4(
+                0, -1,  0,  0,
+                1,  0,  0,  0,
+                0,  0,  1,  0,
+                0,  0,  0,  1);
+    else if( parser.mUpDirection == ColladaParser::UP_Z)
+        pScene->mRootNode->mTransformation *= aiMatrix4x4(
+                1,  0,  0,  0,
+                0,  0,  1,  0,
+                0, -1,  0,  0,
+                0,  0,  0,  1);
+    }
+
     // store all meshes
     StoreSceneMeshes( pScene);
 
@@ -294,7 +295,7 @@ void ColladaLoader::ResolveNodeInstances( const ColladaParser& pParser, const Co
             nd = FindNode(pParser.mRootNode, nodeInst.mNode);
         }
         if (!nd)
-            DefaultLogger::get()->error("Collada: Unable to resolve reference to instanced node " + nodeInst.mNode);
+            ASSIMP_LOG_ERROR_F("Collada: Unable to resolve reference to instanced node ", nodeInst.mNode);
 
         else {
             //  attach this node to the list of children
@@ -311,7 +312,7 @@ void ColladaLoader::ApplyVertexToEffectSemanticMapping(Collada::Sampler& sampler
     std::map<std::string, Collada::InputSemanticMapEntry>::const_iterator it = table.mMap.find(sampler.mUVChannel);
     if (it != table.mMap.end()) {
         if (it->second.mType != Collada::IT_Texcoord)
-            DefaultLogger::get()->error("Collada: Unexpected effect input mapping");
+            ASSIMP_LOG_ERROR("Collada: Unexpected effect input mapping");
 
         sampler.mUVId = it->second.mSet;
     }
@@ -327,7 +328,7 @@ void ColladaLoader::BuildLightsForNode( const ColladaParser& pParser, const Coll
         ColladaParser::LightLibrary::const_iterator srcLightIt = pParser.mLightLibrary.find( lid.mLight);
         if( srcLightIt == pParser.mLightLibrary.end())
         {
-            DefaultLogger::get()->warn("Collada: Unable to find light for ID \"" + lid.mLight + "\". Skipping.");
+            ASSIMP_LOG_WARN_F("Collada: Unable to find light for ID \"" , lid.mLight , "\". Skipping.");
             continue;
         }
         const Collada::Light* srcLight = &srcLightIt->second;
@@ -395,14 +396,14 @@ void ColladaLoader::BuildCamerasForNode( const ColladaParser& pParser, const Col
         ColladaParser::CameraLibrary::const_iterator srcCameraIt = pParser.mCameraLibrary.find( cid.mCamera);
         if( srcCameraIt == pParser.mCameraLibrary.end())
         {
-            DefaultLogger::get()->warn("Collada: Unable to find camera for ID \"" + cid.mCamera + "\". Skipping.");
+            ASSIMP_LOG_WARN_F("Collada: Unable to find camera for ID \"" , cid.mCamera , "\". Skipping.");
             continue;
         }
         const Collada::Camera* srcCamera = &srcCameraIt->second;
 
         // orthographic cameras not yet supported in Assimp
         if (srcCamera->mOrtho) {
-            DefaultLogger::get()->warn("Collada: Orthographic cameras are not supported.");
+            ASSIMP_LOG_WARN("Collada: Orthographic cameras are not supported.");
         }
 
         // now fill our ai data structure
@@ -472,7 +473,7 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll
 
             if( !srcMesh)
             {
-                DefaultLogger::get()->warn( format() << "Collada: Unable to find geometry for ID \"" << mid.mMeshOrController << "\". Skipping." );
+                ASSIMP_LOG_WARN_F( "Collada: Unable to find geometry for ID \"", mid.mMeshOrController, "\". Skipping." );
                 continue;
             }
         } else
@@ -501,7 +502,8 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll
             }
             else
             {
-                DefaultLogger::get()->warn( format() << "Collada: No material specified for subgroup <" << submesh.mMaterial << "> in geometry <" << mid.mMeshOrController << ">." );
+                ASSIMP_LOG_WARN_F( "Collada: No material specified for subgroup <", submesh.mMaterial, "> in geometry <",
+                    mid.mMeshOrController, ">." );
                 if( !mid.mMaterials.empty() )
                     meshMaterial = mid.mMaterials.begin()->second.mMatName;
             }
@@ -739,10 +741,6 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
     // create bones if given
     if( pSrcController && pSrcController->mType == Collada::Skin)
     {
-        // refuse if the vertex count does not match
-//      if( pSrcController->mWeightCounts.size() != dstMesh->mNumVertices)
-//          throw DeadlyImportError( "Joint Controller vertex count does not match mesh vertex count");
-
         // resolve references - joint names
         const Collada::Accessor& jointNamesAcc = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, pSrcController->mJointNameSource);
         const Collada::Data& jointNames = pParser.ResolveLibraryReference( pParser.mDataLibrary, jointNamesAcc.mSource);
@@ -874,7 +872,7 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
             if( bnode)
                 bone->mName.Set( FindNameForNode( bnode));
             else
-                DefaultLogger::get()->warn( format() << "ColladaLoader::CreateMesh(): could not find corresponding node for joint \"" << bone->mName.data << "\"." );
+                ASSIMP_LOG_WARN_F( "ColladaLoader::CreateMesh(): could not find corresponding node for joint \"", bone->mName.data, "\"." );
 
             // and insert bone
             dstMesh->mBones[boneCount++] = bone;
@@ -955,7 +953,7 @@ void ColladaLoader::StoreSceneMaterials( aiScene* pScene)
 // Stores all animations
 void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pParser)
 {
-    // recursivly collect all animations from the collada scene
+    // recursively collect all animations from the collada scene
     StoreAnimations( pScene, pParser, &pParser.mAnims, "");
 
     // catch special case: many animations with the same length, each affecting only a single node.
@@ -970,7 +968,8 @@ void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pPars
             for( size_t b = a+1; b < mAnims.size(); ++b)
             {
                 aiAnimation* other = mAnims[b];
-                if( other->mNumChannels == 1 && other->mDuration == templateAnim->mDuration && other->mTicksPerSecond == templateAnim->mTicksPerSecond )
+                if( other->mNumChannels == 1 && other->mDuration == templateAnim->mDuration && 
+                        other->mTicksPerSecond == templateAnim->mTicksPerSecond )
                     collectedAnimIndices.push_back( b);
             }
 
@@ -1175,9 +1174,8 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
                 else if( subElement == "Z")
                     entry.mSubElement = 2;
                 else
-                    DefaultLogger::get()->warn( format() << "Unknown anim subelement <" << subElement << ">. Ignoring" );
-            } else
-            {
+                    ASSIMP_LOG_WARN_F( "Unknown anim subelement <", subElement, ">. Ignoring" );
+            } else {
                 // no subelement following, transformId is remaining string
                 entry.mTransformId = srcChannel.mTarget.substr( slashPos+1);
             }
@@ -1406,7 +1404,7 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
               anims.push_back( dstAnim);
         } else
         {
-          DefaultLogger::get()->warn( "Collada loader: found empty animation channel, ignored. Please check your exporter.");
+            ASSIMP_LOG_WARN( "Collada loader: found empty animation channel, ignored. Please check your exporter.");
         }
 
         if( !entries.empty() && entries.front().mTimeAccessor->mCount > 0 )
@@ -1561,7 +1559,7 @@ void ColladaLoader::AddTexture ( aiMaterial& mat, const ColladaParser& pParser,
             }
         }
         if (-1 == map) {
-            DefaultLogger::get()->warn("Collada: unable to determine UV channel for texture");
+            ASSIMP_LOG_WARN("Collada: unable to determine UV channel for texture");
             map = 0;
         }
     }
@@ -1598,7 +1596,7 @@ void ColladaLoader::FillMaterials( const ColladaParser& pParser, aiScene* /*pSce
                 break;
 
             default:
-                DefaultLogger::get()->warn("Collada: Unrecognized shading mode, using gouraud shading");
+                ASSIMP_LOG_WARN("Collada: Unrecognized shading mode, using gouraud shading");
                 shadeMode = aiShadingMode_Gouraud;
                 break;
             }
@@ -1657,9 +1655,10 @@ void ColladaLoader::FillMaterials( const ColladaParser& pParser, aiScene* /*pSce
         }
 
         // add textures, if given
-        if( !effect.mTexAmbient.mName.empty())
-             /* It is merely a lightmap */
-            AddTexture( mat, pParser, effect, effect.mTexAmbient, aiTextureType_LIGHTMAP);
+        if (!effect.mTexAmbient.mName.empty()) {
+            // It is merely a light-map
+            AddTexture(mat, pParser, effect, effect.mTexAmbient, aiTextureType_LIGHTMAP);
+        }
 
         if( !effect.mTexEmissive.mName.empty())
             AddTexture( mat, pParser, effect, effect.mTexEmissive, aiTextureType_EMISSIVE);
@@ -1687,8 +1686,8 @@ void ColladaLoader::BuildMaterials( ColladaParser& pParser, aiScene* /*pScene*/)
 {
     newMats.reserve(pParser.mMaterialLibrary.size());
 
-    for( ColladaParser::MaterialLibrary::const_iterator matIt = pParser.mMaterialLibrary.begin(); matIt != pParser.mMaterialLibrary.end(); ++matIt)
-    {
+    for( ColladaParser::MaterialLibrary::const_iterator matIt = pParser.mMaterialLibrary.begin(); 
+        matIt != pParser.mMaterialLibrary.end(); ++matIt) {
         const Collada::Material& material = matIt->second;
         // a material is only a reference to an effect
         ColladaParser::EffectLibrary::iterator effIt = pParser.mEffectLibrary.find( material.mEffect);
@@ -1752,11 +1751,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pPars
     ColladaParser::ImageLibrary::const_iterator imIt = pParser.mImageLibrary.find( name);
     if( imIt == pParser.mImageLibrary.end())
     {
-        //missing texture should not stop the conversion
-        //throw DeadlyImportError( format() <<
-        //    "Collada: Unable to resolve effect texture entry \"" << pName << "\", ended up at ID \"" << name << "\"." );
-
-        DefaultLogger::get()->warn("Collada: Unable to resolve effect texture entry \"" + pName + "\", ended up at ID \"" + name + "\".");
+        ASSIMP_LOG_WARN_F("Collada: Unable to resolve effect texture entry \"", pName, "\", ended up at ID \"", name, "\".");
 
         //set default texture file name
         result.Set(name + ".jpg");
@@ -1775,7 +1770,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pPars
 
         // setup format hint
         if (imIt->second.mEmbeddedFormat.length() > 3) {
-            DefaultLogger::get()->warn("Collada: texture format hint is too long, truncating to 3 characters");
+            ASSIMP_LOG_WARN("Collada: texture format hint is too long, truncating to 3 characters");
         }
         strncpy(tex->achFormatHint,imIt->second.mEmbeddedFormat.c_str(),3);
 
@@ -1787,7 +1782,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pPars
 
         // TODO: check the possibility of using the flag "AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING"
         // In FBX files textures are now stored internally by Assimp with their filename included
-        // Now Assimp can lookup thru the loaded textures after all data is processed
+        // Now Assimp can lookup through the loaded textures after all data is processed
         // We need to load all textures before referencing them, as FBX file format order may reference a texture before loading it
         // This may occur on this case too, it has to be studied
         // setup texture reference string
@@ -1811,7 +1806,7 @@ void ColladaLoader::ConvertPath (aiString& ss)
 {
     // TODO: collada spec, p 22. Handle URI correctly.
     // For the moment we're just stripping the file:// away to make it work.
-    // Windoes doesn't seem to be able to find stuff like
+    // Windows doesn't seem to be able to find stuff like
     // 'file://..\LWO\LWO2\MappingModes\earthSpherical.jpg'
     if (0 == strncmp(ss.data,"file://",7))
     {
@@ -1822,10 +1817,13 @@ void ColladaLoader::ConvertPath (aiString& ss)
 
   // Maxon Cinema Collada Export writes "file:///C:\andsoon" with three slashes...
   // I need to filter it without destroying linux paths starting with "/somewhere"
-  if( ss.data[0] == '/' && isalpha( ss.data[1]) && ss.data[2] == ':' )
-  {
-    ss.length--;
-    memmove( ss.data, ss.data+1, ss.length);
+#if defined( _MSC_VER )
+    if( ss.data[0] == '/' && isalpha( (unsigned char) ss.data[1]) && ss.data[2] == ':' ) {
+#else
+    if (ss.data[ 0 ] == '/' && isalpha( ss.data[ 1 ] ) && ss.data[ 2 ] == ':') {
+#endif
+    --ss.length;
+    ::memmove( ss.data, ss.data+1, ss.length);
     ss.data[ss.length] = 0;
   }
 
@@ -1875,9 +1873,9 @@ const std::string& ColladaLoader::ReadString( const Collada::Accessor& pAccessor
 void ColladaLoader::CollectNodes( const aiNode* pNode, std::vector<const aiNode*>& poNodes) const
 {
     poNodes.push_back( pNode);
-
-    for( size_t a = 0; a < pNode->mNumChildren; ++a)
-        CollectNodes( pNode->mChildren[a], poNodes);
+    for (size_t a = 0; a < pNode->mNumChildren; ++a) {
+        CollectNodes(pNode->mChildren[a], poNodes);
+    }
 }
 
 // ------------------------------------------------------------------------------------------------

+ 36 - 37
code/ColladaParser.cpp

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

+ 6 - 6
code/ComputeUVMappingProcess.cpp

@@ -99,7 +99,7 @@ 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");
+    ASSIMP_LOG_ERROR("Unable to compute UV coordinates, no free UV slot found");
     return UINT_MAX;
 }
 
@@ -384,13 +384,13 @@ void ComputeUVMappingProcess::ComputePlaneMapping(aiMesh* mesh,const aiVector3D&
 // ------------------------------------------------------------------------------------------------
 void ComputeUVMappingProcess::ComputeBoxMapping( aiMesh*, aiVector3D* )
 {
-    DefaultLogger::get()->error("Mapping type currently not implemented");
+    ASSIMP_LOG_ERROR("Mapping type currently not implemented");
 }
 
 // ------------------------------------------------------------------------------------------------
 void ComputeUVMappingProcess::Execute( aiScene* pScene)
 {
-    DefaultLogger::get()->debug("GenUVCoordsProcess begin");
+    ASSIMP_LOG_DEBUG("GenUVCoordsProcess begin");
     char buffer[1024];
 
     if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT)
@@ -418,7 +418,7 @@ void ComputeUVMappingProcess::Execute( aiScene* pScene)
                             TextureTypeToString((aiTextureType)prop->mSemantic),prop->mIndex,
                             MappingTypeToString(mapping));
 
-                        DefaultLogger::get()->info(buffer);
+                        ASSIMP_LOG_INFO(buffer);
                     }
 
                     if (aiTextureMapping_OTHER == mapping)
@@ -485,7 +485,7 @@ void ComputeUVMappingProcess::Execute( aiScene* pScene)
                             }
                             if (m && idx != outIdx)
                             {
-                                DefaultLogger::get()->warn("UV index mismatch. Not all meshes assigned to "
+                                ASSIMP_LOG_WARN("UV index mismatch. Not all meshes assigned to "
                                     "this material have equal numbers of UV channels. The UV index stored in  "
                                     "the material structure does therefore not apply for all meshes. ");
                             }
@@ -502,5 +502,5 @@ void ComputeUVMappingProcess::Execute( aiScene* pScene)
             }
         }
     }
-    DefaultLogger::get()->debug("GenUVCoordsProcess finished");
+    ASSIMP_LOG_DEBUG("GenUVCoordsProcess finished");
 }

+ 9 - 9
code/ConvertToLHProcess.cpp

@@ -85,7 +85,7 @@ void MakeLeftHandedProcess::Execute( aiScene* pScene)
 {
     // Check for an existent root node to proceed
     ai_assert(pScene->mRootNode != NULL);
-    DefaultLogger::get()->debug("MakeLeftHandedProcess begin");
+    ASSIMP_LOG_DEBUG("MakeLeftHandedProcess begin");
 
     // recursively convert all the nodes
     ProcessNode( pScene->mRootNode, aiMatrix4x4());
@@ -110,7 +110,7 @@ void MakeLeftHandedProcess::Execute( aiScene* pScene)
             ProcessAnimation( nodeAnim);
         }
     }
-    DefaultLogger::get()->debug("MakeLeftHandedProcess finished");
+    ASSIMP_LOG_DEBUG("MakeLeftHandedProcess finished");
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -140,7 +140,7 @@ void MakeLeftHandedProcess::ProcessNode( aiNode* pNode, const aiMatrix4x4& pPare
 // Converts a single mesh to left handed coordinates.
 void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh) {
     if ( nullptr == pMesh ) {
-        DefaultLogger::get()->error( "Nullptr to mesh found." );
+        ASSIMP_LOG_ERROR( "Nullptr to mesh found." );
         return;
     }
     // mirror positions, normals and stuff along the Z axis
@@ -180,7 +180,7 @@ void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh) {
 // Converts a single material to left handed coordinates.
 void MakeLeftHandedProcess::ProcessMaterial( aiMaterial* _mat) {
     if ( nullptr == _mat ) {
-        DefaultLogger::get()->error( "Nullptr to aiMaterial found." );
+        ASSIMP_LOG_ERROR( "Nullptr to aiMaterial found." );
         return;
     }
 
@@ -245,13 +245,13 @@ bool FlipUVsProcess::IsActive( unsigned int pFlags) const
 // Executes the post processing step on the given imported data.
 void FlipUVsProcess::Execute( aiScene* pScene)
 {
-    DefaultLogger::get()->debug("FlipUVsProcess begin");
+    ASSIMP_LOG_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");
+    ASSIMP_LOG_DEBUG("FlipUVsProcess finished");
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -262,7 +262,7 @@ void FlipUVsProcess::ProcessMaterial (aiMaterial* _mat)
     for (unsigned int a = 0; a < mat->mNumProperties;++a)   {
         aiMaterialProperty* prop = mat->mProperties[a];
         if( !prop ) {
-            DefaultLogger::get()->debug( "Property is null" );
+            ASSIMP_LOG_DEBUG( "Property is null" );
             continue;
         }
 
@@ -319,10 +319,10 @@ bool FlipWindingOrderProcess::IsActive( unsigned int pFlags) const
 // Executes the post processing step on the given imported data.
 void FlipWindingOrderProcess::Execute( aiScene* pScene)
 {
-    DefaultLogger::get()->debug("FlipWindingOrderProcess begin");
+    ASSIMP_LOG_DEBUG("FlipWindingOrderProcess begin");
     for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
         ProcessMesh(pScene->mMeshes[i]);
-    DefaultLogger::get()->debug("FlipWindingOrderProcess finished");
+    ASSIMP_LOG_DEBUG("FlipWindingOrderProcess finished");
 }
 
 // ------------------------------------------------------------------------------------------------

+ 1 - 1
code/D3MFExporter.cpp

@@ -222,7 +222,7 @@ void D3MFExporter::writeMetaData() {
         return;
     }
 
-    const aiString *key;
+	const aiString *key = nullptr;
     const aiMetadataEntry *entry(nullptr);
     for ( size_t i = 0; i < numMetaEntries; ++i ) {
         mScene->mMetaData->Get( i, key, entry );

+ 3 - 3
code/D3MFImporter.cpp

@@ -115,10 +115,10 @@ public:
         // import the metadata
         if ( !mMetaData.empty() ) {
             const size_t numMeta( mMetaData.size() );
-            scene->mMetaData = aiMetadata::Alloc( numMeta );
+            scene->mMetaData = aiMetadata::Alloc(static_cast<unsigned int>( numMeta ) );
             for ( size_t i = 0; i < numMeta; ++i ) {
                 aiString val( mMetaData[ i ].value );
-                scene->mMetaData->Set( i, mMetaData[ i ].name, val );
+                scene->mMetaData->Set(static_cast<unsigned int>( i ), mMetaData[ i ].name, val );
             }
         }
 
@@ -396,7 +396,7 @@ private:
                 return false;
             }
         }
-        DefaultLogger::get()->error("unexpected EOF, expected closing <" + closeTag + "> tag");
+        ASSIMP_LOG_ERROR("unexpected EOF, expected closing <" + closeTag + "> tag");
 
         return false;
     }

+ 1 - 1
code/D3MFOpcPackage.cpp

@@ -465,7 +465,7 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile)
                 }
             }
 
-            DefaultLogger::get()->debug(rootFile);
+            ASSIMP_LOG_DEBUG(rootFile);
 
             mRootStream = mZipArchive->Open(rootFile.c_str());
             ai_assert( mRootStream != nullptr );

+ 1 - 1
code/DXFHelper.h

@@ -146,7 +146,7 @@ public:
                 for(;splitter->length() && splitter->at(0) != '}'; splitter++, cnt++);
 
                 splitter++;
-                DefaultLogger::get()->debug((Formatter::format("DXF: skipped over control group ("),cnt," lines)"));
+                ASSIMP_LOG_DEBUG((Formatter::format("DXF: skipped over control group ("),cnt," lines)"));
             }
         } catch(std::logic_error&) {
             ai_assert(!splitter);

+ 32 - 59
code/DXFLoader.cpp

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

+ 5 - 7
code/DeboneProcess.cpp

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

+ 7 - 7
code/DefaultIOSystem.cpp

@@ -76,11 +76,11 @@ bool DefaultIOSystem::Exists( const char* pFile) const
 #ifdef _WIN32
     wchar_t fileName16[PATHLIMIT];
 
-    bool isUnicode = IsTextUnicode(pFile, static_cast<int>(strlen(pFile)), NULL);
+    bool isUnicode = IsTextUnicode(pFile, static_cast<int>(strlen(pFile)), NULL) != 0;
     if (isUnicode) {
 
         MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, pFile, -1, fileName16, PATHLIMIT);
-        struct _stat64 filestat;
+        struct __stat64 filestat;
         if (0 != _wstat64(fileName16, &filestat)) {
             return false;
         }
@@ -110,7 +110,7 @@ IOStream* DefaultIOSystem::Open( const char* strFile, const char* strMode)
     FILE* file;
 #ifdef _WIN32
     wchar_t fileName16[PATHLIMIT];
-    bool isUnicode = IsTextUnicode(strFile, static_cast<int>(strlen(strFile)), NULL );
+    bool isUnicode = IsTextUnicode(strFile, static_cast<int>(strlen(strFile)), NULL) != 0;
     if (isUnicode) {
         MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, strFile, -1, fileName16, PATHLIMIT);
         std::string mode8(strMode);
@@ -158,7 +158,7 @@ inline static void MakeAbsolutePath (const char* in, char* _out)
 {
     ai_assert(in && _out);
 #if defined( _MSC_VER ) || defined( __MINGW32__ )
-    bool isUnicode = IsTextUnicode(in, static_cast<int>(strlen(in)), NULL);
+    bool isUnicode = IsTextUnicode(in, static_cast<int>(strlen(in)), NULL) != 0;
     if (isUnicode) {
         wchar_t out16[PATHLIMIT];
         wchar_t in16[PATHLIMIT];
@@ -170,7 +170,7 @@ inline static void MakeAbsolutePath (const char* in, char* _out)
         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));
+            ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in));
             strcpy(_out, in);
         }
 
@@ -179,7 +179,7 @@ inline static void MakeAbsolutePath (const char* in, char* _out)
         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));
+            ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in));
             strcpy(_out, in);
         }
     }
@@ -189,7 +189,7 @@ inline static void MakeAbsolutePath (const char* in, char* _out)
     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));
+        ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in));
         strcpy(_out,in);
     }
 #endif

+ 3 - 5
code/EmbedTexturesProcess.cpp

@@ -93,9 +93,7 @@ void EmbedTexturesProcess::Execute(aiScene* pScene) {
         }
     }
 
-    char stringBuffer[128];
-    ::ai_snprintf(stringBuffer, 128, "EmbedTexturesProcess finished. Embedded %u textures.", embeddedTexturesCount);
-    DefaultLogger::get()->info(stringBuffer);
+    ASSIMP_LOG_INFO_F("EmbedTexturesProcess finished. Embedded ", embeddedTexturesCount, " textures." );
 }
 
 bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const {
@@ -105,7 +103,7 @@ bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const {
     // Test path directly
     std::ifstream file(imagePath, std::ios::binary | std::ios::ate);
     if ((imageSize = file.tellg()) == std::streampos(-1)) {
-        DefaultLogger::get()->warn("EmbedTexturesProcess: Cannot find image: " + imagePath + ". Will try to find it in root folder.");
+        ASSIMP_LOG_WARN_F("EmbedTexturesProcess: Cannot find image: ", imagePath, ". Will try to find it in root folder.");
 
         // Test path in root path
         imagePath = mRootPath + path;
@@ -115,7 +113,7 @@ bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const {
             imagePath = mRootPath + path.substr(path.find_last_of("\\/") + 1u);
             file.open(imagePath, std::ios::binary | std::ios::ate);
             if ((imageSize = file.tellg()) == std::streampos(-1)) {
-                DefaultLogger::get()->error("EmbedTexturesProcess: Unable to embed texture: " + path + ".");
+                ASSIMP_LOG_ERROR_F("EmbedTexturesProcess: Unable to embed texture: ", path, ".");
                 return false;
             }
         }

+ 18 - 11
code/Exporter.cpp

@@ -62,6 +62,7 @@ Here we implement only the C++ interface (Assimp::Exporter).
 #include "JoinVerticesProcess.h"
 #include "MakeVerboseFormat.h"
 #include "ConvertToLHProcess.h"
+#include "PretransformVertices.h"
 #include <assimp/Exceptional.h>
 #include "ScenePrivate.h"
 #include <memory>
@@ -149,13 +150,13 @@ Exporter::ExportFormatEntry gExporters[] =
 #endif
 
 #ifndef ASSIMP_BUILD_NO_GLTF_EXPORTER
-    Exporter::ExportFormatEntry( "gltf", "GL Transmission Format", "gltf", &ExportSceneGLTF,
+    Exporter::ExportFormatEntry( "gltf2", "GL Transmission Format v. 2", "gltf", &ExportSceneGLTF2,
         aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
-    Exporter::ExportFormatEntry( "glb", "GL Transmission Format (binary)", "glb", &ExportSceneGLB,
+    Exporter::ExportFormatEntry( "glb2", "GL Transmission Format v. 2 (binary)", "glb", &ExportSceneGLB2,
         aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
-    Exporter::ExportFormatEntry( "gltf2", "GL Transmission Format v. 2", "gltf2", &ExportSceneGLTF2,
+    Exporter::ExportFormatEntry( "gltf", "GL Transmission Format", "gltf", &ExportSceneGLTF,
         aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
-    Exporter::ExportFormatEntry( "glb2", "GL Transmission Format v. 2 (binary)", "glb2", &ExportSceneGLB2,
+    Exporter::ExportFormatEntry( "glb", "GL Transmission Format (binary)", "glb", &ExportSceneGLB,
         aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
 #endif
 
@@ -363,7 +364,7 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c
                     }
 
                     if (verbosify || (exp.mEnforcePP & aiProcess_JoinIdenticalVertices)) {
-                        DefaultLogger::get()->debug("export: Scene data not in verbose format, applying MakeVerboseFormat step first");
+                        ASSIMP_LOG_DEBUG("export: Scene data not in verbose format, applying MakeVerboseFormat step first");
 
                         MakeVerboseFormatProcess proc;
                         proc.Execute(scenecopy.get());
@@ -397,6 +398,11 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c
                         }
                     }
 
+                    bool exportPointCloud(false);
+                    if (nullptr != pProperties) {
+                        exportPointCloud = pProperties->GetPropertyBool(AI_CONFIG_EXPORT_POINT_CLOUDS);
+                    }
+
                     // dispatch other processes
                     for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
                         BaseProcess* const p = pimpl->mPostProcessingSteps[a];
@@ -405,7 +411,9 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c
                             && !dynamic_cast<FlipUVsProcess*>(p)
                             && !dynamic_cast<FlipWindingOrderProcess*>(p)
                             && !dynamic_cast<MakeLeftHandedProcess*>(p)) {
-
+                            if (dynamic_cast<PretransformVertices*>(p) && exportPointCloud) {
+                                continue;
+                            }
                             p->Execute(scenecopy.get());
                         }
                     }
@@ -441,7 +449,6 @@ const char* Exporter::GetErrorString() const {
     return pimpl->mError.c_str();
 }
 
-
 // ------------------------------------------------------------------------------------------------
 void Exporter::FreeBlob() {
     delete pimpl->blob;
@@ -470,7 +477,7 @@ size_t Exporter::GetExportFormatCount() const {
 // ------------------------------------------------------------------------------------------------
 const aiExportFormatDesc* Exporter::GetExportFormatDescription( size_t index ) const {
     if (index >= GetExportFormatCount()) {
-        return NULL;
+        return nullptr;
     }
 
     // Return from static storage if the requested index is built-in.
@@ -495,7 +502,8 @@ aiReturn Exporter::RegisterExporter(const ExportFormatEntry& desc) {
 
 // ------------------------------------------------------------------------------------------------
 void Exporter::UnregisterExporter(const char* id) {
-    for(std::vector<ExportFormatEntry>::iterator it = pimpl->mExporters.begin(); it != pimpl->mExporters.end(); ++it) {
+    for(std::vector<ExportFormatEntry>::iterator it = pimpl->mExporters.begin();
+            it != pimpl->mExporters.end(); ++it) {
         if (!strcmp((*it).mDescription.id,id)) {
             pimpl->mExporters.erase(it);
             break;
@@ -531,8 +539,7 @@ bool ExportProperties::SetPropertyFloat(const char* szName, ai_real iValue) {
 
 // ------------------------------------------------------------------------------------------------
 // Set a configuration property
-bool ExportProperties :: SetPropertyString(const char* szName, const std::string& value)
-{
+bool ExportProperties::SetPropertyString(const char* szName, const std::string& value) {
     return SetGenericProperty<std::string>(mStringProperties, szName,value);
 }
 

+ 2 - 2
code/FBXBinaryTokenizer.cpp

@@ -448,8 +448,8 @@ void TokenizeBinary(TokenList& output_tokens, const char* input, unsigned int le
 	/*Result ignored*/ ReadByte(input, cursor, input + length);
 	const uint32_t version = ReadWord(input, cursor, input + length);
 	const bool is64bits = version >= 7500;
-    while (cursor < input + length)
-    {
+    const char *end = input + length;
+    while (cursor < end ) {
 		if (!ReadScope(output_tokens, input, cursor, input + length, is64bits)) {
             break;
         }

+ 58 - 49
code/FBXConverter.cpp

@@ -874,7 +874,7 @@ void Converter::ConvertModel( const Model& model, aiNode& nd, const aiMatrix4x4&
 
         const MeshGeometry* const mesh = dynamic_cast< const MeshGeometry* >( geo );
         if ( mesh ) {
-            const std::vector<unsigned int>& indices = ConvertMesh( *mesh, model, node_global_transform );
+            const std::vector<unsigned int>& indices = ConvertMesh( *mesh, model, node_global_transform, nd);
             std::copy( indices.begin(), indices.end(), std::back_inserter( meshes ) );
         }
         else {
@@ -891,7 +891,7 @@ void Converter::ConvertModel( const Model& model, aiNode& nd, const aiMatrix4x4&
 }
 
 std::vector<unsigned int> Converter::ConvertMesh( const MeshGeometry& mesh, const Model& model,
-    const aiMatrix4x4& node_global_transform )
+    const aiMatrix4x4& node_global_transform, aiNode& nd)
 {
     std::vector<unsigned int> temp;
 
@@ -915,17 +915,17 @@ std::vector<unsigned int> Converter::ConvertMesh( const MeshGeometry& mesh, cons
         const MatIndexArray::value_type base = mindices[ 0 ];
         for( MatIndexArray::value_type index : mindices ) {
             if ( index != base ) {
-                return ConvertMeshMultiMaterial( mesh, model, node_global_transform );
+                return ConvertMeshMultiMaterial( mesh, model, node_global_transform, nd);
             }
         }
     }
 
     // faster code-path, just copy the data
-    temp.push_back( ConvertMeshSingleMaterial( mesh, model, node_global_transform ) );
+    temp.push_back( ConvertMeshSingleMaterial( mesh, model, node_global_transform, nd) );
     return temp;
 }
 
-aiMesh* Converter::SetupEmptyMesh( const MeshGeometry& mesh )
+aiMesh* Converter::SetupEmptyMesh( const MeshGeometry& mesh, aiNode& nd)
 {
     aiMesh* const out_mesh = new aiMesh();
     meshes.push_back( out_mesh );
@@ -940,15 +940,19 @@ aiMesh* Converter::SetupEmptyMesh( const MeshGeometry& mesh )
     if ( name.length() ) {
         out_mesh->mName.Set( name );
     }
+    else
+    {
+        out_mesh->mName = nd.mName;
+    }
 
     return out_mesh;
 }
 
 unsigned int Converter::ConvertMeshSingleMaterial( const MeshGeometry& mesh, const Model& model,
-    const aiMatrix4x4& node_global_transform )
+    const aiMatrix4x4& node_global_transform, aiNode& nd)
 {
     const MatIndexArray& mindices = mesh.GetMaterialIndices();
-    aiMesh* const out_mesh = SetupEmptyMesh( mesh );
+    aiMesh* const out_mesh = SetupEmptyMesh(mesh, nd);
 
     const std::vector<aiVector3D>& vertices = mesh.GetVertices();
     const std::vector<unsigned int>& faces = mesh.GetFaceIndexCounts();
@@ -1072,7 +1076,7 @@ unsigned int Converter::ConvertMeshSingleMaterial( const MeshGeometry& mesh, con
 }
 
 std::vector<unsigned int> Converter::ConvertMeshMultiMaterial( const MeshGeometry& mesh, const Model& model,
-    const aiMatrix4x4& node_global_transform )
+    const aiMatrix4x4& node_global_transform, aiNode& nd)
 {
     const MatIndexArray& mindices = mesh.GetMaterialIndices();
     ai_assert( mindices.size() );
@@ -1083,7 +1087,7 @@ std::vector<unsigned int> Converter::ConvertMeshMultiMaterial( const MeshGeometr
     for( MatIndexArray::value_type index : mindices ) {
         if ( had.find( index ) == had.end() ) {
 
-            indices.push_back( ConvertMeshMultiMaterial( mesh, model, index, node_global_transform ) );
+            indices.push_back( ConvertMeshMultiMaterial( mesh, model, index, node_global_transform, nd) );
             had.insert( index );
         }
     }
@@ -1093,9 +1097,10 @@ std::vector<unsigned int> Converter::ConvertMeshMultiMaterial( const MeshGeometr
 
 unsigned int Converter::ConvertMeshMultiMaterial( const MeshGeometry& mesh, const Model& model,
     MatIndexArray::value_type index,
-    const aiMatrix4x4& node_global_transform )
+    const aiMatrix4x4& node_global_transform,
+    aiNode& nd)
 {
-    aiMesh* const out_mesh = SetupEmptyMesh( mesh );
+    aiMesh* const out_mesh = SetupEmptyMesh(mesh, nd);
 
     const MatIndexArray& mindices = mesh.GetMaterialIndices();
     const std::vector<aiVector3D>& vertices = mesh.GetVertices();
@@ -1521,6 +1526,46 @@ unsigned int Converter::ConvertVideo( const Video& video )
     return static_cast<unsigned int>( textures.size() - 1 );
 }
 
+aiString Converter::GetTexturePath(const Texture* tex)
+{
+    aiString path;
+    path.Set(tex->RelativeFilename());
+
+    const Video* media = tex->Media();
+    if (media != nullptr) {
+        bool textureReady = false; //tells if our texture is ready (if it was loaded or if it was found)
+        unsigned int index;
+
+        VideoMap::const_iterator it = textures_converted.find(media);
+        if (it != textures_converted.end()) {
+            index = (*it).second;
+            textureReady = true;
+        }
+        else {
+            if (media->ContentLength() > 0) {
+                index = ConvertVideo(*media);
+                textures_converted[media] = index;
+                textureReady = true;
+            }
+        }
+
+        // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture), if the texture is ready
+        if (doc.Settings().useLegacyEmbeddedTextureNaming) {
+            if (textureReady) {
+                // TODO: check the possibility of using the flag "AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING"
+                // In FBX files textures are now stored internally by Assimp with their filename included
+                // Now Assimp can lookup through the loaded textures after all data is processed
+                // We need to load all textures before referencing them, as FBX file format order may reference a texture before loading it
+                // This may occur on this case too, it has to be studied
+                path.data[0] = '*';
+                path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index);
+            }
+        }
+    }
+
+    return path;
+}
+
 void Converter::TrySetTextureProperties( aiMaterial* out_mat, const TextureMap& textures,
     const std::string& propName,
     aiTextureType target, const MeshGeometry* const mesh )
@@ -1533,41 +1578,7 @@ void Converter::TrySetTextureProperties( aiMaterial* out_mat, const TextureMap&
     const Texture* const tex = ( *it ).second;
     if ( tex != 0 )
     {
-        aiString path;
-        path.Set( tex->RelativeFilename() );
-
-        const Video* media = tex->Media();
-        if (media != 0) {
-			bool textureReady = false; //tells if our texture is ready (if it was loaded or if it was found)
-			unsigned int index;
-
-			VideoMap::const_iterator it = textures_converted.find(media);
-			if (it != textures_converted.end()) {
-				index = (*it).second;
-				textureReady = true;
-			}
-			else {
-				if (media->ContentLength() > 0) {
-					index = ConvertVideo(*media);
-					textures_converted[media] = index;
-					textureReady = true;
-				}
-			}
-
-			// setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture), if the texture is ready
-			if (doc.Settings().useLegacyEmbeddedTextureNaming) {
-                if (textureReady) {
-                    // TODO: check the possibility of using the flag "AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING"
-                    // In FBX files textures are now stored internally by Assimp with their filename included
-                    // Now Assimp can lookup thru the loaded textures after all data is processed
-                    // We need to load all textures before referencing them, as FBX file format order may reference a texture before loading it
-                    // This may occur on this case too, it has to be studied
-                    path.data[0] = '*';
-                    path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index);
-                }
-			}
-		}  
-
+        aiString path = GetTexturePath(tex);
         out_mat->AddProperty( &path, _AI_MATKEY_TEXTURE_BASE, target, 0 );
 
         aiUVTransform uvTrafo;
@@ -1691,9 +1702,7 @@ void Converter::TrySetTextureProperties( aiMaterial* out_mat, const LayeredTextu
     
         const Texture* const tex = ( *it ).second->getTexture(texIndex);
 
-        aiString path;
-        path.Set( tex->RelativeFilename() );
-
+        aiString path = GetTexturePath(tex);
         out_mat->AddProperty( &path, _AI_MATKEY_TEXTURE_BASE, target, texIndex );
 
         aiUVTransform uvTrafo;

+ 9 - 5
code/FBXConverter.h

@@ -172,23 +172,23 @@ private:
     // ------------------------------------------------------------------------------------------------
     // MeshGeometry -> aiMesh, return mesh index + 1 or 0 if the conversion failed
     std::vector<unsigned int> ConvertMesh(const MeshGeometry& mesh, const Model& model,
-        const aiMatrix4x4& node_global_transform);
+        const aiMatrix4x4& node_global_transform, aiNode& nd);
 
     // ------------------------------------------------------------------------------------------------
-    aiMesh* SetupEmptyMesh(const MeshGeometry& mesh);
+    aiMesh* SetupEmptyMesh(const MeshGeometry& mesh, aiNode& nd);
 
     // ------------------------------------------------------------------------------------------------
     unsigned int ConvertMeshSingleMaterial(const MeshGeometry& mesh, const Model& model,
-        const aiMatrix4x4& node_global_transform);
+        const aiMatrix4x4& node_global_transform, aiNode& nd);
 
     // ------------------------------------------------------------------------------------------------
     std::vector<unsigned int> ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model,
-        const aiMatrix4x4& node_global_transform);
+        const aiMatrix4x4& node_global_transform, aiNode& nd);
 
     // ------------------------------------------------------------------------------------------------
     unsigned int ConvertMeshMultiMaterial(const MeshGeometry& mesh, const Model& model,
         MatIndexArray::value_type index,
-        const aiMatrix4x4& node_global_transform);
+        const aiMatrix4x4& node_global_transform, aiNode& nd);
 
     // ------------------------------------------------------------------------------------------------
     static const unsigned int NO_MATERIAL_SEPARATION = /* std::numeric_limits<unsigned int>::max() */
@@ -228,6 +228,10 @@ private:
     // Video -> aiTexture
     unsigned int ConvertVideo(const Video& video);
 
+    // ------------------------------------------------------------------------------------------------
+    // convert embedded texture if necessary and return actual texture path
+    aiString GetTexturePath(const Texture* tex);
+
     // ------------------------------------------------------------------------------------------------
     void TrySetTextureProperties(aiMaterial* out_mat, const TextureMap& textures,
         const std::string& propName,

+ 4 - 4
code/FBXDocument.cpp

@@ -214,7 +214,7 @@ const Object* LazyObject::Get(bool dieOnError)
 
         // note: the error message is already formatted, so raw logging is ok
         if(!DefaultLogger::isNullLogger()) {
-            DefaultLogger::get()->error(ex.what());
+            ASSIMP_LOG_ERROR(ex.what());
         }
         return NULL;
     }
@@ -575,11 +575,11 @@ std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bo
     ai_assert( count != 0 );
     ai_assert( count <= MAX_CLASSNAMES);
 
-    size_t lenghts[MAX_CLASSNAMES];
+    size_t lengths[MAX_CLASSNAMES];
 
     const size_t c = count;
     for (size_t i = 0; i < c; ++i) {
-        lenghts[ i ] = strlen(classnames[i]);
+        lengths[ i ] = strlen(classnames[i]);
     }
 
     std::vector<const Connection*> temp;
@@ -597,7 +597,7 @@ std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bo
 
         for (size_t i = 0; i < c; ++i) {
             ai_assert(classnames[i]);
-            if(static_cast<size_t>(std::distance(key.begin(),key.end())) == lenghts[i] && !strncmp(classnames[i],obtype,lenghts[i])) {
+            if(static_cast<size_t>(std::distance(key.begin(),key.end())) == lengths[i] && !strncmp(classnames[i],obtype,lengths[i])) {
                 obtype = NULL;
                 break;
             }

+ 3 - 3
code/FBXDocumentUtil.cpp

@@ -79,7 +79,7 @@ void DOMError(const std::string& message, const Element* element /*= NULL*/)
 void DOMWarning(const std::string& message, const Token& token)
 {
     if(DefaultLogger::get()) {
-        DefaultLogger::get()->warn(Util::AddTokenText("FBX-DOM",message,&token));
+        ASSIMP_LOG_WARN(Util::AddTokenText("FBX-DOM",message,&token));
     }
 }
 
@@ -91,7 +91,7 @@ void DOMWarning(const std::string& message, const Element* element /*= NULL*/)
         return;
     }
     if(DefaultLogger::get()) {
-        DefaultLogger::get()->warn("FBX-DOM: " + message);
+        ASSIMP_LOG_WARN("FBX-DOM: " + message);
     }
 }
 
@@ -115,7 +115,7 @@ std::shared_ptr<const PropertyTable> GetPropertyTable(const Document& doc,
         }
     }
 
-    if(!Properties70) {
+    if(!Properties70 || !Properties70->Compound()) {
         if(!no_warn) {
             DOMWarning("property table (Properties70) not found",&element);
         }

+ 25 - 21
code/FBXExporter.cpp

@@ -71,7 +71,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 // https://code.blender.org/2013/08/fbx-binary-file-format-specification/
 // https://wiki.blender.org/index.php/User:Mont29/Foundation/FBX_File_Structure
 
-const double DEG = 57.29577951308232087679815481; // degrees per radian
+const ai_real DEG = ai_real( 57.29577951308232087679815481 ); // degrees per radian
 
 // some constants that we'll use for writing metadata
 namespace FBX {
@@ -450,7 +450,7 @@ void FBXExporter::WriteDocuments ()
     p.AddP70string("ActiveAnimStackName", ""); // should do this properly?
     doc.AddChild(p);
 
-    // UID for root node in scene heirarchy.
+    // UID for root node in scene hierarchy.
     // always set to 0 in the case of a single document.
     // not sure what happens if more than one document exists,
     // but that won't matter to us as we're exporting a single scene.
@@ -650,7 +650,7 @@ void FBXExporter::WriteDefinitions ()
     }
 
     // Model / FbxNode
-    // <~~ node heirarchy
+    // <~~ node hierarchy
     count = int32_t(count_nodes(mScene->mRootNode)) - 1; // (not counting root node)
     if (count) {
         n = FBX::Node("ObjectType", "Model");
@@ -980,9 +980,13 @@ aiMatrix4x4 get_world_transform(const aiNode* node, const aiScene* scene)
 
 int64_t to_ktime(double ticks, const aiAnimation* anim) {
     if (anim->mTicksPerSecond <= 0) {
-        return ticks * FBX::SECOND;
+        return static_cast<int64_t>(ticks) * FBX::SECOND;
     }
-    return (ticks / anim->mTicksPerSecond) * FBX::SECOND;
+    return (static_cast<int64_t>(ticks) / static_cast<int64_t>(anim->mTicksPerSecond)) * FBX::SECOND;
+}
+
+int64_t to_ktime(double time) {
+    return (static_cast<int64_t>(time * FBX::SECOND));
 }
 
 void FBXExporter::WriteObjects ()
@@ -1124,7 +1128,7 @@ void FBXExporter::WriteObjects ()
                 err << " has " << m->mNumUVComponents[uvi];
                 err << " components! Data will be preserved,";
                 err << " but may be incorrectly interpreted on load.";
-                DefaultLogger::get()->warn(err.str());
+                ASSIMP_LOG_WARN(err.str());
             }
             FBX::Node uv("LayerElementUV", int32_t(uvi));
             uv.Begin(outstream, binary, indent);
@@ -1223,7 +1227,7 @@ void FBXExporter::WriteObjects ()
         // it's all about this material
         aiMaterial* m = mScene->mMaterials[i];
 
-        // these are used to recieve material data
+        // these are used to receive material data
         float f; aiColor3D c;
 
         // start the node record
@@ -1311,7 +1315,7 @@ void FBXExporter::WriteObjects ()
         // Now the legacy system.
         // For safety let's include it.
         // thrse values don't exist in the property template,
-        // and usualy are completely ignored when loading.
+        // and usually are completely ignored when loading.
         // One notable exception is the "Opacity" property,
         // which Blender uses as (1.0 - alpha).
         c.r = 0.0f; c.g = 0.0f; c.b = 0.0f;
@@ -1449,7 +1453,7 @@ void FBXExporter::WriteObjects ()
                 err << "Multilayer textures not supported (for now),";
                 err << " skipping texture type " << j;
                 err << " of material " << i;
-                DefaultLogger::get()->warn(err.str());
+                ASSIMP_LOG_WARN(err.str());
             }
 
             // get image path for this (single-image) texture
@@ -1484,7 +1488,7 @@ void FBXExporter::WriteObjects ()
                 err << "Not sure how to handle texture of type " << j;
                 err << " on material " << i;
                 err << ", skipping...";
-                DefaultLogger::get()->warn(err.str());
+                ASSIMP_LOG_WARN(err.str());
                 continue;
             }
             const std::string& prop_name = elem2->second;
@@ -1532,7 +1536,7 @@ void FBXExporter::WriteObjects ()
     // bones.
     //
     // output structure:
-    // subset of node heirarchy that are "skeleton",
+    // subset of node hierarchy that are "skeleton",
     // i.e. do not have meshes but only bones.
     // but.. i'm not sure how anyone could guarantee that...
     //
@@ -1544,7 +1548,7 @@ void FBXExporter::WriteObjects ()
     //
     // well. we can assume a sane input, i suppose.
     //
-    // so input is the bone node heirarchy,
+    // so input is the bone node hierarchy,
     // with an extra thing for the transformation of the MESH in BONE space.
     //
     // output is a set of bone nodes,
@@ -1556,7 +1560,7 @@ void FBXExporter::WriteObjects ()
     // and represents the influence of that bone on the grandparent mesh.
     // the subdeformer has a list of indices, and weights,
     // with indices specifying vertex indices,
-    // and weights specifying the correspoding influence of this bone.
+    // and weights specifying the corresponding influence of this bone.
     // it also has Transform and TransformLink elements,
     // specifying the transform of the MESH in BONE space,
     // and the transformation of the BONE in WORLD space,
@@ -1806,7 +1810,7 @@ void FBXExporter::WriteObjects ()
             // and a correct skeleton would still be output.
 
             // transformlink should be the position of the bone in world space.
-            // if the bone is in the bind pose (or nonexistant),
+            // if the bone is in the bind pose (or nonexistent),
             // we can just use the matrix we already calculated
             if (bone_xform_okay) {
                 sdnode.AddChild("TransformLink", bone_xform);
@@ -1945,7 +1949,7 @@ void FBXExporter::WriteObjects ()
 
     // TODO: cameras, lights
 
-    // write nodes (i.e. model heirarchy)
+    // write nodes (i.e. model hierarchy)
     // start at root node
     WriteModelNodes(
         outstream, mScene->mRootNode, 0, limbnodes
@@ -2089,7 +2093,7 @@ void FBXExporter::WriteObjects ()
             // position/translation
             for (size_t ki = 0; ki < na->mNumPositionKeys; ++ki) {
                 const aiVectorKey& k = na->mPositionKeys[ki];
-                times.push_back(to_ktime(k.mTime, anim));
+                times.push_back(to_ktime(k.mTime));
                 xval.push_back(k.mValue.x);
                 yval.push_back(k.mValue.y);
                 zval.push_back(k.mValue.z);
@@ -2103,7 +2107,7 @@ void FBXExporter::WriteObjects ()
             times.clear(); xval.clear(); yval.clear(); zval.clear();
             for (size_t ki = 0; ki < na->mNumRotationKeys; ++ki) {
                 const aiQuatKey& k = na->mRotationKeys[ki];
-                times.push_back(to_ktime(k.mTime, anim));
+                times.push_back(to_ktime(k.mTime));
                 // TODO: aiQuaternion method to convert to Euler...
                 aiMatrix4x4 m(k.mValue.GetMatrix());
                 aiVector3D qs, qr, qt;
@@ -2121,7 +2125,7 @@ void FBXExporter::WriteObjects ()
             times.clear(); xval.clear(); yval.clear(); zval.clear();
             for (size_t ki = 0; ki < na->mNumScalingKeys; ++ki) {
                 const aiVectorKey& k = na->mScalingKeys[ki];
-                times.push_back(to_ktime(k.mTime, anim));
+                times.push_back(to_ktime(k.mTime));
                 xval.push_back(k.mValue.x);
                 yval.push_back(k.mValue.y);
                 zval.push_back(k.mValue.z);
@@ -2203,8 +2207,8 @@ void FBXExporter::WriteModelNode(
     } else {
         // apply the transformation chain.
         // these transformation elements are created when importing FBX,
-        // which has a complex transformation heirarchy for each node.
-        // as such we can bake the heirarchy back into the node on export.
+        // which has a complex transformation hierarchy for each node.
+        // as such we can bake the hierarchy back into the node on export.
         for (auto &item : transform_chain) {
             auto elem = transform_types.find(item.first);
             if (elem == transform_types.end()) {
@@ -2440,7 +2444,7 @@ void FBXExporter::WriteAnimationCurve(
     // TODO: keyattr flags and data (STUB for now)
     n.AddChild("KeyAttrFlags", std::vector<int32_t>{0});
     n.AddChild("KeyAttrDataFloat", std::vector<float>{0,0,0,0});
-    ai_assert(times.size() <= std::numeric_limits<int32_t>::max());
+    ai_assert(static_cast<int32_t>(times.size()) <= std::numeric_limits<int32_t>::max());
     n.AddChild(
         "KeyAttrRefCount",
         std::vector<int32_t>{static_cast<int32_t>(times.size())}

+ 1 - 1
code/FBXExporter.h

@@ -90,7 +90,7 @@ namespace Assimp
         const ExportProperties* mProperties; // currently unused
         std::shared_ptr<IOStream> outfile; // file to write to
 
-        std::vector<FBX::Node> connections; // conection storage
+        std::vector<FBX::Node> connections; // connection storage
 
         std::vector<int64_t> mesh_uids;
         std::vector<int64_t> material_uids;

+ 1 - 1
code/FBXMaterial.cpp

@@ -302,7 +302,7 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std
     }
 
     if(Content) {
-        //this field is ommited when the embedded texture is already loaded, let's ignore if it's not found
+        //this field is omitted when the embedded texture is already loaded, let's ignore if it's not found
         try {
             const Token& token = GetRequiredToken(*Content, 0);
             const char* data = token.begin();

+ 3 - 0
code/FBXMeshGeometry.cpp

@@ -437,6 +437,9 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
     // deal with this more elegantly and with less redundancy, but right
     // now it seems unavoidable.
     if (MappingInformationType == "ByVertice" && isDirect) {
+        if (!HasElement(source, indexDataElementName)) {
+            return;
+        }
         std::vector<T> tempData;
 		ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
 

+ 58 - 19
code/FindDegenerates.cpp

@@ -54,6 +54,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 using namespace Assimp;
 
+//remove mesh at position 'index' from the scene
+static void removeMesh(aiScene* pScene, unsigned const index);
+//correct node indices to meshes and remove references to deleted mesh
+static void updateSceneGraph(aiNode* pNode, unsigned const index);
+
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 FindDegeneratesProcess::FindDegeneratesProcess()
@@ -85,11 +90,50 @@ void FindDegeneratesProcess::SetupProperties(const Importer* pImp) {
 // ------------------------------------------------------------------------------------------------
 // Executes the post processing step on the given imported data.
 void FindDegeneratesProcess::Execute( aiScene* pScene) {
-    DefaultLogger::get()->debug("FindDegeneratesProcess begin");
+    ASSIMP_LOG_DEBUG("FindDegeneratesProcess begin");
     for (unsigned int i = 0; i < pScene->mNumMeshes;++i){
-        ExecuteOnMesh( pScene->mMeshes[ i ] );
+        if (ExecuteOnMesh(pScene->mMeshes[i])) {
+            removeMesh(pScene, i);
+            --i; //the current i is removed, do not skip the next one
+        }
+    }
+    ASSIMP_LOG_DEBUG("FindDegeneratesProcess finished");
+}
+
+static void removeMesh(aiScene* pScene, unsigned const index) {
+    //we start at index and copy the pointers one position forward
+    //save the mesh pointer to delete it later
+    auto delete_me = pScene->mMeshes[index];
+    for (unsigned i = index; i < pScene->mNumMeshes - 1; ++i) {
+        pScene->mMeshes[i] = pScene->mMeshes[i+1];
+    }
+    pScene->mMeshes[pScene->mNumMeshes - 1] = nullptr;
+    --(pScene->mNumMeshes);
+    delete delete_me;
+
+    //removing a mesh also requires updating all references to it in the scene graph
+    updateSceneGraph(pScene->mRootNode, index);
+}
+
+static void updateSceneGraph(aiNode* pNode, unsigned const index) {
+    for (unsigned i = 0; i < pNode->mNumMeshes; ++i) {
+        if (pNode->mMeshes[i] > index) {
+            --(pNode->mMeshes[i]);
+            continue;
+        }
+        if (pNode->mMeshes[i] == index) {
+            for (unsigned j = i; j < pNode->mNumMeshes -1; ++j) {
+                pNode->mMeshes[j] = pNode->mMeshes[j+1];
+            }
+            --(pNode->mNumMeshes);
+            --i;
+            continue;
+        }
+    }
+    //recurse to all children
+    for (unsigned i = 0; i < pNode->mNumChildren; ++i) {
+        updateSceneGraph(pNode->mChildren[i], index);
     }
-    DefaultLogger::get()->debug("FindDegeneratesProcess finished");
 }
 
 static ai_real heron( ai_real a, ai_real b, ai_real c ) {
@@ -125,7 +169,7 @@ static ai_real calculateAreaOfTriangle( const aiFace& face, aiMesh* mesh ) {
 
 // ------------------------------------------------------------------------------------------------
 // Executes the post processing step on the given imported mesh
-void FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) {
+bool FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) {
     mesh->mPrimitiveTypes = 0;
 
     std::vector<bool> remove_me;
@@ -161,7 +205,7 @@ void FindDegeneratesProcess::ExecuteOnMesh( aiMesh* mesh) {
 
                     // NOTE: we set the removed vertex index to an unique value
                     // to make sure the developer gets notified when his
-                    // application attemps to access this data.
+                    // application attempts to access this data.
                     face.mIndices[ face.mNumIndices ] = 0xdeadbeef;
 
                     if(first) {
@@ -227,33 +271,28 @@ evil_jump_outside:
                 if (&face_src != &face_dest) {
                     // clear source
                     face_src.mNumIndices = 0;
-                    face_src.mIndices = NULL;
+                    face_src.mIndices = nullptr;
                 }
             }
             else {
                 // Otherwise delete it if we don't need this face
                 delete[] face_src.mIndices;
-                face_src.mIndices = NULL;
+                face_src.mIndices = nullptr;
                 face_src.mNumIndices = 0;
             }
         }
         // Just leave the rest of the array unreferenced, we don't care for now
         mesh->mNumFaces = n;
         if (!mesh->mNumFaces) {
-            // WTF!?
-            // OK ... for completeness and because I'm not yet tired,
-            // let's write code that willl hopefully never be called
-            // (famous last words)
-
-            // OK ... bad idea.
-            throw DeadlyImportError("Mesh is empty after removal of degenerated primitives ... WTF!?");
+            //The whole mesh consists of degenerated faces
+            //signal upward, that this mesh should be deleted.
+            ASSIMP_LOG_DEBUG("FindDegeneratesProcess removed a mesh full of degenerated primitives");
+            return true;
         }
     }
 
-    if (deg && !DefaultLogger::isNullLogger())
-    {
-        char s[64];
-        ASSIMP_itoa10(s,deg);
-        DefaultLogger::get()->warn(std::string("Found ") + s + " degenerated primitives");
+    if (deg && !DefaultLogger::isNullLogger()) {
+        ASSIMP_LOG_WARN_F( "Found ", deg, " degenerated primitives");
     }
+    return false;
 }

+ 2 - 1
code/FindDegenerates.h

@@ -74,7 +74,8 @@ public:
 
     // -------------------------------------------------------------------
     // Execute step on a given mesh
-    void ExecuteOnMesh( aiMesh* mesh);
+    ///@returns true if the current mesh should be deleted, false otherwise
+    bool ExecuteOnMesh( aiMesh* mesh);
 
     // -------------------------------------------------------------------
     /// @brief Enable the instant removal of degenerated primitives

+ 4 - 6
code/FindInstancesProcess.cpp

@@ -119,7 +119,7 @@ void UpdateMeshIndices(aiNode* node, unsigned int* lookup)
 // Executes the post processing step on the given imported data.
 void FindInstancesProcess::Execute( aiScene* pScene)
 {
-    DefaultLogger::get()->debug("FindInstancesProcess begin");
+    ASSIMP_LOG_DEBUG("FindInstancesProcess begin");
     if (pScene->mNumMeshes) {
 
         // use a pseudo hash for all meshes in the scene to quickly find
@@ -267,13 +267,11 @@ void FindInstancesProcess::Execute( aiScene* pScene)
 
             // write to log
             if (!DefaultLogger::isNullLogger()) {
-
-                char buffer[512];
-                ::ai_snprintf(buffer,512,"FindInstancesProcess finished. Found %i instances",pScene->mNumMeshes-numMeshesOut);
-                DefaultLogger::get()->info(buffer);
+                ASSIMP_LOG_INFO_F( "FindInstancesProcess finished. Found ", (pScene->mNumMeshes - numMeshesOut), " instances" );
             }
             pScene->mNumMeshes = numMeshesOut;
+        } else {
+            ASSIMP_LOG_DEBUG("FindInstancesProcess finished. No instanced meshes found");
         }
-        else DefaultLogger::get()->debug("FindInstancesProcess finished. No instanced meshes found");
     }
 }

+ 7 - 7
code/FindInvalidDataProcess.cpp

@@ -118,7 +118,7 @@ void UpdateMeshReferences(aiNode* node, const std::vector<unsigned int>& meshMap
 // Executes the post processing step on the given imported data.
 void FindInvalidDataProcess::Execute( aiScene* pScene)
 {
-    DefaultLogger::get()->debug("FindInvalidDataProcess begin");
+    ASSIMP_LOG_DEBUG("FindInvalidDataProcess begin");
 
     bool out = false;
     std::vector<unsigned int> meshMapping(pScene->mNumMeshes);
@@ -163,9 +163,10 @@ void FindInvalidDataProcess::Execute( aiScene* pScene)
             pScene->mNumMeshes = real;
         }
 
-        DefaultLogger::get()->info("FindInvalidDataProcess finished. Found issues ...");
+        ASSIMP_LOG_INFO("FindInvalidDataProcess finished. Found issues ...");
+    } else {
+        ASSIMP_LOG_DEBUG("FindInvalidDataProcess finished. Everything seems to be OK.");
     }
-    else DefaultLogger::get()->debug("FindInvalidDataProcess finished. Everything seems to be OK.");
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -212,8 +213,7 @@ inline bool ProcessArray(T*& in, unsigned int num,const char* name,
 {
     const char* err = ValidateArrayContents(in,num,dirtyMask,mayBeIdentical,mayBeZero);
     if (err)    {
-        DefaultLogger::get()->error(std::string("FindInvalidDataProcess fails on mesh ") + name + ": " + err);
-
+        ASSIMP_LOG_ERROR_F( "FindInvalidDataProcess fails on mesh ", name, ": ", err);
         delete[] in;
         in = NULL;
         return true;
@@ -332,7 +332,7 @@ void FindInvalidDataProcess::ProcessAnimationChannel (aiNodeAnim* anim)
         i = 1;
     }
     if (1 == i)
-        DefaultLogger::get()->warn("Simplified dummy tracks with just one key");
+        ASSIMP_LOG_WARN("Simplified dummy tracks with just one key");
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -354,7 +354,7 @@ int FindInvalidDataProcess::ProcessMesh (aiMesh* pMesh)
 
     // Process vertex positions
     if (pMesh->mVertices && ProcessArray(pMesh->mVertices, pMesh->mNumVertices, "positions", dirtyMask)) {
-        DefaultLogger::get()->error("Deleting mesh: Unable to continue without vertex positions");
+        ASSIMP_LOG_ERROR("Deleting mesh: Unable to continue without vertex positions");
 
         return 2;
     }

+ 20 - 18
code/FixNormalsStep.cpp

@@ -82,28 +82,35 @@ bool FixInfacingNormalsProcess::IsActive( unsigned int pFlags) const
 // Executes the post processing step on the given imported data.
 void FixInfacingNormalsProcess::Execute( aiScene* pScene)
 {
-    DefaultLogger::get()->debug("FixInfacingNormalsProcess begin");
+    ASSIMP_LOG_DEBUG("FixInfacingNormalsProcess 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)
-         DefaultLogger::get()->debug("FixInfacingNormalsProcess finished. Found issues.");
-    else DefaultLogger::get()->debug("FixInfacingNormalsProcess finished. No changes to the scene.");
+    if (bHas) {
+        ASSIMP_LOG_DEBUG("FixInfacingNormalsProcess finished. Found issues.");
+    } else {
+        ASSIMP_LOG_DEBUG("FixInfacingNormalsProcess finished. No changes to the scene.");
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 // Apply the step to the mesh
 bool FixInfacingNormalsProcess::ProcessMesh( aiMesh* pcMesh, unsigned int index)
 {
-    ai_assert(NULL != pcMesh);
+    ai_assert(nullptr != pcMesh);
 
     // Nothing to do if there are no model normals
-    if (!pcMesh->HasNormals())return false;
+    if (!pcMesh->HasNormals()) {
+        return false;
+    }
 
     // Compute the bounding box of both the model vertices + normals and
-    // the umodified model vertices. Then check whether the first BB
+    // the unmodified model vertices. Then check whether the first BB
     // is smaller than the second. In this case we can assume that the
     // normals need to be flipped, although there are a few special cases ..
     // convex, concave, planar models ...
@@ -155,14 +162,9 @@ bool FixInfacingNormalsProcess::ProcessMesh( aiMesh* pcMesh, unsigned int index)
     if (fDelta1_z < 0.05f * std::sqrt( fDelta1_y * fDelta1_x ))return false;
 
     // now compare the volumes of the bounding boxes
-    if (std::fabs(fDelta0_x * fDelta0_y * fDelta0_z) <
-        std::fabs(fDelta1_x * fDelta1_yz))
-    {
-        if (!DefaultLogger::isNullLogger())
-        {
-            char buffer[128]; // should be sufficiently large
-            ai_snprintf(buffer,128,"Mesh %u: Normals are facing inwards (or the mesh is planar)",index);
-            DefaultLogger::get()->info(buffer);
+    if (std::fabs(fDelta0_x * fDelta0_y * fDelta0_z) < std::fabs(fDelta1_x * fDelta1_yz)) {
+        if (!DefaultLogger::isNullLogger()) {
+            ASSIMP_LOG_INFO_F("Mesh ", index, ": Normals are facing inwards (or the mesh is planar)", index);
         }
 
         // Invert normals

+ 12 - 11
code/GenFaceNormalsProcess.cpp

@@ -72,16 +72,15 @@ GenFaceNormalsProcess::~GenFaceNormalsProcess()
 
 // ------------------------------------------------------------------------------------------------
 // Returns whether the processing step is present in the given flag field.
-bool GenFaceNormalsProcess::IsActive( unsigned int pFlags) const
-{
+bool GenFaceNormalsProcess::IsActive( unsigned int pFlags) const {
+    force_ = (pFlags & aiProcess_ForceGenNormals) != 0;
     return  (pFlags & aiProcess_GenNormals) != 0;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Executes the post processing step on the given imported data.
-void GenFaceNormalsProcess::Execute( aiScene* pScene)
-{
-    DefaultLogger::get()->debug("GenFaceNormalsProcess begin");
+void GenFaceNormalsProcess::Execute( aiScene* pScene) {
+    ASSIMP_LOG_DEBUG("GenFaceNormalsProcess begin");
 
     if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) {
         throw DeadlyImportError("Post-processing order mismatch: expecting pseudo-indexed (\"verbose\") vertices here");
@@ -94,11 +93,12 @@ void GenFaceNormalsProcess::Execute( aiScene* pScene)
         }
     }
     if (bHas)   {
-        DefaultLogger::get()->info("GenFaceNormalsProcess finished. "
+        ASSIMP_LOG_INFO("GenFaceNormalsProcess finished. "
             "Face normals have been calculated");
+    } else {
+        ASSIMP_LOG_DEBUG("GenFaceNormalsProcess finished. "
+            "Normals are already there");
     }
-    else DefaultLogger::get()->debug("GenFaceNormalsProcess finished. "
-        "Normals are already there");
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -106,14 +106,15 @@ void GenFaceNormalsProcess::Execute( aiScene* pScene)
 bool GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh)
 {
     if (NULL != pMesh->mNormals) {
-        return false;
+        if (force_) delete[] pMesh->mNormals;
+        else 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("Normal vectors are undefined for line and point meshes");
+        ASSIMP_LOG_INFO("Normal vectors are undefined for line and point meshes");
         return false;
     }
 
@@ -135,7 +136,7 @@ bool GenFaceNormalsProcess::GenMeshFaceNormals (aiMesh* pMesh)
         const aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
         const aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
         const aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]];
-        const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).Normalize();
+        const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).NormalizeSafe();
 
         for (unsigned int i = 0;i < face.mNumIndices;++i) {
             pMesh->mNormals[face.mIndices[i]] = vNor;

+ 2 - 1
code/GenFaceNormalsProcess.h

@@ -78,7 +78,8 @@ public:
 
 
 private:
-    bool GenMeshFaceNormals (aiMesh* pcMesh);
+    bool GenMeshFaceNormals(aiMesh* pcMesh);
+    mutable bool force_ = false;
 };
 
 } // end of namespace Assimp

+ 19 - 17
code/GenVertexNormalsProcess.cpp

@@ -72,6 +72,7 @@ GenVertexNormalsProcess::~GenVertexNormalsProcess() {
 // Returns whether the processing step is present in the given flag field.
 bool GenVertexNormalsProcess::IsActive( unsigned int pFlags) const
 {
+    force_ = (pFlags & aiProcess_ForceGenNormals) != 0;
     return (pFlags & aiProcess_GenSmoothNormals) != 0;
 }
 
@@ -88,39 +89,42 @@ void GenVertexNormalsProcess::SetupProperties(const Importer* pImp)
 // Executes the post processing step on the given imported data.
 void GenVertexNormalsProcess::Execute( aiScene* pScene)
 {
-    DefaultLogger::get()->debug("GenVertexNormalsProcess begin");
+    ASSIMP_LOG_DEBUG("GenVertexNormalsProcess begin");
 
-    if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT)
+    if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) {
         throw DeadlyImportError("Post-processing order mismatch: expecting pseudo-indexed (\"verbose\") vertices here");
+    }
 
     bool bHas = false;
-    for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
-    {
+    for( unsigned int a = 0; a < pScene->mNumMeshes; ++a) {
         if(GenMeshVertexNormals( pScene->mMeshes[a],a))
             bHas = true;
     }
 
     if (bHas)   {
-        DefaultLogger::get()->info("GenVertexNormalsProcess finished. "
+        ASSIMP_LOG_INFO("GenVertexNormalsProcess finished. "
             "Vertex normals have been calculated");
+    } else {
+        ASSIMP_LOG_DEBUG("GenVertexNormalsProcess finished. "
+            "Normals are already there");
     }
-    else DefaultLogger::get()->debug("GenVertexNormalsProcess finished. "
-        "Normals are already there");
 }
 
 // ------------------------------------------------------------------------------------------------
 // Executes the post processing step on the given imported data.
 bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int meshIndex)
 {
-    if (NULL != pMesh->mNormals)
-        return false;
+    if (NULL != pMesh->mNormals) {
+        if (force_) delete[] pMesh->mNormals;
+        else 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("Normal vectors are undefined for line and point meshes");
+        ASSIMP_LOG_INFO("Normal vectors are undefined for line and point meshes");
         return false;
     }
 
@@ -145,7 +149,7 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int
         const aiVector3D* pV1 = &pMesh->mVertices[face.mIndices[0]];
         const aiVector3D* pV2 = &pMesh->mVertices[face.mIndices[1]];
         const aiVector3D* pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices-1]];
-        const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1));
+        const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).NormalizeSafe();
 
         for (unsigned int i = 0;i < face.mNumIndices;++i) {
             pMesh->mNormals[face.mIndices[i]] = vNor;
@@ -213,17 +217,15 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals (aiMesh* pMesh, unsigned int
             vertexFinder->FindPositions( pMesh->mVertices[i] , posEpsilon, verticesFound);
 
             aiVector3D vr = pMesh->mNormals[i];
-            ai_real vrlen = vr.Length();
 
             aiVector3D pcNor;
             for (unsigned int a = 0; a < verticesFound.size(); ++a) {
                 aiVector3D v = pMesh->mNormals[verticesFound[a]];
 
-                // check whether the angle between the two normals is not too large
-                // HACK: if v.x is qnan the dot product will become qnan, too
-                //   therefore the comparison against fLimit should be false
-                //   in every case.
-                if (v * vr >= fLimit * vrlen * v.Length())
+                // Check whether the angle between the two normals is not too large.
+                // Skip the angle check on our own normal to avoid false negatives
+                // (v*v is not guaranteed to be 1.0 for all unit vectors v)
+                if (is_not_qnan(v.x) && (verticesFound[a] == i || (v * vr >= fLimit)))
                     pcNor += v;
             }
             pcNew[i] = pcNor.NormalizeSafe();

+ 1 - 0
code/GenVertexNormalsProcess.h

@@ -107,6 +107,7 @@ private:
 
     /** Configuration option: maximum smoothing angle, in radians*/
     ai_real configMaxAngle;
+    mutable bool force_ = false;
 };
 
 } // end of namespace Assimp

+ 3 - 3
code/HMPLoader.cpp

@@ -141,21 +141,21 @@ void HMPImporter::InternReadFile( const std::string& pFile,
     if (AI_HMP_MAGIC_NUMBER_LE_4 == iMagic ||
         AI_HMP_MAGIC_NUMBER_BE_4 == iMagic)
     {
-        DefaultLogger::get()->debug("HMP subtype: 3D GameStudio A4, magic word is HMP4");
+        ASSIMP_LOG_DEBUG("HMP subtype: 3D GameStudio A4, magic word is HMP4");
         InternReadFile_HMP4();
     }
     // HMP5 format
     else if (AI_HMP_MAGIC_NUMBER_LE_5 == iMagic ||
              AI_HMP_MAGIC_NUMBER_BE_5 == iMagic)
     {
-        DefaultLogger::get()->debug("HMP subtype: 3D GameStudio A5, magic word is HMP5");
+        ASSIMP_LOG_DEBUG("HMP subtype: 3D GameStudio A5, magic word is HMP5");
         InternReadFile_HMP5();
     }
     // HMP7 format
     else if (AI_HMP_MAGIC_NUMBER_LE_7 == iMagic ||
              AI_HMP_MAGIC_NUMBER_BE_7 == iMagic)
     {
-        DefaultLogger::get()->debug("HMP subtype: 3D GameStudio A7, magic word is HMP7");
+        ASSIMP_LOG_DEBUG("HMP subtype: 3D GameStudio A7, magic word is HMP7");
         InternReadFile_HMP7();
     }
     else

+ 28 - 28
code/IRRLoader.cpp

@@ -131,7 +131,7 @@ void IRRImporter::SetupProperties(const Importer* pImp)
     // read the output frame rate of all node animation channels
     fps = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_IRR_ANIM_FPS,100);
     if (fps < 10.)  {
-        DefaultLogger::get()->error("IRR: Invalid FPS configuration");
+        ASSIMP_LOG_ERROR("IRR: Invalid FPS configuration");
         fps = 100;
     }
 
@@ -281,7 +281,7 @@ void IRRImporter::CopyMaterial(std::vector<aiMaterial*>& materials,
         return;
     }
     else if (inmaterials.size() > 1)    {
-        DefaultLogger::get()->info("IRR: Skipping additional materials");
+        ASSIMP_LOG_INFO("IRR: Skipping additional materials");
     }
 
     mesh->mMaterialIndex = (unsigned int)materials.size();
@@ -319,17 +319,18 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
     if (root->animators.empty()) {
         return;
     }
-    unsigned int total = 0;
+    unsigned int total( 0 );
     for (std::list<Animator>::iterator it = root->animators.begin();it != root->animators.end(); ++it)  {
         if ((*it).type == Animator::UNKNOWN || (*it).type == Animator::OTHER)   {
-            DefaultLogger::get()->warn("IRR: Skipping unknown or unsupported animator");
+            ASSIMP_LOG_WARN("IRR: Skipping unknown or unsupported animator");
             continue;
         }
         ++total;
     }
-    if (!total)return;
-    else if (1 == total)    {
-        DefaultLogger::get()->warn("IRR: Adding dummy nodes to simulate multiple animators");
+    if (!total) {
+        return;
+    } else if (1 == total)    {
+        ASSIMP_LOG_WARN("IRR: Adding dummy nodes to simulate multiple animators");
     }
 
     // NOTE: 1 tick == i millisecond
@@ -518,9 +519,9 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
                 const int size = (int)in.splineKeys.size();
                 if (!size)  {
                     // We have no point in the spline. That's bad. Really bad.
-                    DefaultLogger::get()->warn("IRR: Spline animators with no points defined");
+                    ASSIMP_LOG_WARN("IRR: Spline animators with no points defined");
 
-                    delete anim;anim = NULL;
+                    delete anim;anim = nullptr;
                     break;
                 }
                 else if (size == 1) {
@@ -672,7 +673,7 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
             // graph we're currently building
             aiScene* scene = batch.GetImport(root->id);
             if (!scene) {
-                DefaultLogger::get()->error("IRR: Unable to load external file: " + root->meshPath);
+                ASSIMP_LOG_ERROR("IRR: Unable to load external file: " + root->meshPath);
                 break;
             }
             attach.push_back(AttachmentInfo(scene,rootOut));
@@ -683,7 +684,7 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
             // should be equal. If they are not, we can impossibly
             // do this  ...
             if (root->materials.size() != (unsigned int)scene->mNumMaterials)   {
-                DefaultLogger::get()->warn("IRR: Failed to match imported materials "
+                ASSIMP_LOG_WARN("IRR: Failed to match imported materials "
                     "with the materials found in the IRR scene file");
 
                 break;
@@ -722,7 +723,7 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
                         }
                     }
                     if (bdo)    {
-                        DefaultLogger::get()->info("IRR: Replacing mesh vertex alpha with common opacity");
+                        ASSIMP_LOG_INFO("IRR: Replacing mesh vertex alpha with common opacity");
 
                         for (unsigned int a = 0; a < mesh->mNumVertices;++a)
                             mesh->mColors[0][a].a = 1.f;
@@ -806,7 +807,7 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
         {
             // A skybox is defined by six materials
             if (root->materials.size() < 6) {
-                DefaultLogger::get()->error("IRR: There should be six materials for a skybox");
+                ASSIMP_LOG_ERROR("IRR: There should be six materials for a skybox");
                 break;
             }
 
@@ -823,7 +824,7 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
             // for IRR skyboxes. We add a 'IRR.SkyBox_' prefix to the node.
             // *************************************************************
             root->name = "IRR.SkyBox_" + root->name;
-            DefaultLogger::get()->info("IRR: Loading skybox, this will "
+            ASSIMP_LOG_INFO("IRR: Loading skybox, this will "
                 "require special handling to be displayed correctly");
         }
         break;
@@ -831,7 +832,7 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
     case Node::TERRAIN:
         {
             // to support terrains, we'd need to have a texture decoder
-            DefaultLogger::get()->error("IRR: Unsupported node - TERRAIN");
+            ASSIMP_LOG_ERROR("IRR: Unsupported node - TERRAIN");
         }
         break;
     default:
@@ -1010,11 +1011,11 @@ void IRRImporter::InternReadFile( const std::string& pFile,
                 }
                 else if (!ASSIMP_stricmp(sz,"billBoard"))   {
                     // We don't support billboards, so ignore them
-                    DefaultLogger::get()->error("IRR: Billboards are not supported by Assimp");
+                    ASSIMP_LOG_ERROR("IRR: Billboards are not supported by Assimp");
                     nd = new Node(Node::DUMMY);
                 }
                 else    {
-                    DefaultLogger::get()->warn("IRR: Found unknown node: " + std::string(sz));
+                    ASSIMP_LOG_WARN("IRR: Found unknown node: " + std::string(sz));
 
                     /*  We skip the contents of nodes we don't know.
                      *  We parse the transformation and all animators
@@ -1041,7 +1042,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
                  */
                 if (!curNode)   {
 #if 0
-                    DefaultLogger::get()->error("IRR: Encountered <attributes> element, but "
+                    ASSIMP_LOG_ERROR("IRR: Encountered <attributes> element, but "
                         "there is no node active");
 #endif
                     continue;
@@ -1269,7 +1270,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
                                         lights.pop_back();
                                         curNode->type = Node::DUMMY;
 
-                                        DefaultLogger::get()->error("Ignoring light of unknown type: " + prop.value);
+                                        ASSIMP_LOG_ERROR("Ignoring light of unknown type: " + prop.value);
                                     }
                                 }
                                 else if ((prop.name == "Mesh" && Node::MESH == curNode->type) ||
@@ -1277,7 +1278,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
                                 {
                                     /*  This is the file name of the mesh - either
                                      *  animated or not. We need to make sure we setup
-                                     *  the correct postprocessing settings here.
+                                     *  the correct post-processing settings here.
                                      */
                                     unsigned int pp = 0;
                                     BatchLoader::PropertyMap map;
@@ -1299,7 +1300,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
 
                                     const std::string extension = GetExtension(prop.value);
                                     if ("irr" == extension) {
-                                        DefaultLogger::get()->error("IRR: Can't load another IRR file recursively");
+                                        ASSIMP_LOG_ERROR("IRR: Can't load another IRR file recursively");
                                     }
                                     else
                                     {
@@ -1323,7 +1324,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
                                         curAnim->type = Animator::FOLLOW_SPLINE;
                                     }
                                     else    {
-                                        DefaultLogger::get()->warn("IRR: Ignoring unknown animator: "
+                                        ASSIMP_LOG_WARN("IRR: Ignoring unknown animator: "
                                             + prop.value);
 
                                         curAnim->type = Animator::UNKNOWN;
@@ -1348,7 +1349,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
                     // back in the node hierarchy
                     if (!curParent) {
                         curParent = root;
-                        DefaultLogger::get()->error("IRR: Too many closing <node> elements");
+                        ASSIMP_LOG_ERROR("IRR: Too many closing <node> elements");
                     }
                     else curParent = curParent->parent;
                 }
@@ -1369,15 +1370,14 @@ void IRRImporter::InternReadFile( const std::string& pFile,
         }
     }
 
-    /*  Now iterate through all cameras and compute their final (horizontal) FOV
-     */
+    //  Now iterate through all cameras and compute their final (horizontal) FOV
     for (aiCamera *cam : cameras) {
-
         // screen aspect could be missing
         if (cam->mAspect)   {
             cam->mHorizontalFOV *= cam->mAspect;
+        } else {
+            ASSIMP_LOG_WARN("IRR: Camera aspect is not given, can't compute horizontal FOV");
         }
-        else DefaultLogger::get()->warn("IRR: Camera aspect is not given, can't compute horizontal FOV");
     }
 
     batch.LoadAll();
@@ -1472,7 +1472,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
      *  models from external files
      */
     if (!pScene->mNumMeshes || !pScene->mNumMaterials)  {
-        DefaultLogger::get()->warn("IRR: No meshes loaded, setting AI_SCENE_FLAGS_INCOMPLETE");
+        ASSIMP_LOG_WARN("IRR: No meshes loaded, setting AI_SCENE_FLAGS_INCOMPLETE");
         pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
     }
 

+ 10 - 10
code/IRRMeshLoader.cpp

@@ -175,7 +175,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
             if (!ASSIMP_stricmp(reader->getNodeName(),"buffer") && (curMat || curMesh)) {
                 // end of previous buffer. A material and a mesh should be there
                 if ( !curMat || !curMesh)   {
-                    DefaultLogger::get()->error("IRRMESH: A buffer must contain a mesh and a material");                    
+                    ASSIMP_LOG_ERROR("IRRMESH: A buffer must contain a mesh and a material");
                     releaseMaterial( &curMat );
                     releaseMesh( &curMesh );
                 } else {
@@ -197,7 +197,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
 
             if (!ASSIMP_stricmp(reader->getNodeName(),"material"))  {
                 if (curMat) {
-                    DefaultLogger::get()->warn("IRRMESH: Only one material description per buffer, please");
+                    ASSIMP_LOG_WARN("IRRMESH: Only one material description per buffer, please");
                     releaseMaterial( &curMat );
                 }
                 curMat = ParseMaterial(curMatFlags);
@@ -208,7 +208,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
 
                 if (!num)   {
                     // This is possible ... remove the mesh from the list and skip further reading
-                    DefaultLogger::get()->warn("IRRMESH: Found mesh with zero vertices");
+                    ASSIMP_LOG_WARN("IRRMESH: Found mesh with zero vertices");
 
                     releaseMaterial( &curMat );
                     releaseMesh( &curMesh );
@@ -255,7 +255,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
                 }
                 else if (ASSIMP_stricmp("standard", t)) {
                     releaseMaterial( &curMat );
-                    DefaultLogger::get()->warn("IRRMESH: Unknown vertex format");
+                    ASSIMP_LOG_WARN("IRRMESH: Unknown vertex format");
                 }
                 else vertexFormat = 0;
                 textMeaning = 1;
@@ -275,7 +275,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
                 curMesh->mNumVertices = reader->getAttributeValueAsInt("indexCount");
                 if (!curMesh->mNumVertices) {
                     // This is possible ... remove the mesh from the list and skip further reading
-                    DefaultLogger::get()->warn("IRRMESH: Found mesh with zero indices");
+                    ASSIMP_LOG_WARN("IRRMESH: Found mesh with zero indices");
 
                     // mesh - away
                     releaseMesh( &curMesh );
@@ -288,7 +288,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
                 }
 
                 if (curMesh->mNumVertices % 3)  {
-                    DefaultLogger::get()->warn("IRRMESH: Number if indices isn't divisible by 3");
+                    ASSIMP_LOG_WARN("IRRMESH: Number if indices isn't divisible by 3");
                 }
 
                 curMesh->mNumFaces = curMesh->mNumVertices / 3;
@@ -439,7 +439,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
                 unsigned int total = 0;
                 while(SkipSpacesAndLineEnd(&sz))    {
                     if (curFace >= faceEnd) {
-                        DefaultLogger::get()->error("IRRMESH: Too many indices");
+                        ASSIMP_LOG_ERROR("IRRMESH: Too many indices");
                         break;
                     }
                     if (!curIdx)    {
@@ -449,7 +449,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
 
                     unsigned int idx = strtoul10(sz,&sz);
                     if (idx >= curVertices.size())  {
-                        DefaultLogger::get()->error("IRRMESH: Index out of range");
+                        ASSIMP_LOG_ERROR("IRRMESH: Index out of range");
                         idx = 0;
                     }
 
@@ -470,7 +470,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
                 }
 
                 if (curFace != faceEnd)
-                    DefaultLogger::get()->error("IRRMESH: Not enough indices");
+                    ASSIMP_LOG_ERROR("IRRMESH: Not enough indices");
 
                 // Finish processing the mesh - do some small material workarounds
                 if (curMatFlags & AI_IRRMESH_MAT_trans_vertex_alpha && !useColors)  {
@@ -492,7 +492,7 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
     // End of the last buffer. A material and a mesh should be there
     if (curMat || curMesh)  {
         if ( !curMat || !curMesh)   {
-            DefaultLogger::get()->error("IRRMESH: A buffer must contain a mesh and a material");
+            ASSIMP_LOG_ERROR("IRRMESH: A buffer must contain a mesh and a material");
             releaseMaterial( &curMat );
             releaseMesh( &curMesh );
         }

+ 10 - 15
code/IRRShared.cpp

@@ -179,14 +179,14 @@ void IrrlichtBase::ReadVectorProperty  (VectorProperty&  out)
             SkipSpaces(&ptr);
             if (',' != *ptr)
             {
-                DefaultLogger::get()->error("IRR(MESH): Expected comma in vector definition");
+                ASSIMP_LOG_ERROR("IRR(MESH): Expected comma in vector definition");
             }
             else SkipSpaces(ptr+1,&ptr);
             ptr = fast_atoreal_move<float>( ptr,(float&)out.value.y );
             SkipSpaces(&ptr);
             if (',' != *ptr)
             {
-                DefaultLogger::get()->error("IRR(MESH): Expected comma in vector definition");
+                ASSIMP_LOG_ERROR("IRR(MESH): Expected comma in vector definition");
             }
             else SkipSpaces(ptr+1,&ptr);
             ptr = fast_atoreal_move<float>( ptr,(float&)out.value.z );
@@ -360,7 +360,7 @@ aiMaterial* IrrlichtBase::ParseMaterial(unsigned int& matFlags)
                             matFlags = AI_IRRMESH_MAT_normalmap_ta;
                         }
                         else {
-                            DefaultLogger::get()->warn("IRRMat: Unrecognized material type: " + prop.value);
+                            ASSIMP_LOG_WARN("IRRMat: Unrecognized material type: " + prop.value);
                         }
                     }
 
@@ -391,9 +391,7 @@ aiMaterial* IrrlichtBase::ParseMaterial(unsigned int& matFlags)
 
                             // set the corresponding material flag
                             matFlags |= AI_IRRMESH_EXTRA_2ND_TEXTURE;
-                        }
-                        // or just as second diffuse texture
-                        else if (matFlags & AI_IRRMESH_MAT_solid_2layer)    {
+                        } else if (matFlags & AI_IRRMESH_MAT_solid_2layer)    {// or just as second diffuse texture
                             ++cnt;
                             s.Set(prop.value);
                             mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(1));
@@ -401,19 +399,15 @@ aiMaterial* IrrlichtBase::ParseMaterial(unsigned int& matFlags)
 
                             // set the corresponding material flag
                             matFlags |= AI_IRRMESH_EXTRA_2ND_TEXTURE;
+                        } else {
+                            ASSIMP_LOG_WARN("IRRmat: Skipping second texture");
                         }
-                        else DefaultLogger::get()->warn("IRRmat: Skipping second texture");
-                    }
-
-                    else if (prop.name == "Texture3" && cnt == 2)
-                    {
+                    } else if (prop.name == "Texture3" && cnt == 2) {
                         // Irrlicht does not seem to use these channels.
                         ++cnt;
                         s.Set(prop.value);
                         mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(nd+1));
-                    }
-                    else if (prop.name == "Texture4" && cnt == 3)
-                    {
+                    } else if (prop.name == "Texture4" && cnt == 3) {
                         // Irrlicht does not seem to use these channels.
                         ++cnt;
                         s.Set(prop.value);
@@ -499,7 +493,8 @@ aiMaterial* IrrlichtBase::ParseMaterial(unsigned int& matFlags)
                 break;
         }
     }
-    DefaultLogger::get()->error("IRRMESH: Unexpected end of file. Material is not complete");
+    ASSIMP_LOG_ERROR("IRRMESH: Unexpected end of file. Material is not complete");
+
     return mat;
 }
 

+ 1 - 1
code/IRRShared.h

@@ -91,7 +91,7 @@ protected:
 
     // -------------------------------------------------------------------
     /** Read a property of the specified type from the current XML element.
-     *  @param out Recives output data
+     *  @param out Receives output data
      */
     void ReadHexProperty    (HexProperty&    out);
     void ReadStringProperty (StringProperty& out);

+ 60 - 67
code/Importer.cpp

@@ -205,7 +205,7 @@ aiReturn Importer::RegisterPPStep(BaseProcess* pImp)
     ASSIMP_BEGIN_EXCEPTION_REGION();
 
         pimpl->mPostProcessingSteps.push_back(pImp);
-        DefaultLogger::get()->info("Registering custom post-processing step");
+        ASSIMP_LOG_INFO("Registering custom post-processing step");
 
     ASSIMP_END_EXCEPTION_REGION(aiReturn);
     return AI_SUCCESS;
@@ -232,7 +232,7 @@ aiReturn Importer::RegisterLoader(BaseImporter* pImp)
 
 #ifdef ASSIMP_BUILD_DEBUG
         if (IsExtensionSupported(*it)) {
-            DefaultLogger::get()->warn("The file extension " + *it + " is already in use");
+            ASSIMP_LOG_WARN_F("The file extension ", *it, " is already in use");
         }
 #endif
         baked += *it;
@@ -240,7 +240,7 @@ aiReturn Importer::RegisterLoader(BaseImporter* pImp)
 
     // add the loader
     pimpl->mImporter.push_back(pImp);
-    DefaultLogger::get()->info("Registering custom importer for these file extensions: " + baked);
+    ASSIMP_LOG_INFO_F("Registering custom importer for these file extensions: ", baked);
     ASSIMP_END_EXCEPTION_REGION(aiReturn);
     return AI_SUCCESS;
 }
@@ -260,10 +260,10 @@ aiReturn Importer::UnregisterLoader(BaseImporter* pImp)
 
     if (it != pimpl->mImporter.end())   {
         pimpl->mImporter.erase(it);
-        DefaultLogger::get()->info("Unregistering custom importer: ");
+        ASSIMP_LOG_INFO("Unregistering custom importer: ");
         return AI_SUCCESS;
     }
-    DefaultLogger::get()->warn("Unable to remove custom importer: I can't find you ...");
+    ASSIMP_LOG_WARN("Unable to remove custom importer: I can't find you ...");
     ASSIMP_END_EXCEPTION_REGION(aiReturn);
     return AI_FAILURE;
 }
@@ -283,10 +283,10 @@ aiReturn Importer::UnregisterPPStep(BaseProcess* pImp)
 
     if (it != pimpl->mPostProcessingSteps.end())    {
         pimpl->mPostProcessingSteps.erase(it);
-        DefaultLogger::get()->info("Unregistering custom post-processing step");
+        ASSIMP_LOG_INFO("Unregistering custom post-processing step");
         return AI_SUCCESS;
     }
-    DefaultLogger::get()->warn("Unable to remove custom post-processing step: I can't find you ..");
+    ASSIMP_LOG_WARN("Unable to remove custom post-processing step: I can't find you ..");
     ASSIMP_END_EXCEPTION_REGION(aiReturn);
     return AI_FAILURE;
 }
@@ -368,11 +368,11 @@ bool Importer::IsDefaultProgressHandler() const
 bool _ValidateFlags(unsigned int pFlags)
 {
     if (pFlags & aiProcess_GenSmoothNormals && pFlags & aiProcess_GenNormals)   {
-        DefaultLogger::get()->error("#aiProcess_GenSmoothNormals and #aiProcess_GenNormals are incompatible");
+        ASSIMP_LOG_ERROR("#aiProcess_GenSmoothNormals and #aiProcess_GenNormals are incompatible");
         return false;
     }
     if (pFlags & aiProcess_OptimizeGraph && pFlags & aiProcess_PreTransformVertices)    {
-        DefaultLogger::get()->error("#aiProcess_OptimizeGraph and #aiProcess_PreTransformVertices are incompatible");
+        ASSIMP_LOG_ERROR("#aiProcess_OptimizeGraph and #aiProcess_PreTransformVertices are incompatible");
         return false;
     }
     return true;
@@ -504,26 +504,15 @@ const aiScene* Importer::ReadFileFromMemory( const void* pBuffer,
 // ------------------------------------------------------------------------------------------------
 void WriteLogOpening(const std::string& file)
 {
-    Logger* l = DefaultLogger::get();
-    if (!l) {
-        return;
-    }
-    l->info("Load " + file);
+    ASSIMP_LOG_INFO_F("Load ", file);
 
     // print a full version dump. This is nice because we don't
     // need to ask the authors of incoming bug reports for
     // the library version they're using - a log dump is
     // sufficient.
-    const unsigned int flags = aiGetCompileFlags();
-    l->debug(format()
-        << "Assimp "
-        << aiGetVersionMajor()
-        << "."
-        << aiGetVersionMinor()
-        << "."
-        << aiGetVersionRevision()
-
-        << " "
+    const unsigned int flags( aiGetCompileFlags() );
+    std::stringstream stream;
+    stream << "Assimp " << aiGetVersionMajor() << "." << aiGetVersionMinor() << "." << aiGetVersionRevision() << " "
 #if defined(ASSIMP_BUILD_ARCHITECTURE)
         << ASSIMP_BUILD_ARCHITECTURE
 #elif defined(_M_IX86) || defined(__x86_32__) || defined(__i386__)
@@ -539,12 +528,11 @@ void WriteLogOpening(const std::string& file)
 #elif defined(__arm__)
         << "arm"
 #else
-    << "<unknown architecture>"
+        << "<unknown architecture>"
 #endif
-
         << " "
 #if defined(ASSIMP_BUILD_COMPILER)
-        << ASSIMP_BUILD_COMPILER
+        << ( ASSIMP_BUILD_COMPILER )
 #elif defined(_MSC_VER)
         << "msvc"
 #elif defined(__GNUC__)
@@ -559,8 +547,9 @@ void WriteLogOpening(const std::string& file)
 
         << (flags & ASSIMP_CFLAGS_NOBOOST ? " noboost" : "")
         << (flags & ASSIMP_CFLAGS_SHARED  ? " shared" : "")
-        << (flags & ASSIMP_CFLAGS_SINGLETHREADED  ? " singlethreaded" : "")
-        );
+        << (flags & ASSIMP_CFLAGS_SINGLETHREADED  ? " singlethreaded" : "");
+
+        ASSIMP_LOG_DEBUG(stream.str());
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -586,7 +575,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
         // a scene. In this case we need to delete the old one
         if (pimpl->mScene)  {
 
-            DefaultLogger::get()->debug("(Deleting previous scene)");
+            ASSIMP_LOG_DEBUG("(Deleting previous scene)");
             FreeScene();
         }
 
@@ -594,7 +583,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
         if( !pimpl->mIOHandler->Exists( pFile)) {
 
             pimpl->mErrorString = "Unable to open file \"" + pFile + "\".";
-            DefaultLogger::get()->error(pimpl->mErrorString);
+            ASSIMP_LOG_ERROR(pimpl->mErrorString);
             return NULL;
         }
 
@@ -617,7 +606,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
             // not so bad yet ... try format auto detection.
             const std::string::size_type s = pFile.find_last_of('.');
             if (s != std::string::npos) {
-                DefaultLogger::get()->info("File extension not known, trying signature-based detection");
+                ASSIMP_LOG_INFO("File extension not known, trying signature-based detection");
                 for( unsigned int a = 0; a < pimpl->mImporter.size(); a++)  {
                     if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, true)) {
                         imp = pimpl->mImporter[a];
@@ -628,7 +617,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
             // Put a proper error message if no suitable importer was found
             if( !imp)   {
                 pimpl->mErrorString = "No suitable reader found for the file format of file \"" + pFile + "\".";
-                DefaultLogger::get()->error(pimpl->mErrorString);
+                ASSIMP_LOG_ERROR(pimpl->mErrorString);
                 return NULL;
             }
         }
@@ -648,7 +637,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
         if ( NULL != desc ) {
             ext = desc->mName;
         }
-        DefaultLogger::get()->info("Found a matching importer for this file format: " + ext + "." );
+        ASSIMP_LOG_INFO("Found a matching importer for this file format: " + ext + "." );
         pimpl->mProgressHandler->UpdateFileRead( 0, fileSize );
 
         if (profiler) {
@@ -716,7 +705,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
         pimpl->mErrorString = std::string("std::exception: ") + e.what();
 #endif
 
-        DefaultLogger::get()->error(pimpl->mErrorString);
+        ASSIMP_LOG_ERROR(pimpl->mErrorString);
         delete pimpl->mScene; pimpl->mScene = NULL;
     }
 #endif // ! ASSIMP_CATCH_GLOBAL_EXCEPTIONS
@@ -744,7 +733,7 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
 
     // In debug builds: run basic flag validation
     ai_assert(_ValidateFlags(pFlags));
-    DefaultLogger::get()->info("Entering post processing pipeline");
+    ASSIMP_LOG_INFO("Entering post processing pipeline");
 
 #ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
     // The ValidateDS process plays an exceptional role. It isn't contained in the global
@@ -762,13 +751,13 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
     if (pimpl->bExtraVerbose)
     {
 #ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
-        DefaultLogger::get()->error("Verbose Import is not available due to build settings");
+        ASSIMP_LOG_ERROR("Verbose Import is not available due to build settings");
 #endif  // no validation
         pFlags |= aiProcess_ValidateDataStructure;
     }
 #else
     if (pimpl->bExtraVerbose) {
-        DefaultLogger::get()->warn("Not a debug build, ignoring extra verbose setting");
+        ASSIMP_LOG_WARN("Not a debug build, ignoring extra verbose setting");
     }
 #endif // ! DEBUG
 
@@ -800,18 +789,19 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
 
         // If the extra verbose mode is active, execute the ValidateDataStructureStep again - after each step
         if (pimpl->bExtraVerbose)   {
-            DefaultLogger::get()->debug("Verbose Import: revalidating data structures");
+            ASSIMP_LOG_DEBUG("Verbose Import: re-validating data structures");
 
             ValidateDSProcess ds;
             ds.ExecuteOnScene (this);
             if( !pimpl->mScene) {
-                DefaultLogger::get()->error("Verbose Import: failed to revalidate data structures");
+                ASSIMP_LOG_ERROR("Verbose Import: failed to re-validate data structures");
                 break;
             }
         }
 #endif // ! DEBUG
     }
-    pimpl->mProgressHandler->UpdatePostProcess( static_cast<int>(pimpl->mPostProcessingSteps.size()), static_cast<int>(pimpl->mPostProcessingSteps.size()) );
+    pimpl->mProgressHandler->UpdatePostProcess( static_cast<int>(pimpl->mPostProcessingSteps.size()), 
+        static_cast<int>(pimpl->mPostProcessingSteps.size()) );
 
     // update private scene flags
     if( pimpl->mScene )
@@ -819,7 +809,7 @@ const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
 
     // clear any data allocated by post-process steps
     pimpl->mPPShared->Clean();
-    DefaultLogger::get()->info("Leaving post processing pipeline");
+    ASSIMP_LOG_INFO("Leaving post processing pipeline");
 
     ASSIMP_END_EXCEPTION_REGION(const aiScene*);
     return pimpl->mScene;
@@ -840,7 +830,7 @@ const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess
     }
 
     // In debug builds: run basic flag validation
-    DefaultLogger::get()->info( "Entering customized post processing pipeline" );
+    ASSIMP_LOG_INFO( "Entering customized post processing pipeline" );
 
 #ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
     // The ValidateDS process plays an exceptional role. It isn't contained in the global
@@ -858,12 +848,12 @@ const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess
     if ( pimpl->bExtraVerbose )
     {
 #ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
-        DefaultLogger::get()->error( "Verbose Import is not available due to build settings" );
+        ASSIMP_LOG_ERROR( "Verbose Import is not available due to build settings" );
 #endif  // no validation
     }
 #else
     if ( pimpl->bExtraVerbose ) {
-        DefaultLogger::get()->warn( "Not a debug build, ignoring extra verbose setting" );
+        ASSIMP_LOG_WARN( "Not a debug build, ignoring extra verbose setting" );
     }
 #endif // ! DEBUG
 
@@ -881,18 +871,18 @@ const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess
 
     // If the extra verbose mode is active, execute the ValidateDataStructureStep again - after each step
     if ( pimpl->bExtraVerbose || requestValidation  ) {
-        DefaultLogger::get()->debug( "Verbose Import: revalidating data structures" );
+        ASSIMP_LOG_DEBUG( "Verbose Import: revalidating data structures" );
 
         ValidateDSProcess ds;
         ds.ExecuteOnScene( this );
         if ( !pimpl->mScene ) {
-            DefaultLogger::get()->error( "Verbose Import: failed to revalidate data structures" );
+            ASSIMP_LOG_ERROR( "Verbose Import: failed to revalidate data structures" );
         }
     }
 
     // clear any data allocated by post-process steps
     pimpl->mPPShared->Clean();
-    DefaultLogger::get()->info( "Leaving customized post processing pipeline" );
+    ASSIMP_LOG_INFO( "Leaving customized post processing pipeline" );
 
     ASSIMP_END_EXCEPTION_REGION( const aiScene* );
 
@@ -903,7 +893,7 @@ const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess
 // Helper function to check whether an extension is supported by ASSIMP
 bool Importer::IsExtensionSupported(const char* szExtension) const
 {
-    return NULL != GetImporter(szExtension);
+    return nullptr != GetImporter(szExtension);
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -980,15 +970,18 @@ void Importer::GetExtensionList(aiString& szOut) const
         (*i)->GetExtensionList(str);
     }
 
-    for (std::set<std::string>::const_iterator it = str.begin();; ) {
-        szOut.Append("*.");
-        szOut.Append((*it).c_str());
-
-        if (++it == str.end()) {
-            break;
-        }
-        szOut.Append(";");
-    }
+	// List can be empty
+	if( !str.empty() ) {
+		for (std::set<std::string>::const_iterator it = str.begin();; ) {
+			szOut.Append("*.");
+			szOut.Append((*it).c_str());
+
+			if (++it == str.end()) {
+				break;
+			}
+			szOut.Append(";");
+		}
+	}
     ASSIMP_END_EXCEPTION_REGION(void);
 }
 
@@ -1007,33 +1000,33 @@ bool Importer::SetPropertyInteger(const char* szName, int iValue)
 // Set a configuration property
 bool Importer::SetPropertyFloat(const char* szName, ai_real iValue)
 {
-    bool exising;
+    bool existing;
     ASSIMP_BEGIN_EXCEPTION_REGION();
-        exising = SetGenericProperty<ai_real>(pimpl->mFloatProperties, szName,iValue);
+        existing = SetGenericProperty<ai_real>(pimpl->mFloatProperties, szName,iValue);
     ASSIMP_END_EXCEPTION_REGION(bool);
-    return exising;
+    return existing;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Set a configuration property
 bool Importer::SetPropertyString(const char* szName, const std::string& value)
 {
-    bool exising;
+    bool existing;
     ASSIMP_BEGIN_EXCEPTION_REGION();
-        exising = SetGenericProperty<std::string>(pimpl->mStringProperties, szName,value);
+        existing = SetGenericProperty<std::string>(pimpl->mStringProperties, szName,value);
     ASSIMP_END_EXCEPTION_REGION(bool);
-    return exising;
+    return existing;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Set a configuration property
 bool Importer::SetPropertyMatrix(const char* szName, const aiMatrix4x4& value)
 {
-    bool exising;
+    bool existing;
     ASSIMP_BEGIN_EXCEPTION_REGION();
-        exising = SetGenericProperty<aiMatrix4x4>(pimpl->mMatrixProperties, szName,value);
+        existing = SetGenericProperty<aiMatrix4x4>(pimpl->mMatrixProperties, szName,value);
     ASSIMP_END_EXCEPTION_REGION(bool);
-    return exising;
+    return existing;
 }
 
 // ------------------------------------------------------------------------------------------------

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

@@ -317,7 +317,7 @@ void TempMesh::FixupFaceOrientation()
         IfcVector3 farthestCenter = std::accumulate(mVerts.begin() + faceStartIndices[farthestIndex],
             mVerts.begin() + faceStartIndices[farthestIndex] + mVertcnt[farthestIndex], IfcVector3(0.0))
             / IfcFloat(mVertcnt[farthestIndex]);
-        // We accapt a bit of negative orientation without reversing. In case of doubt, prefer the orientation given in
+        // We accept a bit of negative orientation without reversing. In case of doubt, prefer the orientation given in
         // the file.
         if( (farthestNormal * (farthestCenter - vavg).Normalize()) < -0.4 )
         {

+ 10 - 10
code/Importer/IFC/STEPFileReader.cpp

@@ -126,7 +126,7 @@ STEP::DB* STEP::ReadFileHeader(std::shared_ptr<IOStream> stream)
 
                 // XXX need support for multiple schemas?
                 if (list->GetSize() > 1)    {
-                    DefaultLogger::get()->warn(AddLineNumber("multiple schemas currently not supported",line));
+                    ASSIMP_LOG_WARN(AddLineNumber("multiple schemas currently not supported",line));
                 }
                 const EXPRESS::STRING* string( nullptr );
                 if (!list->GetSize() || !(string=dynamic_cast<const EXPRESS::STRING*>( (*list)[0].get() ))) {
@@ -192,7 +192,7 @@ void STEP::ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme,
         // LineSplitter already ignores empty lines
         ai_assert(s.length());
         if (s[0] != '#') {
-            DefaultLogger::get()->warn(AddLineNumber("expected token \'#\'",line));
+            ASSIMP_LOG_WARN(AddLineNumber("expected token \'#\'",line));
             ++splitter;
             continue;
         }
@@ -202,14 +202,14 @@ void STEP::ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme,
         // ---
         const std::string::size_type n0 = s.find_first_of('=');
         if (n0 == std::string::npos) {
-            DefaultLogger::get()->warn(AddLineNumber("expected token \'=\'",line));
+            ASSIMP_LOG_WARN(AddLineNumber("expected token \'=\'",line));
             ++splitter;
             continue;
         }
 
         const uint64_t id = strtoul10_64(s.substr(1,n0-1).c_str());
         if (!id) {
-            DefaultLogger::get()->warn(AddLineNumber("expected positive, numeric entity id",line));
+            ASSIMP_LOG_WARN(AddLineNumber("expected positive, numeric entity id",line));
             ++splitter;
             continue;
         }
@@ -236,7 +236,7 @@ void STEP::ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme,
             }
 
             if(!ok) {
-                DefaultLogger::get()->warn(AddLineNumber("expected token \'(\'",line));
+                ASSIMP_LOG_WARN(AddLineNumber("expected token \'(\'",line));
                 continue;
             }
         }
@@ -263,13 +263,13 @@ void STEP::ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme,
                 }
             }
             if(!ok) {
-                DefaultLogger::get()->warn(AddLineNumber("expected token \')\'",line));
+                ASSIMP_LOG_WARN(AddLineNumber("expected token \')\'",line));
                 continue;
             }
         }
 
         if (map.find(id) != map.end()) {
-            DefaultLogger::get()->warn(AddLineNumber((Formatter::format(),"an object with the id #",id," already exists"),line));
+            ASSIMP_LOG_WARN(AddLineNumber((Formatter::format(),"an object with the id #",id," already exists"),line));
         }
 
         std::string::size_type ns = n0;
@@ -292,11 +292,11 @@ void STEP::ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme,
     }
 
     if (!splitter) {
-        DefaultLogger::get()->warn("STEP: ignoring unexpected EOF");
+        ASSIMP_LOG_WARN("STEP: ignoring unexpected EOF");
     }
 
     if ( !DefaultLogger::isNullLogger()){
-        DefaultLogger::get()->debug((Formatter::format(),"STEP: got ",map.size()," object records with ",
+        ASSIMP_LOG_DEBUG((Formatter::format(),"STEP: got ",map.size()," object records with ",
             db.GetRefs().size()," inverse index entries"));
     }
 }
@@ -392,7 +392,7 @@ std::shared_ptr<const EXPRESS::DataType> EXPRESS::DataType::Parse(const char*& i
         std::string stemp = std::string(start, static_cast<size_t>(cur - start));
         if(!StringToUTF8(stemp)) {
             // TODO: route this to a correct logger with line numbers etc., better error messages
-            DefaultLogger::get()->error("an error occurred reading escape sequences in ASCII text");
+            ASSIMP_LOG_ERROR("an error occurred reading escape sequences in ASCII text");
         }
 
         return std::make_shared<EXPRESS::STRING>(stemp);

+ 7 - 15
code/ImproveCacheLocality.cpp

@@ -95,11 +95,11 @@ void ImproveCacheLocalityProcess::SetupProperties(const Importer* pImp)
 void ImproveCacheLocalityProcess::Execute( aiScene* pScene)
 {
     if (!pScene->mNumMeshes) {
-        DefaultLogger::get()->debug("ImproveCacheLocalityProcess skipped; there are no meshes");
+        ASSIMP_LOG_DEBUG("ImproveCacheLocalityProcess skipped; there are no meshes");
         return;
     }
 
-    DefaultLogger::get()->debug("ImproveCacheLocalityProcess begin");
+    ASSIMP_LOG_DEBUG("ImproveCacheLocalityProcess begin");
 
     float out = 0.f;
     unsigned int numf = 0, numm = 0;
@@ -112,12 +112,8 @@ void ImproveCacheLocalityProcess::Execute( aiScene* pScene)
         }
     }
     if (!DefaultLogger::isNullLogger()) {
-        char szBuff[128]; // should be sufficiently large in every case
-        ai_snprintf(szBuff,128,"Cache relevant are %u meshes (%u faces). Average output ACMR is %f",
-            numm,numf,out/numf);
-
-        DefaultLogger::get()->info(szBuff);
-        DefaultLogger::get()->debug("ImproveCacheLocalityProcess finished. ");
+        ASSIMP_LOG_INFO_F("Cache relevant are ", numm, " meshes (", numf," faces). Average output ACMR is ", out / numf );
+        ASSIMP_LOG_DEBUG("ImproveCacheLocalityProcess finished. ");
     }
 }
 
@@ -135,7 +131,7 @@ float ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int mesh
         return 0.f;
 
     if (pMesh->mPrimitiveTypes != aiPrimitiveType_TRIANGLE) {
-        DefaultLogger::get()->error("This algorithm works on triangle meshes only");
+        ASSIMP_LOG_ERROR("This algorithm works on triangle meshes only");
         return 0.f;
     }
 
@@ -186,7 +182,7 @@ float ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int mesh
             // mesh, otherwise this value would normally be at least minimally
             // smaller than 3.0 ...
             ai_snprintf(szBuff,128,"Mesh %u: Not suitable for vcache optimization",meshNum);
-            DefaultLogger::get()->warn(szBuff);
+            ASSIMP_LOG_WARN(szBuff);
             return 0.f;
         }
     }
@@ -364,11 +360,7 @@ float ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int mesh
 
         // very intense verbose logging ... prepare for much text if there are many meshes
         if ( DefaultLogger::get()->getLogSeverity() == Logger::VERBOSE) {
-            char szBuff[128]; // should be sufficiently large in every case
-
-            ai_snprintf(szBuff,128,"Mesh %u | ACMR in: %f out: %f | ~%.1f%%",meshNum,fACMR,fACMR2,
-                ((fACMR - fACMR2) / fACMR) * 100.f);
-            DefaultLogger::get()->debug(szBuff);
+            ASSIMP_LOG_DEBUG_F("Mesh %u | ACMR in: ", meshNum, " out: ", fACMR, " | ~", fACMR2, ((fACMR - fACMR2) / fACMR) * 100.f);
         }
 
         fACMR2 *= pMesh->mNumFaces;

+ 113 - 118
code/JoinVerticesProcess.cpp

@@ -79,7 +79,7 @@ bool JoinVerticesProcess::IsActive( unsigned int pFlags) const
 // Executes the post processing step on the given imported data.
 void JoinVerticesProcess::Execute( aiScene* pScene)
 {
-    DefaultLogger::get()->debug("JoinVerticesProcess begin");
+    ASSIMP_LOG_DEBUG("JoinVerticesProcess begin");
 
     // get the total number of vertices BEFORE the step is executed
     int iNumOldVertices = 0;
@@ -95,19 +95,13 @@ void JoinVerticesProcess::Execute( aiScene* pScene)
         iNumVertices += ProcessMesh( pScene->mMeshes[a],a);
 
     // if logging is active, print detailed statistics
-    if (!DefaultLogger::isNullLogger())
-    {
-        if (iNumOldVertices == iNumVertices)
-        {
-            DefaultLogger::get()->debug("JoinVerticesProcess finished ");
-        } else
-        {
-            char szBuff[128]; // should be sufficiently large in every case
-            ::ai_snprintf(szBuff,128,"JoinVerticesProcess finished | Verts in: %i out: %i | ~%.1f%%",
-                iNumOldVertices,
-                iNumVertices,
-                ((iNumOldVertices - iNumVertices) / (float)iNumOldVertices) * 100.f);
-            DefaultLogger::get()->info(szBuff);
+    if (!DefaultLogger::isNullLogger()) {
+        if (iNumOldVertices == iNumVertices) {
+            ASSIMP_LOG_DEBUG("JoinVerticesProcess finished ");
+        } else {
+            ASSIMP_LOG_INFO_F("JoinVerticesProcess finished | Verts in: ", iNumOldVertices,
+                " out: ", iNumVertices, " | ~",
+                ((iNumOldVertices - iNumVertices) / (float)iNumOldVertices) * 100.f );
         }
     }
 
@@ -118,118 +112,118 @@ namespace {
 
 bool areVerticesEqual(const Vertex &lhs, const Vertex &rhs, bool complex)
 {
-  // A little helper to find locally close vertices faster.
-  // Try to reuse the lookup table from the last step.
-  const static float epsilon = 1e-5f;
-  // Squared because we check against squared length of the vector difference
-  static const float squareEpsilon = epsilon * epsilon;
-
-  // Square compare is useful for animeshes vertexes compare
-  if ((lhs.position - rhs.position).SquareLength() > squareEpsilon) {
-    return false;
-  }
-
-  // We just test the other attributes even if they're not present in the mesh.
-  // In this case they're initialized to 0 so the comparison succeeds.
-  // By this method the non-present attributes are effectively ignored in the comparison.
-  if ((lhs.normal - rhs.normal).SquareLength() > squareEpsilon) {
-    return false;
-  }
-
-  if ((lhs.texcoords[0] - rhs.texcoords[0]).SquareLength() > squareEpsilon) {
-    return false;
-  }
-
-  if ((lhs.tangent - rhs.tangent).SquareLength() > squareEpsilon) {
-    return false;
-  }
-
-  if ((lhs.bitangent - rhs.bitangent).SquareLength() > squareEpsilon) {
-    return false;
-  }
-
-  // Usually we won't have vertex colors or multiple UVs, so we can skip from here
-  // Actually this increases runtime performance slightly, at least if branch
-  // prediction is on our side.
-  if (complex) {
-    for (int i = 0; i < 8; i++) {
-      if (i > 0 && (lhs.texcoords[i] - rhs.texcoords[i]).SquareLength() > squareEpsilon) {
+    // A little helper to find locally close vertices faster.
+    // Try to reuse the lookup table from the last step.
+    const static float epsilon = 1e-5f;
+    // Squared because we check against squared length of the vector difference
+    static const float squareEpsilon = epsilon * epsilon;
+
+    // Square compare is useful for animeshes vertices compare
+    if ((lhs.position - rhs.position).SquareLength() > squareEpsilon) {
+        return false;
+    }
+
+    // We just test the other attributes even if they're not present in the mesh.
+    // In this case they're initialized to 0 so the comparison succeeds.
+    // By this method the non-present attributes are effectively ignored in the comparison.
+    if ((lhs.normal - rhs.normal).SquareLength() > squareEpsilon) {
+        return false;
+    }
+
+    if ((lhs.texcoords[0] - rhs.texcoords[0]).SquareLength() > squareEpsilon) {
         return false;
-      }
-      if (GetColorDifference(lhs.colors[i], rhs.colors[i]) > squareEpsilon) {
+    }
+
+    if ((lhs.tangent - rhs.tangent).SquareLength() > squareEpsilon) {
         return false;
-      }
     }
-  }
-  return true;
+
+    if ((lhs.bitangent - rhs.bitangent).SquareLength() > squareEpsilon) {
+        return false;
+    }
+
+    // Usually we won't have vertex colors or multiple UVs, so we can skip from here
+    // Actually this increases runtime performance slightly, at least if branch
+    // prediction is on our side.
+    if (complex) {
+        for (int i = 0; i < 8; i++) {
+            if (i > 0 && (lhs.texcoords[i] - rhs.texcoords[i]).SquareLength() > squareEpsilon) {
+                return false;
+            }
+            if (GetColorDifference(lhs.colors[i], rhs.colors[i]) > squareEpsilon) {
+                return false;
+            }
+        }
+    }
+    return true;
 }
 
 template<class XMesh>
 void updateXMeshVertices(XMesh *pMesh, std::vector<Vertex> &uniqueVertices) {
-  // replace vertex data with the unique data sets
-  pMesh->mNumVertices = (unsigned int)uniqueVertices.size();
-
-  // ----------------------------------------------------------------------------
-  // NOTE - we're *not* calling Vertex::SortBack() because it would check for
-  // presence of every single vertex component once PER VERTEX. And our CPU
-  // dislikes branches, even if they're easily predictable.
-  // ----------------------------------------------------------------------------
-
-  // Position, if present (check made for aiAnimMesh)
-  if (pMesh->mVertices)
-  {
-    delete [] pMesh->mVertices;
-    pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
-    for (unsigned int a = 0; a < pMesh->mNumVertices; a++) {
-      pMesh->mVertices[a] = uniqueVertices[a].position;
+    // replace vertex data with the unique data sets
+    pMesh->mNumVertices = (unsigned int)uniqueVertices.size();
+
+    // ----------------------------------------------------------------------------
+    // NOTE - we're *not* calling Vertex::SortBack() because it would check for
+    // presence of every single vertex component once PER VERTEX. And our CPU
+    // dislikes branches, even if they're easily predictable.
+    // ----------------------------------------------------------------------------
+
+    // Position, if present (check made for aiAnimMesh)
+    if (pMesh->mVertices)
+    {
+        delete [] pMesh->mVertices;
+        pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
+        for (unsigned int a = 0; a < pMesh->mNumVertices; a++) {
+            pMesh->mVertices[a] = uniqueVertices[a].position;
+        }
     }
-  }
-
-  // Normals, if present
-  if (pMesh->mNormals)
-  {
-    delete [] pMesh->mNormals;
-    pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
-    for( unsigned int a = 0; a < pMesh->mNumVertices; a++) {
-      pMesh->mNormals[a] = uniqueVertices[a].normal;
+
+    // Normals, if present
+    if (pMesh->mNormals)
+    {
+        delete [] pMesh->mNormals;
+        pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
+        for( unsigned int a = 0; a < pMesh->mNumVertices; a++) {
+            pMesh->mNormals[a] = uniqueVertices[a].normal;
+        }
     }
-  }
-  // Tangents, if present
-  if (pMesh->mTangents)
-  {
-    delete [] pMesh->mTangents;
-    pMesh->mTangents = new aiVector3D[pMesh->mNumVertices];
-    for (unsigned int a = 0; a < pMesh->mNumVertices; a++) {
-      pMesh->mTangents[a] = uniqueVertices[a].tangent;
+    // Tangents, if present
+    if (pMesh->mTangents)
+    {
+        delete [] pMesh->mTangents;
+        pMesh->mTangents = new aiVector3D[pMesh->mNumVertices];
+        for (unsigned int a = 0; a < pMesh->mNumVertices; a++) {
+            pMesh->mTangents[a] = uniqueVertices[a].tangent;
+        }
     }
-  }
-  // Bitangents as well
-  if (pMesh->mBitangents)
-  {
-    delete [] pMesh->mBitangents;
-    pMesh->mBitangents = new aiVector3D[pMesh->mNumVertices];
-    for (unsigned int a = 0; a < pMesh->mNumVertices; a++) {
-      pMesh->mBitangents[a] = uniqueVertices[a].bitangent;
+    // Bitangents as well
+    if (pMesh->mBitangents)
+    {
+        delete [] pMesh->mBitangents;
+        pMesh->mBitangents = new aiVector3D[pMesh->mNumVertices];
+        for (unsigned int a = 0; a < pMesh->mNumVertices; a++) {
+            pMesh->mBitangents[a] = uniqueVertices[a].bitangent;
+        }
     }
-  }
-  // Vertex colors
-  for (unsigned int a = 0; pMesh->HasVertexColors(a); a++)
-  {
-    delete [] pMesh->mColors[a];
-    pMesh->mColors[a] = new aiColor4D[pMesh->mNumVertices];
-    for( unsigned int b = 0; b < pMesh->mNumVertices; b++) {
-      pMesh->mColors[a][b] = uniqueVertices[b].colors[a];
+    // Vertex colors
+    for (unsigned int a = 0; pMesh->HasVertexColors(a); a++)
+    {
+        delete [] pMesh->mColors[a];
+        pMesh->mColors[a] = new aiColor4D[pMesh->mNumVertices];
+        for( unsigned int b = 0; b < pMesh->mNumVertices; b++) {
+            pMesh->mColors[a][b] = uniqueVertices[b].colors[a];
+        }
     }
-  }
-  // Texture coords
-  for (unsigned int a = 0; pMesh->HasTextureCoords(a); a++)
-  {
-    delete [] pMesh->mTextureCoords[a];
-    pMesh->mTextureCoords[a] = new aiVector3D[pMesh->mNumVertices];
-    for (unsigned int b = 0; b < pMesh->mNumVertices; b++) {
-      pMesh->mTextureCoords[a][b] = uniqueVertices[b].texcoords[a];
+    // Texture coords
+    for (unsigned int a = 0; pMesh->HasTextureCoords(a); a++)
+    {
+        delete [] pMesh->mTextureCoords[a];
+        pMesh->mTextureCoords[a] = new aiVector3D[pMesh->mNumVertices];
+        for (unsigned int b = 0; b < pMesh->mNumVertices; b++) {
+            pMesh->mTextureCoords[a][b] = uniqueVertices[b].texcoords[a];
+        }
     }
-  }
 }
 } // namespace
 
@@ -288,8 +282,9 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
     const bool hasAnimMeshes = pMesh->mNumAnimMeshes > 0;
 
     // We'll never have more vertices afterwards.
-    std::vector<Vertex> uniqueAnimatedVertices[pMesh->mNumAnimMeshes];
+    std::vector<std::vector<Vertex>> uniqueAnimatedVertices;
     if (hasAnimMeshes) {
+        uniqueAnimatedVertices.resize(pMesh->mNumAnimMeshes);
         for (unsigned int animMeshIndex = 0; animMeshIndex < pMesh->mNumAnimMeshes; animMeshIndex++) {
             uniqueAnimatedVertices[animMeshIndex].reserve(pMesh->mNumVertices);
         }
@@ -360,7 +355,7 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
     }
 
     if (!DefaultLogger::isNullLogger() && DefaultLogger::get()->getLogSeverity() == Logger::VERBOSE)    {
-        DefaultLogger::get()->debug((Formatter::format(),
+        ASSIMP_LOG_DEBUG_F(
             "Mesh ",meshIndex,
             " (",
             (pMesh->mName.length ? pMesh->mName.data : "unnamed"),
@@ -370,7 +365,7 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
             " | ~",
             ((pMesh->mNumVertices - uniqueVertices.size()) / (float)pMesh->mNumVertices) * 100.f,
             "%"
-        ));
+        );
     }
 
     updateXMeshVertices(pMesh, uniqueVertices);
@@ -407,7 +402,7 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
                 }
             }
         } else {
-            DefaultLogger::get()->error( "X-Export: aiBone shall contain weights, but pointer to them is NULL." );
+            ASSIMP_LOG_ERROR( "X-Export: aiBone shall contain weights, but pointer to them is NULL." );
         }
 
         if (newWeights.size() > 0) {
@@ -441,7 +436,7 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
             }
 
             --a;
-            DefaultLogger::get()->warn("Removing bone -> no weights remaining");
+            ASSIMP_LOG_WARN("Removing bone -> no weights remaining");
         }
     }
     return pMesh->mNumVertices;

+ 20 - 16
code/LWOBLoader.cpp

@@ -74,7 +74,7 @@ void LWOImporter::LoadLWOBFile()
         case AI_LWO_PNTS:
             {
                 if (!mCurLayer->mTempPoints.empty())
-                    DefaultLogger::get()->warn("LWO: PNTS chunk encountered twice");
+                    ASSIMP_LOG_WARN("LWO: PNTS chunk encountered twice");
                 else LoadLWOPoints(head.length);
                 break;
             }
@@ -83,7 +83,7 @@ void LWOImporter::LoadLWOBFile()
             {
 
                 if (!mCurLayer->mFaces.empty())
-                    DefaultLogger::get()->warn("LWO: POLS chunk encountered twice");
+                    ASSIMP_LOG_WARN("LWO: POLS chunk encountered twice");
                 else LoadLWOBPolygons(head.length);
                 break;
             }
@@ -91,7 +91,7 @@ void LWOImporter::LoadLWOBFile()
         case AI_LWO_SRFS:
             {
                 if (!mTags->empty())
-                    DefaultLogger::get()->warn("LWO: SRFS chunk encountered twice");
+                    ASSIMP_LOG_WARN("LWO: SRFS chunk encountered twice");
                 else LoadLWOTags(head.length);
                 break;
             }
@@ -183,20 +183,20 @@ void LWOImporter::CopyFaceIndicesLWOB(FaceList::iterator& it,
                 break;
             }
             face.mIndices = new unsigned int[face.mNumIndices];
-            for (unsigned int i = 0; i < face.mNumIndices;++i)
-            {
+            for (unsigned int i = 0; i < face.mNumIndices;++i) {
                 unsigned int & mi = face.mIndices[i];
                 uint16_t index;
                 ::memcpy(&index, cursor++, 2);
                 mi = index;
                 if (mi > mCurLayer->mTempPoints.size())
                 {
-                    DefaultLogger::get()->warn("LWOB: face index is out of range");
+                    ASSIMP_LOG_WARN("LWOB: face index is out of range");
                     mi = (unsigned int)mCurLayer->mTempPoints.size()-1;
                 }
             }
+        } else {
+            ASSIMP_LOG_WARN("LWOB: Face has 0 indices");
         }
-        else DefaultLogger::get()->warn("LWOB: Face has 0 indices");
         int16_t surface;
         ::memcpy(&surface, cursor++, 2);
         if (surface < 0)
@@ -242,7 +242,7 @@ LWO::Texture* LWOImporter::SetupNewTextureLWOB(LWO::TextureList& list,unsigned i
     else
     {
         // procedural or gradient, not supported
-        DefaultLogger::get()->error("LWOB: Unsupported legacy texture: " + type);
+        ASSIMP_LOG_ERROR_F("LWOB: Unsupported legacy texture: ", type);
     }
 
     return tex;
@@ -273,7 +273,7 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
          *  how much storage is actually left and work with this value from now on.
          */
         if (mFileBuffer + head.length > end) {
-            DefaultLogger::get()->error("LWOB: Invalid surface chunk length. Trying to continue.");
+            ASSIMP_LOG_ERROR("LWOB: Invalid surface chunk length. Trying to continue.");
             head.length = (uint16_t) (end - mFileBuffer);
         }
 
@@ -381,8 +381,9 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
             {
                 if (pTex)   {
                     GetS0(pTex->mFileName,head.length);
+                } else {
+                    ASSIMP_LOG_WARN("LWOB: Unexpected TIMG chunk");
                 }
-                else DefaultLogger::get()->warn("LWOB: Unexpected TIMG chunk");
                 break;
             }
         // texture strength
@@ -391,8 +392,9 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
                 AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TVAL,1);
                 if (pTex)   {
                     pTex->mStrength = (float)GetU1()/ 255.f;
+                } else {
+                    ASSIMP_LOG_ERROR("LWOB: Unexpected TVAL chunk");
                 }
-                else DefaultLogger::get()->warn("LWOB: Unexpected TVAL chunk");
                 break;
             }
         // texture flags
@@ -400,8 +402,7 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
             {
                 AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TFLG,2);
 
-                if (pTex)
-                {
+                if (nullptr != pTex) {
                     const uint16_t s = GetU2();
                     if (s & 1)
                         pTex->majorAxis = LWO::Texture::AXIS_X;
@@ -410,10 +411,13 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
                     else if (s & 4)
                         pTex->majorAxis = LWO::Texture::AXIS_Z;
 
-                    if (s & 16)
-                        DefaultLogger::get()->warn("LWOB: Ignoring \'negate\' flag on texture");
+                    if (s & 16) {
+                        ASSIMP_LOG_WARN("LWOB: Ignoring \'negate\' flag on texture");
+                    }
+                }
+                else {
+                    ASSIMP_LOG_WARN("LWOB: Unexpected TFLG chunk");
                 }
-                else DefaultLogger::get()->warn("LWOB: Unexpected TFLG chunk");
                 break;
             }
         }

+ 43 - 36
code/LWOLoader.cpp

@@ -188,7 +188,7 @@ void LWOImporter::InternReadFile( const std::string& pFile,
 
     // old lightwave file format (prior to v6)
     if (AI_LWO_FOURCC_LWOB == fileType) {
-        DefaultLogger::get()->info("LWO file format: LWOB (<= LightWave 5.5)");
+        ASSIMP_LOG_INFO("LWO file format: LWOB (<= LightWave 5.5)");
 
         mIsLWO2 = false;
         mIsLXOB = false;
@@ -197,12 +197,12 @@ void LWOImporter::InternReadFile( const std::string& pFile,
     // New lightwave format
     else if (AI_LWO_FOURCC_LWO2 == fileType)    {
         mIsLXOB = false;
-        DefaultLogger::get()->info("LWO file format: LWO2 (>= LightWave 6)");
+        ASSIMP_LOG_INFO("LWO file format: LWO2 (>= LightWave 6)");
     }
     // MODO file format
     else if (AI_LWO_FOURCC_LXOB == fileType)    {
         mIsLXOB = true;
-        DefaultLogger::get()->info("LWO file format: LXOB (Modo)");
+        ASSIMP_LOG_INFO("LWO file format: LXOB (Modo)");
     }
     // we don't know this format
     else
@@ -271,7 +271,7 @@ void LWOImporter::InternReadFile( const std::string& pFile,
                 unsigned int idx = (*it).surfaceIndex;
                 if (idx >= mTags->size())
                 {
-                    DefaultLogger::get()->warn("LWO: Invalid face surface index");
+                    ASSIMP_LOG_WARN("LWO: Invalid face surface index");
                     idx = UINT_MAX;
                 }
                 if(UINT_MAX == idx || UINT_MAX == (idx = _mMapping[idx]))   {
@@ -423,7 +423,9 @@ void LWOImporter::InternReadFile( const std::string& pFile,
                     // So we use a separate implementation.
                     ComputeNormals(mesh,smoothingGroups,_mSurfaces[i]);
                 }
-                else DefaultLogger::get()->debug("LWO2: No need to compute normals, they're already there");
+                else {
+                    ASSIMP_LOG_DEBUG("LWO2: No need to compute normals, they're already there");
+                }
                 ++p;
             }
         }
@@ -686,13 +688,13 @@ void LWOImporter::ResolveClips()
         if (Clip::REF == clip.type) {
 
             if (clip.clipRef >= mClips.size())  {
-                DefaultLogger::get()->error("LWO2: Clip referrer index is out of range");
+                ASSIMP_LOG_ERROR("LWO2: Clip referrer index is out of range");
                 clip.clipRef = 0;
             }
 
             Clip& dest = mClips[clip.clipRef];
             if (Clip::REF == dest.type) {
-                DefaultLogger::get()->error("LWO2: Clip references another clip reference");
+                ASSIMP_LOG_ERROR("LWO2: Clip references another clip reference");
                 clip.type = Clip::UNSUPPORTED;
             }
 
@@ -711,7 +713,7 @@ void LWOImporter::AdjustTexturePath(std::string& out)
     if (!mIsLWO2 && ::strstr(out.c_str(), "(sequence)"))    {
 
         // remove the (sequence) and append 000
-        DefaultLogger::get()->info("LWOB: Sequence of animated texture found. It will be ignored");
+        ASSIMP_LOG_INFO("LWOB: Sequence of animated texture found. It will be ignored");
         out = out.substr(0,out.length()-10) + "000";
     }
 
@@ -786,10 +788,10 @@ void LWOImporter::LoadLWO2Polygons(unsigned int length)
     {
         // read unsupported stuff too (although we won't process it)
     case  AI_LWO_MBAL:
-        DefaultLogger::get()->warn("LWO2: Encountered unsupported primitive chunk (METABALL)");
+        ASSIMP_LOG_WARN("LWO2: Encountered unsupported primitive chunk (METABALL)");
         break;
     case  AI_LWO_CURV:
-        DefaultLogger::get()->warn("LWO2: Encountered unsupported primitive chunk (SPLINE)");;
+        ASSIMP_LOG_WARN("LWO2: Encountered unsupported primitive chunk (SPLINE)");;
         break;
 
         // These are ok with no restrictions
@@ -801,7 +803,7 @@ void LWOImporter::LoadLWO2Polygons(unsigned int length)
     default:
 
         // hm!? wtf is this? ok ...
-        DefaultLogger::get()->error("LWO2: Ignoring unknown polygon type.");
+        ASSIMP_LOG_ERROR("LWO2: Ignoring unknown polygon type.");
         break;
     }
 
@@ -864,7 +866,7 @@ void LWOImporter::CopyFaceIndicesLWO2(FaceList::iterator& it,
                 face.mIndices[i] = ReadVSizedIntLWO2((uint8_t*&)cursor) + mCurLayer->mPointIDXOfs;
                 if(face.mIndices[i] > mCurLayer->mTempPoints.size())
                 {
-                    DefaultLogger::get()->warn("LWO2: Failure evaluating face record, index is out of range");
+                    ASSIMP_LOG_WARN("LWO2: Failure evaluating face record, index is out of range");
                     face.mIndices[i] = (unsigned int)mCurLayer->mTempPoints.size()-1;
                 }
             }
@@ -891,7 +893,7 @@ void LWOImporter::LoadLWO2PolygonTags(unsigned int length)
         unsigned int j = GetU2();
 
         if (i >= mCurLayer->mFaces.size())  {
-            DefaultLogger::get()->warn("LWO2: face index in PTAG is out of range");
+            ASSIMP_LOG_WARN("LWO2: face index in PTAG is out of range");
             continue;
         }
 
@@ -914,7 +916,7 @@ VMapEntry* FindEntry(std::vector< T >& list,const std::string& name, bool perPol
     for (auto & elem : list)   {
         if (elem.name == name) {
             if (!perPoly)   {
-                DefaultLogger::get()->warn("LWO2: Found two VMAP sections with equal names");
+                ASSIMP_LOG_WARN("LWO2: Found two VMAP sections with equal names");
             }
             return &elem;
         }
@@ -999,7 +1001,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly)
     {
     case AI_LWO_TXUV:
         if (dims != 2)  {
-            DefaultLogger::get()->warn("LWO2: Skipping UV channel \'"
+            ASSIMP_LOG_WARN("LWO2: Skipping UV channel \'"
             + name + "\' with !2 components");
             return;
         }
@@ -1008,7 +1010,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly)
     case AI_LWO_WGHT:
     case AI_LWO_MNVW:
         if (dims != 1)  {
-            DefaultLogger::get()->warn("LWO2: Skipping Weight Channel \'"
+            ASSIMP_LOG_WARN("LWO2: Skipping Weight Channel \'"
             + name + "\' with !1 components");
             return;
         }
@@ -1018,7 +1020,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly)
     case AI_LWO_RGB:
     case AI_LWO_RGBA:
         if (dims != 3 && dims != 4) {
-            DefaultLogger::get()->warn("LWO2: Skipping Color Map \'"
+            ASSIMP_LOG_WARN("LWO2: Skipping Color Map \'"
             + name + "\' with a dimension > 4 or < 3");
             return;
         }
@@ -1033,7 +1035,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly)
         if (name != "vert_normals" || dims != 3 || mCurLayer->mNormals.name.length())
             return;
 
-        DefaultLogger::get()->info("Processing non-standard extension: MODO VMAP.NORM.vert_normals");
+        ASSIMP_LOG_INFO("Processing non-standard extension: MODO VMAP.NORM.vert_normals");
 
         mCurLayer->mNormals.name = name;
         base = & mCurLayer->mNormals;
@@ -1048,7 +1050,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly)
         if (name == "APS.Level") {
             // XXX handle this (seems to be subdivision-related).
         }
-        DefaultLogger::get()->warn("LWO2: Skipping unknown VMAP/VMAD channel \'" + name + "\'");
+        ASSIMP_LOG_WARN_F("LWO2: Skipping unknown VMAP/VMAD channel \'", name, "\'");
         return;
     };
     base->Allocate((unsigned int)mCurLayer->mTempPoints.size());
@@ -1068,7 +1070,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly)
 
         unsigned int idx = ReadVSizedIntLWO2(mFileBuffer) + mCurLayer->mPointIDXOfs;
         if (idx >= numPoints)   {
-            DefaultLogger::get()->warn("LWO2: Failure evaluating VMAP/VMAD entry \'" + name + "\', vertex index is out of range");
+            ASSIMP_LOG_WARN_F("LWO2: Failure evaluating VMAP/VMAD entry \'", name, "\', vertex index is out of range");
             mFileBuffer += base->dims<<2u;
             continue;
         }
@@ -1078,7 +1080,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly)
                 // we have already a VMAP entry for this vertex - thus
                 // we need to duplicate the corresponding polygon.
                 if (polyIdx >= numFaces)    {
-                    DefaultLogger::get()->warn("LWO2: Failure evaluating VMAD entry \'" + name + "\', polygon index is out of range");
+                    ASSIMP_LOG_WARN_F("LWO2: Failure evaluating VMAD entry \'", name, "\', polygon index is out of range");
                     mFileBuffer += base->dims<<2u;
                     continue;
                 }
@@ -1119,7 +1121,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly)
                     CreateNewEntry(mCurLayer->mNormals, srcIdx );
                 }
                 if (!had) {
-                    DefaultLogger::get()->warn("LWO2: Failure evaluating VMAD entry \'" + name + "\', vertex index wasn't found in that polygon");
+                    ASSIMP_LOG_WARN_F("LWO2: Failure evaluating VMAD entry \'", name, "\', vertex index wasn't found in that polygon");
                     ai_assert(had);
                 }
             }
@@ -1180,11 +1182,11 @@ void LWOImporter::LoadLWO2Clip(unsigned int length)
         break;
 
     case AI_LWO_STCC:
-        DefaultLogger::get()->warn("LWO2: Color shifted images are not supported");
+        ASSIMP_LOG_WARN("LWO2: Color shifted images are not supported");
         break;
 
     case AI_LWO_ANIM:
-        DefaultLogger::get()->warn("LWO2: Animated textures are not supported");
+        ASSIMP_LOG_WARN("LWO2: Animated textures are not supported");
         break;
 
     case AI_LWO_XREF:
@@ -1201,7 +1203,7 @@ void LWOImporter::LoadLWO2Clip(unsigned int length)
         break;
 
     default:
-        DefaultLogger::get()->warn("LWO2: Encountered unknown CLIP subchunk");
+        ASSIMP_LOG_WARN("LWO2: Encountered unknown CLIP sub-chunk");
     }
 }
 
@@ -1282,7 +1284,7 @@ void LWOImporter::LoadLWO2Envelope(unsigned int length)
             {
                 AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SPAN,4);
                 if (envelope.keys.size()<2)
-                    DefaultLogger::get()->warn("LWO2: Unexpected SPAN chunk");
+                    ASSIMP_LOG_WARN("LWO2: Unexpected SPAN chunk");
                 else {
                     LWO::Key& key = envelope.keys.back();
                     switch (GetU4())
@@ -1300,7 +1302,7 @@ void LWOImporter::LoadLWO2Envelope(unsigned int length)
                         case AI_LWO_BEZ2:
                             key.inter = LWO::IT_BEZ2;break;
                         default:
-                            DefaultLogger::get()->warn("LWO2: Unknown interval interpolation mode");
+                            ASSIMP_LOG_WARN("LWO2: Unknown interval interpolation mode");
                     };
 
                     // todo ... read params
@@ -1309,7 +1311,8 @@ void LWOImporter::LoadLWO2Envelope(unsigned int length)
             }
 
         default:
-            DefaultLogger::get()->warn("LWO2: Encountered unknown ENVL subchunk");
+            ASSIMP_LOG_WARN("LWO2: Encountered unknown ENVL subchunk");
+            break;
         }
         // regardless how much we did actually read, go to the next chunk
         mFileBuffer = next;
@@ -1408,7 +1411,7 @@ void LWOImporter::LoadLWO2File()
         case AI_LWO_VMAD:
             if (mCurLayer->mFaces.empty())
             {
-                DefaultLogger::get()->warn("LWO2: Unexpected VMAD chunk");
+                ASSIMP_LOG_WARN("LWO2: Unexpected VMAD chunk");
                 break;
             }
             // --- intentionally no break here
@@ -1418,7 +1421,7 @@ void LWOImporter::LoadLWO2File()
                     break;
 
                 if (mCurLayer->mTempPoints.empty())
-                    DefaultLogger::get()->warn("LWO2: Unexpected VMAP chunk");
+                    ASSIMP_LOG_WARN("LWO2: Unexpected VMAP chunk");
                 else LoadLWO2VertexMap(head.length,head.type == AI_LWO_VMAD);
                 break;
             }
@@ -1439,17 +1442,21 @@ void LWOImporter::LoadLWO2File()
                 if (skip)
                     break;
 
-                if (mCurLayer->mFaces.empty())
-                    DefaultLogger::get()->warn("LWO2: Unexpected PTAG");
-                else LoadLWO2PolygonTags(head.length);
+                if (mCurLayer->mFaces.empty()) {
+                    ASSIMP_LOG_WARN("LWO2: Unexpected PTAG");
+                } else {
+                    LoadLWO2PolygonTags(head.length);
+                }
                 break;
             }
             // list of tags
         case AI_LWO_TAGS:
             {
-                if (!mTags->empty())
-                    DefaultLogger::get()->warn("LWO2: SRFS chunk encountered twice");
-                else LoadLWOTags(head.length);
+                if (!mTags->empty()) {
+                    ASSIMP_LOG_WARN("LWO2: SRFS chunk encountered twice");
+                }   else {
+                    LoadLWOTags(head.length);
+                }
                 break;
             }
 

+ 1 - 1
code/LWOLoader.h

@@ -473,7 +473,7 @@ inline void LWOImporter::GetS0(std::string& out,unsigned int max)
     {
         if (++iCursor > max)
         {
-            DefaultLogger::get()->warn("LWO: Invalid file, string is is too long");
+            ASSIMP_LOG_WARN("LWO: Invalid file, string is is too long");
             break;
         }
         ++mFileBuffer;

+ 24 - 22
code/LWOMaterial.cpp

@@ -74,7 +74,7 @@ inline aiTextureMapMode GetMapMode(LWO::Texture::Wrap in)
             return aiTextureMapMode_Mirror;
 
         case LWO::Texture::RESET:
-            DefaultLogger::get()->warn("LWO2: Unsupported texture map mode: RESET");
+            ASSIMP_LOG_WARN("LWO2: Unsupported texture map mode: RESET");
 
             // fall though here
         case LWO::Texture::EDGE:
@@ -117,7 +117,7 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
                 mapping = aiTextureMapping_BOX;
                 break;
             case LWO::Texture::FrontProjection:
-                DefaultLogger::get()->error("LWO2: Unsupported texture mapping: FrontProjection");
+                ASSIMP_LOG_ERROR("LWO2: Unsupported texture mapping: FrontProjection");
                 mapping = aiTextureMapping_OTHER;
                 break;
             case LWO::Texture::UV:
@@ -164,7 +164,7 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
                 static_assert(sizeof(aiUVTransform)/sizeof(ai_real) == 5, "sizeof(aiUVTransform)/sizeof(ai_real) == 5");
                 pcMat->AddProperty(&trafo,1,AI_MATKEY_UVTRANSFORM(type,cur));
             }
-            DefaultLogger::get()->debug("LWO2: Setting up non-UV mapping");
+            ASSIMP_LOG_DEBUG("LWO2: Setting up non-UV mapping");
         }
 
         // The older LWOB format does not use indirect references to clips.
@@ -181,7 +181,7 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
 
             }
             if (candidate == end)   {
-                DefaultLogger::get()->error("LWO2: Clip index is out of bounds");
+                ASSIMP_LOG_ERROR("LWO2: Clip index is out of bounds");
                 temp = 0;
 
                 // fixme: apparently some LWO files shipping with Doom3 don't
@@ -194,7 +194,7 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
             }
             else {
                 if (Clip::UNSUPPORTED == (*candidate).type) {
-                    DefaultLogger::get()->error("LWO2: Clip type is not supported");
+                    ASSIMP_LOG_ERROR("LWO2: Clip type is not supported");
                     continue;
                 }
                 AdjustTexturePath((*candidate).path);
@@ -212,7 +212,7 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
         {
             std::string ss = texture.mFileName;
             if (!ss.length()) {
-                DefaultLogger::get()->error("LWOB: Empty file name");
+                ASSIMP_LOG_WARN("LWOB: Empty file name");
                 continue;
             }
             AdjustTexturePath(ss);
@@ -246,14 +246,15 @@ bool LWOImporter::HandleTextures(aiMaterial* pcMat, const TextureList& in, aiTex
 
             default:
                 temp = (unsigned int)aiTextureOp_Multiply;
-                DefaultLogger::get()->warn("LWO2: Unsupported texture blend mode: alpha or displacement");
+                ASSIMP_LOG_WARN("LWO2: Unsupported texture blend mode: alpha or displacement");
 
         }
         // Setup texture operation
         pcMat->AddProperty<int>((int*)&temp,1,AI_MATKEY_TEXOP(type,cur));
 
         // setup the mapping mode
-        pcMat->AddProperty<int>((int*)&mapping,1,AI_MATKEY_MAPPING(type,cur));
+        int mapping_ = static_cast<int>(mapping);
+        pcMat->AddProperty<int>(&mapping_, 1, AI_MATKEY_MAPPING(type, cur));
 
         // add the u-wrapping
         temp = (unsigned int)GetMapMode(texture.wrapModeWidth);
@@ -347,25 +348,26 @@ void LWOImporter::ConvertMaterial(const LWO::Surface& surf,aiMaterial* pcMat)
     // the surface and  search for a name which we know ...
     for (const auto &shader : surf.mShaders)   {
         if (shader.functionName == "LW_SuperCelShader" || shader.functionName == "AH_CelShader")  {
-            DefaultLogger::get()->info("LWO2: Mapping LW_SuperCelShader/AH_CelShader to aiShadingMode_Toon");
+            ASSIMP_LOG_INFO("LWO2: Mapping LW_SuperCelShader/AH_CelShader to aiShadingMode_Toon");
 
             m = aiShadingMode_Toon;
             break;
         }
         else if (shader.functionName == "LW_RealFresnel" || shader.functionName == "LW_FastFresnel")  {
-            DefaultLogger::get()->info("LWO2: Mapping LW_RealFresnel/LW_FastFresnel to aiShadingMode_Fresnel");
+            ASSIMP_LOG_INFO("LWO2: Mapping LW_RealFresnel/LW_FastFresnel to aiShadingMode_Fresnel");
 
             m = aiShadingMode_Fresnel;
             break;
         }
         else
         {
-            DefaultLogger::get()->warn("LWO2: Unknown surface shader: " + shader.functionName);
+            ASSIMP_LOG_WARN_F("LWO2: Unknown surface shader: ", shader.functionName);
         }
     }
     if (surf.mMaximumSmoothAngle <= 0.0)
         m = aiShadingMode_Flat;
-    pcMat->AddProperty((int*)&m,1,AI_MATKEY_SHADING_MODEL);
+    int m_ = static_cast<int>(m);
+    pcMat->AddProperty(&m_, 1, AI_MATKEY_SHADING_MODEL);
 
     // (the diffuse value is just a scaling factor)
     // If a diffuse texture is set, we set this value to 1.0
@@ -398,7 +400,7 @@ char LWOImporter::FindUVChannels(LWO::TextureList& list,
             }
             else {
                 // channel mismatch. need to duplicate the material.
-                DefaultLogger::get()->warn("LWO: Channel mismatch, would need to duplicate surface [design bug]");
+                ASSIMP_LOG_WARN("LWO: Channel mismatch, would need to duplicate surface [design bug]");
 
                 // TODO
             }
@@ -429,7 +431,7 @@ void LWOImporter::FindUVChannels(LWO::Surface& surf,
 
                     if (extra >= AI_MAX_NUMBER_OF_TEXTURECOORDS) {
 
-                        DefaultLogger::get()->error("LWO: Maximum number of UV channels for "
+                        ASSIMP_LOG_ERROR("LWO: Maximum number of UV channels for "
                             "this mesh reached. Skipping channel \'" + uv.name + "\'");
 
                     }
@@ -502,7 +504,7 @@ void LWOImporter::FindVCChannels(const LWO::Surface& surf, LWO::SortedRep& sorte
                     if (vc.abAssigned[idx] && ((aiColor4D*)&vc.rawData[0])[idx] != aiColor4D(0.0,0.0,0.0,1.0)) {
                         if (next >= AI_MAX_NUMBER_OF_COLOR_SETS) {
 
-                            DefaultLogger::get()->error("LWO: Maximum number of vertex color channels for "
+                            ASSIMP_LOG_ERROR("LWO: Maximum number of vertex color channels for "
                                 "this mesh reached. Skipping channel \'" + vc.name + "\'");
 
                         }
@@ -567,7 +569,7 @@ void LWOImporter::LoadLWO2ImageMap(unsigned int size, LWO::Texture& tex )
 void LWOImporter::LoadLWO2Procedural(unsigned int /*size*/, LWO::Texture& tex )
 {
     // --- not supported at the moment
-    DefaultLogger::get()->error("LWO2: Found procedural texture, this is not supported");
+    ASSIMP_LOG_ERROR("LWO2: Found procedural texture, this is not supported");
     tex.bCanUse = false;
 }
 
@@ -575,7 +577,7 @@ void LWOImporter::LoadLWO2Procedural(unsigned int /*size*/, LWO::Texture& tex )
 void LWOImporter::LoadLWO2Gradient(unsigned int /*size*/, LWO::Texture& tex  )
 {
     // --- not supported at the moment
-    DefaultLogger::get()->error("LWO2: Found gradient texture, this is not supported");
+    ASSIMP_LOG_ERROR("LWO2: Found gradient texture, this is not supported");
     tex.bCanUse = false;
 }
 
@@ -590,7 +592,7 @@ void LWOImporter::LoadLWO2TextureHeader(unsigned int size, LWO::Texture& tex )
     // we could crash later if this is an empty string ...
     if (!tex.ordinal.length())
     {
-        DefaultLogger::get()->error("LWO2: Ill-formed SURF.BLOK ordinal string");
+        ASSIMP_LOG_ERROR("LWO2: Ill-formed SURF.BLOK ordinal string");
         tex.ordinal = "\x00";
     }
     while (true)
@@ -662,7 +664,7 @@ void LWOImporter::LoadLWO2TextureBlock(LE_NCONST IFF::SubChunkHeader* head, unsi
     case AI_LWO_REFL:
         listRef = &surf.mReflectionTextures;break;
     default:
-        DefaultLogger::get()->warn("LWO2: Encountered unknown texture type");
+        ASSIMP_LOG_WARN("LWO2: Encountered unknown texture type");
         return;
     }
 
@@ -691,7 +693,7 @@ void LWOImporter::LoadLWO2ShaderBlock(LE_NCONST IFF::SubChunkHeader* /*head*/, u
     // we could crash later if this is an empty string ...
     if (!shader.ordinal.length())
     {
-        DefaultLogger::get()->error("LWO2: Ill-formed SURF.BLOK ordinal string");
+        ASSIMP_LOG_ERROR("LWO2: Ill-formed SURF.BLOK ordinal string");
         shader.ordinal = "\x00";
     }
 
@@ -750,7 +752,7 @@ void LWOImporter::LoadLWO2Surface(unsigned int size)
             }
         }
         if (derived.size())
-            DefaultLogger::get()->warn("LWO2: Unable to find source surface: " + derived);
+            ASSIMP_LOG_WARN("LWO2: Unable to find source surface: " + derived);
     }
 
     while (true)
@@ -886,7 +888,7 @@ void LWOImporter::LoadLWO2Surface(unsigned int size)
                     break;
 
                 default:
-                    DefaultLogger::get()->warn("LWO2: Found an unsupported surface BLOK");
+                    ASSIMP_LOG_WARN("LWO2: Found an unsupported surface BLOK");
                 };
 
                 break;

+ 23 - 23
code/LWSLoader.cpp

@@ -105,7 +105,7 @@ void LWS::Element::Parse (const char*& buffer)
 
         if (children.back().tokens[0] == "Plugin")
         {
-            DefaultLogger::get()->debug("LWS: Skipping over plugin-specific data");
+            ASSIMP_LOG_DEBUG("LWS: Skipping over plugin-specific data");
 
             // strange stuff inside Plugin/Endplugin blocks. Needn't
             // follow LWS syntax, so we skip over it
@@ -200,7 +200,7 @@ void LWSImporter::SetupProperties(const Importer* pImp)
 void LWSImporter::ReadEnvelope(const LWS::Element& dad, LWO::Envelope& fill )
 {
     if (dad.children.empty()) {
-        DefaultLogger::get()->error("LWS: Envelope descriptions must not be empty");
+        ASSIMP_LOG_ERROR("LWS: Envelope descriptions must not be empty");
         return;
     }
 
@@ -248,7 +248,7 @@ void LWSImporter::ReadEnvelope(const LWS::Element& dad, LWO::Envelope& fill )
                     num = 4;
                     break;
                 default:
-                    DefaultLogger::get()->error("LWS: Unknown span type");
+                    ASSIMP_LOG_ERROR("LWS: Unknown span type");
             }
             for (unsigned int i = 0; i < num;++i) {
                 SkipSpaces(&c);
@@ -305,7 +305,7 @@ void LWSImporter::ReadEnvelope_Old(
     return;
 
 unexpected_end:
-    DefaultLogger::get()->error("LWS: Encountered unexpected end of file while parsing object motion");
+    ASSIMP_LOG_ERROR("LWS: Encountered unexpected end of file while parsing object motion");
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -352,7 +352,7 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector<Attachm
         if (src.path.length() ) {
             obj = batch.GetImport(src.id);
             if (!obj) {
-                DefaultLogger::get()->error("LWS: Failed to read external file " + src.path);
+                ASSIMP_LOG_ERROR("LWS: Failed to read external file " + src.path);
             }
             else {
                 if (obj->mRootNode->mNumChildren == 1) {
@@ -410,7 +410,7 @@ void LWSImporter::BuildGraph(aiNode* nd, LWS::NodeDesc& src, std::vector<Attachm
         // name to attach light to node -> unique due to LWs indexing system
         lit->mName = nd->mName;
 
-        // detemine light type and setup additional members
+        // determine light type and setup additional members
         if (src.lightType == 2) { /* spot light */
 
             lit->mType = aiLightSource_SPOT;
@@ -551,7 +551,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
     // get file format version and print to log
     ++it;
     unsigned int version = strtoul10((*it).tokens[0].c_str());
-    DefaultLogger::get()->info("LWS file format version is " + (*it).tokens[0]);
+    ASSIMP_LOG_INFO("LWS file format version is " + (*it).tokens[0]);
     first = 0.;
     last  = 60.;
     fps   = 25.; /* seems to be a good default frame rate */
@@ -656,7 +656,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
                     d.number = cur_object++;
                     nodes.push_back(d);
                 }
-                else DefaultLogger::get()->error("LWS: Unexpected keyword: \'Channel\'");
+                ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'Channel\'");
             }
 
             // important: index of channel
@@ -673,7 +673,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
         // 'Envelope': a single animation channel
         else if ((*it).tokens[0] == "Envelope") {
             if (nodes.empty() || nodes.back().channels.empty())
-                DefaultLogger::get()->error("LWS: Unexpected keyword: \'Envelope\'");
+                ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'Envelope\'");
             else {
                 ReadEnvelope((*it),nodes.back().channels.back());
             }
@@ -684,7 +684,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
             (*it).tokens[0] == "LightMotion")) {
 
             if (nodes.empty())
-                DefaultLogger::get()->error("LWS: Unexpected keyword: \'<Light|Object|Camera>Motion\'");
+                ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'<Light|Object|Camera>Motion\'");
             else {
                 ReadEnvelope_Old(it,root.children.end(),nodes.back(),version);
             }
@@ -692,7 +692,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
         // 'Pre/PostBehavior': pre/post animation behaviour for LWSC 2
         else if (version == 2 && (*it).tokens[0] == "Pre/PostBehavior") {
             if (nodes.empty())
-                DefaultLogger::get()->error("LWS: Unexpected keyword: \'Pre/PostBehavior'");
+                ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'Pre/PostBehavior'");
             else {
                 for (std::list<LWO::Envelope>::iterator it = nodes.back().channels.begin(); it != nodes.back().channels.end(); ++it) {
                     // two ints per envelope
@@ -705,14 +705,14 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
         // 'ParentItem': specifies the parent of the current element
         else if ((*it).tokens[0] == "ParentItem") {
             if (nodes.empty())
-                DefaultLogger::get()->error("LWS: Unexpected keyword: \'ParentItem\'");
+                ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'ParentItem\'");
 
             else nodes.back().parent = strtoul16(c,&c);
         }
         // 'ParentObject': deprecated one for older formats
         else if (version < 3 && (*it).tokens[0] == "ParentObject") {
             if (nodes.empty())
-                DefaultLogger::get()->error("LWS: Unexpected keyword: \'ParentObject\'");
+                ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'ParentObject\'");
 
             else {
                 nodes.back().parent = strtoul10(c,&c) | (1u << 28u);
@@ -736,7 +736,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
         // 'CameraName': set name of currently active camera
         else if ((*it).tokens[0] == "CameraName") {
             if (nodes.empty() || nodes.back().type != LWS::NodeDesc::CAMERA)
-                DefaultLogger::get()->error("LWS: Unexpected keyword: \'CameraName\'");
+                ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'CameraName\'");
 
             else nodes.back().name = c;
         }
@@ -758,14 +758,14 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
         // 'LightName': set name of currently active light
         else if ((*it).tokens[0] == "LightName") {
             if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT)
-                DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightName\'");
+                ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightName\'");
 
             else nodes.back().name = c;
         }
         // 'LightIntensity': set intensity of currently active light
         else if ((*it).tokens[0] == "LightIntensity" || (*it).tokens[0] == "LgtIntensity" ) {
             if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT)
-                DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightIntensity\'");
+                ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightIntensity\'");
 
             else fast_atoreal_move<float>(c, nodes.back().lightIntensity );
 
@@ -773,7 +773,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
         // 'LightType': set type of currently active light
         else if ((*it).tokens[0] == "LightType") {
             if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT)
-                DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightType\'");
+                ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightType\'");
 
             else nodes.back().lightType = strtoul10(c);
 
@@ -781,7 +781,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
         // 'LightFalloffType': set falloff type of currently active light
         else if ((*it).tokens[0] == "LightFalloffType") {
             if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT)
-                DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightFalloffType\'");
+                ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightFalloffType\'");
 
             else nodes.back().lightFalloffType = strtoul10(c);
 
@@ -789,7 +789,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
         // 'LightConeAngle': set cone angle of currently active light
         else if ((*it).tokens[0] == "LightConeAngle") {
             if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT)
-                DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightConeAngle\'");
+                ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightConeAngle\'");
 
             else nodes.back().lightConeAngle = fast_atof(c);
 
@@ -797,7 +797,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
         // 'LightEdgeAngle': set area where we're smoothing from min to max intensity
         else if ((*it).tokens[0] == "LightEdgeAngle") {
             if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT)
-                DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightEdgeAngle\'");
+                ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightEdgeAngle\'");
 
             else nodes.back().lightEdgeAngle = fast_atof(c);
 
@@ -805,7 +805,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
         // 'LightColor': set color of currently active light
         else if ((*it).tokens[0] == "LightColor") {
             if (nodes.empty() || nodes.back().type != LWS::NodeDesc::LIGHT)
-                DefaultLogger::get()->error("LWS: Unexpected keyword: \'LightColor\'");
+                ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'LightColor\'");
 
             else {
                 c = fast_atoreal_move<float>(c, (float&) nodes.back().lightColor.r );
@@ -819,7 +819,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
         // 'PivotPosition': position of local transformation origin
         else if ((*it).tokens[0] == "PivotPosition" || (*it).tokens[0] == "PivotPoint") {
             if (nodes.empty())
-                DefaultLogger::get()->error("LWS: Unexpected keyword: \'PivotPosition\'");
+                ASSIMP_LOG_ERROR("LWS: Unexpected keyword: \'PivotPosition\'");
             else {
                 c = fast_atoreal_move<float>(c, (float&) nodes.back().pivotPos.x );
                 SkipSpaces(&c);
@@ -840,7 +840,7 @@ void LWSImporter::InternReadFile( const std::string& pFile, aiScene* pScene,
             if (dit != it && *it == (*dit).parent) {
                 if ((*dit).parent_resolved) {
                     // fixme: it's still possible to produce an overflow due to cross references ..
-                    DefaultLogger::get()->error("LWS: Found cross reference in scenegraph");
+                    ASSIMP_LOG_ERROR("LWS: Found cross reference in scene-graph");
                     continue;
                 }
 

+ 7 - 9
code/LimitBoneWeightsProcess.cpp

@@ -76,13 +76,13 @@ bool LimitBoneWeightsProcess::IsActive( unsigned int pFlags) const
 
 // ------------------------------------------------------------------------------------------------
 // Executes the post processing step on the given imported data.
-void LimitBoneWeightsProcess::Execute( aiScene* pScene)
-{
-    DefaultLogger::get()->debug("LimitBoneWeightsProcess begin");
-    for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
-        ProcessMesh( pScene->mMeshes[a]);
+void LimitBoneWeightsProcess::Execute( aiScene* pScene) {
+    ASSIMP_LOG_DEBUG("LimitBoneWeightsProcess begin");
+    for (unsigned int a = 0; a < pScene->mNumMeshes; ++a ) {
+        ProcessMesh(pScene->mMeshes[a]);
+    }
 
-    DefaultLogger::get()->debug("LimitBoneWeightsProcess end");
+    ASSIMP_LOG_DEBUG("LimitBoneWeightsProcess end");
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -195,9 +195,7 @@ void LimitBoneWeightsProcess::ProcessMesh( aiMesh* pMesh)
         }
 
         if (!DefaultLogger::isNullLogger()) {
-            char buffer[1024];
-            ai_snprintf(buffer,1024,"Removed %u weights. Input bones: %u. Output bones: %u",removed,old_bones,pMesh->mNumBones);
-            DefaultLogger::get()->info(buffer);
+            ASSIMP_LOG_INFO_F("Removed ", removed, " weights. Input bones: ", old_bones, ". Output bones: ", pMesh->mNumBones );
         }
     }
 }

+ 10 - 10
code/MD2Loader.cpp

@@ -83,7 +83,7 @@ void MD2::LookupNormalIndex(uint8_t iNormalIndex,aiVector3D& vOut)
 {
     // make sure the normal index has a valid value
     if (iNormalIndex >= ARRAYSIZE(g_avNormals)) {
-        DefaultLogger::get()->warn("Index overflow in Quake II normal vector list");
+        ASSIMP_LOG_WARN("Index overflow in Quake II normal vector list");
         iNormalIndex = ARRAYSIZE(g_avNormals) - 1;
     }
     vOut = *((const aiVector3D*)(&g_avNormals[iNormalIndex]));
@@ -161,7 +161,7 @@ void MD2Importer::ValidateHeader( )
 
     // check file format version
     if (m_pcHeader->version != 8)
-        DefaultLogger::get()->warn( "Unsupported md2 file version. Continuing happily ...");
+        ASSIMP_LOG_WARN( "Unsupported md2 file version. Continuing happily ...");
 
     // check some values whether they are valid
     if (0 == m_pcHeader->numFrames)
@@ -203,11 +203,11 @@ void MD2Importer::ValidateHeader( )
     }
 
     if (m_pcHeader->numSkins > AI_MD2_MAX_SKINS)
-        DefaultLogger::get()->warn("The model contains more skins than Quake 2 supports");
+        ASSIMP_LOG_WARN("The model contains more skins than Quake 2 supports");
     if ( m_pcHeader->numFrames > AI_MD2_MAX_FRAMES)
-        DefaultLogger::get()->warn("The model contains more frames than Quake 2 supports");
+        ASSIMP_LOG_WARN("The model contains more frames than Quake 2 supports");
     if (m_pcHeader->numVertices > AI_MD2_MAX_VERTS)
-        DefaultLogger::get()->warn("The model contains more vertices than Quake 2 supports");
+        ASSIMP_LOG_WARN("The model contains more vertices than Quake 2 supports");
 
     if (m_pcHeader->numFrames <= configFrameID )
         throw DeadlyImportError("The requested frame is not existing the file");
@@ -352,7 +352,7 @@ void MD2Importer::InternReadFile( const std::string& pFile,
             pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0));
         }
         else{
-            DefaultLogger::get()->warn("Texture file name has zero length. It will be skipped.");
+            ASSIMP_LOG_WARN("Texture file name has zero length. It will be skipped.");
         }
     }
     else    {
@@ -390,11 +390,11 @@ void MD2Importer::InternReadFile( const std::string& pFile,
         // check whether the skin width or height are zero (this would
         // cause a division through zero)
         if (!m_pcHeader->skinWidth) {
-            DefaultLogger::get()->error("MD2: No valid skin width given");
+            ASSIMP_LOG_ERROR("MD2: No valid skin width given");
         }
         else fDivisorU = (float)m_pcHeader->skinWidth;
         if (!m_pcHeader->skinHeight){
-            DefaultLogger::get()->error("MD2: No valid skin height given");
+            ASSIMP_LOG_ERROR("MD2: No valid skin height given");
         }
         else fDivisorV = (float)m_pcHeader->skinHeight;
     }
@@ -412,7 +412,7 @@ void MD2Importer::InternReadFile( const std::string& pFile,
             // validate vertex indices
             unsigned int iIndex = (unsigned int)pcTriangles[i].vertexIndices[c];
             if (iIndex >= m_pcHeader->numVertices)  {
-                DefaultLogger::get()->error("MD2: Vertex index is outside the allowed range");
+                ASSIMP_LOG_ERROR("MD2: Vertex index is outside the allowed range");
                 iIndex = m_pcHeader->numVertices-1;
             }
 
@@ -440,7 +440,7 @@ void MD2Importer::InternReadFile( const std::string& pFile,
                 // validate texture coordinates
                 iIndex = pcTriangles[i].textureIndices[c];
                 if (iIndex >= m_pcHeader->numTexCoords) {
-                    DefaultLogger::get()->error("MD2: UV index is outside the allowed range");
+                    ASSIMP_LOG_ERROR("MD2: UV index is outside the allowed range");
                     iIndex = m_pcHeader->numTexCoords-1;
                 }
 

+ 27 - 30
code/MD3Loader.cpp

@@ -101,7 +101,7 @@ Q3Shader::BlendFunc StringToBlendFunc(const std::string& m)
     if (m == "GL_ONE_MINUS_DST_COLOR") {
         return Q3Shader::BLEND_GL_ONE_MINUS_DST_COLOR;
     }
-    DefaultLogger::get()->error("Q3Shader: Unknown blend function: " + m);
+    ASSIMP_LOG_ERROR("Q3Shader: Unknown blend function: " + m);
     return Q3Shader::BLEND_NONE;
 }
 
@@ -113,7 +113,7 @@ bool Q3Shader::LoadShader(ShaderData& fill, const std::string& pFile,IOSystem* i
     if (!file.get())
         return false; // if we can't access the file, don't worry and return
 
-    DefaultLogger::get()->info("Loading Quake3 shader file " + pFile);
+    ASSIMP_LOG_INFO_F("Loading Quake3 shader file ", pFile);
 
     // read file in memory
     const size_t s = file->FileSize();
@@ -136,7 +136,7 @@ bool Q3Shader::LoadShader(ShaderData& fill, const std::string& pFile,IOSystem* i
 
             // append to last section, if any
             if (!curData) {
-                DefaultLogger::get()->error("Q3Shader: Unexpected shader section token \'{\'");
+                ASSIMP_LOG_ERROR("Q3Shader: Unexpected shader section token \'{\'");
                 return true; // still no failure, the file is there
             }
 
@@ -206,19 +206,16 @@ bool Q3Shader::LoadShader(ShaderData& fill, const std::string& pFile,IOSystem* i
                     SkipSpaces(&buff);
                     if (!ASSIMP_strincmp(buff,"back",4)) {
                         curData->cull = Q3Shader::CULL_CCW;
-                    }
-                    else if (!ASSIMP_strincmp(buff,"front",5)) {
+                    } else if (!ASSIMP_strincmp(buff,"front",5)) {
                         curData->cull = Q3Shader::CULL_CW;
-                    }
-                    else if (!ASSIMP_strincmp(buff,"none",4) || !ASSIMP_strincmp(buff,"disable",7)) {
+                    } else if (!ASSIMP_strincmp(buff,"none",4) || !ASSIMP_strincmp(buff,"disable",7)) {
                         curData->cull = Q3Shader::CULL_NONE;
+                    } else {
+                        ASSIMP_LOG_ERROR("Q3Shader: Unrecognized cull mode");
                     }
-                    else DefaultLogger::get()->error("Q3Shader: Unrecognized cull mode");
                 }
             }
-        }
-
-        else {
+        } else {
             // add new section
             fill.blocks.push_back(Q3Shader::ShaderDataBlock());
             curData = &fill.blocks.back();
@@ -238,7 +235,7 @@ bool Q3Shader::LoadSkin(SkinData& fill, const std::string& pFile,IOSystem* io)
     if (!file.get())
         return false; // if we can't access the file, don't worry and return
 
-    DefaultLogger::get()->info("Loading Quake3 skin file " + pFile);
+    ASSIMP_LOG_INFO("Loading Quake3 skin file " + pFile);
 
     // read file in memory
     const size_t s = file->FileSize();
@@ -397,7 +394,7 @@ void MD3Importer::ValidateHeaderOffsets()
 
     // Check file format version
     if (pcHeader->VERSION > 15)
-        DefaultLogger::get()->warn( "Unsupported MD3 file version. Continuing happily ...");
+        ASSIMP_LOG_WARN( "Unsupported MD3 file version. Continuing happily ...");
 
     // Check some offset values whether they are valid
     if (!pcHeader->NUM_SURFACES)
@@ -438,25 +435,24 @@ void MD3Importer::ValidateSurfaceHeaderOffsets(const MD3::Surface* pcSurf)
     // Check whether all requirements for Q3 files are met. We don't
     // care, but probably someone does.
     if (pcSurf->NUM_TRIANGLES > AI_MD3_MAX_TRIANGLES) {
-        DefaultLogger::get()->warn("MD3: Quake III triangle limit exceeded");
+        ASSIMP_LOG_WARN("MD3: Quake III triangle limit exceeded");
     }
 
     if (pcSurf->NUM_SHADER > AI_MD3_MAX_SHADERS) {
-        DefaultLogger::get()->warn("MD3: Quake III shader limit exceeded");
+        ASSIMP_LOG_WARN("MD3: Quake III shader limit exceeded");
     }
 
     if (pcSurf->NUM_VERTICES > AI_MD3_MAX_VERTS) {
-        DefaultLogger::get()->warn("MD3: Quake III vertex limit exceeded");
+        ASSIMP_LOG_WARN("MD3: Quake III vertex limit exceeded");
     }
 
     if (pcSurf->NUM_FRAMES > AI_MD3_MAX_FRAMES) {
-        DefaultLogger::get()->warn("MD3: Quake III frame limit exceeded");
+        ASSIMP_LOG_WARN("MD3: Quake III frame limit exceeded");
     }
 }
 
 // ------------------------------------------------------------------------------------------------
-const aiImporterDesc* MD3Importer::GetInfo () const
-{
+const aiImporterDesc* MD3Importer::GetInfo () const {
     return &desc;
 }
 
@@ -579,7 +575,7 @@ bool MD3Importer::ReadMultipartFile()
         aiNode* tag_torso, *tag_head;
         std::vector<AttachmentInfo> attach;
 
-        DefaultLogger::get()->info("Multi part MD3 player model: lower, upper and head parts are joined");
+        ASSIMP_LOG_INFO("Multi part MD3 player model: lower, upper and head parts are joined");
 
         // ensure we won't try to load ourselves recursively
         BatchLoader::PropertyMap props;
@@ -600,21 +596,21 @@ bool MD3Importer::ReadMultipartFile()
         // ... and get them. We need all of them.
         scene_lower = batch.GetImport(_lower);
         if (!scene_lower) {
-            DefaultLogger::get()->error("M3D: Failed to read multi part model, lower.md3 fails to load");
+            ASSIMP_LOG_ERROR("M3D: Failed to read multi part model, lower.md3 fails to load");
             failure = "lower";
             goto error_cleanup;
         }
 
         scene_upper = batch.GetImport(_upper);
         if (!scene_upper) {
-            DefaultLogger::get()->error("M3D: Failed to read multi part model, upper.md3 fails to load");
+            ASSIMP_LOG_ERROR("M3D: Failed to read multi part model, upper.md3 fails to load");
             failure = "upper";
             goto error_cleanup;
         }
 
         scene_head  = batch.GetImport(_head);
         if (!scene_head) {
-            DefaultLogger::get()->error("M3D: Failed to read multi part model, head.md3 fails to load");
+            ASSIMP_LOG_ERROR("M3D: Failed to read multi part model, head.md3 fails to load");
             failure = "head";
             goto error_cleanup;
         }
@@ -628,7 +624,7 @@ bool MD3Importer::ReadMultipartFile()
         // tag_torso
         tag_torso = scene_lower->mRootNode->FindNode("tag_torso");
         if (!tag_torso) {
-            DefaultLogger::get()->error("M3D: Failed to find attachment tag for multi part model: tag_torso expected");
+            ASSIMP_LOG_ERROR("M3D: Failed to find attachment tag for multi part model: tag_torso expected");
             goto error_cleanup;
         }
         scene_upper->mRootNode->mName.Set("upper");
@@ -637,7 +633,7 @@ bool MD3Importer::ReadMultipartFile()
         // tag_head
         tag_head = scene_upper->mRootNode->FindNode("tag_head");
         if (!tag_head) {
-            DefaultLogger::get()->error("M3D: Failed to find attachment tag for multi part model: tag_head expected");
+            ASSIMP_LOG_ERROR( "M3D: Failed to find attachment tag for multi part model: tag_head expected");
             goto error_cleanup;
         }
         scene_head->mRootNode->mName.Set("head");
@@ -890,7 +886,7 @@ void MD3Importer::InternReadFile( const std::string& pFile,
 
         if (it != skins.textures.end()) {
             texture_name = &*( _texture_name = (*it).second).begin();
-            DefaultLogger::get()->debug("MD3: Assigning skin texture " + (*it).second + " to surface " + pcSurfaces->NAME);
+            ASSIMP_LOG_DEBUG_F("MD3: Assigning skin texture ", (*it).second, " to surface ", pcSurfaces->NAME);
             (*it).resolved = true; // mark entry as resolved
         }
 
@@ -919,9 +915,10 @@ void MD3Importer::InternReadFile( const std::string& pFile,
             if (dit != shaders.blocks.end()) {
                 // Hurra, wir haben einen. Tolle Sache.
                 shader = &*dit;
-                DefaultLogger::get()->info("Found shader record for " +without_ext );
+                ASSIMP_LOG_INFO("Found shader record for " +without_ext );
+            } else {
+                ASSIMP_LOG_WARN("Unable to find shader record for " + without_ext);
             }
-            else DefaultLogger::get()->warn("Unable to find shader record for " +without_ext );
         }
 
         aiMaterial* pcHelper = new aiMaterial();
@@ -950,7 +947,7 @@ void MD3Importer::InternReadFile( const std::string& pFile,
                 szString.Set(convertedPath);
             }
             else    {
-                DefaultLogger::get()->warn("Texture file name has zero length. Using default name");
+                ASSIMP_LOG_WARN("Texture file name has zero length. Using default name");
                 szString.Set("dummy_texture.bmp");
             }
             pcHelper->AddProperty(&szString,AI_MATKEY_TEXTURE_DIFFUSE(0));
@@ -1040,7 +1037,7 @@ void MD3Importer::InternReadFile( const std::string& pFile,
     if (!DefaultLogger::isNullLogger()) {
         for (std::list< Q3Shader::SkinData::TextureEntry>::const_iterator it = skins.textures.begin();it != skins.textures.end(); ++it) {
             if (!(*it).resolved) {
-                DefaultLogger::get()->error("MD3: Failed to match skin " + (*it).first + " to surface " + (*it).second);
+                ASSIMP_LOG_ERROR_F("MD3: Failed to match skin ", (*it).first, " to surface ", (*it).second);
             }
         }
     }

+ 4 - 5
code/MD5Loader.cpp

@@ -359,7 +359,7 @@ void MD5Importer::LoadMD5MeshFile ()
 
     // Check whether we can read from the file
     if( file.get() == NULL || !file->FileSize())    {
-        DefaultLogger::get()->warn("Failed to access MD5MESH file: " + pFile);
+        ASSIMP_LOG_WARN("Failed to access MD5MESH file: " + pFile);
         return;
     }
     bHadMD5Mesh = true;
@@ -482,7 +482,7 @@ void MD5Importer::LoadMD5MeshFile ()
                 for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights;++w)
                     fSum += meshSrc.mWeights[w].mWeight;
                 if (!fSum) {
-                    DefaultLogger::get()->error("MD5MESH: The sum of all vertex bone weights is 0");
+                    ASSIMP_LOG_ERROR("MD5MESH: The sum of all vertex bone weights is 0");
                     continue;
                 }
 
@@ -574,7 +574,7 @@ void MD5Importer::LoadMD5AnimFile ()
 
     // Check whether we can read from the file
     if( !file.get() || !file->FileSize())   {
-        DefaultLogger::get()->warn("Failed to read MD5ANIM file: " + pFile);
+        ASSIMP_LOG_WARN("Failed to read MD5ANIM file: " + pFile);
         return;
     }
     LoadFileIntoMemory(file.get());
@@ -588,8 +588,7 @@ void MD5Importer::LoadMD5AnimFile ()
     // generate and fill the output animation
     if (animParser.mAnimatedBones.empty() || animParser.mFrames.empty() ||
         animParser.mBaseFrames.size() != animParser.mAnimatedBones.size())  {
-
-        DefaultLogger::get()->error("MD5ANIM: No frames or animated bones loaded");
+        ASSIMP_LOG_ERROR("MD5ANIM: No frames or animated bones loaded");
     }
     else {
         bHadMD5Anim = true;

+ 10 - 10
code/MD5Parser.cpp

@@ -70,7 +70,7 @@ MD5Parser::MD5Parser(char* _buffer, unsigned int _fileSize )
     fileSize = _fileSize;
     lineNumber = 0;
 
-    DefaultLogger::get()->debug("MD5Parser begin");
+    ASSIMP_LOG_DEBUG("MD5Parser begin");
 
     // parse the file header
     ParseHeader();
@@ -88,7 +88,7 @@ MD5Parser::MD5Parser(char* _buffer, unsigned int _fileSize )
     if ( !DefaultLogger::isNullLogger())    {
         char szBuffer[128]; // should be sufficiently large
         ::ai_snprintf(szBuffer,128,"MD5Parser end. Parsed %i sections",(int)mSections.size());
-        DefaultLogger::get()->debug(szBuffer);
+        ASSIMP_LOG_DEBUG(szBuffer);
     }
 }
 
@@ -107,7 +107,7 @@ MD5Parser::MD5Parser(char* _buffer, unsigned int _fileSize )
 {
     char szBuffer[1024];
     ::sprintf(szBuffer,"[MD5] Line %u: %s",line,warn);
-    DefaultLogger::get()->warn(szBuffer);
+    ASSIMP_LOG_WARN(szBuffer);
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -130,7 +130,7 @@ void MD5Parser::ParseHeader()
     // FIX: can break the log length limit, so we need to be careful
     char* sz = buffer;
     while (!IsLineEnd( *buffer++));
-    DefaultLogger::get()->info(std::string(sz,std::min((uintptr_t)MAX_LOG_MESSAGE_LENGTH, (uintptr_t)(buffer-sz))));
+    ASSIMP_LOG_INFO(std::string(sz,std::min((uintptr_t)MAX_LOG_MESSAGE_LENGTH, (uintptr_t)(buffer-sz))));
     SkipSpacesAndLineEnd();
 }
 
@@ -243,7 +243,7 @@ bool MD5Parser::ParseSection(Section& out)
 // .MD5MESH parsing function
 MD5MeshParser::MD5MeshParser(SectionList& mSections)
 {
-    DefaultLogger::get()->debug("MD5MeshParser begin");
+    ASSIMP_LOG_DEBUG("MD5MeshParser begin");
 
     // now parse all sections
     for (SectionList::const_iterator iter =  mSections.begin(), iterEnd = mSections.end();iter != iterEnd;++iter){
@@ -354,14 +354,14 @@ MD5MeshParser::MD5MeshParser(SectionList& mSections)
             }
         }
     }
-    DefaultLogger::get()->debug("MD5MeshParser end");
+    ASSIMP_LOG_DEBUG("MD5MeshParser end");
 }
 
 // ------------------------------------------------------------------------------------------------
 // .MD5ANIM parsing function
 MD5AnimParser::MD5AnimParser(SectionList& mSections)
 {
-    DefaultLogger::get()->debug("MD5AnimParser begin");
+    ASSIMP_LOG_DEBUG("MD5AnimParser begin");
 
     fFrameRate = 24.0f;
     mNumAnimatedComponents = UINT_MAX;
@@ -445,14 +445,14 @@ MD5AnimParser::MD5AnimParser(SectionList& mSections)
             fast_atoreal_move<float>((*iter).mGlobalValue.c_str(),fFrameRate);
         }
     }
-    DefaultLogger::get()->debug("MD5AnimParser end");
+    ASSIMP_LOG_DEBUG("MD5AnimParser end");
 }
 
 // ------------------------------------------------------------------------------------------------
 // .MD5CAMERA parsing function
 MD5CameraParser::MD5CameraParser(SectionList& mSections)
 {
-    DefaultLogger::get()->debug("MD5CameraParser begin");
+    ASSIMP_LOG_DEBUG("MD5CameraParser begin");
     fFrameRate = 24.0f;
 
     for (SectionList::const_iterator iter =  mSections.begin(), iterEnd = mSections.end();iter != iterEnd;++iter) {
@@ -483,6 +483,6 @@ MD5CameraParser::MD5CameraParser(SectionList& mSections)
             }
         }
     }
-    DefaultLogger::get()->debug("MD5CameraParser end");
+    ASSIMP_LOG_DEBUG("MD5CameraParser end");
 }
 

+ 6 - 4
code/MDCLoader.cpp

@@ -159,8 +159,9 @@ void MDCImporter::ValidateHeader()
             "magic word found is " + std::string( szBuffer ));
     }
 
-    if (pcHeader->ulVersion != AI_MDC_VERSION)
-        DefaultLogger::get()->warn("Unsupported MDC file version (2 (AI_MDC_VERSION) was expected)");
+    if (pcHeader->ulVersion != AI_MDC_VERSION) {
+        ASSIMP_LOG_WARN("Unsupported MDC file version (2 (AI_MDC_VERSION) was expected)");
+    }
 
     if (pcHeader->ulOffsetBorderFrames + pcHeader->ulNumFrames * sizeof(MDC::Frame) > this->fileSize ||
         pcHeader->ulOffsetSurfaces + pcHeader->ulNumSurfaces * sizeof(MDC::Surface) > this->fileSize)
@@ -169,8 +170,9 @@ void MDCImporter::ValidateHeader()
             "and point to something behind the file.");
     }
 
-    if (this->configFrameID >= this->pcHeader->ulNumFrames)
+    if (this->configFrameID >= this->pcHeader->ulNumFrames) {
         throw DeadlyImportError("The requested frame is not available");
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -388,7 +390,7 @@ void MDCImporter::InternReadFile(
                 uint32_t quak = pcTriangle->aiIndices[iIndex];
                 if (quak >= pcSurface->ulNumVertices)
                 {
-                    DefaultLogger::get()->error("MDC vertex index is out of range");
+                    ASSIMP_LOG_ERROR("MDC vertex index is out of range");
                     quak = pcSurface->ulNumVertices-1;
                 }
 

+ 34 - 34
code/MDLLoader.cpp

@@ -141,7 +141,7 @@ void MDLImporter::SetupProperties(const Importer* pImp)
         configFrameID =  pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0);
     }
 
-    // AI_CONFIG_IMPORT_MDL_COLORMAP - pallette file
+    // AI_CONFIG_IMPORT_MDL_COLORMAP - palette file
     configPalette =  pImp->GetPropertyString(AI_CONFIG_IMPORT_MDL_COLORMAP,"colormap.lmp");
 }
 
@@ -187,37 +187,37 @@ void MDLImporter::InternReadFile( const std::string& pFile,
 
     // Original Quake1 format
     if (AI_MDL_MAGIC_NUMBER_BE == iMagicWord || AI_MDL_MAGIC_NUMBER_LE == iMagicWord)   {
-        DefaultLogger::get()->debug("MDL subtype: Quake 1, magic word is IDPO");
+        ASSIMP_LOG_DEBUG("MDL subtype: Quake 1, magic word is IDPO");
         iGSFileVersion = 0;
         InternReadFile_Quake1();
     }
     // GameStudio A<old> MDL2 format - used by some test models that come with 3DGS
     else if (AI_MDL_MAGIC_NUMBER_BE_GS3 == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS3 == iMagicWord)  {
-        DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A2, magic word is MDL2");
+        ASSIMP_LOG_DEBUG("MDL subtype: 3D GameStudio A2, magic word is MDL2");
         iGSFileVersion = 2;
         InternReadFile_Quake1();
     }
     // GameStudio A4 MDL3 format
     else if (AI_MDL_MAGIC_NUMBER_BE_GS4 == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS4 == iMagicWord)  {
-        DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A4, magic word is MDL3");
+        ASSIMP_LOG_DEBUG("MDL subtype: 3D GameStudio A4, magic word is MDL3");
         iGSFileVersion = 3;
         InternReadFile_3DGS_MDL345();
     }
     // GameStudio A5+ MDL4 format
     else if (AI_MDL_MAGIC_NUMBER_BE_GS5a == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS5a == iMagicWord)    {
-        DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A4, magic word is MDL4");
+        ASSIMP_LOG_DEBUG("MDL subtype: 3D GameStudio A4, magic word is MDL4");
         iGSFileVersion = 4;
         InternReadFile_3DGS_MDL345();
     }
     // GameStudio A5+ MDL5 format
     else if (AI_MDL_MAGIC_NUMBER_BE_GS5b == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS5b == iMagicWord)    {
-        DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A5, magic word is MDL5");
+        ASSIMP_LOG_DEBUG("MDL subtype: 3D GameStudio A5, magic word is MDL5");
         iGSFileVersion = 5;
         InternReadFile_3DGS_MDL345();
     }
     // GameStudio A7 MDL7 format
     else if (AI_MDL_MAGIC_NUMBER_BE_GS7 == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_GS7 == iMagicWord)  {
-        DefaultLogger::get()->debug("MDL subtype: 3D GameStudio A7, magic word is MDL7");
+        ASSIMP_LOG_DEBUG("MDL subtype: 3D GameStudio A7, magic word is MDL7");
         iGSFileVersion = 7;
         InternReadFile_3DGS_MDL7();
     }
@@ -225,7 +225,7 @@ void MDLImporter::InternReadFile( const std::string& pFile,
     else if (AI_MDL_MAGIC_NUMBER_BE_HL2a == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_HL2a == iMagicWord ||
         AI_MDL_MAGIC_NUMBER_BE_HL2b == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_HL2b == iMagicWord)
     {
-        DefaultLogger::get()->debug("MDL subtype: Source(tm) Engine, magic word is IDST/IDSQ");
+        ASSIMP_LOG_DEBUG("MDL subtype: Source(tm) Engine, magic word is IDST/IDSQ");
         iGSFileVersion = 0;
         InternReadFile_HL2();
     }
@@ -258,7 +258,7 @@ void MDLImporter::SizeCheck(const void* szPos)
 }
 
 // ------------------------------------------------------------------------------------------------
-// Just for debgging purposes
+// Just for debugging purposes
 void MDLImporter::SizeCheck(const void* szPos, const char* szFile, unsigned int iLine)
 {
     ai_assert(NULL != szFile);
@@ -298,20 +298,20 @@ void MDLImporter::ValidateHeader_Quake1(const MDL::Header* pcHeader)
     if (!this->iGSFileVersion)
     {
         if (pcHeader->num_verts > AI_MDL_MAX_VERTS)
-            DefaultLogger::get()->warn("Quake 1 MDL model has more than AI_MDL_MAX_VERTS vertices");
+            ASSIMP_LOG_WARN("Quake 1 MDL model has more than AI_MDL_MAX_VERTS vertices");
 
         if (pcHeader->num_tris > AI_MDL_MAX_TRIANGLES)
-            DefaultLogger::get()->warn("Quake 1 MDL model has more than AI_MDL_MAX_TRIANGLES triangles");
+            ASSIMP_LOG_WARN("Quake 1 MDL model has more than AI_MDL_MAX_TRIANGLES triangles");
 
         if (pcHeader->num_frames > AI_MDL_MAX_FRAMES)
-            DefaultLogger::get()->warn("Quake 1 MDL model has more than AI_MDL_MAX_FRAMES frames");
+            ASSIMP_LOG_WARN("Quake 1 MDL model has more than AI_MDL_MAX_FRAMES frames");
 
         // (this does not apply for 3DGS MDLs)
         if (!this->iGSFileVersion && pcHeader->version != AI_MDL_VERSION)
-            DefaultLogger::get()->warn("Quake 1 MDL model has an unknown version: AI_MDL_VERSION (=6) is "
+            ASSIMP_LOG_WARN("Quake 1 MDL model has an unknown version: AI_MDL_VERSION (=6) is "
                 "the expected file format version");
         if(pcHeader->num_skins && (!pcHeader->skinwidth || !pcHeader->skinheight))
-            DefaultLogger::get()->warn("Skin width or height are 0");
+            ASSIMP_LOG_WARN("Skin width or height are 0");
     }
 }
 
@@ -481,7 +481,7 @@ void MDLImporter::InternReadFile_Quake1() {
             if (iIndex >= (unsigned int)pcHeader->num_verts)
             {
                 iIndex = pcHeader->num_verts-1;
-                DefaultLogger::get()->warn("Index overflow in Q1-MDL vertex list.");
+                ASSIMP_LOG_WARN("Index overflow in Q1-MDL vertex list.");
             }
 
             aiVector3D& vec = pcMesh->mVertices[iCurrent];
@@ -692,7 +692,7 @@ void MDLImporter::InternReadFile_3DGS_MDL345( )
                 unsigned int iIndex = pcTriangles->index_xyz[c];
                 if (iIndex >= (unsigned int)pcHeader->num_verts)    {
                     iIndex = pcHeader->num_verts-1;
-                    DefaultLogger::get()->warn("Index overflow in MDLn vertex list");
+                    ASSIMP_LOG_WARN("Index overflow in MDLn vertex list");
                 }
 
                 aiVector3D& vec = pcMesh->mVertices[iCurrent];
@@ -747,7 +747,7 @@ void MDLImporter::InternReadFile_3DGS_MDL345( )
                 unsigned int iIndex = pcTriangles->index_xyz[c];
                 if (iIndex >= (unsigned int)pcHeader->num_verts)    {
                     iIndex = pcHeader->num_verts-1;
-                    DefaultLogger::get()->warn("Index overflow in MDLn vertex list");
+                    ASSIMP_LOG_WARN("Index overflow in MDLn vertex list");
                 }
 
                 aiVector3D& vec = pcMesh->mVertices[iCurrent];
@@ -798,7 +798,7 @@ void MDLImporter::ImportUVCoordinate_3DGS_MDL345(
     // validate UV indices
     if (iIndex >= (unsigned int) pcHeader->synctype)    {
         iIndex = pcHeader->synctype-1;
-        DefaultLogger::get()->warn("Index overflow in MDLn UV coord list");
+        ASSIMP_LOG_WARN("Index overflow in MDLn UV coord list");
     }
 
     float s = (float)pcSrc[iIndex].u;
@@ -835,7 +835,7 @@ void MDLImporter::CalculateUVCoordinates_MDL5()
             iWidth  = (unsigned int)*piPtr;
             if (!iHeight || !iWidth)
             {
-                DefaultLogger::get()->warn("Either the width or the height of the "
+                ASSIMP_LOG_WARN("Either the width or the height of the "
                     "embedded DDS texture is zero. Unable to compute final texture "
                     "coordinates. The texture coordinates remain in their original "
                     "0-x/0-y (x,y = texture size) range.");
@@ -988,7 +988,7 @@ MDL::IntBone_MDL7** MDLImporter::LoadBones_3DGS_MDL7()
             AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_32_CHARS  != pcHeader->bone_stc_size &&
             AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_NOT_THERE != pcHeader->bone_stc_size)
         {
-            DefaultLogger::get()->warn("Unknown size of bone data structure");
+            ASSIMP_LOG_WARN("Unknown size of bone data structure");
             return NULL;
         }
 
@@ -1026,7 +1026,7 @@ void MDLImporter::ReadFaces_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInfo,
             if(iIndex > (unsigned int)groupInfo.pcGroup->numverts)  {
                 // (we might need to read this section a second time - to process frame vertices correctly)
                 pcGroupTris->v_index[c] = iIndex = groupInfo.pcGroup->numverts-1;
-                DefaultLogger::get()->warn("Index overflow in MDL7 vertex list");
+                ASSIMP_LOG_WARN("Index overflow in MDL7 vertex list");
             }
 
             // write the output face index
@@ -1071,7 +1071,7 @@ void MDLImporter::ReadFaces_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInfo,
                     iIndex = pcGroupTris->skinsets[0].st_index[c];
                     if(iIndex > (unsigned int)groupInfo.pcGroup->num_stpts) {
                         iIndex = groupInfo.pcGroup->num_stpts-1;
-                        DefaultLogger::get()->warn("Index overflow in MDL7 UV coordinate list (#1)");
+                        ASSIMP_LOG_WARN("Index overflow in MDL7 UV coordinate list (#1)");
                     }
 
                     float u = groupInfo.pcGroupUVs[iIndex].u;
@@ -1098,7 +1098,7 @@ void MDLImporter::ReadFaces_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInfo,
                     iIndex = pcGroupTris->skinsets[1].st_index[c];
                     if(iIndex > (unsigned int)groupInfo.pcGroup->num_stpts) {
                         iIndex = groupInfo.pcGroup->num_stpts-1;
-                        DefaultLogger::get()->warn("Index overflow in MDL7 UV coordinate list (#2)");
+                        ASSIMP_LOG_WARN("Index overflow in MDL7 UV coordinate list (#2)");
                     }
 
                     float u = groupInfo.pcGroupUVs[ iIndex ].u;
@@ -1153,7 +1153,7 @@ bool MDLImporter::ProcessFrames_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInf
             frame.pcFrame->transmatrix_count * pcHeader->bonetrans_stc_size;
 
         if (((const char*)szCurrent - (const char*)pcHeader) + iAdd > (unsigned int)pcHeader->data_size)    {
-            DefaultLogger::get()->warn("Index overflow in frame area. "
+            ASSIMP_LOG_WARN("Index overflow in frame area. "
                 "Ignoring all frames and all further mesh groups, too.");
 
             // don't parse more groups if we can't even read one
@@ -1171,7 +1171,7 @@ bool MDLImporter::ProcessFrames_3DGS_MDL7(const MDL::IntGroupInfo_MDL7& groupInf
                 uint16_t iIndex = _AI_MDL7_ACCESS(pcFrameVertices,qq,pcHeader->framevertex_stc_size,MDL::Vertex_MDL7).vertindex;
                 AI_SWAP2(iIndex);
                 if (iIndex >= groupInfo.pcGroup->numverts)  {
-                    DefaultLogger::get()->warn("Invalid vertex index in frame vertex section");
+                    ASSIMP_LOG_WARN("Invalid vertex index in frame vertex section");
                     continue;
                 }
 
@@ -1257,7 +1257,7 @@ void MDLImporter::SortByMaterials_3DGS_MDL7(
                 // sometimes MED writes -1, but normally only if there is only
                 // one skin assigned. No warning in this case
                 if(0xFFFFFFFF != groupData.pcFaces[iFace].iMatIndex[0])
-                    DefaultLogger::get()->warn("Index overflow in MDL7 material list [#0]");
+                    ASSIMP_LOG_WARN("Index overflow in MDL7 material list [#0]");
             }
             else splitGroupData.aiSplit[groupData.pcFaces[iFace].
                 iMatIndex[0]]->push_back(iFace);
@@ -1282,7 +1282,7 @@ void MDLImporter::SortByMaterials_3DGS_MDL7(
                 // sometimes MED writes -1, but normally only if there is only
                 // one skin assigned. No warning in this case
                 if(UINT_MAX != iMatIndex)
-                    DefaultLogger::get()->warn("Index overflow in MDL7 material list [#1]");
+                    ASSIMP_LOG_WARN("Index overflow in MDL7 material list [#1]");
                 iMatIndex = iNumMaterials-1;
             }
             unsigned int iMatIndex2 = groupData.pcFaces[iFace].iMatIndex[1];
@@ -1292,7 +1292,7 @@ void MDLImporter::SortByMaterials_3DGS_MDL7(
                 if (iMatIndex2 >= iNumMaterials)    {
                     // sometimes MED writes -1, but normally only if there is only
                     // one skin assigned. No warning in this case
-                    DefaultLogger::get()->warn("Index overflow in MDL7 material list [#2]");
+                    ASSIMP_LOG_WARN("Index overflow in MDL7 material list [#2]");
                     iMatIndex2 = iNumMaterials-1;
                 }
 
@@ -1414,7 +1414,7 @@ void MDLImporter::InternReadFile_3DGS_MDL7( )
 
         if (1 != groupInfo.pcGroup->typ)    {
             // Not a triangle-based mesh
-            DefaultLogger::get()->warn("[3DGS MDL7] Not a triangle mesh group. Continuing happily");
+            ASSIMP_LOG_WARN("[3DGS MDL7] Not a triangle mesh group. Continuing happily");
         }
 
         // store the name of the group
@@ -1496,7 +1496,7 @@ void MDLImporter::InternReadFile_3DGS_MDL7( )
                 groupData.vTextureCoords1.resize(iNumVertices,aiVector3D());
 
                 // check whether the triangle data structure is large enough
-                // to contain a second UV coodinate set
+                // to contain a second UV coordinate set
                 if (pcHeader->triangle_stc_size >= AI_MDL7_TRIANGLE_STD_SIZE_TWO_UV)    {
                     groupData.vTextureCoords2.resize(iNumVertices,aiVector3D());
                     groupData.bNeed2UV = true;
@@ -1516,7 +1516,7 @@ void MDLImporter::InternReadFile_3DGS_MDL7( )
                     sharedData.abNeedMaterials[qq] = true;
             }
         }
-        else DefaultLogger::get()->warn("[3DGS MDL7] Mesh group consists of 0 "
+        else ASSIMP_LOG_WARN("[3DGS MDL7] Mesh group consists of 0 "
             "vertices or faces. It will be skipped.");
 
         // process all frames and generate output meshes
@@ -1664,7 +1664,7 @@ void MDLImporter::ParseBoneTrafoKeys_3DGS_MDL7(
             // read all transformation matrices
             for (unsigned int iTrafo = 0; iTrafo < frame.pcFrame->transmatrix_count;++iTrafo)   {
                 if(pcBoneTransforms->bone_index >= pcHeader->bones_num) {
-                    DefaultLogger::get()->warn("Index overflow in frame area. "
+                    ASSIMP_LOG_WARN("Index overflow in frame area. "
                         "Unable to parse this bone transformation");
                 }
                 else    {
@@ -1676,7 +1676,7 @@ void MDLImporter::ParseBoneTrafoKeys_3DGS_MDL7(
             }
         }
         else    {
-            DefaultLogger::get()->warn("Ignoring animation keyframes in groups != 0");
+            ASSIMP_LOG_WARN("Ignoring animation keyframes in groups != 0");
         }
     }
 }
@@ -1894,7 +1894,7 @@ void MDLImporter::GenerateOutputMeshes_3DGS_MDL7(
                         unsigned int iBone = groupData.aiBones[ oldFace.mIndices[c] ];
                         if (UINT_MAX != iBone)  {
                             if (iBone >= iNumOutBones)  {
-                                DefaultLogger::get()->error("Bone index overflow. "
+                                ASSIMP_LOG_ERROR("Bone index overflow. "
                                     "The bone index of a vertex exceeds the allowed range. ");
                                 iBone = iNumOutBones-1;
                             }

+ 9 - 8
code/MDLMaterialLoader.cpp

@@ -64,7 +64,7 @@ using namespace Assimp;
 static aiTexel* const bad_texel = reinterpret_cast<aiTexel*>(SIZE_MAX);
 
 // ------------------------------------------------------------------------------------------------
-// Find a suitable pallette file or take the default one
+// Find a suitable palette file or take the default one
 void MDLImporter::SearchPalette(const unsigned char** pszColorMap)
 {
     // now try to find the color map in the current directory
@@ -75,10 +75,11 @@ void MDLImporter::SearchPalette(const unsigned char** pszColorMap)
     {
         if (pcStream->FileSize() >= 768)
         {
-            unsigned char* colorMap = new unsigned char[256*3];
+            size_t len = 256 * 3;
+            unsigned char* colorMap = new unsigned char[len];
             szColorMap = colorMap;
-            pcStream->Read(colorMap,256*3,1);
-            DefaultLogger::get()->info("Found valid colormap.lmp in directory. "
+            pcStream->Read(colorMap, len,1);
+            ASSIMP_LOG_INFO("Found valid colormap.lmp in directory. "
                 "It will be used to decode embedded textures in palletized formats.");
         }
         delete pcStream;
@@ -186,7 +187,7 @@ void MDLImporter::CreateTexture_3DGS_MDL4(const unsigned char* szData,
 
     if (iType == 1 || iType > 3)
     {
-        DefaultLogger::get()->error("Unsupported texture file format");
+        ASSIMP_LOG_ERROR("Unsupported texture file format");
         return;
     }
 
@@ -508,7 +509,7 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
         // ***** EMBEDDED DDS FILE *****
         if (1 != iHeight)
         {
-            DefaultLogger::get()->warn("Found a reference to an embedded DDS texture, "
+            ASSIMP_LOG_WARN("Found a reference to an embedded DDS texture, "
                 "but texture height is not equal to 1, which is not supported by MED");
         }
 
@@ -531,7 +532,7 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
         // ***** REFERENCE TO EXTERNAL FILE *****
         if (1 != iHeight)
         {
-            DefaultLogger::get()->warn("Found a reference to an external texture, "
+            ASSIMP_LOG_WARN("Found a reference to an external texture, "
                 "but texture height is not equal to 1, which is not supported by MED");
         }
 
@@ -552,7 +553,7 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
         pcNew.reset(new aiTexture());
         if (!iHeight || !iWidth)
         {
-            DefaultLogger::get()->warn("Found embedded texture, but its width "
+            ASSIMP_LOG_WARN("Found embedded texture, but its width "
                 "an height are both 0. Is this a joke?");
 
             // generate an empty chess pattern

+ 1 - 1
code/MMDImporter.cpp

@@ -217,7 +217,7 @@ aiMesh *MMDImporter::CreateMesh(const pmx::PmxModel *pModel,
   pMesh->mNumFaces = indexCount / 3;
   pMesh->mFaces = new aiFace[pMesh->mNumFaces];
 
-  const int numIndices = 3; // trianglular face
+  const int numIndices = 3; // triangular face
   for (unsigned int index = 0; index < pMesh->mNumFaces; index++) {
     pMesh->mFaces[index].mNumIndices = numIndices;
     unsigned int *indices = new unsigned int[numIndices];

+ 3 - 6
code/MS3DLoader.cpp

@@ -142,7 +142,7 @@ void MS3DImporter :: ReadComments(StreamReaderLE& stream, std::vector<T>& outp)
         stream >> index >> clength;
 
         if(index >= outp.size()) {
-            DefaultLogger::get()->warn("MS3D: Invalid index in comment section");
+            ASSIMP_LOG_WARN("MS3D: Invalid index in comment section");
         }
         else if (clength > stream.GetRemainingSize()) {
             throw DeadlyImportError("MS3D: Failure reading comment, length field is out of range");
@@ -349,9 +349,6 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
         stream.CopyAndAdvance(j.parentName,32);
         j.parentName[32] = '\0';
 
-    //  DefaultLogger::get()->debug(j.name);
-    //  DefaultLogger::get()->debug(j.parentName);
-
         ReadVector(stream,j.rotation);
         ReadVector(stream,j.position);
 
@@ -386,7 +383,7 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
                 }
 
                 const std::string& s = std::string(reinterpret_cast<char*>(stream.GetPtr()),len);
-                DefaultLogger::get()->debug("MS3D: Model comment: " + s);
+                ASSIMP_LOG_DEBUG_F("MS3D: Model comment: ", s);
             }
 
             if(stream.GetRemainingSize() > 4 && inrange((stream >> subversion,subversion),1u,3u)) {
@@ -408,7 +405,7 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
     // 2 ------------ convert to proper aiXX data structures -----------------------------------
 
     if (need_default && materials.size()) {
-        DefaultLogger::get()->warn("MS3D: Found group with no material assigned, spawning default material");
+        ASSIMP_LOG_WARN("MS3D: Found group with no material assigned, spawning default material");
         // if one of the groups has no material assigned, but there are other
         // groups with materials, a default material needs to be added (
         // scenepreprocessor adds a default material only if nummat==0).

+ 7 - 4
code/MakeVerboseFormat.cpp

@@ -65,7 +65,7 @@ MakeVerboseFormatProcess::~MakeVerboseFormatProcess()
 void MakeVerboseFormatProcess::Execute( aiScene* pScene)
 {
     ai_assert(NULL != pScene);
-    DefaultLogger::get()->debug("MakeVerboseFormatProcess begin");
+    ASSIMP_LOG_DEBUG("MakeVerboseFormatProcess begin");
 
     bool bHas = false;
     for( unsigned int a = 0; a < pScene->mNumMeshes; a++)
@@ -73,12 +73,15 @@ void MakeVerboseFormatProcess::Execute( aiScene* pScene)
         if( MakeVerboseFormat( pScene->mMeshes[a]))
             bHas = true;
     }
-    if (bHas) DefaultLogger::get()->info("MakeVerboseFormatProcess finished. There was much work to do ...");
-    else DefaultLogger::get()->debug("MakeVerboseFormatProcess. There was nothing to do.");
+    if (bHas) {
+        ASSIMP_LOG_INFO("MakeVerboseFormatProcess finished. There was much work to do ...");
+    } else {
+        ASSIMP_LOG_DEBUG("MakeVerboseFormatProcess. There was nothing to do.");
+    }
 
     pScene->mFlags &= ~AI_SCENE_FLAGS_NON_VERBOSE_FORMAT;
-
 }
+
 // ------------------------------------------------------------------------------------------------
 // Executes the post processing step on the given imported data.
 bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh)

+ 6 - 5
code/MaterialSystem.cpp

@@ -160,7 +160,7 @@ aiReturn aiGetMaterialFloatArray(const aiMaterial* pMat,
                 break;
             }
             if ( !IsSpace(*cur) ) {
-                DefaultLogger::get()->error("Material property" + std::string(pKey) +
+                ASSIMP_LOG_ERROR("Material property" + std::string(pKey) +
                     " is a string; failed to parse a float array out of it.");
                 return AI_FAILURE;
             }
@@ -233,7 +233,7 @@ aiReturn aiGetMaterialIntegerArray(const aiMaterial* pMat,
                 break;
             }
             if(!IsSpace(*cur)) {
-                DefaultLogger::get()->error("Material property" + std::string(pKey) +
+                ASSIMP_LOG_ERROR("Material property" + std::string(pKey) +
                     " is a string; failed to parse an integer array out of it.");
                 return AI_FAILURE;
             }
@@ -305,7 +305,7 @@ aiReturn aiGetMaterialString(const aiMaterial* pMat,
     }
     else {
         // TODO - implement lexical cast as well
-        DefaultLogger::get()->error("Material property" + std::string(pKey) +
+        ASSIMP_LOG_ERROR("Material property" + std::string(pKey) +
             " was found, but is no string" );
         return AI_FAILURE;
     }
@@ -354,8 +354,9 @@ aiReturn aiGetMaterialTexture(const C_STRUCT aiMaterial* mat,
         return AI_FAILURE;
     }
     // Determine mapping type
-    aiTextureMapping mapping = aiTextureMapping_UV;
-    aiGetMaterialInteger(mat,AI_MATKEY_MAPPING(type,index),(int*)&mapping);
+    int mapping_ = static_cast<int>(aiTextureMapping_UV);
+    aiGetMaterialInteger(mat,AI_MATKEY_MAPPING(type,index), &mapping_);
+    aiTextureMapping mapping = static_cast<aiTextureMapping>(mapping_);
     if (_mapping)
         *_mapping = mapping;
 

+ 4 - 4
code/NDOLoader.cpp

@@ -130,18 +130,18 @@ void NDOImporter::InternReadFile( const std::string& pFile,
     unsigned int file_format = 12;
     if (!strncmp("1.0",head+6,3)) {
         file_format = 10;
-        DefaultLogger::get()->info("NDO file format is 1.0");
+        ASSIMP_LOG_INFO("NDO file format is 1.0");
     }
     else if (!strncmp("1.1",head+6,3)) {
         file_format = 11;
-        DefaultLogger::get()->info("NDO file format is 1.1");
+        ASSIMP_LOG_INFO("NDO file format is 1.1");
     }
     else if (!strncmp("1.2",head+6,3)) {
         file_format = 12;
-        DefaultLogger::get()->info("NDO file format is 1.2");
+        ASSIMP_LOG_INFO("NDO file format is 1.2");
     }
     else {
-        DefaultLogger::get()->warn(std::string("Unrecognized nendo file format version, continuing happily ... :") + (head+6));
+        ASSIMP_LOG_WARN_F( "Unrecognized nendo file format version, continuing happily ... :", (head+6));
     }
 
     reader.IncPtr(2); /* skip flags */

Някои файлове не бяха показани, защото твърде много файлове са промени