Fix compression for fbx
parent
23b43d1825
commit
3e09d462fa
|
@ -175,7 +175,7 @@ void BlenderImporter::InternReadFile(const std::string &pFile,
|
||||||
|
|
||||||
size_t total = 0;
|
size_t total = 0;
|
||||||
Compression compression;
|
Compression compression;
|
||||||
if (compression.open(Compression::Format::Binary)) {
|
if (compression.open(Compression::Format::Binary, Compression::FlushMode::Finish) ) {
|
||||||
total = compression.decompress((unsigned char *)reader->GetPtr(), reader->GetRemainingSize(), uncompressed);
|
total = compression.decompress((unsigned char *)reader->GetPtr(), reader->GetRemainingSize(), uncompressed);
|
||||||
compression.close();
|
compression.close();
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
|
||||||
|
|
||||||
Copyright (c) 2006-2022, assimp team
|
Copyright (c) 2006-2022, assimp team
|
||||||
|
|
||||||
|
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use of this software in source and binary forms,
|
Redistribution and use of this software in source and binary forms,
|
||||||
|
@ -48,10 +47,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
//#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
|
//#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
|
||||||
#include "Common/Compression.h"
|
#include "Common/Compression.h"
|
||||||
/*# include <zlib.h>
|
//# include <zlib.h>
|
||||||
#else
|
//#else
|
||||||
# include "../contrib/zlib/zlib.h"
|
//# include "../contrib/zlib/zlib.h"
|
||||||
#endif*/
|
//#endif
|
||||||
|
|
||||||
#include "FBXTokenizer.h"
|
#include "FBXTokenizer.h"
|
||||||
#include "FBXParser.h"
|
#include "FBXParser.h"
|
||||||
|
@ -116,9 +115,7 @@ namespace Assimp {
|
||||||
namespace FBX {
|
namespace FBX {
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
Element::Element(const Token& key_token, Parser& parser)
|
Element::Element(const Token& key_token, Parser& parser) : key_token(key_token) {
|
||||||
: key_token(key_token)
|
|
||||||
{
|
|
||||||
TokenPtr n = nullptr;
|
TokenPtr n = nullptr;
|
||||||
do {
|
do {
|
||||||
n = parser.AdvanceToNextToken();
|
n = parser.AdvanceToNextToken();
|
||||||
|
@ -211,8 +208,7 @@ Scope::Scope(Parser& parser,bool topLevel)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
Scope::~Scope()
|
Scope::~Scope() {
|
||||||
{
|
|
||||||
for(ElementMap::value_type& v : elements) {
|
for(ElementMap::value_type& v : elements) {
|
||||||
delete v.second;
|
delete v.second;
|
||||||
}
|
}
|
||||||
|
@ -528,9 +524,7 @@ void ReadBinaryDataArrayHead(const char*& data, const char* end, char& type, uin
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// read binary data array, assume cursor points to the 'compression mode' field (i.e. behind the header)
|
// read binary data array, assume cursor points to the 'compression mode' field (i.e. behind the header)
|
||||||
void ReadBinaryDataArray(char type, uint32_t count, const char*& data, const char* end,
|
void ReadBinaryDataArray(char type, uint32_t count, const char*& data, const char* end,
|
||||||
std::vector<char>& buff,
|
std::vector<char>& buff, const Element& /*el*/) {
|
||||||
const Element& /*el*/)
|
|
||||||
{
|
|
||||||
BE_NCONST uint32_t encmode = SafeParse<uint32_t>(data, end);
|
BE_NCONST uint32_t encmode = SafeParse<uint32_t>(data, end);
|
||||||
AI_SWAP4(encmode);
|
AI_SWAP4(encmode);
|
||||||
data += 4;
|
data += 4;
|
||||||
|
@ -572,11 +566,12 @@ void ReadBinaryDataArray(char type, uint32_t count, const char*& data, const cha
|
||||||
else if(encmode == 1) {
|
else if(encmode == 1) {
|
||||||
// zlib/deflate, next comes ZIP head (0x78 0x01)
|
// zlib/deflate, next comes ZIP head (0x78 0x01)
|
||||||
// see http://www.ietf.org/rfc/rfc1950.txt
|
// see http://www.ietf.org/rfc/rfc1950.txt
|
||||||
Compression compress;
|
Compression compress;
|
||||||
if (compress.open(Compression::Format::Binary)) {
|
if (compress.open(Compression::Format::Binary, Compression::FlushMode::Finish)) {
|
||||||
compress.decompress(data, comp_len, buff);
|
compress.decompress(data, comp_len, buff);
|
||||||
|
compress.close();
|
||||||
}
|
}
|
||||||
/* z_stream zstream;
|
/* z_stream zstream = {};
|
||||||
zstream.opaque = Z_NULL;
|
zstream.opaque = Z_NULL;
|
||||||
zstream.zalloc = Z_NULL;
|
zstream.zalloc = Z_NULL;
|
||||||
zstream.zfree = Z_NULL;
|
zstream.zfree = Z_NULL;
|
||||||
|
@ -585,9 +580,9 @@ void ReadBinaryDataArray(char type, uint32_t count, const char*& data, const cha
|
||||||
// http://hewgill.com/journal/entries/349-how-to-decompress-gzip-stream-with-zlib
|
// http://hewgill.com/journal/entries/349-how-to-decompress-gzip-stream-with-zlib
|
||||||
if(Z_OK != inflateInit(&zstream)) {
|
if(Z_OK != inflateInit(&zstream)) {
|
||||||
ParseError("failure initializing zlib");
|
ParseError("failure initializing zlib");
|
||||||
}*/
|
}
|
||||||
|
|
||||||
/* zstream.next_in = reinterpret_cast<Bytef *>(const_cast<char *>(data));
|
zstream.next_in = reinterpret_cast<Bytef *>(const_cast<char *>(data));
|
||||||
zstream.avail_in = comp_len;
|
zstream.avail_in = comp_len;
|
||||||
|
|
||||||
zstream.avail_out = static_cast<uInt>(buff.size());
|
zstream.avail_out = static_cast<uInt>(buff.size());
|
||||||
|
@ -705,7 +700,6 @@ void ParseVectorDataArray(std::vector<aiVector3D>& out, const Element& el)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// read an array of color4 tuples
|
// read an array of color4 tuples
|
||||||
void ParseVectorDataArray(std::vector<aiColor4D>& out, const Element& el)
|
void ParseVectorDataArray(std::vector<aiColor4D>& out, const Element& el)
|
||||||
|
@ -790,8 +784,7 @@ void ParseVectorDataArray(std::vector<aiColor4D>& out, const Element& el)
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// read an array of float2 tuples
|
// read an array of float2 tuples
|
||||||
void ParseVectorDataArray(std::vector<aiVector2D>& out, const Element& el)
|
void ParseVectorDataArray(std::vector<aiVector2D>& out, const Element& el) {
|
||||||
{
|
|
||||||
out.resize( 0 );
|
out.resize( 0 );
|
||||||
const TokenList& tok = el.Tokens();
|
const TokenList& tok = el.Tokens();
|
||||||
if(tok.empty()) {
|
if(tok.empty()) {
|
||||||
|
@ -835,8 +828,7 @@ void ParseVectorDataArray(std::vector<aiVector2D>& out, const Element& el)
|
||||||
out.push_back(aiVector2D(static_cast<float>(d[0]),
|
out.push_back(aiVector2D(static_cast<float>(d[0]),
|
||||||
static_cast<float>(d[1])));
|
static_cast<float>(d[1])));
|
||||||
}
|
}
|
||||||
}
|
} else if (type == 'f') {
|
||||||
else if (type == 'f') {
|
|
||||||
const float* f = reinterpret_cast<const float*>(&buff[0]);
|
const float* f = reinterpret_cast<const float*>(&buff[0]);
|
||||||
for (unsigned int i = 0; i < count2; ++i, f += 2) {
|
for (unsigned int i = 0; i < count2; ++i, f += 2) {
|
||||||
out.push_back(aiVector2D(f[0],f[1]));
|
out.push_back(aiVector2D(f[0],f[1]));
|
||||||
|
@ -869,8 +861,7 @@ void ParseVectorDataArray(std::vector<aiVector2D>& out, const Element& el)
|
||||||
|
|
||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
// read an array of ints
|
// read an array of ints
|
||||||
void ParseVectorDataArray(std::vector<int>& out, const Element& el)
|
void ParseVectorDataArray(std::vector<int>& out, const Element& el) {
|
||||||
{
|
|
||||||
out.resize( 0 );
|
out.resize( 0 );
|
||||||
const TokenList& tok = el.Tokens();
|
const TokenList& tok = el.Tokens();
|
||||||
if(tok.empty()) {
|
if(tok.empty()) {
|
||||||
|
|
|
@ -188,7 +188,7 @@ XFileParser::XFileParser(const std::vector<char> &pBuffer) :
|
||||||
Compression compression;
|
Compression compression;
|
||||||
uncompressed.resize(est_out + 1);
|
uncompressed.resize(est_out + 1);
|
||||||
char *out = &uncompressed.front();
|
char *out = &uncompressed.front();
|
||||||
if (compression.open(mIsBinaryFormat ? Compression::Format::Binary : Compression::Format::ASCII)) {
|
if (compression.open(mIsBinaryFormat ? Compression::Format::Binary : Compression::Format::ASCII, Compression::FlushMode::SyncFlush)) {
|
||||||
while (mP + 3 < mEnd) {
|
while (mP + 3 < mEnd) {
|
||||||
uint16_t ofs = *((uint16_t *)mP);
|
uint16_t ofs = *((uint16_t *)mP);
|
||||||
AI_SWAP2(ofs);
|
AI_SWAP2(ofs);
|
||||||
|
@ -238,8 +238,9 @@ void XFileParser::ParseFile() {
|
||||||
while (running) {
|
while (running) {
|
||||||
// read name of next object
|
// read name of next object
|
||||||
std::string objectName = GetNextToken();
|
std::string objectName = GetNextToken();
|
||||||
if (objectName.length() == 0)
|
if (objectName.length() == 0) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// parse specific object
|
// parse specific object
|
||||||
if (objectName == "template")
|
if (objectName == "template")
|
||||||
|
|
|
@ -130,13 +130,13 @@ void XGLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
|
||||||
#else
|
#else
|
||||||
std::unique_ptr<StreamReaderLE> raw_reader(new StreamReaderLE(stream));
|
std::unique_ptr<StreamReaderLE> raw_reader(new StreamReaderLE(stream));
|
||||||
|
|
||||||
Compression c;
|
Compression compression;
|
||||||
size_t total = 0l;
|
size_t total = 0l;
|
||||||
if (c.open(Compression::Format::Binary)) {
|
if (compression.open(Compression::Format::Binary, Compression::FlushMode::NoFlush)) {
|
||||||
// skip two extra bytes, zgl files do carry a crc16 upfront (I think)
|
// skip two extra bytes, zgl files do carry a crc16 upfront (I think)
|
||||||
raw_reader->IncPtr(2);
|
raw_reader->IncPtr(2);
|
||||||
total = c.decompress((unsigned char *)raw_reader->GetPtr(), raw_reader->GetRemainingSize(), uncompressed);
|
total = compression.decompress((unsigned char *)raw_reader->GetPtr(), raw_reader->GetRemainingSize(), uncompressed);
|
||||||
c.close();
|
compression.close();
|
||||||
}
|
}
|
||||||
// replace the input stream with a memory stream
|
// replace the input stream with a memory stream
|
||||||
stream.reset(new MemoryIOStream(reinterpret_cast<uint8_t *>(uncompressed.data()), total));
|
stream.reset(new MemoryIOStream(reinterpret_cast<uint8_t *>(uncompressed.data()), total));
|
||||||
|
|
|
@ -54,9 +54,12 @@ namespace Assimp {
|
||||||
struct Compression::impl {
|
struct Compression::impl {
|
||||||
bool mOpen;
|
bool mOpen;
|
||||||
z_stream mZSstream;
|
z_stream mZSstream;
|
||||||
|
FlushMode mFlushMode;
|
||||||
impl() :
|
impl() :
|
||||||
mOpen(false) {}
|
mOpen(false),
|
||||||
|
mFlushMode(Compression::FlushMode::NoFlush) {
|
||||||
|
// empty
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Compression::Compression() :
|
Compression::Compression() :
|
||||||
|
@ -70,7 +73,7 @@ Compression::~Compression() {
|
||||||
delete mImpl;
|
delete mImpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Compression::open(Format format) {
|
bool Compression::open(Format format, FlushMode flush) {
|
||||||
ai_assert(mImpl != nullptr);
|
ai_assert(mImpl != nullptr);
|
||||||
|
|
||||||
if (mImpl->mOpen) {
|
if (mImpl->mOpen) {
|
||||||
|
@ -81,6 +84,7 @@ bool Compression::open(Format format) {
|
||||||
mImpl->mZSstream.opaque = Z_NULL;
|
mImpl->mZSstream.opaque = Z_NULL;
|
||||||
mImpl->mZSstream.zalloc = Z_NULL;
|
mImpl->mZSstream.zalloc = Z_NULL;
|
||||||
mImpl->mZSstream.zfree = Z_NULL;
|
mImpl->mZSstream.zfree = Z_NULL;
|
||||||
|
mImpl->mFlushMode = flush;
|
||||||
if (format == Format::Binary) {
|
if (format == Format::Binary) {
|
||||||
mImpl->mZSstream.data_type = Z_BINARY;
|
mImpl->mZSstream.data_type = Z_BINARY;
|
||||||
} else {
|
} else {
|
||||||
|
@ -88,7 +92,7 @@ bool Compression::open(Format format) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// raw decompression without a zlib or gzip header
|
// raw decompression without a zlib or gzip header
|
||||||
inflateInit2(&mImpl->mZSstream, -MAX_WBITS);
|
inflateInit(&mImpl->mZSstream);
|
||||||
mImpl->mOpen = true;
|
mImpl->mOpen = true;
|
||||||
|
|
||||||
return mImpl->mOpen;
|
return mImpl->mOpen;
|
||||||
|
@ -96,30 +100,62 @@ bool Compression::open(Format format) {
|
||||||
|
|
||||||
constexpr size_t MYBLOCK = 32786;
|
constexpr size_t MYBLOCK = 32786;
|
||||||
|
|
||||||
|
static int getFlushMode(Compression::FlushMode flush) {
|
||||||
|
int z_flush = 0;
|
||||||
|
switch (flush) {
|
||||||
|
case Compression::FlushMode::NoFlush:
|
||||||
|
z_flush = Z_NO_FLUSH;
|
||||||
|
break;
|
||||||
|
case Compression::FlushMode::SyncFlush:
|
||||||
|
z_flush = Z_SYNC_FLUSH;
|
||||||
|
break;
|
||||||
|
case Compression::FlushMode::Finish:
|
||||||
|
z_flush = Z_FINISH;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ai_assert(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return z_flush;
|
||||||
|
}
|
||||||
|
|
||||||
size_t Compression::decompress(const void *data, size_t in, std::vector<char> &uncompressed) {
|
size_t Compression::decompress(const void *data, size_t in, std::vector<char> &uncompressed) {
|
||||||
ai_assert(mImpl != nullptr);
|
ai_assert(mImpl != nullptr);
|
||||||
|
|
||||||
mImpl->mZSstream.next_in = (Bytef*)(data);
|
mImpl->mZSstream.next_in = (Bytef*)(data);
|
||||||
mImpl->mZSstream.avail_in = (uInt)in;
|
mImpl->mZSstream.avail_in = (uInt)in;
|
||||||
|
|
||||||
Bytef block[MYBLOCK] = {};
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
size_t total = 0l;
|
size_t total = 0l;
|
||||||
do {
|
|
||||||
mImpl->mZSstream.avail_out = MYBLOCK;
|
const int flushMode = getFlushMode(mImpl->mFlushMode);
|
||||||
mImpl->mZSstream.next_out = block;
|
if (flushMode == Z_FINISH) {
|
||||||
|
mImpl->mZSstream.avail_out = static_cast<uInt>(uncompressed.size());
|
||||||
ret = inflate(&mImpl->mZSstream, Z_NO_FLUSH);
|
mImpl->mZSstream.next_out = reinterpret_cast<Bytef *>(&*uncompressed.begin());
|
||||||
|
ret = inflate(&mImpl->mZSstream, Z_FINISH);
|
||||||
|
|
||||||
if (ret != Z_STREAM_END && ret != Z_OK) {
|
if (ret != Z_STREAM_END && ret != Z_OK) {
|
||||||
throw DeadlyImportError("Compression", "Failure decompressing this file using gzip.");
|
throw DeadlyImportError("Compression", "Failure decompressing this file using gzip.");
|
||||||
|
|
||||||
}
|
}
|
||||||
const size_t have = MYBLOCK - mImpl->mZSstream.avail_out;
|
total = mImpl->mZSstream.avail_out;
|
||||||
total += have;
|
} else {
|
||||||
uncompressed.resize(total);
|
do {
|
||||||
::memcpy(uncompressed.data() + total - have, block, have);
|
Bytef block[MYBLOCK] = {};
|
||||||
} while (ret != Z_STREAM_END);
|
mImpl->mZSstream.avail_out = MYBLOCK;
|
||||||
|
mImpl->mZSstream.next_out = block;
|
||||||
|
|
||||||
|
ret = inflate(&mImpl->mZSstream, flushMode);
|
||||||
|
|
||||||
|
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;
|
return total;
|
||||||
}
|
}
|
||||||
|
@ -140,11 +176,6 @@ size_t Compression::decompressBlock(const void *data, size_t in, char *out, size
|
||||||
::inflateReset(&mImpl->mZSstream);
|
::inflateReset(&mImpl->mZSstream);
|
||||||
::inflateSetDictionary(&mImpl->mZSstream, (const Bytef *)out, (uInt)availableOut - mImpl->mZSstream.avail_out);
|
::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;
|
return availableOut - (size_t)mImpl->mZSstream.avail_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -55,6 +55,16 @@ public:
|
||||||
NumFormats,
|
NumFormats,
|
||||||
InvalidFormat
|
InvalidFormat
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class FlushMode {
|
||||||
|
NoFlush = 0,
|
||||||
|
SyncFlush,
|
||||||
|
Finish,
|
||||||
|
|
||||||
|
NumModes,
|
||||||
|
InvalidMode
|
||||||
|
};
|
||||||
|
|
||||||
/// @brief The class constructor.
|
/// @brief The class constructor.
|
||||||
Compression();
|
Compression();
|
||||||
|
|
||||||
|
@ -63,7 +73,7 @@ public:
|
||||||
|
|
||||||
/// @brief Will open the access to the compression.
|
/// @brief Will open the access to the compression.
|
||||||
/// @return true if close was successful, false if not.
|
/// @return true if close was successful, false if not.
|
||||||
bool open(Format format);
|
bool open(Format format, FlushMode flush);
|
||||||
|
|
||||||
/// @brief Will return the open state.
|
/// @brief Will return the open state.
|
||||||
/// @return true if the access is opened, false if not.
|
/// @return true if the access is opened, false if not.
|
||||||
|
|
|
@ -53,7 +53,7 @@ using namespace Assimp;
|
||||||
|
|
||||||
class utFBXImporterExporter : public AbstractImportExportBase {
|
class utFBXImporterExporter : public AbstractImportExportBase {
|
||||||
public:
|
public:
|
||||||
virtual bool importerTest() {
|
bool importerTest() override {
|
||||||
Assimp::Importer importer;
|
Assimp::Importer importer;
|
||||||
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/FBX/spider.fbx", aiProcess_ValidateDataStructure);
|
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/FBX/spider.fbx", aiProcess_ValidateDataStructure);
|
||||||
return nullptr != scene;
|
return nullptr != scene;
|
||||||
|
|
Loading…
Reference in New Issue