浏览代码

Merge branch 'master' of https://github.com/assimp/assimp

Kim Kulling 9 年之前
父节点
当前提交
50803b897c

+ 10 - 9
CMakeLists.txt

@@ -40,20 +40,20 @@ cmake_minimum_required( VERSION 2.8 )
 PROJECT( Assimp )
 
 # All supported options ###############################################
-OPTION( BUILD_SHARED_LIBS 
-  "Build package with shared libraries." 
+OPTION( BUILD_SHARED_LIBS
+  "Build package with shared libraries."
   ON
 )
 OPTION( ASSIMP_DOUBLE_PRECISION
   "Set to ON to enable double precision processing"
   OFF
 )
-OPTION( ASSIMP_OPT_BUILD_PACKAGES 
-  "Set to ON to generate CPack configuration files and packaging targets" 
+OPTION( ASSIMP_OPT_BUILD_PACKAGES
+  "Set to ON to generate CPack configuration files and packaging targets"
   OFF
 )
-OPTION( ASSIMP_ANDROID_JNIIOSYSTEM 
-  "Android JNI IOSystem support is active" 
+OPTION( ASSIMP_ANDROID_JNIIOSYSTEM
+  "Android JNI IOSystem support is active"
   OFF
 )
 OPTION( ASSIMP_NO_EXPORT
@@ -77,6 +77,7 @@ OPTION ( ASSIMP_BUILD_TESTS
   ON
 )
 IF(MSVC)
+  set (CMAKE_PREFIX_PATH "D:\\libs\\devil")
   OPTION( ASSIMP_INSTALL_PDB
     "Install MSVC debug files."
     ON
@@ -336,10 +337,10 @@ IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
   # Why here? Maybe user do not want Qt viewer and have no Qt.
   # Why assimp_qt_viewer/CMakeLists.txt still contain similar check?
   # Because viewer can be build independently of Assimp.
-  FIND_PACKAGE(Qt5 QUIET)
+  FIND_PACKAGE(Qt5Widgets QUIET)
   FIND_PACKAGE(DevIL QUIET)
   FIND_PACKAGE(OpenGL QUIET)
-  IF ( Qt5_FOUND AND IL_FOUND AND OPENGL_FOUND)
+  IF ( Qt5Widgets_FOUND AND IL_FOUND AND OPENGL_FOUND)
     ADD_SUBDIRECTORY( tools/assimp_qt_viewer/ )
   ELSE()
     SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "")
@@ -356,7 +357,7 @@ IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
     ENDIF (NOT OPENGL_FOUND)
 
     MESSAGE (WARNING "Build of assimp_qt_viewer is disabled. Unsatisfied dendencies: ${ASSIMP_QT_VIEWER_DEPENDENCIES}")
-  ENDIF ( Qt5_FOUND AND IL_FOUND AND OPENGL_FOUND)
+  ENDIF ( Qt5Widgets_FOUND AND IL_FOUND AND OPENGL_FOUND)
 ENDIF ( ASSIMP_BUILD_ASSIMP_TOOLS )
 
 IF ( ASSIMP_BUILD_SAMPLES)

+ 3 - 3
code/AssimpCExport.cpp

@@ -70,11 +70,11 @@ ASSIMP_API const aiExportFormatDesc* aiGetExportFormatDescription( size_t index)
     }
 
     aiExportFormatDesc *desc = new aiExportFormatDesc;
-    desc->description = new char[ strlen( orig->description ) + 1 ];
+    desc->description = new char[ strlen( orig->description ) + 1 ]();
     ::strncpy( (char*) desc->description, orig->description, strlen( orig->description ) );
-    desc->fileExtension = new char[ strlen( orig->fileExtension ) + 1 ];
+    desc->fileExtension = new char[ strlen( orig->fileExtension ) + 1 ]();
     ::strncpy( ( char* ) desc->fileExtension, orig->fileExtension, strlen( orig->fileExtension ) );
-    desc->id = new char[ strlen( orig->id ) + 1 ];
+    desc->id = new char[ strlen( orig->id ) + 1 ]();
     ::strncpy( ( char* ) desc->id, orig->id, strlen( orig->id ) );
 
     return desc;

+ 75 - 16
code/FBXBinaryTokenizer.cpp

@@ -55,6 +55,46 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 namespace Assimp {
 namespace FBX {
 
+enum Flag
+{
+   e_unknown_0 = 1 << 0,
+   e_unknown_1 = 1 << 1,
+   e_unknown_2 = 1 << 2,
+   e_unknown_3 = 1 << 3,
+   e_unknown_4 = 1 << 4,
+   e_unknown_5 = 1 << 5,
+   e_unknown_6 = 1 << 6,
+   e_unknown_7 = 1 << 7,
+   e_unknown_8 = 1 << 8,
+   e_unknown_9 = 1 << 9,
+   e_unknown_10 = 1 << 10,
+   e_unknown_11 = 1 << 11,
+   e_unknown_12 = 1 << 12,
+   e_unknown_13 = 1 << 13,
+   e_unknown_14 = 1 << 14,
+   e_unknown_15 = 1 << 15,
+   e_unknown_16 = 1 << 16,
+   e_unknown_17 = 1 << 17,
+   e_unknown_18 = 1 << 18,
+   e_unknown_19 = 1 << 19,
+   e_unknown_20 = 1 << 20,
+   e_unknown_21 = 1 << 21,
+   e_unknown_22 = 1 << 22,
+   e_unknown_23 = 1 << 23,
+   e_flag_field_size_64_bit = 1 << 24, // Not sure what is 
+   e_unknown_25 = 1 << 25,
+   e_unknown_26 = 1 << 26,
+   e_unknown_27 = 1 << 27,
+   e_unknown_28 = 1 << 28,
+   e_unknown_29 = 1 << 29,
+   e_unknown_30 = 1 << 30,
+   e_unknown_31 = 1 << 31
+};
+
+bool check_flag(uint32_t flags, Flag to_check)
+{
+   return (flags & to_check) != 0;
+}
 
 // ------------------------------------------------------------------------------------------------
 Token::Token(const char* sbegin, const char* send, TokenType type, unsigned int offset)
@@ -118,6 +158,21 @@ uint32_t ReadWord(const char* input, const char*& cursor, const char* end)
     return word;
 }
 
+uint64_t ReadDoubleWord(const char* input, const char*& cursor, const char* end)
+{
+    const size_t k_to_read = sizeof(uint64_t);
+    if(Offset(cursor, end) < k_to_read) {
+        TokenizeError("cannot ReadDoubleWord, out of bounds",input, cursor);
+    }
+
+    uint64_t dword = *reinterpret_cast<const uint64_t*>(cursor);
+    AI_SWAP8(dword);
+
+    cursor += k_to_read;
+
+    return dword;
+}
+
 
 // ------------------------------------------------------------------------------------------------
 uint8_t ReadByte(const char* input, const char*& cursor, const char* end)
@@ -287,10 +342,10 @@ void ReadData(const char*& sbegin_out, const char*& send_out, const char* input,
 
 
 // ------------------------------------------------------------------------------------------------
-bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor, const char* end)
+bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor, const char* end, uint32_t const flags)
 {
     // the first word contains the offset at which this block ends
-    const uint32_t end_offset = ReadWord(input, cursor, end);
+    const uint64_t end_offset = check_flag(flags, e_flag_field_size_64_bit) ? ReadDoubleWord(input, cursor, end) : ReadWord(input, cursor, end);
 
     // we may get 0 if reading reached the end of the file -
     // fbx files have a mysterious extra footer which I don't know
@@ -308,10 +363,10 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor,
     }
 
     // the second data word contains the number of properties in the scope
-    const uint32_t prop_count = ReadWord(input, cursor, end);
+    const uint64_t prop_count = check_flag(flags, e_flag_field_size_64_bit) ? ReadDoubleWord(input, cursor, end) : ReadWord(input, cursor, end);
 
     // the third data word contains the length of the property list
-    const uint32_t prop_length = ReadWord(input, cursor, end);
+    const uint64_t prop_length = check_flag(flags, e_flag_field_size_64_bit) ? ReadDoubleWord(input, cursor, end) : ReadWord(input, cursor, end);
 
     // now comes the name of the scope/key
     const char* sbeg, *send;
@@ -337,29 +392,28 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor,
 
     // at the end of each nested block, there is a NUL record to indicate
     // that the sub-scope exists (i.e. to distinguish between P: and P : {})
-    // this NUL record is 13 bytes long.
-#define BLOCK_SENTINEL_LENGTH 13
+    // this NUL record is 13 bytes long on 32 bit version and 25 bytes long on 64 bit.
+    const size_t sentinel_block_length = check_flag(flags, e_flag_field_size_64_bit) ? (sizeof(uint64_t) * 3 + 1) : (sizeof(uint32_t) * 3 + 1);
 
     if (Offset(input, cursor) < end_offset) {
-
-        if (end_offset - Offset(input, cursor) < BLOCK_SENTINEL_LENGTH) {
+        if (end_offset - Offset(input, cursor) < sentinel_block_length) {
             TokenizeError("insufficient padding bytes at block end",input, cursor);
         }
 
         output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_OPEN_BRACKET, Offset(input, cursor) ));
 
         // XXX this is vulnerable to stack overflowing ..
-        while(Offset(input, cursor) < end_offset - BLOCK_SENTINEL_LENGTH) {
-            ReadScope(output_tokens, input, cursor, input + end_offset - BLOCK_SENTINEL_LENGTH);
+        while(Offset(input, cursor) < end_offset - sentinel_block_length) {
+            ReadScope(output_tokens, input, cursor, input + end_offset - sentinel_block_length, flags);
         }
         output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_CLOSE_BRACKET, Offset(input, cursor) ));
 
-        for (unsigned int i = 0; i < BLOCK_SENTINEL_LENGTH; ++i) {
+        for (unsigned int i = 0; i < sentinel_block_length; ++i) {
             if(cursor[i] != '\0') {
                 TokenizeError("failed to read nested block sentinel, expected all bytes to be 0",input, cursor);
             }
         }
-        cursor += BLOCK_SENTINEL_LENGTH;
+        cursor += sentinel_block_length;
     }
 
     if (Offset(input, cursor) != end_offset) {
@@ -386,12 +440,17 @@ void TokenizeBinary(TokenList& output_tokens, const char* input, unsigned int le
     }
 
 
-    //uint32_t offset = 0x1b;
+    //uint32_t offset = 0x15;
+    const char* cursor = input + 0x15;
+
+    const uint32_t flags = ReadWord(input, cursor, input + length);
 
-    const char* cursor = input + 0x1b;
+    const uint8_t padding_0 = ReadByte(input, cursor, input + length); // unused
+    const uint8_t padding_1 = ReadByte(input, cursor, input + length); // unused
 
-    while (cursor < input + length) {
-        if(!ReadScope(output_tokens, input, cursor, input + length)) {
+    while (cursor < input + length)
+    {
+        if(!ReadScope(output_tokens, input, cursor, input + length, flags)) {
             break;
         }
     }

+ 7 - 2
code/ObjFileParser.cpp

@@ -182,9 +182,14 @@ void ObjFileParser::parseFile()
 
         case 'm': // Parse a material library or merging group ('mg')
             {
-				std::string name;
+                std::string name;
+
+                getName(m_DataIt, m_DataItEnd, name);
+
+                size_t nextSpace = name.find(" ");
+                if (nextSpace != std::string::npos)
+                    name = name.substr(0, nextSpace);
 
-				getName(m_DataIt, m_DataItEnd, name);
                 if (name == "mg")
                     getGroupNumberAndResolution();
                 else if(name == "mtllib")

+ 1 - 1
code/Q3BSPFileData.h

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

+ 2 - 11
code/Q3BSPFileImporter.cpp

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------------------------------
 
-Copyright (c) 2006-2008, assimp team
+Copyright (c) 2006-2016, assimp team
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -40,7 +40,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #ifndef ASSIMP_BUILD_NO_Q3BSP_IMPORTER
 
-//#include <windows.h>
 #include "DefaultIOSystem.h"
 #include "Q3BSPFileImporter.h"
 #include "Q3BSPZipArchive.h"
@@ -76,14 +75,6 @@ static const aiImporterDesc desc = {
 
 namespace Assimp {
 
-/*
-static void getSupportedExtensions(std::vector<std::string> &supportedExtensions) {
-    supportedExtensions.push_back( ".jpg" );
-    supportedExtensions.push_back( ".png" );
-    supportedExtensions.push_back( ".tga" );
-}
-*/
-
 using namespace Q3BSP;
 
 // ------------------------------------------------------------------------------------------------
@@ -175,7 +166,7 @@ Q3BSPFileImporter::~Q3BSPFileImporter() {
 bool Q3BSPFileImporter::CanRead( const std::string& rFile, IOSystem* /*pIOHandler*/, bool checkSig ) const
 {
     if(!checkSig) {
-        return SimpleExtensionCheck( rFile, "pk3" );
+        return SimpleExtensionCheck( rFile, "pk3", "bsp" );
     }
     // TODO perhaps add keyword based detection
     return false;

+ 1 - 1
code/Q3BSPFileImporter.h

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

+ 1 - 1
code/Q3BSPFileParser.cpp

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

+ 1 - 1
code/Q3BSPFileParser.h

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

+ 1 - 1
code/Q3BSPZipArchive.cpp

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

+ 42 - 76
code/Q3BSPZipArchive.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2008, assimp team
+Copyright (c) 2006-2016, assimp team
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -58,24 +58,15 @@ namespace Q3BSP {
 /// \brief
 // ------------------------------------------------------------------------------------------------
 class IOSystem2Unzip {
-
-    public:
-
-        static voidpf open(voidpf opaque, const char* filename, int mode);
-
-        static uLong read(voidpf opaque, voidpf stream, void* buf, uLong size);
-
-        static uLong write(voidpf opaque, voidpf stream, const void* buf, uLong size);
-
-        static long tell(voidpf opaque, voidpf stream);
-
-        static long seek(voidpf opaque, voidpf stream, uLong offset, int origin);
-
-        static int close(voidpf opaque, voidpf stream);
-
-        static int testerror(voidpf opaque, voidpf stream);
-
-        static zlib_filefunc_def get(IOSystem* pIOHandler);
+public:
+    static voidpf open(voidpf opaque, const char* filename, int mode);
+    static uLong read(voidpf opaque, voidpf stream, void* buf, uLong size);
+    static uLong write(voidpf opaque, voidpf stream, const void* buf, uLong size);
+    static long tell(voidpf opaque, voidpf stream);
+    static long seek(voidpf opaque, voidpf stream, uLong offset, int origin);
+    static int close(voidpf opaque, voidpf stream);
+    static int testerror(voidpf opaque, voidpf stream);
+    static zlib_filefunc_def get(IOSystem* pIOHandler);
 };
 
 // ------------------------------------------------------------------------------------------------
@@ -85,32 +76,21 @@ class IOSystem2Unzip {
 /// \brief
 // ------------------------------------------------------------------------------------------------
 class ZipFile : public IOStream {
-
     friend class Q3BSPZipArchive;
 
-    public:
-
-        explicit ZipFile(size_t size);
-
-        ~ZipFile();
-
-        size_t Read(void* pvBuffer, size_t pSize, size_t pCount );
-
-        size_t Write(const void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/);
-
-        size_t FileSize() const;
-
-        aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/);
-
-        size_t Tell() const;
-
-        void Flush();
-
-    private:
-
-        void* m_Buffer;
-
-        size_t m_Size;
+public:
+    explicit ZipFile(size_t size);
+    ~ZipFile();
+    size_t Read(void* pvBuffer, size_t pSize, size_t pCount );
+    size_t Write(const void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/);
+    size_t FileSize() const;
+    aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/);
+    size_t Tell() const;
+    void Flush();
+
+private:
+    void* m_Buffer;
+    size_t m_Size;
 };
 
 // ------------------------------------------------------------------------------------------------
@@ -121,39 +101,25 @@ class ZipFile : public IOStream {
 /// from a P3K archive ( Quake level format ).
 // ------------------------------------------------------------------------------------------------
 class Q3BSPZipArchive : public Assimp::IOSystem {
-
-    public:
-
-        static const unsigned int FileNameSize = 256;
-
-    public:
-
-        Q3BSPZipArchive(IOSystem* pIOHandler, const std::string & rFile);
-
-        ~Q3BSPZipArchive();
-
-        bool Exists(const char* pFile) const;
-
-        char getOsSeparator() const;
-
-        IOStream* Open(const char* pFile, const char* pMode = "rb");
-
-        void Close(IOStream* pFile);
-
-        bool isOpen() const;
-
-        void getFileList(std::vector<std::string> &rFileList);
-
-    private:
-
-        bool mapArchive();
-
-    private:
-
-        unzFile m_ZipFileHandle;
-
-        std::map<std::string, ZipFile*> m_ArchiveMap;
-
+public:
+    static const unsigned int FileNameSize = 256;
+
+public:
+    Q3BSPZipArchive(IOSystem* pIOHandler, const std::string & rFile);
+    ~Q3BSPZipArchive();
+    bool Exists(const char* pFile) const;
+    char getOsSeparator() const;
+    IOStream* Open(const char* pFile, const char* pMode = "rb");
+    void Close(IOStream* pFile);
+    bool isOpen() const;
+    void getFileList(std::vector<std::string> &rFileList);
+
+private:
+    bool mapArchive();
+
+private:
+    unzFile m_ZipFileHandle;
+    std::map<std::string, ZipFile*> m_ArchiveMap;
 };
 
 // ------------------------------------------------------------------------------------------------

+ 6 - 5
tools/assimp_qt_viewer/CMakeLists.txt

@@ -3,12 +3,12 @@ set(PROJECT_VERSION "")
 
 cmake_minimum_required(VERSION 2.6)
 
-find_package(Qt4 REQUIRED)
+find_package(Qt5Widgets REQUIRED)
 find_package(DevIL REQUIRED)
 find_package(OpenGL REQUIRED)
 
 include_directories(
-	${QT_INCLUDES}
+	${Qt5Widgets_INCLUDES}
 	${Assimp_SOURCE_DIR}/include
 	${Assimp_SOURCE_DIR}/code
 	${CMAKE_CURRENT_BINARY_DIR}
@@ -21,15 +21,16 @@ link_directories(${Assimp_BINARY_DIR})
 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pedantic -Wall")
 
 set(assimp_qt_viewer_SRCS main.cpp loggerview.cpp glview.cpp mainwindow.cpp)
-qt4_wrap_ui(UISrcs mainwindow.ui)
-qt4_wrap_cpp(MOCrcs mainwindow.hpp glview.hpp)
+qt5_wrap_ui(UISrcs mainwindow.ui)
+qt5_wrap_cpp(MOCrcs mainwindow.hpp glview.hpp)
 
 add_executable(${PROJECT_NAME} ${assimp_qt_viewer_SRCS} ${UISrcs} ${MOCrcs})
 target_link_libraries(${PROJECT_NAME} ${QT_LIBRARIES} ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY} ${QT_QTOPENGL_LIBRARY} ${IL_LIBRARIES} ${OPENGL_LIBRARIES} assimp)
 
+qt5_use_modules(${PROJECT_NAME} Widgets OpenGL)
 if(WIN32) # Check if we are on Windows
 	if(MSVC) # Check if we are using the Visual Studio compiler
-		set_target_properties(TestProject PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS")
+		#set_target_properties(TestProject PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS")
 	elseif(CMAKE_COMPILER_IS_GNUCXX)
 		# SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mwindows") # Not tested
 	else()

+ 126 - 123
tools/assimp_qt_viewer/glview.cpp

@@ -9,7 +9,7 @@
 #include <GL/glu.h>
 
 // Header files, DevIL.
-#include <IL/il.h>
+#include <il.h>
 
 // Header files, Assimp.
 #include <assimp/DefaultLogger.hpp>
@@ -56,15 +56,15 @@ void CGLView::SHelper_Camera::SetDefault()
 
 void CGLView::Material_Apply(const aiMaterial* pMaterial)
 {
-GLfloat tcol[4];
-aiColor4D taicol;
-unsigned int max;
-int ret1, ret2;
-int texture_index = 0;
-aiString texture_path;
+    GLfloat tcol[4];
+    aiColor4D taicol;
+    unsigned int max;
+    int ret1, ret2;
+    int texture_index = 0;
+    aiString texture_path;
 
-auto set_float4 = [](float f[4], float a, float b, float c, float d) { f[0] = a, f[1] = b, f[2] = c, f[3] = d; };
-auto color4_to_float4 = [](const aiColor4D *c, float f[4]) { f[0] = c->r, f[1] = c->g, f[2] = c->b, f[3] = c->a; };
+    auto set_float4 = [](float f[4], float a, float b, float c, float d) { f[0] = a, f[1] = b, f[2] = c, f[3] = d; };
+    auto color4_to_float4 = [](const aiColor4D *c, float f[4]) { f[0] = c->r, f[1] = c->g, f[2] = c->b, f[3] = c->a; };
 
 	///TODO: cache materials
 	// Disable color material because glMaterial is used.
@@ -158,124 +158,127 @@ std::list<aiMatrix4x4> mat_list;
 		} while(node_cur != nullptr);
 	}
 
-	// multiplicate all matrices in reverse order
-	for(std::list<aiMatrix4x4>::reverse_iterator rit = mat_list.rbegin(); rit != mat_list.rend(); rit++) pOutMatrix = pOutMatrix * (*rit);
+	// multiply all matrices in reverse order
+    for ( std::list<aiMatrix4x4>::reverse_iterator rit = mat_list.rbegin(); rit != mat_list.rend(); rit++)
+    {
+        pOutMatrix = pOutMatrix * (*rit);
+    }
 }
 
 void CGLView::ImportTextures(const QString& pScenePath)
 {
-auto LoadTexture = [&](const QString& pFileName) -> bool ///TODO: IME texture mode, operation.
-{
-ILboolean success;
-GLuint id_ogl_texture;// OpenGL texture ID.
-
-	if(!pFileName.startsWith(AI_EMBEDDED_TEXNAME_PREFIX))
-	{
-		ILuint id_image;// DevIL image ID.
-		QString basepath = pScenePath.left(pScenePath.lastIndexOf('/') + 1);// path with '/' at the end.
-		QString fileloc = (basepath + pFileName);
-
-		fileloc.replace('\\', "/");
-		ilGenImages(1, &id_image);// Generate DevIL image ID.
-		ilBindImage(id_image);
-		success = ilLoadImage(fileloc.toLocal8Bit());
-		if(!success)
-		{
-			LogError(QString("Couldn't load Image: %1").arg(fileloc));
-
-			return false;
-		}
-
-		// Convert every colour component into unsigned byte. If your image contains alpha channel you can replace IL_RGB with IL_RGBA.
-		success = ilConvertImage(IL_RGBA, IL_UNSIGNED_BYTE);
-		if(!success)
-		{
-			LogError("Couldn't convert image.");
-
-			return false;
-		}
-
-		glGenTextures(1, &id_ogl_texture);// Texture ID generation.
-		mTexture_IDMap[pFileName] = id_ogl_texture;// save texture ID for filename in map
-		glBindTexture(GL_TEXTURE_2D, id_ogl_texture);// Binding of texture ID.
-		// Redefine standard texture values
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);// We will use linear interpolation for magnification filter.
-		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);// We will use linear interpolation for minifying filter.
-		glTexImage2D(GL_TEXTURE_2D, 0, ilGetInteger(IL_IMAGE_BPP), ilGetInteger(IL_IMAGE_WIDTH), ilGetInteger(IL_IMAGE_HEIGHT), 0,
-						ilGetInteger(IL_IMAGE_FORMAT), GL_UNSIGNED_BYTE, ilGetData());// Texture specification.
-
-		//Cleanup
-		ilDeleteImages(1, &id_image);// Because we have already copied image data into texture data we can release memory used by image.
-	}
-	else
-	{
-		struct SPixel_Description
-		{
-			const char* FormatHint;
-			const GLint Image_InternalFormat;
-			const GLint Pixel_Format;
-		};
-
-		constexpr SPixel_Description Pixel_Description[] = {
-			{"rgba8880", GL_RGB, GL_RGB},
-			{"rgba8888", GL_RGBA, GL_RGBA}
-		};
-
-		constexpr size_t Pixel_Description_Count = sizeof(Pixel_Description) / sizeof(SPixel_Description);
-
-		size_t idx_description;
-		// Get texture index.
-		bool ok;
-		size_t idx_texture = pFileName.right(strlen(AI_EMBEDDED_TEXNAME_PREFIX)).toULong(&ok);
-
-		if(!ok)
-		{
-			LogError("Can not get index of the embedded texture from path in material.");
-
-			return false;
-		}
-
-		// Create alias for conveniance.
-		const aiTexture& als = *mScene->mTextures[idx_texture];
-
-		if(als.mHeight == 0)// Compressed texture.
-		{
-			LogError("IME: compressed embedded textures are not implemented.");
-		}
-		else
-		{
-			ok = false;
-			for(size_t idx = 0; idx < Pixel_Description_Count; idx++)
-			{
-				if(als.CheckFormat(Pixel_Description[idx].FormatHint))
-				{
-					idx_description = idx;
-					ok = true;
-					break;
-				}
-			}
-
-			if(!ok)
-			{
-				LogError(QString("Unsupported format hint for embedded texture: [%1]").arg(als.achFormatHint));
-
-				return false;
-			}
-
-			glGenTextures(1, &id_ogl_texture);// Texture ID generation.
-			mTexture_IDMap[pFileName] = id_ogl_texture;// save texture ID for filename in map
-			glBindTexture(GL_TEXTURE_2D, id_ogl_texture);// Binding of texture ID.
-			// Redefine standard texture values
-			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);// We will use linear interpolation for magnification filter.
-			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);// We will use linear interpolation for minifying filter.
-			// Texture specification.
-			glTexImage2D(GL_TEXTURE_2D, 0, Pixel_Description[idx_description].Image_InternalFormat, als.mWidth, als.mHeight, 0,
-							Pixel_Description[idx_description].Pixel_Format, GL_UNSIGNED_BYTE, (uint8_t*)als.pcData);
-		}// if(als.mHeight == 0) else
-	}// if(!filename.startsWith(AI_EMBEDDED_TEXNAME_PREFIX)) else
-
-	return true;
-};// auto LoadTexture = [&](const aiString& pPath)
+    auto LoadTexture = [&](const QString& pFileName) -> bool ///TODO: IME texture mode, operation.
+    {
+        ILboolean success;
+        GLuint id_ogl_texture;// OpenGL texture ID.
+
+	    if(!pFileName.startsWith(AI_EMBEDDED_TEXNAME_PREFIX))
+	    {
+		    ILuint id_image;// DevIL image ID.
+		    QString basepath = pScenePath.left(pScenePath.lastIndexOf('/') + 1);// path with '/' at the end.
+		    QString fileloc = (basepath + pFileName);
+
+		    fileloc.replace('\\', "/");
+		    ilGenImages(1, &id_image);// Generate DevIL image ID.
+		    ilBindImage(id_image);
+		    success = ilLoadImage(fileloc.toLocal8Bit());
+		    if(!success)
+		    {
+			    LogError(QString("Couldn't load Image: %1").arg(fileloc));
+
+			    return false;
+		    }
+
+		    // Convert every colour component into unsigned byte. If your image contains alpha channel you can replace IL_RGB with IL_RGBA.
+		    success = ilConvertImage(IL_RGBA, IL_UNSIGNED_BYTE);
+		    if(!success)
+		    {
+			    LogError("Couldn't convert image.");
+
+			    return false;
+		    }
+
+		    glGenTextures(1, &id_ogl_texture);// Texture ID generation.
+		    mTexture_IDMap[pFileName] = id_ogl_texture;// save texture ID for filename in map
+		    glBindTexture(GL_TEXTURE_2D, id_ogl_texture);// Binding of texture ID.
+		    // Redefine standard texture values
+		    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);// We will use linear interpolation for magnification filter.
+		    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);// We will use linear interpolation for minifying filter.
+		    glTexImage2D(GL_TEXTURE_2D, 0, ilGetInteger(IL_IMAGE_BPP), ilGetInteger(IL_IMAGE_WIDTH), ilGetInteger(IL_IMAGE_HEIGHT), 0,
+						    ilGetInteger(IL_IMAGE_FORMAT), GL_UNSIGNED_BYTE, ilGetData());// Texture specification.
+
+		    //Cleanup
+		    ilDeleteImages(1, &id_image);// Because we have already copied image data into texture data we can release memory used by image.
+	    }
+	    else
+	    {
+		    struct SPixel_Description
+		    {
+			    const char* FormatHint;
+			    const GLint Image_InternalFormat;
+			    const GLint Pixel_Format;
+		    };
+
+		    constexpr SPixel_Description Pixel_Description[] = {
+			    {"rgba8880", GL_RGB, GL_RGB},
+			    {"rgba8888", GL_RGBA, GL_RGBA}
+		    };
+
+		    constexpr size_t Pixel_Description_Count = sizeof(Pixel_Description) / sizeof(SPixel_Description);
+
+		    size_t idx_description;
+		    // Get texture index.
+		    bool ok;
+		    size_t idx_texture = pFileName.right(strlen(AI_EMBEDDED_TEXNAME_PREFIX)).toULong(&ok);
+
+		    if(!ok)
+		    {
+			    LogError("Can not get index of the embedded texture from path in material.");
+
+			    return false;
+		    }
+
+		    // Create alias for conveniance.
+		    const aiTexture& als = *mScene->mTextures[idx_texture];
+
+		    if(als.mHeight == 0)// Compressed texture.
+		    {
+			    LogError("IME: compressed embedded textures are not implemented.");
+		    }
+		    else
+		    {
+			    ok = false;
+			    for(size_t idx = 0; idx < Pixel_Description_Count; idx++)
+			    {
+				    if(als.CheckFormat(Pixel_Description[idx].FormatHint))
+				    {
+					    idx_description = idx;
+					    ok = true;
+					    break;
+				    }
+			    }
+
+			    if(!ok)
+			    {
+				    LogError(QString("Unsupported format hint for embedded texture: [%1]").arg(als.achFormatHint));
+
+				    return false;
+			    }
+
+			    glGenTextures(1, &id_ogl_texture);// Texture ID generation.
+			    mTexture_IDMap[pFileName] = id_ogl_texture;// save texture ID for filename in map
+			    glBindTexture(GL_TEXTURE_2D, id_ogl_texture);// Binding of texture ID.
+			    // Redefine standard texture values
+			    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);// We will use linear interpolation for magnification filter.
+			    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);// We will use linear interpolation for minifying filter.
+			    // Texture specification.
+			    glTexImage2D(GL_TEXTURE_2D, 0, Pixel_Description[idx_description].Image_InternalFormat, als.mWidth, als.mHeight, 0,
+							    Pixel_Description[idx_description].Pixel_Format, GL_UNSIGNED_BYTE, (uint8_t*)als.pcData);
+		    }// if(als.mHeight == 0) else
+	    }// if(!filename.startsWith(AI_EMBEDDED_TEXNAME_PREFIX)) else
+
+	    return true;
+    };// auto LoadTexture = [&](const aiString& pPath)
 
 	if(mScene == nullptr)
 	{

+ 1 - 1
tools/assimp_qt_viewer/mainwindow.cpp

@@ -325,7 +325,7 @@ bool selected = ui->lstLight->isItemSelected(ui->lstLight->currentItem());
 	mGLView->updateGL();
 }
 
-void MainWindow::on_lstCamera_clicked(__unused const QModelIndex &index)
+void MainWindow::on_lstCamera_clicked( const QModelIndex &)
 {
 	mGLView->Camera_Set(ui->lstLight->currentRow());
 	mGLView->updateGL();

+ 1 - 1
tools/assimp_qt_viewer/mainwindow.hpp

@@ -6,7 +6,7 @@
 #pragma once
 
 // Header files, Qt.
-#include <QMainWindow>
+#include <QtWidgets>
 
 // Header files, project.
 #include "glview.hpp"