فهرست منبع

Merge branch 'master' into fix-mingw-debug-build

Kim Kulling 6 سال پیش
والد
کامیت
e108b6f1d2
52فایلهای تغییر یافته به همراه1146 افزوده شده و 369 حذف شده
  1. 1 0
      .gitignore
  2. 1 1
      .travis.yml
  3. 22 12
      CMakeLists.txt
  4. 3 1
      Readme.md
  5. 12 6
      appveyor.yml
  6. 1 1
      code/AssbinLoader.cpp
  7. 0 2
      code/AssxmlExporter.cpp
  8. 1 1
      code/BlenderDNA.h
  9. 63 92
      code/C4DImporter.cpp
  10. 6 12
      code/C4DImporter.h
  11. 16 6
      code/CMakeLists.txt
  12. 5 5
      code/COBLoader.cpp
  13. 34 4
      code/ColladaExporter.cpp
  14. 11 0
      code/ColladaLoader.cpp
  15. 77 3
      code/ColladaParser.cpp
  16. 15 0
      code/ColladaParser.h
  17. 4 1
      code/D3MFOpcPackage.cpp
  18. 2 2
      code/Exporter.cpp
  19. 46 25
      code/FBXConverter.cpp
  20. 12 8
      code/FBXConverter.h
  21. 2 2
      code/FBXExportNode.cpp
  22. 35 2
      code/FBXMaterial.cpp
  23. 3 2
      code/FBXMeshGeometry.cpp
  24. 44 0
      code/FBXUtil.cpp
  25. 15 0
      code/FBXUtil.h
  26. 12 13
      code/IRRLoader.cpp
  27. 3 3
      code/Importer/STEPParser/STEPFileReader.cpp
  28. 9 9
      code/MD5Loader.cpp
  29. 1 1
      code/STLExporter.cpp
  30. 4 3
      code/glTF2Asset.h
  31. 4 4
      code/glTFAssetWriter.inl
  32. 1 1
      code/glTFExporter.cpp
  33. 4 4
      code/res/assimp.rc
  34. 8 1
      contrib/irrXML/CMakeLists.txt
  35. 9 4
      contrib/irrXML/CXMLReaderImpl.h
  36. 2 2
      contrib/irrXML/irrXML.cpp
  37. 15 9
      contrib/irrXML/irrXML.h
  38. 7 2
      contrib/zlib/CMakeLists.txt
  39. 1 1
      include/assimp/Exporter.hpp
  40. 4 0
      include/assimp/color4.inl
  41. 1 0
      include/assimp/material.h
  42. 0 103
      packaging/windows-innosetup/script.iss
  43. 71 0
      packaging/windows-innosetup/script_x64.iss
  44. 72 0
      packaging/windows-innosetup/script_x86.iss
  45. 11 0
      revision.h.in
  46. 444 0
      test/models/FBX/embedded_ascii/box.FBX
  47. 1 1
      test/models/PLY/cube_test.ply
  48. 9 13
      test/unit/utColladaExportCamera.cpp
  49. 15 0
      test/unit/utFBXImporterExporter.cpp
  50. 3 6
      tools/assimp_cmd/ImageExtractor.cpp
  51. 2 1
      tools/assimp_qt_viewer/CMakeLists.txt
  52. 2 0
      tools/assimp_view/CMakeLists.txt

+ 1 - 0
.gitignore

@@ -17,6 +17,7 @@ CMakeLists.txt.user
 
 # Generated
 assimp.pc
+assimp.aps
 revision.h
 contrib/zlib/zconf.h
 contrib/zlib/zlib.pc

+ 1 - 1
.travis.yml

@@ -70,6 +70,6 @@ addons:
     project:
       name: "assimp/assimp"
     notification_email: [email protected]
-    build_command_prepend: "cmake . -DASSIMP_ENABLE_BOOST_WORKAROUND=YES"
+    build_command_prepend: "cmake ./"
     build_command: "make -j4"
     branch_pattern: coverity_scan

+ 22 - 12
CMakeLists.txt

