diff --git a/code/AssetLib/Assbin/AssbinFileWriter.cpp b/code/AssetLib/Assbin/AssbinFileWriter.cpp
index 72fbfdcb11af771c0a99c116bc2efb657a4428b7..1d16f179ec1f4d1426323654636dbb2c30591ffd 100644
--- a/code/AssetLib/Assbin/AssbinFileWriter.cpp
+++ b/code/AssetLib/Assbin/AssbinFileWriter.cpp
@@ -182,6 +182,8 @@ inline size_t Write<aiVertexWeight>(IOStream *stream, const aiVertexWeight &v) {
     return t + Write<float>(stream, v.mWeight);
 }
 
+constexpr size_t MatrixSize = 64;
+
 // -----------------------------------------------------------------------------------
 // Serialize a mat4x4
 template <>
@@ -192,7 +194,7 @@ inline size_t Write<aiMatrix4x4>(IOStream *stream, const aiMatrix4x4 &m) {
         }
     }
 
-    return 64;
+    return MatrixSize;
 }
 
 // -----------------------------------------------------------------------------------
diff --git a/code/AssetLib/XGL/XGLLoader.cpp b/code/AssetLib/XGL/XGLLoader.cpp
index b003f852a297e726eaf2015231e26c0c93c329b1..a711598f95444ddd24bdb62b921a07140c79fd0e 100644
--- a/code/AssetLib/XGL/XGLLoader.cpp
+++ b/code/AssetLib/XGL/XGLLoader.cpp
@@ -44,9 +44,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef ASSIMP_BUILD_NO_XGL_IMPORTER
 
 #include "XGLLoader.h"
+#include "Common/Compression.h"
+
 #include <assimp/ParsingUtils.h>
 #include <assimp/fast_atof.h>
-
 #include <assimp/MemoryIOWrapper.h>
 #include <assimp/StreamReader.h>
 #include <assimp/importerdesc.h>
@@ -57,15 +58,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 using namespace Assimp;
 
