Переглянути джерело

Fix X-Importer decompress algorithm

Kim Kulling 3 роки тому
батько
коміт
23b43d1825
3 змінених файлів з 42 додано та 63 видалено
  1. 15 63
      code/AssetLib/X/XFileParser.cpp
  2. 25 0
      code/Common/Compression.cpp
  3. 2 0
      code/Common/Compression.h

+ 15 - 63
code/AssetLib/X/XFileParser.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,
@@ -60,26 +58,11 @@ using namespace Assimp::Formatter;
 
 #ifndef ASSIMP_BUILD_NO_COMPRESSED_X
 
-/* #ifdef ASSIMP_BUILD_NO_OWN_ZLIB
-#include <zlib.h>
-#else
-#include "../contrib/zlib/zlib.h"
-#endif*/
 #include "Common/Compression.h"
 
 // Magic identifier for MSZIP compressed data
-#define MSZIP_MAGIC 0x4B43
-#define MSZIP_BLOCK 32786
-
-// ------------------------------------------------------------------------------------------------
-// Dummy memory wrappers for use with zlib
-/* static void *dummy_alloc(void * opaque, unsigned int items, unsigned int size) {
-    return ::operator new(items *size);
-}
-
-static void dummy_free(void * opaque, void *address) {
-    return ::operator delete(address);
-}*/
+constexpr unsigned int MSZIP_MAGIC = 0x4B43;
+constexpr size_t MSZIP_BLOCK = 32786l;
 
 #endif // !! ASSIMP_BUILD_NO_COMPRESSED_X
 
@@ -172,17 +155,6 @@ XFileParser::XFileParser(const std::vector<char> &pBuffer) :
          * ///////////////////////////////////////////////////////////////////////
          */
 
-        Compression compression;
-        // build a zlib stream
-        /* z_stream stream;
-        stream.opaque = nullptr;
-        stream.zalloc = &dummy_alloc;
-        stream.zfree = &dummy_free;
-        stream.data_type = (mIsBinaryFormat ? Z_BINARY : Z_ASCII);
-
-        // initialize the inflation algorithm
-        ::inflateInit2(&stream, -MAX_WBITS);*/
-
         // skip unknown data (checksum, flags?)
         mP += 6;
 
@@ -211,46 +183,26 @@ XFileParser::XFileParser(const std::vector<char> &pBuffer) :
             P1 += ofs;
             est_out += MSZIP_BLOCK; // one decompressed block is 32786 in size
         }
-
+        
         // Allocate storage and terminating zero and do the actual uncompressing
+        Compression compression;
         uncompressed.resize(est_out + 1);
         char *out = &uncompressed.front();
-        
         if (compression.open(mIsBinaryFormat ? Compression::Format::Binary : Compression::Format::ASCII)) {
-            compression.decompress(mP, std::distance(mP, mEnd-3), uncompressed);
-            compression.close();
-        }
-        /* while (mP + 3 < mEnd) {
-            uint16_t ofs = *((uint16_t *)mP);
-            AI_SWAP2(ofs);
-            mP += 4;
+            while (mP + 3 < mEnd) {
+                uint16_t ofs = *((uint16_t *)mP);
+                AI_SWAP2(ofs);
+                mP += 4;
 
-            if (mP + ofs > mEnd + 2) {
-                throw DeadlyImportError("X: Unexpected EOF in compressed chunk");
+                if (mP + ofs > mEnd + 2) {
+                    throw DeadlyImportError("X: Unexpected EOF in compressed chunk");
+                }
+                out += compression.decompressBlock(mP, ofs, out, MSZIP_BLOCK);
+                mP += ofs;
             }
-
-            // push data to the stream
-            stream.next_in = (Bytef *)mP;
-            stream.avail_in = ofs;
-            stream.next_out = (Bytef *)out;
-            stream.avail_out = MSZIP_BLOCK;
-
-            // and decompress the data ....
-            int ret = ::inflate(&stream, Z_SYNC_FLUSH);
-            if (ret != Z_OK && ret != Z_STREAM_END)
-                throw DeadlyImportError("X: Failed to decompress MSZIP-compressed data");
-
-            ::inflateReset(&stream);
-            ::inflateSetDictionary(&stream, (const Bytef *)out, MSZIP_BLOCK - stream.avail_out);
-
-            // and advance to the next offset
-            out += MSZIP_BLOCK - stream.avail_out;
-            mP += ofs;
+            compression.close();
         }
 
-        // terminate zlib
-        ::inflateEnd(&stream);*/
-
         // ok, update pointers to point to the uncompressed file data
         mP = &uncompressed[0];
         mEnd = out;
@@ -507,7 +459,7 @@ void XFileParser::ParseDataObjectSkinWeights(Mesh *pMesh) {
     bone.mWeights.reserve(numWeights);
 
     for (unsigned int a = 0; a < numWeights; a++) {
-        BoneWeight weight;
+        BoneWeight weight = {};
         weight.mVertex = ReadInt();
         bone.mWeights.push_back(weight);
     }

+ 25 - 0
code/Common/Compression.cpp

@@ -108,6 +108,7 @@ size_t Compression::decompress(const void *data, size_t in, std::vector<char> &u
     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) {
@@ -123,6 +124,30 @@ size_t Compression::decompress(const void *data, size_t in, std::vector<char> &u
     return total;
 }
 
+size_t Compression::decompressBlock(const void *data, size_t in, char *out, size_t availableOut) {
+
+    // push data to the stream
+    mImpl->mZSstream.next_in = (Bytef *)data;
+    mImpl->mZSstream.avail_in = (uInt)in;
+    mImpl->mZSstream.next_out = (Bytef *)out;
+    mImpl->mZSstream.avail_out = (uInt)availableOut;
+
+    // and decompress the data ....
+    int ret = ::inflate(&mImpl->mZSstream, Z_SYNC_FLUSH);
+    if (ret != Z_OK && ret != Z_STREAM_END)
+        throw DeadlyImportError("X: Failed to decompress MSZIP-compressed data");
+
+    ::inflateReset(&mImpl->mZSstream);
+    ::inflateSetDictionary(&mImpl->mZSstream, (const Bytef *)out, (uInt)availableOut - mImpl->mZSstream.avail_out);
+
+
+
+    ::inflateReset(&mImpl->mZSstream);
+    ::inflateSetDictionary(&mImpl->mZSstream, (const Bytef *)out, (uInt)availableOut - mImpl->mZSstream.avail_out);
+
+    return availableOut - (size_t)mImpl->mZSstream.avail_out;
+}
+
 bool Compression::isOpen() const {
     ai_assert(mImpl != nullptr);
 

+ 2 - 0
code/Common/Compression.h

@@ -79,6 +79,8 @@ public:
     /// @param[out uncompressed A std::vector containing the decompressed data.
     size_t decompress(const void *data, size_t in, std::vector<char> &uncompressed);
 
+    size_t decompressBlock(const void *data, size_t in, char *out, size_t availableOut);
+
 private:
     struct impl;
     impl *mImpl;