|
@@ -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>
|
|
@@ -73,6 +74,7 @@ const char *LogFunctions<XGLImporter>::Prefix() {
|
|
|
static auto prefix = "XGL: ";
|
|
|
return prefix;
|
|
|
}
|
|
|
+
|
|
|
} // namespace Assimp
|
|
|
|
|
|
static const aiImporterDesc desc = {
|
|
@@ -137,46 +139,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 +261,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 +446,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 +510,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 +564,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 +738,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");
|