-// zlib is needed for compressed XGL files
-#ifndef ASSIMP_BUILD_NO_COMPRESSED_XGL
-#  ifdef ASSIMP_BUILD_NO_OWN_ZLIB
-#    include <zlib.h>
-#  else
-#    include <contrib/zlib/zlib.h>
-#  endif
-#endif
-
 namespace Assimp { // this has to be in here because LogFunctions is in ::Assimp
 
 template <>
@@ -73,6 +65,7 @@ const char *LogFunctions<XGLImporter>::Prefix() {
     static auto prefix = "XGL: ";
 	return prefix;
 }
+
 } // namespace Assimp
 
 static const aiImporterDesc desc = {
@@ -118,8 +111,8 @@ const aiImporterDesc *XGLImporter::GetInfo() const {
 // ------------------------------------------------------------------------------------------------
 // Imports the given file into the given scene structure.
 void XGLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
-#ifndef ASSIMP_BUILD_NO_COMPRESSED_XGL
-	std::vector<Bytef> uncompressed;
+ #ifndef ASSIMP_BUILD_NO_COMPRESSED_XGL
+	std::vector<unsigned char> uncompressed;
 #endif
 
 	m_scene = pScene;
@@ -137,46 +130,14 @@ void XGLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
 #else
 		std::unique_ptr<StreamReaderLE> raw_reader(new StreamReaderLE(stream));
 
-		// build a zlib stream
-		z_stream zstream;
-		zstream.opaque = Z_NULL;
-		zstream.zalloc = Z_NULL;
-		zstream.zfree = Z_NULL;
-		zstream.data_type = Z_BINARY;
-
-		// raw decompression without a zlib or gzip header
-		inflateInit2(&zstream, -MAX_WBITS);
-
-		// skip two extra bytes, zgl files do carry a crc16 upfront (I think)
-		raw_reader->IncPtr(2);
-
-		zstream.next_in = reinterpret_cast<Bytef *>(raw_reader->GetPtr());
-		zstream.avail_in = (uInt) raw_reader->GetRemainingSize();
-
-		size_t total = 0l;
-
-		// TODO: be smarter about this, decompress directly into heap buffer
-		// and decompress the data .... do 1k chunks in the hope that we won't kill the stack
-#define MYBLOCK 1024
-		Bytef block[MYBLOCK];
-		int ret;
-		do {
-			zstream.avail_out = MYBLOCK;
-			zstream.next_out = block;
-			ret = inflate(&zstream, Z_NO_FLUSH);
-
-			if (ret != Z_STREAM_END && ret != Z_OK) {
-				ThrowException("Failure decompressing this file using gzip, seemingly it is NOT a compressed .XGL file");
-			}
-			const size_t have = MYBLOCK - zstream.avail_out;
-			total += have;
-			uncompressed.resize(total);
-			memcpy(uncompressed.data() + total - have, block, have);
-		} while (ret != Z_STREAM_END);
-
-		// terminate zlib
-		inflateEnd(&zstream);
-
+        Compression c;
+        size_t total = 0l;
+        if (c.open()) {
+            // skip two extra bytes, zgl files do carry a crc16 upfront (I think)
+            raw_reader->IncPtr(2);
+            total = c.decompress((unsigned char *)raw_reader->GetPtr(), raw_reader->GetRemainingSize(), uncompressed);
+            c.close();
+        }
 		// replace the input stream with a memory stream
 		stream.reset(new MemoryIOStream(reinterpret_cast<uint8_t *>(uncompressed.data()), total));
 #endif
@@ -291,7 +252,8 @@ aiNode *XGLImporter::ReadObject(XmlNode &node, TempScope &scope) {
 			const std::string &s = ai_stdStrToLower(child.name());
 			if (s == "mesh") {
 				const size_t prev = scope.meshes_linear.size();
-				if (ReadMesh(child, scope)) {
+                bool empty;
+				if (ReadMesh(child, scope, empty)) {
 					const size_t newc = scope.meshes_linear.size();
 					for (size_t i = 0; i < newc - prev; ++i) {
 						meshes.push_back(static_cast<unsigned int>(i + prev));
@@ -475,12 +437,12 @@ aiMesh *XGLImporter::ToOutputMesh(const TempMaterialMesh &m) {
 }
 
 // ------------------------------------------------------------------------------------------------
-bool XGLImporter::ReadMesh(XmlNode &node, TempScope &scope) {
+bool XGLImporter::ReadMesh(XmlNode &node, TempScope &scope, bool &empty) {
 	TempMesh t;
 
 	std::map<unsigned int, TempMaterialMesh> bymat;
     const unsigned int mesh_id = ReadIDAttr(node);
-
+    bool empty_mesh = true;
 	for (XmlNode &child : node.children()) {
         const std::string &s = ai_stdStrToLower(child.name());
 
@@ -539,6 +501,9 @@ bool XGLImporter::ReadMesh(XmlNode &node, TempScope &scope) {
 					mid = ResolveMaterialRef(sub_child, scope);
 				}
 			}
+            if (has[0] || has[1] || has[2]) {
+                empty_mesh = false;
+            }
 
 			if (mid == ~0u) {
 				ThrowException("missing material index");
@@ -590,6 +555,11 @@ bool XGLImporter::ReadMesh(XmlNode &node, TempScope &scope) {
 			scope.meshes.insert(std::pair<unsigned int, aiMesh *>(mesh_id, m));
 		}
 	}
+    if (empty_mesh) {
+        LogWarn("Mesh is empty, skipping.");
+        empty = empty_mesh;
+        return false;
+    }
 
 	// no id == not a reference, insert this mesh right *here*
 	return mesh_id == ~0u;
@@ -759,7 +729,7 @@ aiVector2D XGLImporter::ReadVec2(XmlNode &node) {
     std::string val;
     XmlParser::getValueAsString(node, val);
     const char *s = val.c_str();
-	ai_real v[2];
+    ai_real v[2] = {};
 	for (int i = 0; i < 2; ++i) {
 		if (!SkipSpaces(&s)) {
 			LogError("unexpected EOL, failed to parse vec2");
diff --git a/code/AssetLib/XGL/XGLLoader.h b/code/AssetLib/XGL/XGLLoader.h
index 903f114cfbee9d9d6c104c3aec8fe46186cca4db..ae7ccddc2ed38292269cfbb66756b8c7e1504660 100644
--- a/code/AssetLib/XGL/XGLLoader.h
+++ b/code/AssetLib/XGL/XGLLoader.h
@@ -186,7 +186,7 @@ private:
     void ReadLighting(XmlNode &node, TempScope &scope);
     aiLight *ReadDirectionalLight(XmlNode &node);
     aiNode *ReadObject(XmlNode &node, TempScope &scope);
-    bool ReadMesh(XmlNode &node, TempScope &scope);
+    bool ReadMesh(XmlNode &node, TempScope &scope, bool &empty);
     void ReadMaterial(XmlNode &node, TempScope &scope);
     aiVector2D ReadVec2(XmlNode &node);
     aiVector3D ReadVec3(XmlNode &node);
diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt
index 7ce933585f3a04e6c6b7e3fd56419df24ca8e0d8..5936d6d06f3725886106f3da4c635011ba05ad79 100644
--- a/code/CMakeLists.txt
+++ b/code/CMakeLists.txt
@@ -166,6 +166,8 @@ SET( Logging_SRCS
 SOURCE_GROUP(Logging FILES ${Logging_SRCS})
 
 SET( Common_SRCS
+  Common/Compression.cpp
+  Common/Compression.h
   Common/BaseImporter.cpp
   Common/BaseProcess.cpp
   Common/BaseProcess.h
diff --git a/code/Common/Base64.cpp b/code/Common/Base64.cpp
index 2916cae7f2880355ab355aa24ff168a1c8707262..3e9c474059a7cc2a7f7843b0264249617bbc9324 100644
--- a/code/Common/Base64.cpp
+++ b/code/Common/Base64.cpp
@@ -3,7 +3,7 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2021, assimp team
+Copyright (c) 2006-2022, assimp team
 
 All rights reserved.
 
@@ -57,7 +57,7 @@ static const uint8_t tableDecodeBase64[128] = {
     41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0
 };
 
-static const char* tableEncodeBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+static const char *tableEncodeBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
 
 static inline char EncodeChar(uint8_t b) {
     return tableEncodeBase64[size_t(b)];
@@ -104,17 +104,16 @@ void Encode(const uint8_t *in, size_t inLength, std::string &out) {
     }
 }
 
-void Encode(const std::vector<uint8_t>& in, std::string &out) {
-    Encode (in.data (), in.size (), out);
+void Encode(const std::vector<uint8_t> &in, std::string &out) {
+    Encode(in.data(), in.size(), out);
 }
 
-std::string Encode (const std::vector<uint8_t>& in) {
+std::string Encode(const std::vector<uint8_t> &in) {
     std::string encoded;
-    Encode (in, encoded);
+    Encode(in, encoded);
     return encoded;
 }
 
-
 size_t Decode(const char *in, size_t inLength, uint8_t *&out) {
     if (inLength % 4 != 0) {
         throw DeadlyImportError("Invalid base64 encoded data: \"", std::string(in, std::min(size_t(32), inLength)), "\", length:", inLength);
@@ -159,23 +158,22 @@ size_t Decode(const char *in, size_t inLength, uint8_t *&out) {
     return outLength;
 }
 
-size_t Decode(const std::string& in, std::vector<uint8_t>& out) {
-    uint8_t* outPtr = nullptr;
-    size_t decodedSize = Decode (in.data (), in.size (), outPtr);
+size_t Decode(const std::string &in, std::vector<uint8_t> &out) {
+    uint8_t *outPtr = nullptr;
+    size_t decodedSize = Decode(in.data(), in.size(), outPtr);
     if (outPtr == nullptr) {
         return 0;
     }
-    out.assign (outPtr, outPtr + decodedSize);
+    out.assign(outPtr, outPtr + decodedSize);
     delete[] outPtr;
     return decodedSize;
 }
 
-std::vector<uint8_t> Decode (const std::string& in) {
+std::vector<uint8_t> Decode(const std::string &in) {
     std::vector<uint8_t> result;
-    Decode (in, result);
+    Decode(in, result);
     return result;
 }
 
-}
-
-}
+} // namespace Base64
+} // namespace Assimp
diff --git a/code/Common/Compression.cpp b/code/Common/Compression.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2e3defa8ccaa1e023f7dce1b86ae8f01f3d4957c
--- /dev/null
+++ b/code/Common/Compression.cpp
@@ -0,0 +1,141 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2022, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+#include "Compression.h"
+#include <assimp/ai_assert.h>
+#include <assimp/Exceptional.h>
+
+#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
+#include <zlib.h>
+#else
+#include "../contrib/zlib/zlib.h"
+#endif
+
+namespace Assimp {
+
+struct Compression::impl {
+    bool mOpen;
+    z_stream mZSstream;
+
+    impl() :
+            mOpen(false) {}
+};
+
+Compression::Compression() :
+        mImpl(new impl) {
+    // empty
+}
+
+Compression::~Compression() {
+    ai_assert(mImpl != nullptr);
+
+    delete mImpl;
+}
+
+bool Compression::open() {
+    ai_assert(mImpl != nullptr);
+
+    if (mImpl->mOpen) {
+        return false;
+    }
+
+    // build a zlib stream
+    mImpl->mZSstream.opaque = Z_NULL;
+    mImpl->mZSstream.zalloc = Z_NULL;
+    mImpl->mZSstream.zfree = Z_NULL;
+    mImpl->mZSstream.data_type = Z_BINARY;
+
+    // raw decompression without a zlib or gzip header
+    inflateInit2(&mImpl->mZSstream, -MAX_WBITS);
+    mImpl->mOpen = true;
+
+    return mImpl->mOpen;
+}
+
+constexpr size_t MYBLOCK = 1024;
+
+size_t Compression::decompress(unsigned char *data, size_t in, std::vector<unsigned char> &uncompressed) {
+    ai_assert(mImpl != nullptr);
+
+    mImpl->mZSstream.next_in = reinterpret_cast<Bytef *>(data);
+    mImpl->mZSstream.avail_in = (uInt)in;
+
+    Bytef block[MYBLOCK] = {};
+    int ret = 0;
+    size_t total = 0l;
+    do {
+        mImpl->mZSstream.avail_out = MYBLOCK;
+        mImpl->mZSstream.next_out = block;
+        ret = inflate(&mImpl->mZSstream, Z_NO_FLUSH);
+
+        if (ret != Z_STREAM_END && ret != Z_OK) {
+            throw DeadlyImportError("Compression", "Failure decompressing this file using gzip.");
+
+        }
+        const size_t have = MYBLOCK - mImpl->mZSstream.avail_out;
+        total += have;
+        uncompressed.resize(total);
+        ::memcpy(uncompressed.data() + total - have, block, have);
+    } while (ret != Z_STREAM_END);
+
+    return total;
+}
+
+bool Compression::isOpen() const {
+    ai_assert(mImpl != nullptr);
+
+    return mImpl->mOpen;
+}
+
+bool Compression::close() {
+    ai_assert(mImpl != nullptr);
+
+    if (!mImpl->mOpen) {
+        return false;
+    }
+
+    inflateEnd(&mImpl->mZSstream);
+    mImpl->mOpen = false;
+
+    return true;
+}
+
+} // namespace Assimp
diff --git a/code/Common/Compression.h b/code/Common/Compression.h
new file mode 100644
index 0000000000000000000000000000000000000000..20c92cb60fd3f6a5d36a6af3b1c9f38580af3815
--- /dev/null
+++ b/code/Common/Compression.h
@@ -0,0 +1,80 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2022, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+#pragma once
+
+#include <vector>
+
+namespace Assimp {
+
+/// @brief This class provides the decompression of zlib-compressed data.
+class Compression {
+public:
+    /// @brief  The class constructor.
+    Compression();
+
+    ///	@brief  The class destructor.
+    ~Compression();
+
+    /// @brief  Will open the access to the compression.
+    /// @return true if close was successful, false if not.
+    bool open();
+
+    /// @brief  Will return the open state.
+    /// @return true if the access is opened, false if not.
+    bool isOpen() const;
+
+    /// @brief  Will close the decompress access.
+    /// @return true if close was successful, false if not.
+    bool close();
+
+    /// @brief Will decompress the data buffer.
+    /// @param[in] data         The data to decompress
+    /// @param[in] in           The size of the data.
+    /// @param[out uncompressed A std::vector containing the decompressed data.
+    size_t decompress(unsigned char *data, size_t in, std::vector<unsigned char> &uncompressed);
+
+private:
+    struct impl;
+    impl *mImpl;
+};
+
+} // namespace Assimp
diff --git a/code/Common/IOSystem.cpp b/code/Common/IOSystem.cpp
index 77305d1932c47f0c1ec13b59888fd88fc6d8010b..1e63827ba47baa4398c5f1dd3f3af77774e27dfe 100644
--- a/code/Common/IOSystem.cpp
+++ b/code/Common/IOSystem.cpp
@@ -3,7 +3,7 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2019, assimp team
+Copyright (c) 2006-2022, assimp team
 
 All rights reserved.
 
diff --git a/code/Common/material.cpp b/code/Common/material.cpp
index 8f791a3131b2e392bf5f7364a03ea64012fcc734..a7541d4f1f0c2920b965ecc85d242df24ae22634 100644
--- a/code/Common/material.cpp
+++ b/code/Common/material.cpp
@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2022, assimp team
 
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
diff --git a/code/Common/simd.cpp b/code/Common/simd.cpp
index 9eb547f9ac96f0aa00fe3f0d4a78bf903b74b959..0dd437d267383adab9771531622f38d4c643dc63 100644
--- a/code/Common/simd.cpp
+++ b/code/Common/simd.cpp
@@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2022, assimp team
 
-
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
diff --git a/include/assimp/Base64.hpp b/include/assimp/Base64.hpp
index 894eb449bfce2db06ca03753ebe803ef0c2e2e4d..ee319aceb89b3af820e28aaac60c489ab29953f0 100644
--- a/include/assimp/Base64.hpp
+++ b/include/assimp/Base64.hpp
@@ -50,6 +50,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 namespace Assimp {
 namespace Base64 {
 
+/// @brief Will encode the given 
+/// @param in 
+/// @param inLength 
+/// @param out 
 void Encode(const uint8_t *in, size_t inLength, std::string &out);
 void Encode(const std::vector<uint8_t>& in, std::string &out);
 std::string Encode(const std::vector<uint8_t>& in);