From cbd20f89ddc2b417ad157892bb98e4b512bd5c43 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 11 Sep 2017 10:26:27 -0700 Subject: [PATCH] separate elementBag logic from EntityTreeSendThread --- .../src/entities/EntityTreeSendThread.h | 7 ++- .../src/octree/OctreeSendThread.cpp | 47 ++++++++++--------- .../src/octree/OctreeSendThread.h | 10 +++- 3 files changed, 38 insertions(+), 26 deletions(-) diff --git a/assignment-client/src/entities/EntityTreeSendThread.h b/assignment-client/src/entities/EntityTreeSendThread.h index c9751c5835..72ad2d0b10 100644 --- a/assignment-client/src/entities/EntityTreeSendThread.h +++ b/assignment-client/src/entities/EntityTreeSendThread.h @@ -30,7 +30,6 @@ public: EntityTreeSendThread(OctreeServer* myServer, const SharedNodePointer& node); protected: - void preDistributionProcessing() override; void traverseTreeAndSendContents(SharedNodePointer node, OctreeQueryNode* nodeData, bool viewFrustumChanged, bool isFullScene) override; @@ -42,6 +41,12 @@ private: void startNewTraversal(const ViewFrustum& viewFrustum, EntityTreeElementPointer root, int32_t lodLevelOffset, bool usesViewFrustum); bool traverseTreeAndBuildNextPacketPayload(EncodeBitstreamParams& params, const QJsonObject& jsonFilters) override; + void preDistributionProcessing() override; + bool hasSomethingToSend(OctreeQueryNode* nodeData) override { return !_sendQueue.empty(); } + bool shouldStartNewTraversal(OctreeQueryNode* nodeData, bool viewFrustumChanged) override { return viewFrustumChanged || _traversal.finished(); } + void preStartNewScene(OctreeQueryNode* nodeData, bool isFullScene) override {}; + bool shouldTraverseAndSend(OctreeQueryNode* nodeData) override { return true; } + DiffTraversal _traversal; EntityPriorityQueue _sendQueue; std::unordered_set _entitiesInQueue; diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 5a563037bc..7d209e64dc 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -17,7 +17,6 @@ #include #include -#include "OctreeQueryNode.h" #include "OctreeSendThread.h" #include "OctreeServer.h" #include "OctreeServerConsts.h" @@ -301,9 +300,25 @@ int OctreeSendThread::handlePacketSend(SharedNodePointer node, OctreeQueryNode* return numPackets; } +void OctreeSendThread::preStartNewScene(OctreeQueryNode* nodeData, bool isFullScene) { + // If we're starting a full scene, then definitely we want to empty the elementBag + if (isFullScene) { + nodeData->elementBag.deleteAll(); + } + + // This is the start of "resending" the scene. + bool dontRestartSceneOnMove = false; // this is experimental + if (dontRestartSceneOnMove) { + if (nodeData->elementBag.isEmpty()) { + nodeData->elementBag.insert(_myServer->getOctree()->getRoot()); + } + } else { + nodeData->elementBag.insert(_myServer->getOctree()->getRoot()); + } +} + /// Version of octree element distributor that sends the deepest LOD level at once int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode* nodeData, bool viewFrustumChanged) { - OctreeServer::didPacketDistributor(this); // if shutting down, exit early @@ -311,7 +326,7 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode* return 0; } - if (nodeData->elementBag.isEmpty()) { + if (shouldStartNewTraversal(nodeData, viewFrustumChanged)) { // if we're about to do a fresh pass, // give our pre-distribution processing a chance to do what it needs preDistributionProcessing(); @@ -345,7 +360,7 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode* // If the current view frustum has changed OR we have nothing to send, then search against // the current view frustum for things to send. - if (viewFrustumChanged || nodeData->elementBag.isEmpty()) { + if (shouldStartNewTraversal(nodeData, viewFrustumChanged)) { // if our view has changed, we need to reset these things... if (viewFrustumChanged) { @@ -367,11 +382,6 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode* _packetsSentThisInterval += handlePacketSend(node, nodeData, isFullScene); - // If we're starting a full scene, then definitely we want to empty the elementBag - if (isFullScene) { - nodeData->elementBag.deleteAll(); - } - // TODO: add these to stats page //::startSceneSleepTime = _usleepTime; @@ -380,19 +390,11 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode* nodeData->stats.sceneStarted(isFullScene, viewFrustumChanged, _myServer->getOctree()->getRoot(), _myServer->getJurisdiction()); - // This is the start of "resending" the scene. - bool dontRestartSceneOnMove = false; // this is experimental - if (dontRestartSceneOnMove) { - if (nodeData->elementBag.isEmpty()) { - nodeData->elementBag.insert(_myServer->getOctree()->getRoot()); - } - } else { - nodeData->elementBag.insert(_myServer->getOctree()->getRoot()); - } + preStartNewScene(nodeData, isFullScene); } // If we have something in our elementBag, then turn them into packets and send them out... - if (!nodeData->elementBag.isEmpty()) { + if (shouldTraverseAndSend(nodeData)) { quint64 start = usecTimestampNow(); traverseTreeAndSendContents(node, nodeData, viewFrustumChanged, isFullScene); @@ -441,7 +443,7 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode* // if after sending packets we've emptied our bag, then we want to remember that we've sent all // the octree elements from the current view frustum - if (nodeData->elementBag.isEmpty()) { + if (!hasSomethingToSend(nodeData)) { nodeData->updateLastKnownViewFrustum(); nodeData->setViewSent(true); @@ -502,8 +504,7 @@ void OctreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, Octre EncodeBitstreamParams params(INT_MAX, WANT_EXISTS_BITS, DONT_CHOP, viewFrustumChanged, boundaryLevelAdjust, octreeSizeScale, isFullScene, _myServer->getJurisdiction(), nodeData); - // Our trackSend() function is implemented by the server subclass, and will be called back - // during the encodeTreeBitstream() as new entities/data elements are sent + // Our trackSend() function is implemented by the server subclass, and will be called back as new entities/data elements are sent params.trackSend = [this](const QUuid& dataID, quint64 dataEdited) { _myServer->trackSend(dataID, dataEdited, _nodeUuid); }; @@ -513,7 +514,7 @@ void OctreeSendThread::traverseTreeAndSendContents(SharedNodePointer node, Octre } bool somethingToSend = true; // assume we have something - bool bagHadSomething = !nodeData->elementBag.isEmpty(); + bool bagHadSomething = hasSomethingToSend(nodeData); while (somethingToSend && _packetsSentThisInterval < maxPacketsPerInterval && !nodeData->isShuttingDown()) { float compressAndWriteElapsedUsec = OctreeServer::SKIP_TIME; float packetSendingElapsedUsec = OctreeServer::SKIP_TIME; diff --git a/assignment-client/src/octree/OctreeSendThread.h b/assignment-client/src/octree/OctreeSendThread.h index a6ceba0e95..bc7d2c2588 100644 --- a/assignment-client/src/octree/OctreeSendThread.h +++ b/assignment-client/src/octree/OctreeSendThread.h @@ -19,6 +19,7 @@ #include #include #include +#include "OctreeQueryNode.h" class OctreeQueryNode; class OctreeServer; @@ -51,8 +52,6 @@ protected: /// Implements generic processing behavior for this thread. virtual bool process() override; - /// Called before a packetDistributor pass to allow for pre-distribution processing - virtual void preDistributionProcessing() {}; virtual void traverseTreeAndSendContents(SharedNodePointer node, OctreeQueryNode* nodeData, bool viewFrustumChanged, bool isFullScene); virtual bool traverseTreeAndBuildNextPacketPayload(EncodeBitstreamParams& params, const QJsonObject& jsonFilters); @@ -62,9 +61,16 @@ protected: OctreeServer* _myServer { nullptr }; private: + /// Called before a packetDistributor pass to allow for pre-distribution processing + virtual void preDistributionProcessing() {}; int handlePacketSend(SharedNodePointer node, OctreeQueryNode* nodeData, bool dontSuppressDuplicate = false); int packetDistributor(SharedNodePointer node, OctreeQueryNode* nodeData, bool viewFrustumChanged); + virtual bool hasSomethingToSend(OctreeQueryNode* nodeData) { return !nodeData->elementBag.isEmpty(); } + virtual bool shouldStartNewTraversal(OctreeQueryNode* nodeData, bool viewFrustumChanged) { return viewFrustumChanged || !hasSomethingToSend(nodeData); } + virtual void preStartNewScene(OctreeQueryNode* nodeData, bool isFullScene); + virtual bool shouldTraverseAndSend(OctreeQueryNode* nodeData) { return hasSomethingToSend(nodeData); } + QUuid _nodeUuid; int _truePacketsSent { 0 }; // available for debug stats