@@ -67,7 +67,7 @@ OPTION( ASSIMP_NO_EXPORT
 )
 OPTION( ASSIMP_BUILD_ZLIB
   "Build your own zlib"
-  OFF
+  OFF  
 )
 OPTION( ASSIMP_BUILD_ASSIMP_TOOLS
   "If the supplementary tools for Assimp are built in addition to the library."
@@ -106,7 +106,7 @@ OPTION ( BUILD_DOCS
   OFF
 )
 OPTION( INJECT_DEBUG_POSTFIX
-  "Inject debug postfix in .a/.so lib names"
+  "Inject debug postfix in .a/.so/.dll lib names"
   ON
 )
 
@@ -127,12 +127,15 @@ if (WIN32)
   ADD_DEFINITIONS( -DWIN32_LEAN_AND_MEAN )
 endif()
 
-
 IF(MSVC)
   OPTION( ASSIMP_INSTALL_PDB
     "Install MSVC debug files."
     ON
   )
+  IF(NOT (MSVC_VERSION LESS 1900))
+    # Multibyte character set is deprecated since at least MSVC2015 (possibly earlier)
+    ADD_DEFINITIONS( -DUNICODE -D_UNICODE )
+  ENDIF()
 ENDIF(MSVC)
 
 IF (BUILD_FRAMEWORK)
@@ -306,7 +309,9 @@ SET( ASSIMP_INCLUDE_INSTALL_DIR "include" CACHE STRING
 SET( ASSIMP_BIN_INSTALL_DIR "bin" CACHE STRING
   "Path the tool executables are installed to." )
 
-IF (CMAKE_BUILD_TYPE STREQUAL "Debug")
+get_cmake_property(is_multi_config GENERATOR_IS_MULTI_CONFIG)
+
+IF (is_multi_config OR (CMAKE_BUILD_TYPE STREQUAL "Debug"))
   SET(CMAKE_DEBUG_POSTFIX "d" CACHE STRING "Debug Postfix for lib, samples and tools")
 ELSE()
   SET(CMAKE_DEBUG_POSTFIX "" CACHE STRING "Debug Postfix for lib, samples and tools")
@@ -482,6 +487,7 @@ ENDIF ( ASSIMP_BUILD_ASSIMP_TOOLS )
 IF ( ASSIMP_BUILD_SAMPLES)
   IF ( WIN32 )
     ADD_SUBDIRECTORY( samples/SimpleTexturedOpenGL/ )
+    ADD_SUBDIRECTORY( samples/SimpleTexturedDirectx11 )
   ENDIF ( WIN32 )
   ADD_SUBDIRECTORY( samples/SimpleOpenGL/ )
 ENDIF ( ASSIMP_BUILD_SAMPLES )
@@ -547,18 +553,22 @@ if(WIN32)
   if (CMAKE_SIZEOF_VOID_P EQUAL 8)
     SET(BIN_DIR "${PROJECT_SOURCE_DIR}/bin64/")
     SET(LIB_DIR "${PROJECT_SOURCE_DIR}/lib64/")
-  elseif()
+  else()
     SET(BIN_DIR "${PROJECT_SOURCE_DIR}/bin32/")
     SET(LIB_DIR "${PROJECT_SOURCE_DIR}/lib32/")
   ENDIF()
 
-  IF(MSVC12)
-    SET(ASSIMP_MSVC_VERSION "vc120")
-  ELSEIF(MSVC14)
-    SET(ASSIMP_MSVC_VERSION "vc140")
-  ELSEIF(MSVC15)
-    SET(ASSIMP_MSVC_VERSION "vc141")
-  ENDIF(MSVC12)
+  IF(MSVC_TOOLSET_VERSION)
+    set(MSVC_PREFIX "vc${MSVC_TOOLSET_VERSION}")
+  ELSE()
+    IF(MSVC12)
+      SET(ASSIMP_MSVC_VERSION "vc120")
+    ELSEIF(MSVC14)
+      SET(ASSIMP_MSVC_VERSION "vc140")
+    ELSEIF(MSVC15)
+      SET(ASSIMP_MSVC_VERSION "vc141")
+    ENDIF(MSVC12)
+  ENDIF()
 
   IF(MSVC12 OR MSVC14 OR MSVC15 )
     ADD_CUSTOM_TARGET(UpdateAssimpLibsDebugSymbolsAndDLLs COMMENT "Copying Assimp Libraries ..." VERBATIM)

+ 3 - 1
Readme.md

@@ -17,6 +17,8 @@ A library to import and export various 3d-model-formats including scene-post-pro
 
 APIs are provided for C and C++. There are various bindings to other languages (C#, Java, Python, Delphi, D). Assimp also runs on Android and iOS.
 
+[Check the latest doc](https://assimp-docs.readthedocs.io/en/latest/).
+
 Additionally, assimp features various __mesh post processing tools__: normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials and many more.
 
 This is the development repo containing the latest features and bugfixes. For productive use though, we recommend one of the stable releases available from [Github Assimp Releases](https://github.com/assimp/assimp/releases).
@@ -99,7 +101,7 @@ __Importers__:
 
 Additionally, some formats are supported by dependency on non-free code or external SDKs (not built by default):
 
-- [C4D](https://en.wikipedia.org/wiki/Cinema_4D) (https://github.com/assimp/assimp/wiki/Cinema4D-&-Melange)
+- [C4D](https://en.wikipedia.org/wiki/Cinema_4D) (https://github.com/assimp/assimp/wiki/Cinema4D-&-Melange) IMporting geometry + node hierarchy are currently supported
 
 __Exporters__:
 

+ 12 - 6
appveyor.yml

@@ -15,8 +15,8 @@ matrix:
     
 image:
   - Visual Studio 2013
-  - Previous Visual Studio 2015
-  - Previous Visual Studio 2017
+  - Visual Studio 2015
+  - Visual Studio 2017
     
 platform:
   - Win32
@@ -28,10 +28,10 @@ install:
   - set PATH=C:\Ruby24-x64\bin;%PATH%
   - set CMAKE_DEFINES -DASSIMP_WERROR=ON
   - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2013" set CMAKE_GENERATOR_NAME=Visual Studio 12 2013
-  - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Previous Visual Studio 2015" set CMAKE_GENERATOR_NAME=Visual Studio 14 2015
-  - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Previous Visual Studio 2017" set CMAKE_GENERATOR_NAME=Visual Studio 15 2017
+  - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" set CMAKE_GENERATOR_NAME=Visual Studio 14 2015
+  - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" set CMAKE_GENERATOR_NAME=Visual Studio 15 2017
   - if "%platform%"=="x64" set CMAKE_GENERATOR_NAME=%CMAKE_GENERATOR_NAME% Win64
-  - cmake %CMAKE_DEFINES% -G "%CMAKE_GENERATOR_NAME%"
+  - 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
@@ -53,7 +53,13 @@ build:
   project: Assimp.sln
   
 after_build:
-  - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" iscc packaging\windows-innosetup\script.iss
+  - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" (
+        if "%platform%"=="x64" (
+            iscc packaging\windows-innosetup\script_x64.iss
+        ) else (
+            iscc packaging\windows-innosetup\script_x86.iss
+        )
+    )
   - 7z a assimp.7z bin\%CONFIGURATION%\* lib\%CONFIGURATION%\*
 
 test_script:

+ 1 - 1
code/AssbinLoader.cpp

@@ -68,7 +68,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 using namespace Assimp;
 
 static const aiImporterDesc desc = {
-    ".assbin Importer",
+    "Assimp Binary Importer",
     "Gargaj / Conspiracy",
     "",
     "",

+ 0 - 2
code/AssxmlExporter.cpp

@@ -555,8 +555,6 @@ void WriteDump(const aiScene* scene, IOStream* io, bool shortened) {
                             mesh->mNormals[n].z);
                     }
                 }
-                else {
-                }
                 ioprintf(io,"\t\t</Normals>\n");
             }
 

+ 1 - 1
code/BlenderDNA.h

@@ -416,7 +416,7 @@ template <> struct Structure :: _defaultInitializer<ErrorPolicy_Fail> {
     void operator ()(T& /*out*/,const char* = "") {
         // obviously, it is crucial that _DefaultInitializer is used
         // only from within a catch clause.
-        throw;
+        throw DeadlyImportError("Constructing BlenderDNA Structure encountered an error");
     }
 };
 

+ 63 - 92
code/C4DImporter.cpp

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2019, assimp team
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -68,8 +68,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 using namespace melange;
 
 // overload this function and fill in your own unique data
-void GetWriterInfo(int &id, String &appname)
-{
+void GetWriterInfo(int &id, String &appname) {
     id = 2424226;
     appname = "Open Asset Import Library";
 }
@@ -78,7 +77,10 @@ using namespace Assimp;
 using namespace Assimp::Formatter;
 
 namespace Assimp {
-    template<> const std::string LogFunctions<C4DImporter>::log_prefix = "C4D: ";
+    template<> const char* LogFunctions<C4DImporter>::Prefix() {
+        static auto prefix = "C4D: ";
+        return prefix;
+    }
 }
 
 static const aiImporterDesc desc = {
@@ -97,47 +99,44 @@ static const aiImporterDesc desc = {
 
 // ------------------------------------------------------------------------------------------------
 C4DImporter::C4DImporter()
-{}
+: BaseImporter() {
+    // empty
+}
 
 // ------------------------------------------------------------------------------------------------
-C4DImporter::~C4DImporter()
-{}
+C4DImporter::~C4DImporter() {
+    // empty
+}
 
 // ------------------------------------------------------------------------------------------------
-bool C4DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
-{
+bool C4DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const {
     const std::string& extension = GetExtension(pFile);
     if (extension == "c4d") {
         return true;
-    }
-
-    else if ((!extension.length() || checkSig) && pIOHandler)   {
+    } else if ((!extension.length() || checkSig) && pIOHandler)   {
         // TODO
     }
+
     return false;
 }
 
 // ------------------------------------------------------------------------------------------------
-const aiImporterDesc* C4DImporter::GetInfo () const
-{
+const aiImporterDesc* C4DImporter::GetInfo () const {
     return &desc;
 }
 
 // ------------------------------------------------------------------------------------------------
-void C4DImporter::SetupProperties(const Importer* /*pImp*/)
-{
+void C4DImporter::SetupProperties(const Importer* /*pImp*/) {
     // nothing to be done for the moment
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // Imports the given file into the given scene structure.
-void C4DImporter::InternReadFile( const std::string& pFile,
-    aiScene* pScene, IOSystem* pIOHandler)
-{
+void C4DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) {
     std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
 
-    if( file.get() == NULL) {
+    if( file.get() == nullptr ) {
         ThrowException("failed to open file " + pFile);
     }
 
@@ -151,7 +150,7 @@ void C4DImporter::InternReadFile( const std::string& pFile,
 
     // open document first
     BaseDocument* doc = LoadDocument(f, SCENEFILTER_OBJECTS | SCENEFILTER_MATERIALS);
-    if(doc == NULL) {
+    if(doc == nullptr ) {
         ThrowException("failed to read document " + pFile);
     }
 
@@ -160,11 +159,10 @@ void C4DImporter::InternReadFile( const std::string& pFile,
     // first convert all materials
     ReadMaterials(doc->GetFirstMaterial());
 
-    // process C4D scenegraph recursively
+    // process C4D scene-graph recursively
     try {
         RecurseHierarchy(doc->GetFirstObject(), pScene->mRootNode);
-    }
-    catch(...) {
+    } catch(...) {
         for(aiMesh* mesh : meshes) {
             delete mesh;
         }
@@ -201,8 +199,7 @@ void C4DImporter::InternReadFile( const std::string& pFile,
 
 
 // ------------------------------------------------------------------------------------------------
-bool C4DImporter::ReadShader(aiMaterial* out, melange::BaseShader* shader)
-{
+bool C4DImporter::ReadShader(aiMaterial* out, melange::BaseShader* shader) {
     // based on Melange sample code (C4DImportExport.cpp)
     while(shader) {
         if(shader->GetType() == Xlayer) {
@@ -220,15 +217,12 @@ bool C4DImporter::ReadShader(aiMaterial* out, melange::BaseShader* shader)
             // Ignore the actual layer blending - models for real-time rendering should not
             // use them in a non-trivial way. Just try to find textures that we can apply
             // to the model.
-            while (lsl)
-            {
-                if (lsl->GetType() == TypeFolder)
-                {
+            while (lsl) {
+                if (lsl->GetType() == TypeFolder) {
                     BlendFolder* const folder = dynamic_cast<BlendFolder*>(lsl);
                     LayerShaderLayer *subLsl = dynamic_cast<LayerShaderLayer*>(folder->m_Children.GetObject(0));
 
-                    while (subLsl)
-                    {
+                    while (subLsl) {
                         if (subLsl->GetType() == TypeShader) {
                             BlendShader* const shader = dynamic_cast<BlendShader*>(subLsl);
                             if(ReadShader(out, static_cast<BaseShader*>(shader->m_pLink->GetLink()))) {
@@ -238,8 +232,7 @@ bool C4DImporter::ReadShader(aiMaterial* out, melange::BaseShader* shader)
 
                         subLsl = subLsl->GetNext();
                     }
-                }
-                else if (lsl->GetType() == TypeShader) {
+                } else if (lsl->GetType() == TypeShader) {
                     BlendShader* const shader = dynamic_cast<BlendShader*>(lsl);
                     if(ReadShader(out, static_cast<BaseShader*>(shader->m_pLink->GetLink()))) {
                         return true;
@@ -248,33 +241,27 @@ bool C4DImporter::ReadShader(aiMaterial* out, melange::BaseShader* shader)
 
                 lsl = lsl->GetNext();
             }
-        }
-        else if ( shader->GetType() == Xbitmap )
-        {
+        } else if ( shader->GetType() == Xbitmap ) {
             aiString path;
             shader->GetFileName().GetString().GetCString(path.data, MAXLEN-1);
             path.length = ::strlen(path.data);
             out->AddProperty(&path, AI_MATKEY_TEXTURE_DIFFUSE(0));
             return true;
-        }
-        else {
+        } else {
             LogWarn("ignoring shader type: " + std::string(GetObjectTypeName(shader->GetType())));
         }
         shader = shader->GetNext();
     }
+
     return false;
 }
 
-
 // ------------------------------------------------------------------------------------------------
-void C4DImporter::ReadMaterials(melange::BaseMaterial* mat)
-{
+void C4DImporter::ReadMaterials(melange::BaseMaterial* mat) {
     // based on Melange sample code
-    while (mat)
-    {
+    while (mat) {
         const String& name = mat->GetName();
-        if (mat->GetType() == Mmaterial)
-        {
+        if (mat->GetType() == Mmaterial) {
             aiMaterial* out = new aiMaterial();
             material_mapping[mat] = static_cast<unsigned int>(materials.size());
             materials.push_back(out);
@@ -286,8 +273,7 @@ void C4DImporter::ReadMaterials(melange::BaseMaterial* mat)
 
             Material& m = dynamic_cast<Material&>(*mat);
 
-            if (m.GetChannelState(CHANNEL_COLOR))
-            {
+            if (m.GetChannelState(CHANNEL_COLOR)) {
                 GeData data;
                 mat->GetParameter(MATERIAL_COLOR_COLOR, data);
                 Vector color = data.GetVector();
@@ -307,9 +293,7 @@ void C4DImporter::ReadMaterials(melange::BaseMaterial* mat)
             if(shader) {
                 ReadShader(out, shader);
             }
-        }
-        else
-        {
+        } else {
             LogWarn("ignoring plugin material: " + std::string(GetObjectTypeName(mat->GetType())));
         }
         mat = mat->GetNext();
@@ -317,14 +301,12 @@ void C4DImporter::ReadMaterials(melange::BaseMaterial* mat)
 }
 
 // ------------------------------------------------------------------------------------------------
-void C4DImporter::RecurseHierarchy(BaseObject* object, aiNode* parent)
-{
-    ai_assert(parent != NULL);
+void C4DImporter::RecurseHierarchy(BaseObject* object, aiNode* parent) {
+    ai_assert(parent != nullptr );
     std::vector<aiNode*> nodes;
 
     // based on Melange sample code
-    while (object)
-    {
+    while (object) {
         const String& name = object->GetName();
         const LONG type = object->GetType();
         const Matrix& ml = object->GetMl();
@@ -356,26 +338,20 @@ void C4DImporter::RecurseHierarchy(BaseObject* object, aiNode* parent)
         nodes.push_back(nd);
 
         GeData data;
-        if (type == Ocamera)
-        {
+        if (type == Ocamera) {
             object->GetParameter(CAMERAOBJECT_FOV, data);
             // TODO: read camera
-        }
-        else if (type == Olight)
-        {
+        } else if (type == Olight) {
             // TODO: read light
-        }
-        else if (type == Opolygon)
-        {
+        } else if (type == Opolygon) {
             aiMesh* const mesh = ReadMesh(object);
-            if(mesh != NULL) {
+            if(mesh != nullptr) {
                 nd->mNumMeshes = 1;
                 nd->mMeshes = new unsigned int[1];
                 nd->mMeshes[0] = static_cast<unsigned int>(meshes.size());
                 meshes.push_back(mesh);
             }
-        }
-        else {
+        } else {
             LogWarn("ignoring object: " + std::string(GetObjectTypeName(type)));
         }
 
@@ -389,28 +365,27 @@ void C4DImporter::RecurseHierarchy(BaseObject* object, aiNode* parent)
     std::copy(nodes.begin(), nodes.end(), parent->mChildren);
 }
 
-
 // ------------------------------------------------------------------------------------------------
-aiMesh* C4DImporter::ReadMesh(BaseObject* object)
-{
-    ai_assert(object != NULL && object->GetType() == Opolygon);
+aiMesh* C4DImporter::ReadMesh(BaseObject* object) {
+    ai_assert(object != nullptr);
+    ai_assert( object->GetType() == Opolygon );
 
     // based on Melange sample code
     PolygonObject* const polyObject = dynamic_cast<PolygonObject*>(object);
-    ai_assert(polyObject != NULL);
+    ai_assert(polyObject != nullptr);
 
     const LONG pointCount = polyObject->GetPointCount();
     const LONG polyCount = polyObject->GetPolygonCount();
     if(!polyObject || !pointCount) {
         LogWarn("ignoring mesh with zero vertices or faces");
-        return NULL;
+        return nullptr;
     }
 
     const Vector* points = polyObject->GetPointR();
-    ai_assert(points != NULL);
+    ai_assert(points != nullptr);
 
     const CPolygon* polys = polyObject->GetPolygonR();
-    ai_assert(polys != NULL);
+    ai_assert(polys != nullptr);
 
     std::unique_ptr<aiMesh> mesh(new aiMesh());
     mesh->mNumFaces = static_cast<unsigned int>(polyCount);
@@ -443,14 +418,14 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object)
 
     // check if there are normals, tangents or UVW coordinates
     BaseTag* tag = object->GetTag(Tnormal);
-    NormalTag* normals_src = NULL;
+    NormalTag* normals_src = nullptr;
     if(tag) {
         normals_src = dynamic_cast<NormalTag*>(tag);
         normals = mesh->mNormals = new aiVector3D[mesh->mNumVertices]();
     }
 
     tag = object->GetTag(Ttangent);
-    TangentTag* tangents_src = NULL;
+    TangentTag* tangents_src = nullptr;
     if(tag) {
         tangents_src = dynamic_cast<TangentTag*>(tag);
         tangents = mesh->mTangents = new aiVector3D[mesh->mNumVertices]();
@@ -458,15 +433,14 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object)
     }
 
     tag = object->GetTag(Tuvw);
-    UVWTag* uvs_src = NULL;
+    UVWTag* uvs_src = nullptr;
     if(tag) {
         uvs_src = dynamic_cast<UVWTag*>(tag);
         uvs = mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices]();
     }
 
     // copy vertices and extra channels over and populate faces
-    for (LONG i = 0; i < polyCount; ++i, ++face)
-    {
+    for (LONG i = 0; i < polyCount; ++i, ++face) {
         ai_assert(polys[i].a < pointCount && polys[i].a >= 0);
         const Vector& pointA = points[polys[i].a];
         verts->x = pointA.x;
@@ -489,8 +463,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object)
         ++verts;
 
         // TODO: do we also need to handle lines or points with similar checks?
-        if (polys[i].c != polys[i].d)
-        {
+        if (polys[i].c != polys[i].d) {
             ai_assert(polys[i].d < pointCount && polys[i].d >= 0);
 
             face->mNumIndices = 4;
@@ -500,8 +473,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object)
             verts->y = pointD.y;
             verts->z = pointD.z;
             ++verts;
-        }
-        else {
+        } else {
             face->mNumIndices = 3;
         }
         face->mIndices = new unsigned int[face->mNumIndices];
@@ -513,8 +485,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object)
         if (normals_src) {
             if(i >= normals_src->GetDataCount()) {
                 LogError("unexpected number of normals, ignoring");
-            }
-            else {
+            } else {
                 ConstNormalHandle normal_handle = normals_src->GetDataAddressR();
                 NormalStruct nor;
                 NormalTag::Get(normal_handle, i, nor);
@@ -616,26 +587,25 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object)
     }
 
     mesh->mMaterialIndex = ResolveMaterial(polyObject);
+
     return mesh.release();
 }
 
-
 // ------------------------------------------------------------------------------------------------
-unsigned int C4DImporter::ResolveMaterial(PolygonObject* obj)
-{
-    ai_assert(obj != NULL);
+unsigned int C4DImporter::ResolveMaterial(PolygonObject* obj) {
+    ai_assert(obj != nullptr);
 
     const unsigned int mat_count = static_cast<unsigned int>(materials.size());
 
     BaseTag* tag = obj->GetTag(Ttexture);
-    if(tag == NULL) {
+    if(tag == nullptr) {
         return mat_count;
     }
 
     TextureTag& ttag = dynamic_cast<TextureTag&>(*tag);
 
     BaseMaterial* const mat = ttag.GetMaterial();
-    ai_assert(mat != NULL);
+    ai_assert(mat != nullptr);
 
     const MaterialMap::const_iterator it = material_mapping.find(mat);
     if(it == material_mapping.end()) {
@@ -643,6 +613,7 @@ unsigned int C4DImporter::ResolveMaterial(PolygonObject* obj)
     }
 
     ai_assert((*it).second < mat_count);
+
     return (*it).second;
 }
 

+ 6 - 12
code/C4DImporter.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2012, assimp team
+Copyright (c) 2006-2019, assimp team
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -48,6 +48,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/LogAux.h>
 
 #include <map>
+
+// Forward declarations
 struct aiNode;
 struct aiMesh;
 struct aiMaterial;
@@ -61,8 +63,7 @@ namespace melange {
     class BaseShader;
 }
 
-namespace Assimp    {
-
+namespace Assimp  {
     // TinyFormatter.h
     namespace Formatter {
         template <typename T,typename TR, typename A> class basic_formatter;
@@ -75,17 +76,10 @@ namespace Assimp    {
  *
  *  Note that Melange is not free software. */
 // -------------------------------------------------------------------------------------------
-class C4DImporter : public BaseImporter, public LogFunctions<C4DImporter>
-{
+class C4DImporter : public BaseImporter, public LogFunctions<C4DImporter> {
 public:
-
     C4DImporter();
     ~C4DImporter();
-
-
-public:
-
-    // --------------------
     bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
         bool checkSig) const;
 
@@ -119,5 +113,5 @@ private:
 }; // !class C4DImporter
 
 } // end of namespace Assimp
-#endif // INCLUDED_AI_CINEMA_4D_LOADER_H
 
+#endif // INCLUDED_AI_CINEMA_4D_LOADER_H

+ 16 - 6
code/CMakeLists.txt

@@ -145,6 +145,10 @@ SET( Core_SRCS
   Assimp.cpp
 )
 
+IF(MSVC)
+  list(APPEND Core_SRCS "res/assimp.rc")
+ENDIF(MSVC)
+
 SET( Logging_SRCS
   ${HEADER_PATH}/DefaultLogger.hpp
   ${HEADER_PATH}/LogStream.hpp
@@ -841,12 +845,11 @@ SET( Extra_SRCS
 )
 SOURCE_GROUP( Extra FILES ${Extra_SRCS})
 
-
 SET( Clipper_SRCS
   ../contrib/clipper/clipper.hpp
   ../contrib/clipper/clipper.cpp
 )
-SOURCE_GROUP( Clipper FILES ${Clipper_SRCS})
+SOURCE_GROUP( Contrib\\Clipper FILES ${Clipper_SRCS})
 
 SET( Poly2Tri_SRCS
   ../contrib/poly2tri/poly2tri/common/shapes.cc
@@ -861,7 +864,7 @@ SET( Poly2Tri_SRCS
   ../contrib/poly2tri/poly2tri/sweep/sweep_context.cc
   ../contrib/poly2tri/poly2tri/sweep/sweep_context.h
 )
-SOURCE_GROUP( Poly2Tri FILES ${Poly2Tri_SRCS})
+SOURCE_GROUP( Contrib\\Poly2Tri FILES ${Poly2Tri_SRCS})
 
 SET( unzip_SRCS
   ../contrib/unzip/crypt.h
@@ -870,7 +873,7 @@ SET( unzip_SRCS
   ../contrib/unzip/unzip.c
   ../contrib/unzip/unzip.h
 )
-SOURCE_GROUP( unzip FILES ${unzip_SRCS})
+SOURCE_GROUP(Contrib\\unzip FILES ${unzip_SRCS})
 
 SET( ziplib_SRCS
   ../contrib/zip/src/miniz.h
@@ -902,7 +905,7 @@ SET ( openddl_parser_SRCS
   ../contrib/openddlparser/include/openddlparser/DDLNode.h
   ../contrib/openddlparser/include/openddlparser/Value.h
 )
-SOURCE_GROUP( openddl_parser FILES ${openddl_parser_SRCS})
+SOURCE_GROUP( Contrib\\openddl_parser FILES ${openddl_parser_SRCS})
 
 SET ( open3dgc_SRCS
   ../contrib/Open3DGC/o3dgcAdjacencyInfo.h
@@ -935,7 +938,7 @@ SET ( open3dgc_SRCS
   ../contrib/Open3DGC/o3dgcVector.h
   ../contrib/Open3DGC/o3dgcVector.inl
 )
-SOURCE_GROUP( open3dgc FILES ${open3dgc_SRCS})
+SOURCE_GROUP( Contrib\\open3dgc FILES ${open3dgc_SRCS})
 
 # Check dependencies for glTF importer with Open3DGC-compression.
 # RT-extensions is used in "contrib/Open3DGC/o3dgcTimer.h" for collecting statistics. Pointed file
@@ -1046,6 +1049,10 @@ ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
 
 if( MSVC )
   # in order to prevent DLL hell, each of the DLLs have to be suffixed with the major version and msvc prefix
+  # CMake 3.12 added a variable for this
+  if(MSVC_TOOLSET_VERSION)
+    set(MSVC_PREFIX "vc${MSVC_TOOLSET_VERSION}")
+  else()
   if( MSVC70 OR MSVC71 )
     set(MSVC_PREFIX "vc70")
   elseif( MSVC80 )
@@ -1060,9 +1067,12 @@ if( MSVC )
     set(MSVC_PREFIX "vc120")
   elseif( MSVC14 )
     set(MSVC_PREFIX "vc140")
+  elseif( MSVC15 )
+    set(MSVC_PREFIX "vc141")
   else()
     set(MSVC_PREFIX "vc150")
   endif()
+  endif()
   set(LIBRARY_SUFFIX "${ASSIMP_LIBRARY_SUFFIX}-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library")
 endif()
 

+ 5 - 5
code/COBLoader.cpp

@@ -144,7 +144,7 @@ void COBImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
     // check header
     char head[32];
     stream->CopyAndAdvance(head,32);
-    if (strncmp(head,"Caligari ",9)) {
+    if (strncmp(head,"Caligari ",9) != 0) {
         ThrowException("Could not found magic id: `Caligari`");
     }
 
@@ -656,14 +656,14 @@ void COBImporter::ReadLght_Ascii(Scene& out, LineSplitter& splitter, const Chunk
     ReadFloat3Tuple_Ascii(msh.color ,&rgb);
 
     SkipSpaces(&rgb);
-    if (strncmp(rgb,"cone angle",10)) {
+    if (strncmp(rgb,"cone angle",10) != 0) {
         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)) {
+    if (strncmp(rgb,"inner angle",11) != 0) {
         ASSIMP_LOG_WARN_F( "Expected `inner angle` entity in `color` line in `Lght` chunk ", nfo.id);
     }
     SkipSpaces(rgb+11,&rgb);
@@ -903,7 +903,7 @@ public:
         if(nfo.size != static_cast<unsigned int>(-1)) {
             try {
                 reader.IncPtr( static_cast< int >( nfo.size ) - reader.GetCurrentPos() + cur );
-            } catch ( DeadlyImportError e ) {
+            } catch (const DeadlyImportError& e ) {
                 // out of limit so correct the value
                 reader.IncPtr( reader.GetReadLimit() );
             }
@@ -1214,7 +1214,7 @@ void COBImporter::ReadGrou_Binary(COB::Scene& out, StreamReaderLE& reader, const
 
     const chunk_guard cn(nfo,reader);
 
-    out.nodes.push_back(std::shared_ptr<Group>(new Group()));
+    out.nodes.push_back(std::make_shared<Group>());
     Group& msh = (Group&)(*out.nodes.back().get());
     msh = nfo;
 

+ 34 - 4
code/ColladaExporter.cpp

@@ -238,7 +238,11 @@ void ColladaExporter::WriteHeader()
     mOutput << startstr << "<contributor>" << endstr;
     PushTag();
 
-    aiMetadata* meta = mScene->mRootNode->mMetaData;
+    // If no Scene metadata, use root node metadata
+    aiMetadata* meta = mScene->mMetaData;
+    if (!meta)
+        meta = mScene->mRootNode->mMetaData;
+
     aiString value;
     if (!meta || !meta->Get("Author", value))
         mOutput << startstr << "<author>" << "Assimp" << "</author>" << endstr;
@@ -250,13 +254,39 @@ void ColladaExporter::WriteHeader()
     else
         mOutput << startstr << "<authoring_tool>" << XMLEscape(value.C_Str()) << "</authoring_tool>" << endstr;
 
-    //mOutput << startstr << "<author>" << mScene->author.C_Str() << "</author>" << endstr;
-    //mOutput << startstr << "<authoring_tool>" << mScene->authoringTool.C_Str() << "</authoring_tool>" << endstr;
+    if (meta)
+    {
+        if (meta->Get("Comments", value))
+            mOutput << startstr << "<comments>" << XMLEscape(value.C_Str()) << "</comments>" << endstr;
+        if (meta->Get("Copyright", value))
+            mOutput << startstr << "<copyright>" << XMLEscape(value.C_Str()) << "</copyright>" << endstr;
+        if (meta->Get("SourceData", value))
+            mOutput << startstr << "<source_data>" << XMLEscape(value.C_Str()) << "</source_data>" << endstr;
+    }
 
     PopTag();
     mOutput << startstr << "</contributor>" << endstr;
-    mOutput << startstr << "<created>" << date_str << "</created>" << endstr;
+
+    if (!meta || !meta->Get("Created", value))
+        mOutput << startstr << "<created>" << date_str << "</created>" << endstr;
+    else
+        mOutput << startstr << "<created>" << XMLEscape(value.C_Str()) << "</created>" << endstr;
+
+    // Modified date is always the date saved
     mOutput << startstr << "<modified>" << date_str << "</modified>" << endstr;
+
+    if (meta)
+    {
+        if (meta->Get("Keywords", value))
+            mOutput << startstr << "<keywords>" << XMLEscape(value.C_Str()) << "</keywords>" << endstr;
+        if (meta->Get("Revision", value))
+            mOutput << startstr << "<revision>" << XMLEscape(value.C_Str()) << "</revision>" << endstr;
+        if (meta->Get("Subject", value))
+            mOutput << startstr << "<subject>" << XMLEscape(value.C_Str()) << "</subject>" << endstr;
+        if (meta->Get("Title", value))
+            mOutput << startstr << "<title>" << XMLEscape(value.C_Str()) << "</title>" << endstr;
+    }
+
     mOutput << startstr << "<unit name=\"meter\" meter=\"" << scale << "\" />" << endstr;
     mOutput << startstr << "<up_axis>" << up_axis << "</up_axis>" << endstr;
     PopTag();

+ 11 - 0
code/ColladaLoader.cpp

@@ -207,6 +207,17 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
                 0,  0,  0,  1);
     }
 
+    // Store scene metadata
+    if (!parser.mAssetMetaData.empty()) {
+        const size_t numMeta(parser.mAssetMetaData.size());
+        pScene->mMetaData = aiMetadata::Alloc(static_cast<unsigned int>(numMeta));
+        size_t i = 0;
+        for (auto it = parser.mAssetMetaData.cbegin(); it != parser.mAssetMetaData.cend(); ++it, ++i)
+        {
+            pScene->mMetaData->Set(static_cast<unsigned int>(i), (*it).first, (*it).second);
+        }
+    }
+
     // store all meshes
     StoreSceneMeshes( pScene);
 

+ 77 - 3
code/ColladaParser.cpp

@@ -264,14 +264,19 @@ void ColladaParser::ReadAssetInfo()
 
                 // check element end
                 TestClosing( "up_axis");
-            } else
+            }
+            else if(IsElement("contributor"))
             {
-                SkipElement();
+                ReadContributorInfo();
+            }
+            else
+            {
+                ReadMetaDataItem(mAssetMetaData);
             }
         }
         else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
         {
-            if( strcmp( mReader->getNodeName(), "asset") != 0)
+            if (strcmp( mReader->getNodeName(), "asset") != 0)
                 ThrowException( "Expected end of <asset> element.");
 
             break;
@@ -279,6 +284,75 @@ void ColladaParser::ReadAssetInfo()
     }
 }
 
+// ------------------------------------------------------------------------------------------------
+// Reads the contributor info
+void ColladaParser::ReadContributorInfo()
+{
+    if (mReader->isEmptyElement())
+        return;
+
+    while (mReader->read())
+    {
+        if (mReader->getNodeType() == irr::io::EXN_ELEMENT)
+        {
+            ReadMetaDataItem(mAssetMetaData);
+        }
+        else if (mReader->getNodeType() == irr::io::EXN_ELEMENT_END)
+        {
+            if (strcmp(mReader->getNodeName(), "contributor") != 0)
+                ThrowException("Expected end of <contributor> element.");
+            break;
+        }
+    }
+}
+
+// ------------------------------------------------------------------------------------------------
+// Reads a single string metadata item
+void ColladaParser::ReadMetaDataItem(StringMetaData &metadata)
+{
+    // Metadata such as created, keywords, subject etc
+    const char* key_char = mReader->getNodeName();
+    if (key_char != nullptr)
+    {
+        const std::string key_str(key_char);
+        const char* value_char = TestTextContent();
+        if (value_char != nullptr)
+        {
+            std::string camel_key_str = key_str;
+            ToCamelCase(camel_key_str);
+            aiString aistr;
+            aistr.Set(value_char);
+            metadata.emplace(camel_key_str, aistr);
+            TestClosing(key_str.c_str());
+        }
+        else
+            SkipElement();
+    }
+    else
+        SkipElement();
+}
+
+// ------------------------------------------------------------------------------------------------
+// Convert underscore_seperated to CamelCase: "authoring_tool" becomes "AuthoringTool"
+void ColladaParser::ToCamelCase(std::string &text)
+{
+    if (text.empty())
+        return;
+    // Capitalise first character
+    text[0] = ToUpper(text[0]);
+    for (auto it = text.begin(); it != text.end(); /*iterated below*/)
+    {
+        if ((*it) == '_')
+        {
+            it = text.erase(it);
+            if (it != text.end())
+                (*it) = ToUpper(*it);
+        }
+        else
+            ++it;
+    }
+}
+
 // ------------------------------------------------------------------------------------------------
 // Reads the animation clips
 void ColladaParser::ReadAnimationClipLibrary()

+ 15 - 0
code/ColladaParser.h

@@ -66,6 +66,9 @@ namespace Assimp
         friend class ColladaLoader;
 
     protected:
+        /** Map for generic metadata as aiString */
+        typedef std::map<std::string, aiString> StringMetaData;
+
         /** Constructor from XML file */
         ColladaParser( IOSystem* pIOHandler, const std::string& pFile);
 
@@ -81,6 +84,15 @@ namespace Assimp
         /** Reads asset information such as coordinate system information and legal blah */
         void ReadAssetInfo();
 
+        /** Reads contributor information such as author and legal blah */
+        void ReadContributorInfo();
+
+        /** Reads generic metadata into provided map */
+        void ReadMetaDataItem(StringMetaData &metadata);
+
+        /** Convert underscore_seperated to CamelCase "authoring_tool" becomes "AuthoringTool" */
+        static void ToCamelCase(std::string &text);
+
         /** Reads the animation library */
         void ReadAnimationLibrary();
 
@@ -343,6 +355,9 @@ namespace Assimp
         /** Which is the up vector */
         enum { UP_X, UP_Y, UP_Z } mUpDirection;
 
+        /** Asset metadata (global for scene) */
+        StringMetaData mAssetMetaData;
+
         /** Collada file format version */
         Collada::FormatVersion mFormat;
     };

+ 4 - 1
code/D3MFOpcPackage.cpp

@@ -476,8 +476,11 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile)
             mZipArchive->Close( fileStream );
 
         } else if( file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE) {
-
+            ASSIMP_LOG_WARN_F("Ignored file of unsupported type CONTENT_TYPES_ARCHIVES",file);
+        } else {
+            ASSIMP_LOG_WARN_F("Ignored file of unknown type: ",file);
         }
+
     }
 }
 

+ 2 - 2
code/Exporter.cpp

@@ -288,7 +288,7 @@ void Exporter::SetProgressHandler(ProgressHandler* pHandler) {
 
 // ------------------------------------------------------------------------------------------------
 const aiExportDataBlob* Exporter::ExportToBlob( const aiScene* pScene, const char* pFormatId,
-                                                unsigned int, const ExportProperties* /*pProperties*/ ) {
+                                                unsigned int pPreprocessing, const ExportProperties* pProperties) {
     if (pimpl->blob) {
         delete pimpl->blob;
         pimpl->blob = nullptr;
@@ -298,7 +298,7 @@ const aiExportDataBlob* Exporter::ExportToBlob( const aiScene* pScene, const cha
     BlobIOSystem* blobio = new BlobIOSystem();
     pimpl->mIOSystem = std::shared_ptr<IOSystem>( blobio );
 
-    if (AI_SUCCESS != Export(pScene,pFormatId,blobio->GetMagicFileName())) {
+    if (AI_SUCCESS != Export(pScene,pFormatId,blobio->GetMagicFileName(), pPreprocessing, pProperties)) {
         pimpl->mIOSystem = old;
         return nullptr;
     }

+ 46 - 25
code/FBXConverter.cpp

@@ -77,9 +77,19 @@ namespace Assimp {
 #define CONVERT_FBX_TIME(time) static_cast<double>(time) / 46186158000L
 
         FBXConverter::FBXConverter(aiScene* out, const Document& doc)
-            : defaultMaterialIndex()
-            , out(out)
-            , doc(doc) {
+        : defaultMaterialIndex()
+        , lights()
+        , cameras()
+        , textures()
+        , materials_converted()
+        , textures_converted()
+        , meshes_converted()
+        , node_anim_chain_bits()
+        , mNodeNameInstances()
+        , mNodeNames()
+        , anim_fps()
+        , out(out)
+        , doc(doc) {
             // animations need to be converted first since this will
             // populate the node_anim_chain_bits map, which is needed
             // to determine which nodes need to be generated.
@@ -410,19 +420,24 @@ namespace Assimp {
 
         void FBXConverter::GetUniqueName(const std::string &name, std::string &uniqueName)
         {
-            int i = 0;
             uniqueName = name;
-            while (mNodeNames.find(uniqueName) != mNodeNames.end())
+            int i = 0;
+            auto it = mNodeNameInstances.find(name); // duplicate node name instance count
+            if (it != mNodeNameInstances.end())
             {
-                ++i;
-                std::stringstream ext;
-                ext << name << std::setfill('0') << std::setw(3) << i;
-                uniqueName = ext.str();
+                i = it->second;
+                while (mNodeNames.find(uniqueName) != mNodeNames.end())
+                {
+                    i++;
+                    std::stringstream ext;
+                    ext << name << std::setfill('0') << std::setw(3) << i;
+                    uniqueName = ext.str();
+                }
             }
+            mNodeNameInstances[name] = i;
             mNodeNames.insert(uniqueName);
         }
 
-
         const char* FBXConverter::NameTransformationComp(TransformationComp comp) {
             switch (comp) {
             case TransformationComp_Translation:
@@ -1712,22 +1727,22 @@ namespace Assimp {
                         if (!mesh)
                         {
                             for (const MeshMap::value_type& v : meshes_converted) {
-                                const MeshGeometry* const mesh = dynamic_cast<const MeshGeometry*> (v.first);
-                                if (!mesh) {
+                                const MeshGeometry* const meshGeom = dynamic_cast<const MeshGeometry*> (v.first);
+                                if (!meshGeom) {
                                     continue;
                                 }
 
-                                const MatIndexArray& mats = mesh->GetMaterialIndices();
+                                const MatIndexArray& mats = meshGeom->GetMaterialIndices();
                                 if (std::find(mats.begin(), mats.end(), matIndex) == mats.end()) {
                                     continue;
                                 }
 
                                 int index = -1;
                                 for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
-                                    if (mesh->GetTextureCoords(i).empty()) {
+                                    if (meshGeom->GetTextureCoords(i).empty()) {
                                         break;
                                     }
-                                    const std::string& name = mesh->GetTextureCoordChannelName(i);
+                                    const std::string& name = meshGeom->GetTextureCoordChannelName(i);
                                     if (name == uvSet) {
                                         index = static_cast<int>(i);
                                         break;
@@ -1835,22 +1850,22 @@ namespace Assimp {
                         if (!mesh)
                         {
                             for (const MeshMap::value_type& v : meshes_converted) {
-                                const MeshGeometry* const mesh = dynamic_cast<const MeshGeometry*> (v.first);
-                                if (!mesh) {
+                                const MeshGeometry* const meshGeom = dynamic_cast<const MeshGeometry*> (v.first);
+                                if (!meshGeom) {
                                     continue;
                                 }
 
-                                const MatIndexArray& mats = mesh->GetMaterialIndices();
+                                const MatIndexArray& mats = meshGeom->GetMaterialIndices();
                                 if (std::find(mats.begin(), mats.end(), matIndex) == mats.end()) {
                                     continue;
                                 }
 
                                 int index = -1;
                                 for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
-                                    if (mesh->GetTextureCoords(i).empty()) {
+                                    if (meshGeom->GetTextureCoords(i).empty()) {
                                         break;
                                     }
-                                    const std::string& name = mesh->GetTextureCoordChannelName(i);
+                                    const std::string& name = meshGeom->GetTextureCoordChannelName(i);
                                     if (name == uvSet) {
                                         index = static_cast<int>(i);
                                         break;
@@ -2041,6 +2056,12 @@ namespace Assimp {
                 CalculatedOpacity = 1.0f - ((Transparent.r + Transparent.g + Transparent.b) / 3.0f);
             }
 
+            // try to get the transparency factor
+            const float TransparencyFactor = PropertyGet<float>(props, "TransparencyFactor", ok);
+            if (ok) {
+                out_mat->AddProperty(&TransparencyFactor, 1, AI_MATKEY_TRANSPARENCYFACTOR);
+            }
+
             // use of TransparencyFactor is inconsistent.
             // Maya always stores it as 1.0,
             // so we can't use it to set AI_MATKEY_OPACITY.
@@ -2191,22 +2212,22 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa
                     if (!mesh)
                     {
                         for (const MeshMap::value_type& v : meshes_converted) {
-                            const MeshGeometry* const mesh = dynamic_cast<const MeshGeometry*>(v.first);
-                            if (!mesh) {
+                            const MeshGeometry* const meshGeom = dynamic_cast<const MeshGeometry*>(v.first);
+                            if (!meshGeom) {
                                 continue;
                             }
 
-                            const MatIndexArray& mats = mesh->GetMaterialIndices();
+                            const MatIndexArray& mats = meshGeom->GetMaterialIndices();
                             if (std::find(mats.begin(), mats.end(), matIndex) == mats.end()) {
                                 continue;
                             }
 
                             int index = -1;
                             for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
-                                if (mesh->GetTextureCoords(i).empty()) {
+                                if (meshGeom->GetTextureCoords(i).empty()) {
                                     break;
                                 }
-                                const std::string& name = mesh->GetTextureCoordChannelName(i);
+                                const std::string& name = meshGeom->GetTextureCoordChannelName(i);
                                 if (name == uvSet) {
                                     index = static_cast<int>(i);
                                     break;

+ 12 - 8
code/FBXConverter.h

@@ -58,6 +58,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/texture.h>
 #include <assimp/camera.h>
 #include <assimp/StringComparison.h>
+#include <unordered_map>
+#include <unordered_set>
 
 struct aiScene;
 struct aiNode;
@@ -74,8 +76,6 @@ namespace FBX {
 
 class Document;
 
-using NodeNameCache = std::set<std::string>;
-
 /** 
  *  Convert a FBX #Document to #aiScene
  *  @param out Empty scene to be populated
@@ -419,7 +419,6 @@ private:
     void TransferDataToScene();
 
 private:
-
     // 0: not assigned yet, others: index is value - 1
     unsigned int defaultMaterialIndex;
 
@@ -429,22 +428,27 @@ private:
     std::vector<aiLight*> lights;
     std::vector<aiCamera*> cameras;
     std::vector<aiTexture*> textures;
-    
 
-    typedef std::map<const Material*, unsigned int> MaterialMap;
+    using MaterialMap = std::map<const Material*, unsigned int>;
     MaterialMap materials_converted;
 
-    typedef std::map<const Video*, unsigned int> VideoMap;
+    using VideoMap = std::map<const Video*, unsigned int>;
     VideoMap textures_converted;
 
-    typedef std::map<const Geometry*, std::vector<unsigned int> > MeshMap;
+    using MeshMap = std::map<const Geometry*, std::vector<unsigned int> >;
     MeshMap meshes_converted;
 
     // fixed node name -> which trafo chain components have animations?
-    typedef std::map<std::string, unsigned int> NodeAnimBitMap;
+    using NodeAnimBitMap = std::map<std::string, unsigned int> ;
     NodeAnimBitMap node_anim_chain_bits;
 
+    // number of nodes with the same name
+    using NodeAnimNameMap = std::unordered_map<std::string, unsigned int>;
+    NodeAnimNameMap mNodeNameInstances;
+
+    using NodeNameCache = std::unordered_set<std::string>;
     NodeNameCache mNodeNames;
+
     double anim_fps;
 
     aiScene* const out;

+ 2 - 2
code/FBXExportNode.cpp

@@ -432,7 +432,7 @@ void FBX::Node::WritePropertyNodeAscii(
     char buffer[32];
     FBX::Node node(name);
     node.Begin(s, false, indent);
-    std::string vsize = std::to_string(v.size());
+    std::string vsize = to_string(v.size());
     // *<size> {
     s.PutChar('*'); s.PutString(vsize); s.PutString(" {\n");
     // indent + 1
@@ -468,7 +468,7 @@ void FBX::Node::WritePropertyNodeAscii(
     char buffer[32];
     FBX::Node node(name);
     node.Begin(s, false, indent);
-    std::string vsize = std::to_string(v.size());
+    std::string vsize = to_string(v.size());
     // *<size> {
     s.PutChar('*'); s.PutString(vsize); s.PutString(" {\n");
     // indent + 1

+ 35 - 2
code/FBXMaterial.cpp

@@ -55,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/ByteSwapper.h>
 
 #include <algorithm> // std::transform
+#include "FBXUtil.h"
 
 namespace Assimp {
 namespace FBX {
@@ -206,6 +207,20 @@ Texture::Texture(uint64_t id, const Element& element, const Document& doc, const
 
     props = GetPropertyTable(doc,"Texture.FbxFileTexture",element,sc);
 
+    // 3DS Max and FBX SDK use "Scaling" and "Translation" instead of "ModelUVScaling" and "ModelUVTranslation". Use these properties if available.
+    bool ok;
+    const aiVector3D& scaling = PropertyGet<aiVector3D>(*props, "Scaling", ok);
+    if (ok) {
+        uvScaling.x = scaling.x;
+        uvScaling.y = scaling.y;
+    }
+
+    const aiVector3D& trans = PropertyGet<aiVector3D>(*props, "Translation", ok);
+    if (ok) {
+        uvTrans.x = trans.x;
+        uvTrans.y = trans.y;
+    }
+
     // resolve video links
     if(doc.Settings().readTextures) {
         const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID());
@@ -307,7 +322,22 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std
             const Token& token = GetRequiredToken(*Content, 0);
             const char* data = token.begin();
             if (!token.IsBinary()) {
-                DOMWarning("video content is not binary data, ignoring", &element);
+                if (*data != '"') {
+                    DOMError("embedded content is not surrounded by quotation marks", &element);
+                }
+                else {
+                    const char* encodedData = data + 1;
+                    size_t encodedDataLen = static_cast<size_t>(token.end() - token.begin());
+                    // search for last quotation mark
+                    while (encodedDataLen > 1 && encodedData[encodedDataLen] != '"')
+                        encodedDataLen--;
+                    if (encodedDataLen % 4 != 0) {
+                        DOMError("embedded content is invalid, needs to be in base64", &element);
+                    }
+                    else {
+                        contentLength = Util::DecodeBase64(encodedData, encodedDataLen, content);
+                    }
+                }
             }
             else if (static_cast<size_t>(token.end() - data) < 5) {
                 DOMError("binary data array is too short, need five (5) bytes for type signature and element count", &element);
@@ -326,8 +356,11 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std
                 content = new uint8_t[len];
                 ::memcpy(content, data + 5, len);
             }
-        } catch (runtime_error runtimeError) {
+        } catch (const runtime_error& runtimeError)
+        {
             //we don't need the content data for contents that has already been loaded
+            ASSIMP_LOG_DEBUG_F("Caught exception in FBXMaterial (likely because content was already loaded): ",
+                    runtimeError.what());
         }
     }
 

+ 3 - 2
code/FBXMeshGeometry.cpp

@@ -630,10 +630,11 @@ void MeshGeometry::ReadVertexDataMaterials(std::vector<int>& materials_out, cons
             materials_out.clear();
         }
 
-        m_materials.assign(m_vertices.size(),materials_out[0]);
+        materials_out.resize(m_vertices.size());
+        std::fill(materials_out.begin(), materials_out.end(), materials_out.at(0));
     }
     else if (MappingInformationType == "ByPolygon" && ReferenceInformationType == "IndexToDirect") {
-        m_materials.resize(face_count);
+        materials_out.resize(face_count);
 
         if(materials_out.size() != face_count) {
             FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygon mapping: ")

+ 44 - 0
code/FBXUtil.cpp

@@ -49,6 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <assimp/TinyFormatter.h>
 #include <string>
+#include <cstring>
 
 #ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
 
@@ -113,6 +114,49 @@ std::string AddTokenText(const std::string& prefix, const std::string& text, con
         text) );
 }
 
+static const uint8_t base64DecodeTable[128] = {
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 62,  0,  0,  0, 63,
+    52, 53, 54, 55, 56, 57, 58, 59, 60, 61,  0,  0,  0, 64,  0,  0,
+    0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
+    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,  0,  0,  0,  0,  0,
+    0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,  0,  0,  0,  0,  0
+};
+
+uint8_t DecodeBase64(char ch)
+{
+    return base64DecodeTable[size_t(ch)];
+}
+
+size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out)
+{
+    if (inLength < 4) {
+        out = 0;
+        return 0;
+    }
+
+    const size_t outLength = (inLength * 3) / 4;
+    out = new uint8_t[outLength];
+    memset(out, 0, outLength);
+
+    size_t i = 0;
+    size_t j = 0;
+    for (i = 0; i < inLength - 4; i += 4)
+    {
+        uint8_t b0 = Util::DecodeBase64(in[i]);
+        uint8_t b1 = Util::DecodeBase64(in[i + 1]);
+        uint8_t b2 = Util::DecodeBase64(in[i + 2]);
+        uint8_t b3 = Util::DecodeBase64(in[i + 3]);
+
+        out[j++] = (uint8_t)((b0 << 2) | (b1 >> 4));
+        out[j++] = (uint8_t)((b1 << 4) | (b2 >> 2));
+        out[j++] = (uint8_t)((b2 << 6) | b3);
+    }
+    return outLength;
+}
+
 } // !Util
 } // !FBX
 } // !Assimp

+ 15 - 0
code/FBXUtil.h

@@ -48,6 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include "FBXCompileConfig.h"
 #include "FBXTokenizer.h"
+#include <stdint.h>
 
 namespace Assimp {
 namespace FBX {
@@ -98,6 +99,20 @@ std::string AddLineAndColumn(const std::string& prefix, const std::string& text,
  *  @return A string of the following format: {prefix} ({token-type}, line {line}, col {column}) {text}*/
 std::string AddTokenText(const std::string& prefix, const std::string& text, const Token* tok);
 
+/** Decode a single Base64-encoded character.
+*
+*  @param ch Character to decode (from base64 to binary).
+*  @return decoded byte value*/
+uint8_t DecodeBase64(char ch);
+
+/** Decode a Base64-encoded string
+*
+*  @param in Characters to decode.
+*  @param inLength Number of characters to decode.
+*  @param out Reference to pointer where we will store the decoded data.
+*  @return size of the decoded data (number of bytes)*/
+size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out);
+
 }
 }
 }

+ 12 - 13
code/IRRLoader.cpp

@@ -300,13 +300,10 @@ int ClampSpline(int idx, int size) {
 // ------------------------------------------------------------------------------------------------
 inline void FindSuitableMultiple(int& angle)
 {
-    if (angle < 3)angle = 3;
+    if (angle < 3) angle = 3;
     else if (angle < 10) angle = 10;
     else if (angle < 20) angle = 20;
     else if (angle < 30) angle = 30;
-    else
-    {
-    }
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -317,6 +314,8 @@ void IRRImporter::ComputeAnimations(Node* root, aiNode* real, std::vector<aiNode
     // XXX totally WIP - doesn't produce proper results, need to evaluate
     // whether there's any use for Irrlicht's proprietary scene format
     // outside Irrlicht ...
+    // This also applies to the above function of FindSuitableMultiple and ClampSpline which are
+    // solely used in this function
 
     if (root->animators.empty()) {
         return;
@@ -674,38 +673,38 @@ void IRRImporter::GenerateGraph(Node* root,aiNode* rootOut ,aiScene* scene,
             // Get the loaded mesh from the scene and add it to
             // the list of all scenes to be attached to the
             // graph we're currently building
-            aiScene* scene = batch.GetImport(root->id);
-            if (!scene) {
+            aiScene* localScene = batch.GetImport(root->id);
+            if (!localScene) {
                 ASSIMP_LOG_ERROR("IRR: Unable to load external file: " + root->meshPath);
                 break;
             }
-            attach.push_back(AttachmentInfo(scene,rootOut));
+            attach.push_back(AttachmentInfo(localScene,rootOut));
 
             // Now combine the material we've loaded for this mesh
             // with the real materials we got from the file. As we
             // don't execute any pp-steps on the file, the numbers
             // should be equal. If they are not, we can impossibly
             // do this  ...
-            if (root->materials.size() != (unsigned int)scene->mNumMaterials)   {
+            if (root->materials.size() != (unsigned int)localScene->mNumMaterials)   {
                 ASSIMP_LOG_WARN("IRR: Failed to match imported materials "
                     "with the materials found in the IRR scene file");
 
                 break;
             }
-            for (unsigned int i = 0; i < scene->mNumMaterials;++i)  {
+            for (unsigned int i = 0; i < localScene->mNumMaterials;++i)  {
                 // Delete the old material, we don't need it anymore
-                delete scene->mMaterials[i];
+                delete localScene->mMaterials[i];
 
                 std::pair<aiMaterial*, unsigned int>& src = root->materials[i];
-                scene->mMaterials[i] = src.first;
+                localScene->mMaterials[i] = src.first;
             }
 
             // NOTE: Each mesh should have exactly one material assigned,
             // but we do it in a separate loop if this behaviour changes
             // in future.
-            for (unsigned int i = 0; i < scene->mNumMeshes;++i) {
+            for (unsigned int i = 0; i < localScene->mNumMeshes;++i) {
                 // Process material flags
-                aiMesh* mesh = scene->mMeshes[i];
+                aiMesh* mesh = localScene->mMeshes[i];
 
 
                 // If "trans_vertex_alpha" mode is enabled, search all vertex colors

+ 3 - 3
code/Importer/STEPParser/STEPFileReader.cpp

@@ -278,10 +278,10 @@ void STEP::ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme,
         std::transform( type.begin(), type.end(), type.begin(), &Assimp::ToLower<char>  );
         const char* sz = scheme.GetStaticStringForToken(type);
         if(sz) {
-            const std::string::size_type len = n2-n1+1;
-            char* const copysz = new char[len+1];
+            const std::string::size_type szLen = n2-n1+1;
+            char* const copysz = new char[szLen+1];
             std::copy(s.c_str()+n1,s.c_str()+n2+1,copysz);
-            copysz[len] = '\0';
+            copysz[szLen] = '\0';
             db.InternInsert(new LazyObject(db,id,line,sz,copysz));
         }
         if(!has_next) {

+ 9 - 9
code/MD5Loader.cpp

@@ -443,10 +443,10 @@ void MD5Importer::LoadMD5MeshFile ()
         for (MD5::VertexList::const_iterator iter =  meshSrc.mVertices.begin();iter != meshSrc.mVertices.end();++iter,++pv) {
             for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights;++w)
             {
-                MD5::WeightDesc& desc = meshSrc.mWeights[w];
+                MD5::WeightDesc& weightDesc = meshSrc.mWeights[w];
                 /* FIX for some invalid exporters */
-                if (!(desc.mWeight < AI_MD5_WEIGHT_EPSILON && desc.mWeight >= -AI_MD5_WEIGHT_EPSILON ))
-                    ++piCount[desc.mBone];
+                if (!(weightDesc.mWeight < AI_MD5_WEIGHT_EPSILON && weightDesc.mWeight >= -AI_MD5_WEIGHT_EPSILON ))
+                    ++piCount[weightDesc.mBone];
             }
         }
 
@@ -493,20 +493,20 @@ void MD5Importer::LoadMD5MeshFile ()
                     if (w >= meshSrc.mWeights.size())
                         throw DeadlyImportError("MD5MESH: Invalid weight index");
 
-                    MD5::WeightDesc& desc = meshSrc.mWeights[w];
-                    if ( desc.mWeight < AI_MD5_WEIGHT_EPSILON && desc.mWeight >= -AI_MD5_WEIGHT_EPSILON) {
+                    MD5::WeightDesc& weightDesc = meshSrc.mWeights[w];
+                    if ( weightDesc.mWeight < AI_MD5_WEIGHT_EPSILON && weightDesc.mWeight >= -AI_MD5_WEIGHT_EPSILON) {
                         continue;
                     }
 
-                    const ai_real fNewWeight = desc.mWeight / fSum;
+                    const ai_real fNewWeight = weightDesc.mWeight / fSum;
 
                     // transform the local position into worldspace
-                    MD5::BoneDesc& boneSrc = meshParser.mJoints[desc.mBone];
-                    const aiVector3D v = boneSrc.mRotationQuatConverted.Rotate (desc.vOffsetPosition);
+                    MD5::BoneDesc& boneSrc = meshParser.mJoints[weightDesc.mBone];
+                    const aiVector3D v = boneSrc.mRotationQuatConverted.Rotate (weightDesc.vOffsetPosition);
 
                     // use the original weight to compute the vertex position
                     // (some MD5s seem to depend on the invalid weight values ...)
-                    *pv += ((boneSrc.mPositionXYZ+v)* (ai_real)desc.mWeight);
+                    *pv += ((boneSrc.mPositionXYZ+v)* (ai_real)weightDesc.mWeight);
 
                     aiBone* bone = mesh->mBones[boneSrc.mMap];
                     *bone->mWeights++ = aiVertexWeight((unsigned int)(pv-mesh->mVertices),fNewWeight);

+ 1 - 1
code/STLExporter.cpp

@@ -127,7 +127,7 @@ STLExporter::STLExporter(const char* _filename, const aiScene* pScene, bool expo
         mOutput.write((char *)&meshnum, 4);
 
         if (exportPointClouds) {
-
+            throw DeadlyExportError("This functionality is not yet implemented for binary output.");
         }
 
         for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) {

+ 4 - 3
code/glTF2Asset.h

@@ -223,7 +223,8 @@ namespace glTF2
         ComponentType_FLOAT = 5126
     };
 
-    inline unsigned int ComponentTypeSize(ComponentType t)
+    inline
+    unsigned int ComponentTypeSize(ComponentType t)
     {
         switch (t) {
             case ComponentType_SHORT:
@@ -250,7 +251,7 @@ namespace glTF2
     };
 
     //! Values for the Sampler::magFilter field
-    enum class SamplerMagFilter: unsigned int
+    enum class SamplerMagFilter : unsigned int
     {
         UNSET = 0,
         SamplerMagFilter_Nearest = 9728,
@@ -258,7 +259,7 @@ namespace glTF2
     };
 
     //! Values for the Sampler::minFilter field
-    enum class SamplerMinFilter: unsigned int
+    enum class SamplerMinFilter : unsigned int
     {
         UNSET = 0,
         SamplerMinFilter_Nearest = 9728,

+ 4 - 4
code/glTFAssetWriter.inl

@@ -294,17 +294,17 @@ namespace glTF {
 							// filling object "compressedData"
 							json_comp_data.SetObject();
 							json_comp_data.AddMember("buffer", ptr_ext_comp->Buffer, w.mAl);
-							json_comp_data.AddMember("byteOffset", ptr_ext_comp->Offset, w.mAl);
+							json_comp_data.AddMember("byteOffset", static_cast<uint64_t>(ptr_ext_comp->Offset), w.mAl);
 							json_comp_data.AddMember("componentType", 5121, w.mAl);
 							json_comp_data.AddMember("type", "SCALAR", w.mAl);
-							json_comp_data.AddMember("count", ptr_ext_comp->Count, w.mAl);
+							json_comp_data.AddMember("count", static_cast<uint64_t>(ptr_ext_comp->Count), w.mAl);
 							if(ptr_ext_comp->Binary)
 								json_comp_data.AddMember("mode", "binary", w.mAl);
 							else
 								json_comp_data.AddMember("mode", "ascii", w.mAl);
 
-							json_comp_data.AddMember("indicesCount", ptr_ext_comp->IndicesCount, w.mAl);
-							json_comp_data.AddMember("verticesCount", ptr_ext_comp->VerticesCount, w.mAl);
+							json_comp_data.AddMember("indicesCount", static_cast<uint64_t>(ptr_ext_comp->IndicesCount), w.mAl);
+							json_comp_data.AddMember("verticesCount", static_cast<uint64_t>(ptr_ext_comp->VerticesCount), w.mAl);
 							// filling object "Open3DGC-compression"
 							Value json_o3dgc;
 

+ 1 - 1
code/glTFExporter.cpp

@@ -245,7 +245,7 @@ inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& bu
 
 namespace {
     void GetMatScalar(const aiMaterial* mat, float& val, const char* propName, int type, int idx) {
-        if (mat->Get(propName, type, idx, val) == AI_SUCCESS) {}
+        ai_assert(mat->Get(propName, type, idx, val) == AI_SUCCESS);
     }
 }
 

+ 4 - 4
code/res/assimp.rc

@@ -31,8 +31,8 @@ LANGUAGE LANG_GERMAN, SUBLANG_GERMAN
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,1,SVNRevision, 0
- PRODUCTVERSION 1,1,SVNRevision,0
+ FILEVERSION VER_FILEVERSION
+ PRODUCTVERSION VER_FILEVERSION
  FILEFLAGSMASK 0x17L
 #ifdef _DEBUG
  FILEFLAGS 0x1L
@@ -50,12 +50,12 @@ BEGIN
             VALUE "Comments", "Licensed under a 3-clause BSD license"
             VALUE "CompanyName", "assimp team"
             VALUE "FileDescription", "Open Asset Import Library"
-            VALUE "FileVersion", 1,1,SVNRevision,0
+            VALUE "FileVersion", VER_FILEVERSION
             VALUE "InternalName", "assimp "
             VALUE "LegalCopyright", "Copyright (C) 2006-2010"
             VALUE "OriginalFilename", "assimpNN.dll"
             VALUE "ProductName", "Open Asset Import Library"
-            VALUE "ProductVersion", 1,1,SVNRevision,0
+            VALUE "ProductVersion", VER_FILEVERSION_STR
 		,0
         END
     END

+ 8 - 1
contrib/irrXML/CMakeLists.txt

@@ -13,10 +13,17 @@ if ( MSVC )
   ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
 endif ( MSVC )
 
-add_library(IrrXML STATIC ${IrrXML_SRCS})
+IF(CMAKE_SYSTEM_NAME MATCHES "(Darwin|FreeBSD)")
+  add_library(IrrXML ${IrrXML_SRCS})
+ELSE()
+  add_library(IrrXML STATIC ${IrrXML_SRCS})
+ENDIF()
 set(IRRXML_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}" CACHE INTERNAL "IrrXML_Include" )
 set(IRRXML_LIBRARY "IrrXML" CACHE INTERNAL "IrrXML" )
 
 install(TARGETS IrrXML
+  LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
   ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
+  RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR}
+  FRAMEWORK DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
   COMPONENT ${LIBASSIMP_COMPONENT})

+ 9 - 4
contrib/irrXML/CXMLReaderImpl.h

@@ -10,8 +10,11 @@
 #include "irrArray.h"
 
 #include <cassert>
+#include <stdlib.h>    
+#include <cctype>
+#include <cstdint>
+//using namespace Assimp;
 
-using namespace Assimp;
 
 #ifdef _DEBUG
 #define IRR_DEBUGPRINT(x) printf((x));
@@ -162,7 +165,8 @@ public:
 			return 0;
 
 		core::stringc c = attr->Value.c_str();
-		return fast_atof(c.c_str());
+        return static_cast<float>(atof(c.c_str()));
+        //return fast_atof(c.c_str());
 	}
 
 
@@ -174,7 +178,8 @@ public:
 			return 0;
 
 		core::stringc c = attrvalue;
-		return fast_atof(c.c_str());
+        return static_cast<float>(atof(c.c_str()));
+		//return fast_atof(c.c_str());
 	}
 
 
@@ -428,7 +433,7 @@ private:
 			++P;
 
     // remove trailing whitespace, if any
-    while( isspace( P[-1]))
+    while( std::isspace( P[-1]))
       --P;
 
 		NodeName = core::string<char_type>(pBeginClose, (int)(P - pBeginClose));

+ 2 - 2
contrib/irrXML/irrXML.cpp

@@ -9,7 +9,7 @@
 #include "irrXML.h"
 #include "irrString.h"
 #include "irrArray.h"
-#include <assimp/fast_atof.h>
+//#include <assimp/fast_atof.h>
 #include "CXMLReaderImpl.h"
 
 namespace irr
@@ -18,7 +18,7 @@ namespace io
 {
 
 //! Implementation of the file read callback for ordinary files
-class CFileReadCallBack : public IFileReadCallBack
+class IRRXML_API CFileReadCallBack : public IFileReadCallBack
 {
 public:
 

+ 15 - 9
contrib/irrXML/irrXML.h

@@ -7,6 +7,12 @@
 
 #include <stdio.h>
 
+#ifdef _WIN32
+#   define IRRXML_API __declspec(dllexport)
+#else
+#   define IRRXML_API __attribute__ ((visibility("default")))
+#endif // _WIN32
+
 /** \mainpage irrXML 1.2 API documentation
  <div align="center"><img src="logobig.png" ></div>
 
@@ -409,7 +415,7 @@ namespace io
 	\return Returns a pointer to the created xml parser. This pointer should be 
 	deleted using 'delete' after no longer needed. Returns 0 if an error occured
 	and the file could not be opened. */
-	IrrXMLReader* createIrrXMLReader(const char* filename);
+    IRRXML_API IrrXMLReader* createIrrXMLReader(const char* filename);
 
 	//! Creates an instance of an UFT-8 or ASCII character xml parser.
 	/** This means that all character data will be returned in 8 bit ASCII or UTF-8. The file to read can 
@@ -421,7 +427,7 @@ namespace io
 	\return Returns a pointer to the created xml parser. This pointer should be 
 	deleted using 'delete' after no longer needed. Returns 0 if an error occured
 	and the file could not be opened. */
-	IrrXMLReader* createIrrXMLReader(FILE* file);
+    IRRXML_API IrrXMLReader* createIrrXMLReader(FILE* file);
 
 	//! Creates an instance of an UFT-8 or ASCII character xml parser. 
 	/** This means that all character data will be returned in 8 bit ASCII or UTF-8. The file to read can 
@@ -434,7 +440,7 @@ namespace io
 	 \return Returns a pointer to the created xml parser. This pointer should be 
 	 deleted using 'delete' after no longer needed. Returns 0 if an error occured
 	 and the file could not be opened. */
-	IrrXMLReader* createIrrXMLReader(IFileReadCallBack* callback);
+    IRRXML_API IrrXMLReader* createIrrXMLReader(IFileReadCallBack* callback);
 
 	//! Creates an instance of an UFT-16 xml parser. 
 	/** This means that
@@ -446,7 +452,7 @@ namespace io
 	\return Returns a pointer to the created xml parser. This pointer should be 
 	deleted using 'delete' after no longer needed. Returns 0 if an error occured
 	and the file could not be opened. */
-	IrrXMLReaderUTF16* createIrrXMLReaderUTF16(const char* filename);
+    IRRXML_API IrrXMLReaderUTF16* createIrrXMLReaderUTF16(const char* filename);
 
 	//! Creates an instance of an UFT-16 xml parser. 
 	/** This means that all character data will be returned in UTF-16. The file to read can 
@@ -458,7 +464,7 @@ namespace io
 	\return Returns a pointer to the created xml parser. This pointer should be 
 	deleted using 'delete' after no longer needed. Returns 0 if an error occured
 	and the file could not be opened. */
-	IrrXMLReaderUTF16* createIrrXMLReaderUTF16(FILE* file);
+    IRRXML_API IrrXMLReaderUTF16* createIrrXMLReaderUTF16(FILE* file);
 
 	//! Creates an instance of an UFT-16 xml parser. 
 	/** This means that all character data will be returned in UTF-16. The file to read can 
@@ -471,7 +477,7 @@ namespace io
 	\return Returns a pointer to the created xml parser. This pointer should be 
 	deleted using 'delete' after no longer needed. Returns 0 if an error occured
 	and the file could not be opened. */
-	IrrXMLReaderUTF16* createIrrXMLReaderUTF16(IFileReadCallBack* callback);
+    IRRXML_API IrrXMLReaderUTF16* createIrrXMLReaderUTF16(IFileReadCallBack* callback);
 
 
 	//! Creates an instance of an UFT-32 xml parser. 
@@ -483,7 +489,7 @@ namespace io
 	\return Returns a pointer to the created xml parser. This pointer should be 
 	deleted using 'delete' after no longer needed. Returns 0 if an error occured
 	and the file could not be opened. */
-	IrrXMLReaderUTF32* createIrrXMLReaderUTF32(const char* filename);
+    IRRXML_API IrrXMLReaderUTF32* createIrrXMLReaderUTF32(const char* filename);
 
 	//! Creates an instance of an UFT-32 xml parser. 
 	/** This means that all character data will be returned in UTF-32. The file to read can 
@@ -495,7 +501,7 @@ namespace io
 	\return Returns a pointer to the created xml parser. This pointer should be 
 	deleted using 'delete' after no longer needed. Returns 0 if an error occured
 	and the file could not be opened. */
-	IrrXMLReaderUTF32* createIrrXMLReaderUTF32(FILE* file);
+    IRRXML_API IrrXMLReaderUTF32* createIrrXMLReaderUTF32(FILE* file);
 
 	//! Creates an instance of an UFT-32 xml parser. 
 	/** This means that
@@ -509,7 +515,7 @@ namespace io
 	\return Returns a pointer to the created xml parser. This pointer should be 
 	deleted using 'delete' after no longer needed. Returns 0 if an error occured
 	and the file could not be opened. */
-	IrrXMLReaderUTF32* createIrrXMLReaderUTF32(IFileReadCallBack* callback);
+    IRRXML_API IrrXMLReaderUTF32* createIrrXMLReaderUTF32(IFileReadCallBack* callback);
 	
 
 	/*! \file irrxml.h

+ 7 - 2
contrib/zlib/CMakeLists.txt

@@ -5,12 +5,17 @@ set(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)
 # See http://www.cmake.org/cmake/help/v3.0/policy/CMP0048.html
 cmake_policy(PUSH)
 if(CMAKE_MAJOR_VERSION GREATER 2)
-	cmake_policy(SET CMP0048 OLD)
+	cmake_policy(SET CMP0048 NEW)
 endif()
 project(zlib C)
+SET (ZLIB_VERSION_MAJOR 1)
+SET (ZLIB_VERSION_MINOR 2)
+SET (ZLIB_VERSION_PATCH 11)
+SET (ZLIB_VERSION ${ZLIB_VERSION_MAJOR}.${ZLIB_VERSION_MINOR}.${ZLIB_VERSION_PATCH})
+SET (ZLIB_SOVERSION 1)
+SET (PROJECT_VERSION "${ZLIB_VERSION}")
 cmake_policy(POP)
 
-set(VERSION "1.2.11.1")
 
 option(ASM686 "Enable building i686 assembly implementation")
 option(AMD64 "Enable building amd64 assembly implementation")

+ 1 - 1
include/assimp/Exporter.hpp

@@ -190,7 +190,7 @@ public:
     * @note Use aiCopyScene() to get a modifiable copy of a previously
     *   imported scene. */
     const aiExportDataBlob* ExportToBlob(const aiScene* pScene, const char* pFormatId,
-        unsigned int pPreprocessing = 0u, const ExportProperties* = nullptr);
+        unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = nullptr);
     const aiExportDataBlob* ExportToBlob(  const aiScene* pScene, const std::string& pFormatId,
         unsigned int pPreprocessing = 0u, const ExportProperties* pProperties = nullptr);
 

+ 4 - 0
include/assimp/color4.inl

@@ -85,6 +85,8 @@ AI_FORCE_INLINE TReal aiColor4t<TReal>::operator[](unsigned int i) const {
             return g;
         case 2:
             return b;
+        case 3:
+            return a;
         default:
             break;
     }
@@ -100,6 +102,8 @@ AI_FORCE_INLINE TReal& aiColor4t<TReal>::operator[](unsigned int i) {
             return g;
         case 2:
             return b;
+        case 3:
+            return a;
         default:
             break;
     }

+ 1 - 0
include/assimp/material.h

@@ -900,6 +900,7 @@ extern "C" {
 #define AI_MATKEY_ENABLE_WIREFRAME "$mat.wireframe",0,0
 #define AI_MATKEY_BLEND_FUNC "$mat.blend",0,0
 #define AI_MATKEY_OPACITY "$mat.opacity",0,0
+#define AI_MATKEY_TRANSPARENCYFACTOR "$mat.transparencyfactor",0,0
 #define AI_MATKEY_BUMPSCALING "$mat.bumpscaling",0,0
 #define AI_MATKEY_SHININESS "$mat.shininess",0,0
 #define AI_MATKEY_REFLECTIVITY "$mat.reflectivity",0,0

+ 0 - 103
packaging/windows-innosetup/script.iss

@@ -1,103 +0,0 @@
-; Setup script for use with Inno Setup.
-
-[Setup]
-AppName=Open Asset Import Library - SDK
-AppVerName=Open Asset Import Library - SDK (v4.1.0)
-DefaultDirName={pf}\Assimp
-DefaultGroupName=Assimp
-UninstallDisplayIcon={app}\bin\x86\assimp.exe
-OutputDir=out
-AppCopyright=Assimp Development Team
-SetupIconFile=..\..\tools\shared\assimp_tools_icon.ico
-WizardImageFile=compiler:WizModernImage-IS.BMP
-WizardSmallImageFile=compiler:WizModernSmallImage-IS.BMP
-LicenseFile=License.rtf
-OutputBaseFileName=assimp-sdk-4.1.0-setup
-VersionInfoVersion=4.1.0.0
-VersionInfoTextVersion=4.1.0
-VersionInfoCompany=Assimp Development Team
-ArchitecturesInstallIn64BitMode=x64
-
-[Types]
-Name: "full";    Description: "Full installation"
-Name: "compact"; Description: "Compact installation, no test models or language bindings"
-Name: "custom";  Description: "Custom installation"; Flags: iscustom
-
-[Components]
-Name: "main";        Description: "Main Files (32 and 64 Bit)"; Types: full compact custom; Flags: fixed
-Name: "tools";       Description: "Asset Viewer & Command Line Tools (32 and 64 Bit)"; Types: full compact
-Name: "help";        Description: "Help Files"; Types: full compact
-Name: "samples";     Description: "Samples"; Types: full
-Name: "test";        Description: "Test Models (BSD-licensed)"; Types: full
-Name: "test_nonbsd"; Description: "Test Models (other (free) licenses)"; Types: full
-;Name: "pyassimp";    Description: "Python Bindings"; Types: full
-;Name: "dassimp";     Description: "D Bindings"; Types: full
-;Name: "assimp_net";  Description: "C#/.NET Bindings"; Types: full
-
-[Run]
-;Filename: "{app}\stub\vc_redist.x86.exe"; Parameters: "/qb"; StatusMsg: "Installing VS2017 redistributable package (32 Bit)"; Check: not IsWin64
-Filename: "{app}\stub\vc_redist.x64.exe"; Parameters: "/qb"; StatusMsg: "Installing VS2017 redistributable package (64 Bit)"; Check: IsWin64
-
-[Files]
-Source: "readme_installer.txt"; DestDir: "{app}"; Flags: isreadme
-
-; Installer stub
-;Source: "vc_redist.x86.exe"; DestDir: "{app}\stub\"; Check: not IsWin64
-Source: "vc_redist.x64.exe"; DestDir: "{app}\stub\"; Check: IsWin64
-
-; Common stuff
-Source: "..\..\CREDITS"; DestDir: "{app}"
-Source: "..\..\LICENSE"; DestDir: "{app}"
-Source: "..\..\README"; DestDir: "{app}"
-Source: "WEB"; DestDir: "{app}"
-
-Source: "..\..\scripts\*"; DestDir: "{app}\scripts"; Flags: recursesubdirs
-
-; x86 binaries
-;Source: "..\..\bin\release\x86\assimp-vc140-mt.dll";  DestDir: "{app}\bin\x86"
-;Source: "..\..\bin\release\x86\assimp_viewer.exe";    DestDir: "{app}\bin\x86"; Components: tools
-;Source: "C:\Windows\SysWOW64\D3DCompiler_42.dll";     DestDir: "{app}\bin\x86"; Components: tools
-;Source: "C:\Windows\SysWOW64\D3DX9_42.dll";           DestDir: "{app}\bin\x86"; Components: tools
-;Source: "..\..\bin\release\x86\assimp.exe";           DestDir: "{app}\bin\x86"; Components: tools
-
-; x64 binaries
-Source: "..\..\bin\release\assimp-vc140-mt.dll";  DestDir: "{app}\bin\x64"
-Source: "..\..\bin\release\assimp_viewer.exe";    DestDir: "{app}\bin\x64"; Components: tools
-Source: "C:\Windows\SysWOW64\D3DCompiler_42.dll"; DestDir: "{app}\bin\x64"; DestName: "D3DCompiler_42.dll"; Components: tools
-Source: "C:\Windows\SysWOW64\D3DX9_42.dll";       DestDir: "{app}\bin\x64"; DestName: "D3DX9_42.dll"; Components: tools
-Source: "..\..\bin\release\assimp.exe";           DestDir: "{app}\bin\x64"; Components: tools
-
-; Documentation
-;Source: "..\..\doc\AssimpDoc_Html\AssimpDoc.chm"; DestDir: "{app}\doc"; Components: help
-;Source: "..\..\doc\AssimpCmdDoc_Html\AssimpCmdDoc.chm"; DestDir: "{app}\doc"; Components: help
-;Source: "..\..\doc\datastructure.xml"; DestDir: "{app}\doc"; Components: help
-
-; Import libraries
-;Source: "..\..\lib\release\x86\assimp.lib"; DestDir: "{app}\lib\x86"
-Source: "..\..\lib\release\assimp-vc140-mt.lib"; DestDir: "{app}\lib\x64"
-
-; Samples
-Source: "..\..\samples\*"; DestDir: "{app}\samples"; Flags: recursesubdirs; Components: samples
-
-; Include files
-Source: "..\..\include\*"; DestDir: "{app}\include"; Flags: recursesubdirs
-
-; dAssimp
-;Source: "..\..\port\dAssimp\*"; DestDir: "{app}\port\D"; Flags: recursesubdirs; Components: dassimp
-
-; Assimp.NET
-;Source: "..\..\port\Assimp.NET\*"; DestDir: "{app}\port\C#"; Flags: recursesubdirs; Components: assimp_net
-
-; PyAssimp
-;Source: "..\..\port\PyAssimp\*"; DestDir: "{app}\port\Python"; Excludes: "*.pyc,*.dll"; Flags: recursesubdirs; Components: pyassimp
-
-; Test repository
-;Source: "..\..\test\models\*"; DestDir: "{app}\test\models"; Flags: recursesubdirs; Components: test
-;Source: "..\..\test\regression\*"; DestDir: "{app}\test\regression"; Flags: recursesubdirs; Components: test
-;Source: "..\..\test\models-nonbsd\*"; DestDir: "{app}\test\models-nonbsd"; Flags: recursesubdirs; Components: test_nonbsd
-
-[Icons]
-Name: "{group}\Assimp Manual"; Filename: "{app}\doc\AssimpDoc.chm" ; Components: help
-Name: "{group}\Assimp Command Line Manual"; Filename: "{app}\doc\AssimpCmdDoc.chm"; Components: help
-Name: "{group}\AssimpView"; Filename: "{app}\bin\x64\assimp_view.exe"; Components: tools; Check: IsWin64
-Name: "{group}\AssimpView"; Filename: "{app}\bin\x86\assimp_view.exe"; Components: tools; Check: not IsWin64

+ 71 - 0
packaging/windows-innosetup/script_x64.iss

@@ -0,0 +1,71 @@
+; Setup script for use with Inno Setup.
+
+[Setup]
+AppName=Open Asset Import Library - SDK
+AppVerName=Open Asset Import Library - SDK (v4.1.0)
+DefaultDirName={pf}\Assimp
+DefaultGroupName=Assimp
+UninstallDisplayIcon={app}\bin\x86\assimp.exe
+OutputDir=out
+AppCopyright=Assimp Development Team
+SetupIconFile=..\..\tools\shared\assimp_tools_icon.ico
+WizardImageFile=compiler:WizModernImage-IS.BMP
+WizardSmallImageFile=compiler:WizModernSmallImage-IS.BMP
+LicenseFile=License.rtf
+OutputBaseFileName=assimp-sdk-4.1.0-setup
+VersionInfoVersion=4.1.0.0
+VersionInfoTextVersion=4.1.0
+VersionInfoCompany=Assimp Development Team
+ArchitecturesInstallIn64BitMode=x64
+
+[Types]
+Name: "full";    Description: "Full installation"
+Name: "compact"; Description: "Compact installation, no test models or language bindings"
+Name: "custom";  Description: "Custom installation"; Flags: iscustom
+
+[Components]
+Name: "main";        Description: "Main Files ( 64 Bit )"; Types: full compact custom; Flags: fixed
+Name: "tools";       Description: "Asset Viewer & Command Line Tools (32 and 64 Bit)"; Types: full compact
+Name: "help";        Description: "Help Files"; Types: full compact
+Name: "samples";     Description: "Samples"; Types: full
+Name: "test";        Description: "Test Models (BSD-licensed)"; Types: full
+Name: "test_nonbsd"; Description: "Test Models (other (free) licenses)"; Types: full
+
+[Run]
+Filename: "{app}\stub\vc_redist.x64.exe"; Parameters: "/qb"; StatusMsg: "Installing VS2017 redistributable package (64 Bit)"; Check: IsWin64
+
+[Files]
+Source: "readme_installer.txt"; DestDir: "{app}"; Flags: isreadme
+
+; Installer stub
+Source: "vc_redist.x64.exe"; DestDir: "{app}\stub\"; Check: IsWin64
+
+; Common stuff
+Source: "..\..\CREDITS"; DestDir: "{app}"
+Source: "..\..\LICENSE"; DestDir: "{app}"
+Source: "..\..\README"; DestDir: "{app}"
+Source: "WEB"; DestDir: "{app}"
+
+Source: "..\..\scripts\*"; DestDir: "{app}\scripts"; Flags: recursesubdirs
+
+; x64 binaries
+Source: "..\..\bin\release\assimp-vc141-mt.dll";  DestDir: "{app}\bin\x64"
+Source: "..\..\bin\release\assimp_viewer.exe";    DestDir: "{app}\bin\x64"; Components: tools
+Source: "C:\Windows\SysWOW64\D3DCompiler_42.dll"; DestDir: "{app}\bin\x64"; DestName: "D3DCompiler_42.dll"; Components: tools
+Source: "C:\Windows\SysWOW64\D3DX9_42.dll";       DestDir: "{app}\bin\x64"; DestName: "D3DX9_42.dll"; Components: tools
+Source: "..\..\bin\release\assimp.exe";           DestDir: "{app}\bin\x64"; Components: tools
+
+; Import libraries
+Source: "..\..\lib\release\assimp-vc141-mt.lib"; DestDir: "{app}\lib\x64"
+
+; Samples
+Source: "..\..\samples\*"; DestDir: "{app}\samples"; Flags: recursesubdirs; Components: samples
+
+; Include files
+Source: "..\..\include\*"; DestDir: "{app}\include"; Flags: recursesubdirs
+
+[Icons]
+; Name: "{group}\Assimp Manual"; Filename: "{app}\doc\AssimpDoc.chm" ; Components: help
+; Name: "{group}\Assimp Command Line Manual"; Filename: "{app}\doc\AssimpCmdDoc.chm"; Components: help
+; Name: "{group}\AssimpView"; Filename: "{app}\bin\x64\assimp_view.exe"; Components: tools; Check: IsWin64
+; Name: "{group}\AssimpView"; Filename: "{app}\bin\x86\assimp_view.exe"; Components: tools; Check: not IsWin64

+ 72 - 0
packaging/windows-innosetup/script_x86.iss

@@ -0,0 +1,72 @@
+; Setup script for use with Inno Setup.
+
+[Setup]
+AppName=Open Asset Import Library - SDK
+AppVerName=Open Asset Import Library - SDK (v4.1.0)
+DefaultDirName={pf}\Assimp
+DefaultGroupName=Assimp
+UninstallDisplayIcon={app}\bin\x86\assimp.exe
+OutputDir=out
+AppCopyright=Assimp Development Team
+SetupIconFile=..\..\tools\shared\assimp_tools_icon.ico
+WizardImageFile=compiler:WizModernImage-IS.BMP
+WizardSmallImageFile=compiler:WizModernSmallImage-IS.BMP
+LicenseFile=License.rtf
+OutputBaseFileName=assimp-sdk-4.1.0-setup
+VersionInfoVersion=4.1.0.0
+VersionInfoTextVersion=4.1.0
+VersionInfoCompany=Assimp Development Team
+ArchitecturesInstallIn64BitMode=x64
+
+[Types]
+Name: "full";    Description: "Full installation"
+Name: "compact"; Description: "Compact installation, no test models or language bindings"
+Name: "custom";  Description: "Custom installation"; Flags: iscustom
+
+[Components]
+Name: "main";        Description: "Main Files (32 and 64 Bit)"; Types: full compact custom; Flags: fixed
+Name: "tools";       Description: "Asset Viewer & Command Line Tools (32 and 64 Bit)"; Types: full compact
+Name: "help";        Description: "Help Files"; Types: full compact
+Name: "samples";     Description: "Samples"; Types: full
+Name: "test";        Description: "Test Models (BSD-licensed)"; Types: full
+Name: "test_nonbsd"; Description: "Test Models (other (free) licenses)"; Types: full
+
+[Run]
+Filename: "{app}\stub\vc_redist.x86.exe"; Parameters: "/qb"; StatusMsg: "Installing VS2017 redistributable package (32 Bit)"; Check: not IsWin64
+
+[Files]
+Source: "readme_installer.txt"; DestDir: "{app}"; Flags: isreadme
+
+; Installer stub
+Source: "vc_redist.x86.exe"; DestDir: "{app}\stub\"; Check: not IsWin64
+
+; Common stuff
+Source: "..\..\CREDITS"; DestDir: "{app}"
+Source: "..\..\LICENSE"; DestDir: "{app}"
+Source: "..\..\README"; DestDir: "{app}"
+Source: "WEB"; DestDir: "{app}"
+
+Source: "..\..\scripts\*"; DestDir: "{app}\scripts"; Flags: recursesubdirs
+
+; x86 binaries
+Source: "..\..\bin\release\assimp-vc141-mt.dll";  DestDir: "{app}\bin\x86"
+Source: "..\..\bin\release\assimp_viewer.exe";    DestDir: "{app}\bin\x86"; Components: tools
+Source: "C:\Windows\SysWOW64\D3DCompiler_42.dll";     DestDir: "{app}\bin\x86"; Components: tools
+Source: "C:\Windows\SysWOW64\D3DX9_42.dll";           DestDir: "{app}\bin\x86"; Components: tools
+Source: "..\..\bin\release\assimp.exe";           DestDir: "{app}\bin\x86"; Components: tools
+
+
+; Import libraries
+Source: "..\..\lib\release\assimp-vc141-mt.lib"; DestDir: "{app}\lib\x86"
+
+; Samples
+Source: "..\..\samples\*"; DestDir: "{app}\samples"; Flags: recursesubdirs; Components: samples
+
+; Include files
+Source: "..\..\include\*"; DestDir: "{app}\include"; Flags: recursesubdirs
+
+[Icons]
+; Name: "{group}\Assimp Manual"; Filename: "{app}\doc\AssimpDoc.chm" ; Components: help
+; Name: "{group}\Assimp Command Line Manual"; Filename: "{app}\doc\AssimpCmdDoc.chm"; Components: help
+; Name: "{group}\AssimpView"; Filename: "{app}\bin\x64\assimp_view.exe"; Components: tools; Check: IsWin64
+; Name: "{group}\AssimpView"; Filename: "{app}\bin\x86\assimp_view.exe"; Components: tools; Check: not IsWin64

+ 11 - 0
revision.h.in

@@ -4,4 +4,15 @@
 #define GitVersion 0x@GIT_COMMIT_HASH@
 #define GitBranch "@GIT_BRANCH@"
 
+#define VER_MAJOR @ASSIMP_VERSION_MAJOR@
+#define VER_MINOR @ASSIMP_VERSION_MINOR@
+#define VER_PATCH @ASSIMP_VERSION_PATCH@
+#define VER_BUILD @ASSIMP_PACKAGE_VERSION@
+
+#define STR_HELP(x) #x
+#define STR(x) STR_HELP(x)
+
+#define VER_FILEVERSION             VER_MAJOR,VER_MINOR,VER_PATCH,VER_BUILD
+#define VER_FILEVERSION_STR         STR(VER_MAJOR) "." STR(VER_MINOR) "." STR(VER_PATCH) "." STR(VER_BUILD)
+
 #endif // ASSIMP_REVISION_H_INC

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 444 - 0
test/models/FBX/embedded_ascii/box.FBX


+ 1 - 1
test/models/PLY/cube_test.ply

@@ -1,6 +1,6 @@
 ply
 format ascii 1.0
-comment Created by Open Asset Import Library - http://assimp.sf.net (v4.1.4208963464)
+comment Created by Open Asset Import Library - http://assimp.sf.net (v4.1.412856994)
 element vertex 8
 property float x
 property float y

+ 9 - 13
test/unit/utColladaExportCamera.cpp

@@ -52,18 +52,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 class ColladaExportCamera : public ::testing::Test {
 public:
-
-    virtual void SetUp()
-    {
+    void SetUp() override{
         ex = new Assimp::Exporter();
         im = new Assimp::Importer();
 
     }
 
-    virtual void TearDown()
-    {
+    void TearDown() override {
         delete ex;
+        ex = nullptr;
         delete im;
+        im = nullptr;
     }
 
 protected:
@@ -71,16 +70,15 @@ protected:
     Assimp::Importer* im;
 };
 
-TEST_F(ColladaExportCamera, testExportCamera)
-{
+TEST_F(ColladaExportCamera, testExportCamera) {
     const char* file = "cameraExp.dae";
 
     const aiScene* pTest = im->ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/cameras.dae", aiProcess_ValidateDataStructure);
-    ASSERT_TRUE(pTest!=NULL);
+    ASSERT_NE( nullptr, pTest );
     ASSERT_TRUE(pTest->HasCameras());
 
 
-    EXPECT_EQ(AI_SUCCESS,ex->Export(pTest,"collada",file));
+    EXPECT_EQ( AI_SUCCESS, ex->Export(pTest,"collada",file));
     const unsigned int origNumCams( pTest->mNumCameras );
     std::unique_ptr<float[]> origFOV( new float[ origNumCams ] );
     std::unique_ptr<float[]> orifClipPlaneNear( new float[ origNumCams ] );
@@ -89,7 +87,7 @@ TEST_F(ColladaExportCamera, testExportCamera)
     std::unique_ptr<aiVector3D[]> pos( new aiVector3D[ origNumCams ] );
     for (size_t i = 0; i < origNumCams; i++) {
         const aiCamera *orig = pTest->mCameras[ i ];
-        ASSERT_TRUE( orig != nullptr );
+        ASSERT_NE(nullptr, orig );
 
         origFOV[ i ] = orig->mHorizontalFOV;
         orifClipPlaneNear[ i ] = orig->mClipPlaneNear;
@@ -99,7 +97,7 @@ TEST_F(ColladaExportCamera, testExportCamera)
     }
     const aiScene* imported = im->ReadFile(file, aiProcess_ValidateDataStructure);
 
-    ASSERT_TRUE(imported!=NULL);
+    ASSERT_NE(nullptr, imported );
 
     EXPECT_TRUE( imported->HasCameras() );
     EXPECT_EQ( origNumCams, imported->mNumCameras );
@@ -119,5 +117,3 @@ TEST_F(ColladaExportCamera, testExportCamera)
 }
 
 #endif // ASSIMP_BUILD_NO_EXPORT
-
-

+ 15 - 0
test/unit/utFBXImporterExporter.cpp

@@ -114,3 +114,18 @@ TEST_F(utFBXImporterExporter, importUnitScaleFactor) {
     scene->mMetaData->Get("UnitScaleFactor", factor);
     EXPECT_DOUBLE_EQ(500.0, factor);
 }
+
+TEST_F(utFBXImporterExporter, importEmbeddedAsciiTest) {
+    // see https://github.com/assimp/assimp/issues/1957
+    Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/FBX/embedded_ascii/box.FBX", aiProcess_ValidateDataStructure);
+    EXPECT_NE(nullptr, scene);
+
+    EXPECT_EQ(1, scene->mNumMaterials);
+    aiMaterial *mat = scene->mMaterials[0];
+    ASSERT_NE(nullptr, mat);
+
+    aiString path;
+    aiTextureMapMode modes[2];
+    EXPECT_EQ(aiReturn_SUCCESS, mat->GetTexture(aiTextureType_DIFFUSE, 0, &path, nullptr, nullptr, nullptr, nullptr, modes));
+}

+ 3 - 6
tools/assimp_cmd/ImageExtractor.cpp

@@ -228,7 +228,8 @@ int DoExport(const aiTexture* tx, FILE* p, const std::string& extension,
 // Implementation of the assimp extract utility
 int Assimp_Extract (const char* const* params, unsigned int num)
 {
-    const char* const invalid = "assimp extract: Invalid number of arguments. See \'assimp extract --help\'\n"; 
+    const char* const invalid = "assimp extract: Invalid number of arguments. See \'assimp extract --help\'\n";
+    // assimp extract in out [options]
     if (num < 1) {
         printf(invalid);
         return 1;
@@ -240,11 +241,7 @@ int Assimp_Extract (const char* const* params, unsigned int num)
         return 0;
     }
 
-    // asssimp extract in out [options]
-    if (num < 1) {
-        printf(invalid);
-        return 1;
-    }
+
 
     std::string in  = std::string(params[0]);
     std::string out = (num > 1 ? std::string(params[1]) : "-");

+ 2 - 1
tools/assimp_qt_viewer/CMakeLists.txt

@@ -1,7 +1,8 @@
 set(PROJECT_VERSION "")
 project(assimp_qt_viewer)
 
-cmake_minimum_required(VERSION 3.0)
+# Qt5 requires cmake 3.1 or newer
+cmake_minimum_required(VERSION 3.1)
 
 FIND_PACKAGE(OpenGL QUIET)
 

+ 2 - 0
tools/assimp_view/CMakeLists.txt

@@ -88,6 +88,8 @@ SET_PROPERTY(TARGET assimp_viewer PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
 IF ( MSVC )
   ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
   ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
+  # assimp_viewer is ANSI (MBCS) throughout
+  REMOVE_DEFINITIONS( -DUNICODE -D_UNICODE )
 ENDIF ( MSVC )
 
 

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