From f5b4e1da37ed8be7ae00b35415969bdaa149aac9 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 16 May 2014 10:00:35 -0700 Subject: [PATCH 1/4] fix potential floating point error when animations have no frames --- libraries/models/src/ModelItem.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/libraries/models/src/ModelItem.cpp b/libraries/models/src/ModelItem.cpp index c04f9a76ae..3dd1c99e60 100644 --- a/libraries/models/src/ModelItem.cpp +++ b/libraries/models/src/ModelItem.cpp @@ -714,6 +714,7 @@ void ModelItem::mapJoints(const QStringList& modelJointNames) { if (!_jointMappingCompleted) { QStringList animationJointNames = myAnimation->getJointNames(); + if (modelJointNames.size() > 0 && animationJointNames.size() > 0) { _jointMapping.resize(modelJointNames.size()); for (int i = 0; i < modelJointNames.size(); i++) { @@ -729,13 +730,17 @@ QVector ModelItem::getAnimationFrame() { if (hasAnimation() && _jointMappingCompleted) { Animation* myAnimation = getAnimation(_animationURL); QVector frames = myAnimation->getFrames(); - int animationFrameIndex = (int)std::floor(_animationFrameIndex) % frames.size(); - QVector rotations = frames[animationFrameIndex].rotations; - frameData.resize(_jointMapping.size()); - for (int j = 0; j < _jointMapping.size(); j++) { - int rotationIndex = _jointMapping[j]; - if (rotationIndex != -1 && rotationIndex < rotations.size()) { - frameData[j] = rotations[rotationIndex]; + int frameCount = frames.size(); + + if (frameCount > 0) { + int animationFrameIndex = (int)glm::floor(_animationFrameIndex) % frameCount; + QVector rotations = frames[animationFrameIndex].rotations; + frameData.resize(_jointMapping.size()); + for (int j = 0; j < _jointMapping.size(); j++) { + int rotationIndex = _jointMapping[j]; + if (rotationIndex != -1 && rotationIndex < rotations.size()) { + frameData[j] = rotations[rotationIndex]; + } } } } From 0e446d0fc5d2e2a0f90fc6d25539fa93a2621a0a Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 16 May 2014 16:53:14 -0700 Subject: [PATCH 2/4] fix two bugs in models not rendering --- libraries/models/src/ModelTree.cpp | 8 +++++++- libraries/models/src/ModelTree.h | 2 ++ libraries/octree/src/Octree.cpp | 15 ++++----------- libraries/octree/src/Octree.h | 2 ++ 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/libraries/models/src/ModelTree.cpp b/libraries/models/src/ModelTree.cpp index 4e92544f40..637079560b 100644 --- a/libraries/models/src/ModelTree.cpp +++ b/libraries/models/src/ModelTree.cpp @@ -108,6 +108,7 @@ bool FindAndUpdateModelOperator::PostRecursion(OctreeElement* element) { return !_found; // if we haven't yet found it, keep looking } +// TODO: improve this to not use multiple recursions void ModelTree::storeModel(const ModelItem& model, const SharedNodePointer& senderNode) { // First, look for the existing model in the tree.. FindAndUpdateModelOperator theOperator(model); @@ -118,8 +119,13 @@ void ModelTree::storeModel(const ModelItem& model, const SharedNodePointer& send AABox modelBox = model.getAABox(); ModelTreeElement* element = (ModelTreeElement*)getOrCreateChildElementContaining(model.getAABox()); element->storeModel(model); + + // In the case where we stored it, we also need to mark the entire "path" down to the model as + // having changed. Otherwise viewers won't see this change. So we call this recursion now that + // we know it will be found, this find/update will correctly mark the tree as changed. + recurseTreeWithOperator(&theOperator); } - // what else do we need to do here to get reaveraging to work + _isDirty = true; } diff --git a/libraries/models/src/ModelTree.h b/libraries/models/src/ModelTree.h index 10ef62c0a0..ddd8417db7 100644 --- a/libraries/models/src/ModelTree.h +++ b/libraries/models/src/ModelTree.h @@ -41,6 +41,8 @@ public: virtual int processEditPacketData(PacketType packetType, const unsigned char* packetData, int packetLength, const unsigned char* editData, int maxLength, const SharedNodePointer& senderNode); + virtual bool recurseChildrenWithData() const { return false; } + virtual void update(); void storeModel(const ModelItem& model, const SharedNodePointer& senderNode = SharedNodePointer()); diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 128677ff2b..b352096673 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -1389,6 +1389,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element, keepDiggingDeeper = (inViewNotLeafCount > 0); if (continueThisLevel && keepDiggingDeeper) { + // at this point, we need to iterate the children who are in view, even if not colored // and we need to determine if there's a deeper tree below them that we care about. // @@ -1424,6 +1425,8 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element, int childTreeBytesOut = 0; + // TODO - UPDATE THIS COMMENT!!! + // // XXXBHG - Note, this seems like the correct logic here, if we included the color in this packet, then // the LOD logic determined that the child nodes would not be visible... and if so, we shouldn't recurse // them further. But... for some time now the code has included and recursed into these child nodes, which @@ -1433,7 +1436,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element, // // This only applies in the view frustum case, in other cases, like file save and copy/past where // no viewFrustum was requested, we still want to recurse the child tree. - if (!params.viewFrustum || !oneAtBit(childrenColoredBits, originalIndex)) { + if (recurseChildrenWithData() || !params.viewFrustum || !oneAtBit(childrenColoredBits, originalIndex)) { childTreeBytesOut = encodeTreeBitstreamRecursion(childElement, packetData, bag, params, thisLevel, nodeLocationThisView); } @@ -1519,16 +1522,6 @@ 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... - /** - printf("This Level's BitMasks: childInTree:"); - outputBits(childrenExistInTreeBits, false, true); - printf(" childInPacket:"); - outputBits(childrenExistInPacketBits, false, true); - printf(" childrenColored:"); - outputBits(childrenColoredBits, false, true); - qDebug(""); - **/ - // 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 84212586f8..1e71884faa 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -209,6 +209,8 @@ public: virtual bool handlesEditPacketType(PacketType packetType) const { return false; } virtual int processEditPacketData(PacketType packetType, const unsigned char* packetData, int packetLength, const unsigned char* editData, int maxLength, const SharedNodePointer& sourceNode) { return 0; } + + virtual bool recurseChildrenWithData() const { return true; } virtual void update() { }; // nothing to do by default From 51ad8194de98883647eb34143be9becac550c265 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 16 May 2014 16:55:37 -0700 Subject: [PATCH 3/4] fix two bugs in models not rendering --- libraries/octree/src/Octree.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index b352096673..3042626a51 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -1425,8 +1425,6 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element, int childTreeBytesOut = 0; - // TODO - UPDATE THIS COMMENT!!! - // // XXXBHG - Note, this seems like the correct logic here, if we included the color in this packet, then // the LOD logic determined that the child nodes would not be visible... and if so, we shouldn't recurse // them further. But... for some time now the code has included and recursed into these child nodes, which @@ -1436,6 +1434,11 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElement* element, // // This only applies in the view frustum case, in other cases, like file save and copy/past where // no viewFrustum was requested, we still want to recurse the child tree. + // + // NOTE: some octree styles (like models and particles) will store content in parent elements, and child + // elements. In this case, if we stop recursion when we include any data (the colorbits should really be + // called databits), then we wouldn't send the children. So those types of Octree's should tell us to keep + // recursing, by returning TRUE in recurseChildrenWithData(). if (recurseChildrenWithData() || !params.viewFrustum || !oneAtBit(childrenColoredBits, originalIndex)) { childTreeBytesOut = encodeTreeBitstreamRecursion(childElement, packetData, bag, params, thisLevel, nodeLocationThisView); From bb204154a11527e010fe872076fa21e8b2a155fb Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 16 May 2014 16:59:58 -0700 Subject: [PATCH 4/4] tweak --- libraries/models/src/ModelTree.h | 2 -- libraries/voxels/src/VoxelTree.h | 1 + 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/libraries/models/src/ModelTree.h b/libraries/models/src/ModelTree.h index ddd8417db7..10ef62c0a0 100644 --- a/libraries/models/src/ModelTree.h +++ b/libraries/models/src/ModelTree.h @@ -41,8 +41,6 @@ public: virtual int processEditPacketData(PacketType packetType, const unsigned char* packetData, int packetLength, const unsigned char* editData, int maxLength, const SharedNodePointer& senderNode); - virtual bool recurseChildrenWithData() const { return false; } - virtual void update(); void storeModel(const ModelItem& model, const SharedNodePointer& senderNode = SharedNodePointer()); diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index 2915774fe3..03d07a1649 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -55,6 +55,7 @@ public: virtual bool handlesEditPacketType(PacketType packetType) const; virtual int processEditPacketData(PacketType packetType, const unsigned char* packetData, int packetLength, const unsigned char* editData, int maxLength, const SharedNodePointer& node); + virtual bool recurseChildrenWithData() const { return false; } private: // helper functions for nudgeSubTree