From 379306204530c1afa5e81649ee61ec329c973637 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 13 Sep 2017 09:51:06 -0700 Subject: [PATCH 1/5] Add optional FBX 2015 encoding to FBXWriter --- libraries/fbx/src/FBX.h | 1 + libraries/fbx/src/FBXWriter.cpp | 26 ++++++++++++++++++++------ libraries/fbx/src/FBXWriter.h | 2 ++ 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/libraries/fbx/src/FBX.h b/libraries/fbx/src/FBX.h index 9f5fad7d66..6af23a0151 100644 --- a/libraries/fbx/src/FBX.h +++ b/libraries/fbx/src/FBX.h @@ -30,6 +30,7 @@ static const QByteArray FBX_BINARY_PROLOG = "Kaydara FBX Binary "; static const int FBX_HEADER_BYTES_BEFORE_VERSION = 23; +static const quint32 FBX_VERSION_2015 = 7400; static const quint32 FBX_VERSION_2016 = 7500; diff --git a/libraries/fbx/src/FBXWriter.cpp b/libraries/fbx/src/FBXWriter.cpp index 7195d2abb4..764d8df6cf 100644 --- a/libraries/fbx/src/FBXWriter.cpp +++ b/libraries/fbx/src/FBXWriter.cpp @@ -13,6 +13,16 @@ #include +#ifdef USE_FBX_2016_FORMAT + using FBXEndOffset = int64_t; + using FBXPropertyCount = uint64_t; + using FBXListLength = uint64_t; +#else + using FBXEndOffset = int32_t; + using FBXPropertyCount = uint32_t; + using FBXListLength = uint32_t; +#endif + template void writeVector(QDataStream& out, char ch, QVector list) { out.device()->write(&ch, 1); @@ -34,7 +44,11 @@ QByteArray FBXWriter::encodeFBX(const FBXNode& root) { auto bytes = QByteArray(FBX_HEADER_BYTES_BEFORE_VERSION - FBX_BINARY_PROLOG.size(), '\0'); out.writeRawData(bytes, bytes.size()); +#ifdef USE_FBX_2016_FORMAT out << FBX_VERSION_2016; +#else + out << FBX_VERSION_2015; +#endif for (auto& child : root.children) { encodeNode(out, child); @@ -51,13 +65,13 @@ void FBXWriter::encodeNode(QDataStream& out, const FBXNode& node) { auto nodeStartPos = device->pos(); // endOffset (temporary, updated later) - out << (qint64)0; + out << (FBXEndOffset)0; // Property count - out << (quint64)node.properties.size(); + out << (FBXPropertyCount)node.properties.size(); // Property list length (temporary, updated later) - out << (quint64)0; + out << (FBXListLength)0; out << (quint8)node.name.size(); out.writeRawData(node.name, node.name.size()); @@ -70,8 +84,8 @@ void FBXWriter::encodeNode(QDataStream& out, const FBXNode& node) { // Go back and write property list length auto nodePropertiesEndPos = device->pos(); - device->seek(nodeStartPos + sizeof(qint64) + sizeof(quint64)); - out << (quint64)(nodePropertiesEndPos - nodePropertiesStartPos); + device->seek(nodeStartPos + sizeof(FBXEndOffset) + sizeof(FBXPropertyCount)); + out << (FBXListLength)(nodePropertiesEndPos - nodePropertiesStartPos); device->seek(nodePropertiesEndPos); @@ -86,7 +100,7 @@ void FBXWriter::encodeNode(QDataStream& out, const FBXNode& node) { // Go back and write actual endOffset auto nodeEndPos = device->pos(); device->seek(nodeStartPos); - out << (qint64)(nodeEndPos); + out << (FBXEndOffset)(nodeEndPos); device->seek(nodeEndPos); } diff --git a/libraries/fbx/src/FBXWriter.h b/libraries/fbx/src/FBXWriter.h index fa33983345..57c33e0e1c 100644 --- a/libraries/fbx/src/FBXWriter.h +++ b/libraries/fbx/src/FBXWriter.h @@ -17,6 +17,8 @@ #include #include +#define USE_FBX_2016_FORMAT + class FBXWriter { public: static QByteArray encodeFBX(const FBXNode& root); From 7db8d1dcbc3f66c1da75281cadd27fc121d0b7b7 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 14 Sep 2017 14:29:54 -0700 Subject: [PATCH 2/5] Add support for baked skinned meshes --- libraries/baking/src/FBXBaker.cpp | 21 +++++++++++++---- libraries/fbx/src/FBX.h | 2 ++ libraries/fbx/src/FBXReader.h | 2 +- libraries/fbx/src/FBXReader_Mesh.cpp | 34 +++++++++++++++++++--------- libraries/fbx/src/FBXWriter.cpp | 9 +++++--- 5 files changed, 48 insertions(+), 20 deletions(-) diff --git a/libraries/baking/src/FBXBaker.cpp b/libraries/baking/src/FBXBaker.cpp index 791d89e503..380e893c9b 100644 --- a/libraries/baking/src/FBXBaker.cpp +++ b/libraries/baking/src/FBXBaker.cpp @@ -298,7 +298,7 @@ void FBXBaker::rewriteAndBakeSceneModels() { if (objectChild.name == "Geometry") { // TODO Pull this out of _geometry instead so we don't have to reprocess it - auto extractedMesh = FBXReader::extractMesh(objectChild, meshIndex); + auto extractedMesh = FBXReader::extractMesh(objectChild, meshIndex, false); auto& mesh = extractedMesh.mesh; Q_ASSERT(mesh.normals.size() == 0 || mesh.normals.size() == mesh.vertices.size()); @@ -338,6 +338,9 @@ void FBXBaker::rewriteAndBakeSceneModels() { const int positionAttributeID = meshBuilder.AddAttribute(draco::GeometryAttribute::POSITION, 3, draco::DT_FLOAT32); + const int originalIndexAttributeID = meshBuilder.AddAttribute( + (draco::GeometryAttribute::Type)DRACO_ATTRIBUTE_ORIGINAL_INDEX, + 1, draco::DT_INT32); if (hasNormals) { normalsAttributeID = meshBuilder.AddAttribute(draco::GeometryAttribute::NORMAL, @@ -367,14 +370,14 @@ void FBXBaker::rewriteAndBakeSceneModels() { draco::FaceIndex face; for (auto& part : mesh.parts) { const auto& matTex = extractedMesh.partMaterialTextures[partIndex]; + uint16_t materialID = matTex.first; auto addFace = [&](QVector& indices, int index, draco::FaceIndex face) { - auto idx0 = indices[index]; - auto idx1 = indices[index + 1]; - auto idx2 = indices[index + 2]; + int32_t idx0 = indices[index]; + int32_t idx1 = indices[index + 1]; + int32_t idx2 = indices[index + 2]; if (hasPerFaceMaterials) { - uint16_t materialID = matTex.first; meshBuilder.SetPerFaceAttributeValueForFace(faceMaterialAttributeID, face, &materialID); } @@ -382,6 +385,12 @@ void FBXBaker::rewriteAndBakeSceneModels() { &mesh.vertices[idx0], &mesh.vertices[idx1], &mesh.vertices[idx2]); + if (originalIndexAttributeID) { + meshBuilder.SetAttributeValuesForFace(originalIndexAttributeID, face, + &mesh.originalIndex[idx0], + &mesh.originalIndex[idx1], + &mesh.originalIndex[idx2]); + } if (hasNormals) { meshBuilder.SetAttributeValuesForFace(normalsAttributeID, face, &mesh.normals[idx0], &mesh.normals[idx1], @@ -432,6 +441,8 @@ void FBXBaker::rewriteAndBakeSceneModels() { dracoMesh->attribute(texCoords1AttributeID)->set_unique_id(DRACO_ATTRIBUTE_TEX_COORD_1); } + dracoMesh->attribute(originalIndexAttributeID)->set_unique_id(DRACO_ATTRIBUTE_ORIGINAL_INDEX); + draco::Encoder encoder; encoder.SetAttributeQuantization(draco::GeometryAttribute::POSITION, 14); diff --git a/libraries/fbx/src/FBX.h b/libraries/fbx/src/FBX.h index 6af23a0151..78d35889cf 100644 --- a/libraries/fbx/src/FBX.h +++ b/libraries/fbx/src/FBX.h @@ -38,6 +38,7 @@ static const quint32 FBX_VERSION_2016 = 7500; static const int DRACO_BEGIN_CUSTOM_HIFI_ATTRIBUTES = 1000; static const int DRACO_ATTRIBUTE_MATERIAL_ID = DRACO_BEGIN_CUSTOM_HIFI_ATTRIBUTES; static const int DRACO_ATTRIBUTE_TEX_COORD_1 = DRACO_BEGIN_CUSTOM_HIFI_ATTRIBUTES + 1; +static const int DRACO_ATTRIBUTE_ORIGINAL_INDEX = DRACO_BEGIN_CUSTOM_HIFI_ATTRIBUTES + 2; class FBXNode; @@ -217,6 +218,7 @@ public: QVector parts; QVector vertices; + QVector originalIndex; QVector normals; QVector tangents; QVector colors; diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 8a5e394da9..843a874a62 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -110,7 +110,7 @@ public: FBXGeometry* extractFBXGeometry(const QVariantHash& mapping, const QString& url); - static ExtractedMesh extractMesh(const FBXNode& object, unsigned int& meshIndex); + static ExtractedMesh extractMesh(const FBXNode& object, unsigned int& meshIndex, bool deduplicate = true); QHash meshes; static void buildModelMesh(FBXMesh& extractedMesh, const QString& url); diff --git a/libraries/fbx/src/FBXReader_Mesh.cpp b/libraries/fbx/src/FBXReader_Mesh.cpp index bef36770a0..3d70fa45ae 100644 --- a/libraries/fbx/src/FBXReader_Mesh.cpp +++ b/libraries/fbx/src/FBXReader_Mesh.cpp @@ -84,7 +84,7 @@ public: }; -void appendIndex(MeshData& data, QVector& indices, int index) { +void appendIndex(MeshData& data, QVector& indices, int index, bool deduplicate) { if (index >= data.polygonIndices.size()) { return; } @@ -156,12 +156,13 @@ void appendIndex(MeshData& data, QVector& indices, int index) { } QHash::const_iterator it = data.indices.find(vertex); - if (it == data.indices.constEnd()) { + if (!deduplicate || it == data.indices.constEnd()) { int newIndex = data.extracted.mesh.vertices.size(); indices.append(newIndex); data.indices.insert(vertex, newIndex); data.extracted.newIndices.insert(vertexIndex, newIndex); data.extracted.mesh.vertices.append(position); + data.extracted.mesh.originalIndices.append(vertexIndex); data.extracted.mesh.normals.append(normal); data.extracted.mesh.texCoords.append(vertex.texCoord); if (hasColors) { @@ -176,7 +177,7 @@ void appendIndex(MeshData& data, QVector& indices, int index) { } } -ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIndex) { +ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIndex, bool deduplicate) { MeshData data; data.extracted.mesh.meshIndex = meshIndex++; @@ -355,6 +356,7 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn auto extraTexCoordAttribute = dracoMesh->GetAttributeByUniqueId(DRACO_ATTRIBUTE_TEX_COORD_1); auto colorAttribute = dracoMesh->GetNamedAttribute(draco::GeometryAttribute::COLOR); auto matTexAttribute = dracoMesh->GetAttributeByUniqueId(DRACO_ATTRIBUTE_MATERIAL_ID); + auto originalIndexAttribute = dracoMesh->GetAttributeByUniqueId(DRACO_ATTRIBUTE_ORIGINAL_INDEX); // setup extracted mesh data structures given number of points auto numVertices = dracoMesh->num_points(); @@ -423,7 +425,17 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn reinterpret_cast(&data.extracted.mesh.colors[i])); } - data.extracted.newIndices.insert(i, i); + if (originalIndexAttribute) { + auto mappedIndex = originalIndexAttribute->mapped_index(vertexIndex); + + int32_t originalIndex; + + originalIndexAttribute->ConvertValue(mappedIndex, &originalIndex); + + data.extracted.newIndices.insert(originalIndex, i); + } else { + data.extracted.newIndices.insert(i, i); + } } for (int i = 0; i < dracoMesh->num_faces(); ++i) { @@ -487,10 +499,10 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn FBXMeshPart& part = data.extracted.mesh.parts[partIndex - 1]; if (endIndex - beginIndex == 4) { - appendIndex(data, part.quadIndices, beginIndex++); - appendIndex(data, part.quadIndices, beginIndex++); - appendIndex(data, part.quadIndices, beginIndex++); - appendIndex(data, part.quadIndices, beginIndex++); + appendIndex(data, part.quadIndices, beginIndex++, deduplicate); + appendIndex(data, part.quadIndices, beginIndex++, deduplicate); + appendIndex(data, part.quadIndices, beginIndex++, deduplicate); + appendIndex(data, part.quadIndices, beginIndex++, deduplicate); int quadStartIndex = part.quadIndices.size() - 4; int i0 = part.quadIndices[quadStartIndex + 0]; @@ -515,9 +527,9 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn } else { for (int nextIndex = beginIndex + 1;; ) { - appendIndex(data, part.triangleIndices, beginIndex); - appendIndex(data, part.triangleIndices, nextIndex++); - appendIndex(data, part.triangleIndices, nextIndex); + appendIndex(data, part.triangleIndices, beginIndex, deduplicate); + appendIndex(data, part.triangleIndices, nextIndex++, deduplicate); + appendIndex(data, part.triangleIndices, nextIndex, deduplicate); if (nextIndex >= data.polygonIndices.size() || data.polygonIndices.at(nextIndex) < 0) { break; } diff --git a/libraries/fbx/src/FBXWriter.cpp b/libraries/fbx/src/FBXWriter.cpp index 764d8df6cf..f7bf3517f6 100644 --- a/libraries/fbx/src/FBXWriter.cpp +++ b/libraries/fbx/src/FBXWriter.cpp @@ -59,8 +59,6 @@ QByteArray FBXWriter::encodeFBX(const FBXNode& root) { } void FBXWriter::encodeNode(QDataStream& out, const FBXNode& node) { - qDebug() << "Encoding " << node.name; - auto device = out.device(); auto nodeStartPos = device->pos(); @@ -108,8 +106,12 @@ void FBXWriter::encodeNode(QDataStream& out, const FBXNode& node) { void FBXWriter::encodeFBXProperty(QDataStream& out, const QVariant& prop) { auto type = prop.userType(); switch (type) { - case QVariant::Type::Bool: + case QMetaType::Short: + out.device()->write("Y", 1); + out << prop.value(); + break; + case QVariant::Type::Bool: out.device()->write("C", 1); out << prop.toBool(); break; @@ -229,6 +231,7 @@ void FBXWriter::encodeFBXProperty(QDataStream& out, const QVariant& prop) { writeVector(out, 'b', prop.value>()); } else { qDebug() << "Unsupported property type in FBXWriter::encodeNode: " << type << prop; + throw("Unsupported property type in FBXWriter::encodeNode: " + QString::number(type) + " " + prop.toString()); } } From fd1d4b9bd1e9a518e48e48c0971b3501c82cea66 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 14 Sep 2017 16:49:53 -0700 Subject: [PATCH 3/5] Update FBXBaker to only pack original indices if needed --- libraries/baking/src/FBXBaker.cpp | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/libraries/baking/src/FBXBaker.cpp b/libraries/baking/src/FBXBaker.cpp index 380e893c9b..46f3df7493 100644 --- a/libraries/baking/src/FBXBaker.cpp +++ b/libraries/baking/src/FBXBaker.cpp @@ -292,6 +292,20 @@ QUrl FBXBaker::getTextureURL(const QFileInfo& textureFileInfo, QString relativeF void FBXBaker::rewriteAndBakeSceneModels() { unsigned int meshIndex = 0; + bool hasDeformers { false }; + for (FBXNode& rootChild : _rootNode.children) { + if (rootChild.name == "Objects") { + for (FBXNode& objectChild : rootChild.children) { + if (objectChild.name == "Deformer") { + hasDeformers = true; + break; + } + } + } + if (hasDeformers) { + break; + } + } for (FBXNode& rootChild : _rootNode.children) { if (rootChild.name == "Objects") { for (FBXNode& objectChild : rootChild.children) { @@ -329,18 +343,22 @@ void FBXBaker::rewriteAndBakeSceneModels() { bool hasTexCoords { mesh.texCoords.size() > 0 }; bool hasTexCoords1 { mesh.texCoords1.size() > 0 }; bool hasPerFaceMaterials { mesh.parts.size() > 1 }; + bool needsOriginalIndices { hasDeformers }; int normalsAttributeID { -1 }; int colorsAttributeID { -1 }; int texCoordsAttributeID { -1 }; int texCoords1AttributeID { -1 }; int faceMaterialAttributeID { -1 }; + int originalIndexAttributeID { -1 }; const int positionAttributeID = meshBuilder.AddAttribute(draco::GeometryAttribute::POSITION, 3, draco::DT_FLOAT32); - const int originalIndexAttributeID = meshBuilder.AddAttribute( - (draco::GeometryAttribute::Type)DRACO_ATTRIBUTE_ORIGINAL_INDEX, - 1, draco::DT_INT32); + if (needsOriginalIndices) { + originalIndexAttributeID = meshBuilder.AddAttribute( + (draco::GeometryAttribute::Type)DRACO_ATTRIBUTE_ORIGINAL_INDEX, + 1, draco::DT_INT32); + } if (hasNormals) { normalsAttributeID = meshBuilder.AddAttribute(draco::GeometryAttribute::NORMAL, @@ -385,7 +403,7 @@ void FBXBaker::rewriteAndBakeSceneModels() { &mesh.vertices[idx0], &mesh.vertices[idx1], &mesh.vertices[idx2]); - if (originalIndexAttributeID) { + if (needsOriginalIndices) { meshBuilder.SetAttributeValuesForFace(originalIndexAttributeID, face, &mesh.originalIndex[idx0], &mesh.originalIndex[idx1], @@ -441,7 +459,9 @@ void FBXBaker::rewriteAndBakeSceneModels() { dracoMesh->attribute(texCoords1AttributeID)->set_unique_id(DRACO_ATTRIBUTE_TEX_COORD_1); } - dracoMesh->attribute(originalIndexAttributeID)->set_unique_id(DRACO_ATTRIBUTE_ORIGINAL_INDEX); + if (needsOriginalIndices) { + dracoMesh->attribute(originalIndexAttributeID)->set_unique_id(DRACO_ATTRIBUTE_ORIGINAL_INDEX); + } draco::Encoder encoder; From c5852dfbe81ca620c0bdf6c2b8178e91241ba3f2 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 15 Sep 2017 11:43:06 -0700 Subject: [PATCH 4/5] Add list compression to FBXWriter --- libraries/baking/src/FBXBaker.cpp | 6 ++--- libraries/fbx/src/FBX.h | 6 ++--- libraries/fbx/src/FBXReader_Mesh.cpp | 8 +++---- libraries/fbx/src/FBXReader_Node.cpp | 6 ++--- libraries/fbx/src/FBXWriter.cpp | 33 +++++++++++++++++++++++----- libraries/fbx/src/FBXWriter.h | 2 +- 6 files changed, 40 insertions(+), 21 deletions(-) diff --git a/libraries/baking/src/FBXBaker.cpp b/libraries/baking/src/FBXBaker.cpp index 46f3df7493..aa05a135fd 100644 --- a/libraries/baking/src/FBXBaker.cpp +++ b/libraries/baking/src/FBXBaker.cpp @@ -405,9 +405,9 @@ void FBXBaker::rewriteAndBakeSceneModels() { if (needsOriginalIndices) { meshBuilder.SetAttributeValuesForFace(originalIndexAttributeID, face, - &mesh.originalIndex[idx0], - &mesh.originalIndex[idx1], - &mesh.originalIndex[idx2]); + &mesh.originalIndices[idx0], + &mesh.originalIndices[idx1], + &mesh.originalIndices[idx2]); } if (hasNormals) { meshBuilder.SetAttributeValuesForFace(normalsAttributeID, face, diff --git a/libraries/fbx/src/FBX.h b/libraries/fbx/src/FBX.h index 78d35889cf..836195f125 100644 --- a/libraries/fbx/src/FBX.h +++ b/libraries/fbx/src/FBX.h @@ -33,13 +33,13 @@ static const int FBX_HEADER_BYTES_BEFORE_VERSION = 23; static const quint32 FBX_VERSION_2015 = 7400; static const quint32 FBX_VERSION_2016 = 7500; - -// TODO Convert to GeometryAttribute type static const int DRACO_BEGIN_CUSTOM_HIFI_ATTRIBUTES = 1000; static const int DRACO_ATTRIBUTE_MATERIAL_ID = DRACO_BEGIN_CUSTOM_HIFI_ATTRIBUTES; static const int DRACO_ATTRIBUTE_TEX_COORD_1 = DRACO_BEGIN_CUSTOM_HIFI_ATTRIBUTES + 1; static const int DRACO_ATTRIBUTE_ORIGINAL_INDEX = DRACO_BEGIN_CUSTOM_HIFI_ATTRIBUTES + 2; +static const int32_t FBX_PROPERTY_UNCOMPRESSED_FLAG = 0; +static const int32_t FBX_PROPERTY_COMPRESSED_FLAG = 1; class FBXNode; using FBXNodeList = QList; @@ -218,7 +218,6 @@ public: QVector parts; QVector vertices; - QVector originalIndex; QVector normals; QVector tangents; QVector colors; @@ -226,6 +225,7 @@ public: QVector texCoords1; QVector clusterIndices; QVector clusterWeights; + QVector originalIndices; QVector clusters; diff --git a/libraries/fbx/src/FBXReader_Mesh.cpp b/libraries/fbx/src/FBXReader_Mesh.cpp index 3d70fa45ae..d4b6dde5fe 100644 --- a/libraries/fbx/src/FBXReader_Mesh.cpp +++ b/libraries/fbx/src/FBXReader_Mesh.cpp @@ -355,7 +355,7 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn auto texCoordAttribute = dracoMesh->GetNamedAttribute(draco::GeometryAttribute::TEX_COORD); auto extraTexCoordAttribute = dracoMesh->GetAttributeByUniqueId(DRACO_ATTRIBUTE_TEX_COORD_1); auto colorAttribute = dracoMesh->GetNamedAttribute(draco::GeometryAttribute::COLOR); - auto matTexAttribute = dracoMesh->GetAttributeByUniqueId(DRACO_ATTRIBUTE_MATERIAL_ID); + auto materialIDAttribute = dracoMesh->GetAttributeByUniqueId(DRACO_ATTRIBUTE_MATERIAL_ID); auto originalIndexAttribute = dracoMesh->GetAttributeByUniqueId(DRACO_ATTRIBUTE_ORIGINAL_INDEX); // setup extracted mesh data structures given number of points @@ -445,11 +445,11 @@ ExtractedMesh FBXReader::extractMesh(const FBXNode& object, unsigned int& meshIn uint16_t materialID { 0 }; - if (matTexAttribute) { + if (materialIDAttribute) { // read material ID and texture ID mappings into materials and texture vectors - auto mappedIndex = matTexAttribute->mapped_index(firstCorner); + auto mappedIndex = materialIDAttribute->mapped_index(firstCorner); - matTexAttribute->ConvertValue(mappedIndex, &materialID); + materialIDAttribute->ConvertValue(mappedIndex, &materialID); } QPair materialTexture(materialID, 0); diff --git a/libraries/fbx/src/FBXReader_Node.cpp b/libraries/fbx/src/FBXReader_Node.cpp index 111b4a295a..c4454421b6 100644 --- a/libraries/fbx/src/FBXReader_Node.cpp +++ b/libraries/fbx/src/FBXReader_Node.cpp @@ -48,9 +48,8 @@ QVariant readBinaryArray(QDataStream& in, int& position) { QVector values; if ((int)QSysInfo::ByteOrder == (int)in.byteOrder()) { values.resize(arrayLength); - const unsigned int DEFLATE_ENCODING = 1; QByteArray arrayData; - if (encoding == DEFLATE_ENCODING) { + if (encoding == FBX_PROPERTY_COMPRESSED_FLAG) { // preface encoded data with uncompressed length QByteArray compressed(sizeof(quint32) + compressedLength, 0); *((quint32*)compressed.data()) = qToBigEndian(arrayLength * sizeof(T)); @@ -72,8 +71,7 @@ QVariant readBinaryArray(QDataStream& in, int& position) { } } else { values.reserve(arrayLength); - const unsigned int DEFLATE_ENCODING = 1; - if (encoding == DEFLATE_ENCODING) { + if (encoding == FBX_PROPERTY_COMPRESSED_FLAG) { // preface encoded data with uncompressed length QByteArray compressed(sizeof(quint32) + compressedLength, 0); *((quint32*)compressed.data()) = qToBigEndian(arrayLength * sizeof(T)); diff --git a/libraries/fbx/src/FBXWriter.cpp b/libraries/fbx/src/FBXWriter.cpp index f7bf3517f6..bc0013b9ac 100644 --- a/libraries/fbx/src/FBXWriter.cpp +++ b/libraries/fbx/src/FBXWriter.cpp @@ -24,13 +24,34 @@ #endif template -void writeVector(QDataStream& out, char ch, QVector list) { - out.device()->write(&ch, 1); - out << (int32_t)list.length(); - out << (int32_t)0; - out << (int32_t)0; +void writeVector(QDataStream& out, char ch, QVector vec) { + // Minimum number of bytes to consider compressing + const int ATTEMPT_COMPRESSION_THRESHOLD_BYTES = 2000; - out.writeBytes(reinterpret_cast(list.constData()), list.length() * sizeof(T)); + out.device()->write(&ch, 1); + out << (int32_t)vec.length(); + + auto data { QByteArray::fromRawData((const char*)vec.constData(), vec.length() * sizeof(T)) }; + + if (data.size() >= ATTEMPT_COMPRESSION_THRESHOLD_BYTES) { + auto compressedDataWithLength { qCompress(data) }; + + // qCompress packs a length uint32 at the beginning of the buffer, but the FBX format + // does not expect it. This removes it. + auto compressedData = QByteArray::fromRawData( + compressedDataWithLength.constData() + sizeof(uint32_t), compressedDataWithLength.size() - sizeof(uint32_t)); + + if (compressedData.size() < data.size()) { + out << (int32_t)1; + out << (int32_t)compressedData.size(); + out.writeRawData(compressedData.constData(), compressedData.size()); + return; + } + } + + out << FBX_PROPERTY_UNCOMPRESSED_FLAG; + out << (int32_t)0; + out.writeRawData(data.constData(), data.size()); } diff --git a/libraries/fbx/src/FBXWriter.h b/libraries/fbx/src/FBXWriter.h index 57c33e0e1c..f20d208cb1 100644 --- a/libraries/fbx/src/FBXWriter.h +++ b/libraries/fbx/src/FBXWriter.h @@ -17,7 +17,7 @@ #include #include -#define USE_FBX_2016_FORMAT +//#define USE_FBX_2016_FORMAT class FBXWriter { public: From 2a4f7712c32988ada4b5862f442199fefd837452 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 15 Sep 2017 14:41:38 -0700 Subject: [PATCH 5/5] Replace magic number for compressed flag in FBXWriter --- libraries/fbx/src/FBXWriter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/fbx/src/FBXWriter.cpp b/libraries/fbx/src/FBXWriter.cpp index bc0013b9ac..900fddc0a2 100644 --- a/libraries/fbx/src/FBXWriter.cpp +++ b/libraries/fbx/src/FBXWriter.cpp @@ -42,7 +42,7 @@ void writeVector(QDataStream& out, char ch, QVector vec) { compressedDataWithLength.constData() + sizeof(uint32_t), compressedDataWithLength.size() - sizeof(uint32_t)); if (compressedData.size() < data.size()) { - out << (int32_t)1; + out << FBX_PROPERTY_COMPRESSED_FLAG; out << (int32_t)compressedData.size(); out.writeRawData(compressedData.constData(), compressedData.size()); return;