From 1278470a91de5f7945132bc646d5029e38e6bc28 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 20 May 2014 13:31:08 -0700 Subject: [PATCH 1/5] properly handle FSTs that have translations and rotations --- interface/src/renderer/Model.cpp | 17 ++++++++++++----- libraries/fbx/src/FBXReader.cpp | 1 - libraries/fbx/src/FBXReader.h | 2 -- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 90ae9e5e46..a53d0486ec 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -435,8 +435,12 @@ Extents Model::getMeshExtents() const { return Extents(); } const Extents& extents = _geometry->getFBXGeometry().meshExtents; - glm::vec3 scale = _scale * _geometry->getFBXGeometry().fstScaled; - Extents scaledExtents = { extents.minimum * scale, extents.maximum * scale }; + + // even though our caller asked for "unscaled" we need to include any fst scaling, translation, and rotation, which + // is captured in the offset matrix + glm::vec3 minimum = glm::vec3(_geometry->getFBXGeometry().offset * glm::vec4(extents.minimum, 1.0)); + glm::vec3 maximum = glm::vec3(_geometry->getFBXGeometry().offset * glm::vec4(extents.maximum, 1.0)); + Extents scaledExtents = { minimum * _scale, maximum * _scale }; return scaledExtents; } @@ -447,9 +451,12 @@ Extents Model::getUnscaledMeshExtents() const { const Extents& extents = _geometry->getFBXGeometry().meshExtents; - // even though our caller asked for "unscaled" we need to include any fst scaling - float scale = _geometry->getFBXGeometry().fstScaled; - Extents scaledExtents = { extents.minimum * scale, extents.maximum * scale }; + // even though our caller asked for "unscaled" we need to include any fst scaling, translation, and rotation, which + // is captured in the offset matrix + glm::vec3 minimum = glm::vec3(_geometry->getFBXGeometry().offset * glm::vec4(extents.minimum, 1.0)); + glm::vec3 maximum = glm::vec3(_geometry->getFBXGeometry().offset * glm::vec4(extents.maximum, 1.0)); + Extents scaledExtents = { minimum, maximum }; + return scaledExtents; } diff --git a/libraries/fbx/src/FBXReader.cpp b/libraries/fbx/src/FBXReader.cpp index 44ef3f3aab..897c9b6f98 100644 --- a/libraries/fbx/src/FBXReader.cpp +++ b/libraries/fbx/src/FBXReader.cpp @@ -1399,7 +1399,6 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping) // get offset transform from mapping float offsetScale = mapping.value("scale", 1.0f).toFloat(); - geometry.fstScaled = offsetScale; glm::quat offsetRotation = glm::quat(glm::radians(glm::vec3(mapping.value("rx").toFloat(), mapping.value("ry").toFloat(), mapping.value("rz").toFloat()))); geometry.offset = glm::translate(glm::vec3(mapping.value("tx").toFloat(), mapping.value("ty").toFloat(), diff --git a/libraries/fbx/src/FBXReader.h b/libraries/fbx/src/FBXReader.h index 2aabdab6fa..38251e4065 100644 --- a/libraries/fbx/src/FBXReader.h +++ b/libraries/fbx/src/FBXReader.h @@ -211,8 +211,6 @@ public: Extents bindExtents; Extents meshExtents; - float fstScaled; - QVector animationFrames; QVector attachments; From e7425a81288edb25ee0a78683ae4a74b0ebfdb3b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 20 May 2014 15:20:27 -0700 Subject: [PATCH 2/5] support for models in root element --- libraries/models/src/ModelTree.h | 1 + libraries/networking/src/PacketHeaders.cpp | 6 +++--- libraries/octree/src/Octree.cpp | 24 +++++++++++++++++++++- libraries/octree/src/Octree.h | 1 + 4 files changed, 28 insertions(+), 4 deletions(-) diff --git a/libraries/models/src/ModelTree.h b/libraries/models/src/ModelTree.h index 10ef62c0a0..b8df1c1a22 100644 --- a/libraries/models/src/ModelTree.h +++ b/libraries/models/src/ModelTree.h @@ -41,6 +41,7 @@ public: virtual int processEditPacketData(PacketType packetType, const unsigned char* packetData, int packetLength, const unsigned char* editData, int maxLength, const SharedNodePointer& senderNode); + virtual bool rootElementHasData() const { return true; } virtual void update(); void storeModel(const ModelItem& model, const SharedNodePointer& senderNode = SharedNodePointer()); diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index b9eee6e0c9..0f0b57635c 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -53,8 +53,6 @@ PacketVersion versionForPacketType(PacketType type) { return 1; case PacketTypeEnvironmentData: return 1; - case PacketTypeParticleData: - return 1; case PacketTypeDomainList: case PacketTypeDomainListRequest: return 3; @@ -66,8 +64,10 @@ PacketVersion versionForPacketType(PacketType type) { return 1; case PacketTypeOctreeStats: return 1; + case PacketTypeParticleData: + return 1; case PacketTypeModelData: - return 1; + return 2; default: return 0; } diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 3042626a51..fd0cbcff7c 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -301,6 +301,13 @@ int Octree::readElementData(OctreeElement* destinationElement, const unsigned ch } } } + + // if this is the root, and there is more data to read, allow it to read it's element data... + if (destinationElement == _rootElement && rootElementHasData() && (bytesLeftToRead - bytesRead) > 0) { + // tell the element to read the subsequent data + bytesRead += _rootElement->readElementDataFromBuffer(nodeData + bytesRead, bytesLeftToRead - bytesRead, args); + } + return bytesRead; } @@ -1524,7 +1531,22 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element, } } // end keepDiggingDeeper - // At this point all our BitMasks are complete... so let's output them to see how they compare... + // If we made it this far, then we've written all of our child data... if this element is the root + // element, then we also allow the root element to write out it's data... + if (continueThisLevel && element == _rootElement && rootElementHasData()) { + int bytesBeforeChild = packetData->getUncompressedSize(); + continueThisLevel = element->appendElementData(packetData, params); + int bytesAfterChild = packetData->getUncompressedSize(); + + if (continueThisLevel) { + bytesAtThisLevel += (bytesAfterChild - bytesBeforeChild); // keep track of byte count for this child + + if (params.stats) { + params.stats->colorSent(element); + } + } + } + // if we were unable to fit this level in our packet, then rewind and add it to the element bag for // sending later... if (continueThisLevel) { diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index 1e71884faa..81a9823dd5 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -211,6 +211,7 @@ public: const unsigned char* editData, int maxLength, const SharedNodePointer& sourceNode) { return 0; } virtual bool recurseChildrenWithData() const { return true; } + virtual bool rootElementHasData() const { return false; } virtual void update() { }; // nothing to do by default From 412e870f98916163083e8c4fda35f8b84e365793 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 20 May 2014 15:32:50 -0700 Subject: [PATCH 3/5] add support for backward compatibility in old versions of models.svo --- libraries/models/src/ModelItem.h | 1 + libraries/models/src/ModelTreeElement.cpp | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/libraries/models/src/ModelItem.h b/libraries/models/src/ModelItem.h index 847e58e7c2..838dbc0fc8 100644 --- a/libraries/models/src/ModelItem.h +++ b/libraries/models/src/ModelItem.h @@ -56,6 +56,7 @@ const QString MODEL_DEFAULT_ANIMATION_URL(""); const float MODEL_DEFAULT_ANIMATION_FPS = 30.0f; const PacketVersion VERSION_MODELS_HAVE_ANIMATION = 1; +const PacketVersion VERSION_ROOT_ELEMENT_HAS_DATA = 2; /// A collection of properties of a model item used in the scripting API. Translates between the actual properties of a model /// and a JavaScript style hash/QScriptValue storing a set of properties. Used in scripting to set/get the complete set of diff --git a/libraries/models/src/ModelTreeElement.cpp b/libraries/models/src/ModelTreeElement.cpp index 2f57818044..4929edb484 100644 --- a/libraries/models/src/ModelTreeElement.cpp +++ b/libraries/models/src/ModelTreeElement.cpp @@ -324,6 +324,14 @@ bool ModelTreeElement::removeModelWithID(uint32_t id) { int ModelTreeElement::readElementDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args) { + // If we're the root, but this bitstream doesn't support root elements with data, then + // return without reading any bytes + if (this == _myTree->getRoot() && args.bitstreamVersion < VERSION_ROOT_ELEMENT_HAS_DATA) { + qDebug() << "ROOT ELEMENT: no root data for " + "bitstreamVersion=" << (int)args.bitstreamVersion << " bytesLeftToRead=" << bytesLeftToRead; + return 0; + } + const unsigned char* dataAt = data; int bytesRead = 0; uint16_t numberOfModels = 0; From 22a6e4679a8b0bfaceb6fdfddf23a8838386ec8c Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 20 May 2014 16:19:14 -0700 Subject: [PATCH 4/5] properly discard piggy back packets that don't match expected version --- interface/src/voxels/VoxelPacketProcessor.cpp | 17 +++++++++++++++++ libraries/networking/src/PacketHeaders.h | 4 ++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/interface/src/voxels/VoxelPacketProcessor.cpp b/interface/src/voxels/VoxelPacketProcessor.cpp index 8576f14b16..aedf9e6b41 100644 --- a/interface/src/voxels/VoxelPacketProcessor.cpp +++ b/interface/src/voxels/VoxelPacketProcessor.cpp @@ -61,6 +61,23 @@ void VoxelPacketProcessor::processPacket(const SharedNodePointer& sendingNode, c } // fall through to piggyback message voxelPacketType = packetTypeForPacket(mutablePacket); + PacketVersion packetVersion = mutablePacket[1]; + PacketVersion expectedVersion = versionForPacketType(voxelPacketType); + + // check version of piggyback packet against expected version + if (packetVersion != expectedVersion) { + static QMultiMap versionDebugSuppressMap; + + QUuid senderUUID = uuidFromPacketHeader(packet); + if (!versionDebugSuppressMap.contains(senderUUID, voxelPacketType)) { + qDebug() << "Packet version mismatch on" << voxelPacketType << "- Sender" + << senderUUID << "sent" << (int)packetVersion << "but" + << (int)expectedVersion << "expected."; + + versionDebugSuppressMap.insert(senderUUID, voxelPacketType); + } + } + if (Menu::getInstance()->isOptionChecked(MenuOption::Voxels)) { app->trackIncomingVoxelPacket(mutablePacket, sendingNode, wasStatsPacket); diff --git a/libraries/networking/src/PacketHeaders.h b/libraries/networking/src/PacketHeaders.h index d5b1e8301c..9c764f9f02 100644 --- a/libraries/networking/src/PacketHeaders.h +++ b/libraries/networking/src/PacketHeaders.h @@ -47,7 +47,7 @@ enum PacketType { PacketTypeVoxelSet, PacketTypeVoxelSetDestructive, PacketTypeVoxelErase, - PacketTypeOctreeStats, + PacketTypeOctreeStats, // 26 PacketTypeJurisdiction, PacketTypeJurisdictionRequest, PacketTypeParticleQuery, @@ -62,7 +62,7 @@ enum PacketType { PacketTypeDomainServerRequireDTLS, PacketTypeNodeJsonStats, PacketTypeModelQuery, - PacketTypeModelData, + PacketTypeModelData, // 41 PacketTypeModelAddOrEdit, PacketTypeModelErase, PacketTypeModelAddResponse, From 2665f3af67b45739c9022914c1aecfdaaeeeeb16 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 20 May 2014 16:31:03 -0700 Subject: [PATCH 5/5] properly bail on version mismatch --- interface/src/voxels/VoxelPacketProcessor.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/voxels/VoxelPacketProcessor.cpp b/interface/src/voxels/VoxelPacketProcessor.cpp index aedf9e6b41..c0f27264f6 100644 --- a/interface/src/voxels/VoxelPacketProcessor.cpp +++ b/interface/src/voxels/VoxelPacketProcessor.cpp @@ -76,6 +76,7 @@ void VoxelPacketProcessor::processPacket(const SharedNodePointer& sendingNode, c versionDebugSuppressMap.insert(senderUUID, voxelPacketType); } + return; // bail since piggyback version doesn't match }