From 34cebc36c75024e06c6410ffd5e6b46360615c30 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 11 Jul 2013 09:11:09 -0700 Subject: [PATCH 1/5] short circuit node recursion for delta sending --- libraries/voxels/src/VoxelTree.cpp | 26 +++++++++++++++++++------- voxel-server/src/VoxelNodeData.cpp | 7 +++++-- voxel-server/src/VoxelNodeData.h | 1 + voxel-server/src/main.cpp | 4 +++- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 70bca504cb..3be28e9b93 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -1182,7 +1182,26 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp if (!node->isInView(*params.viewFrustum)) { return bytesAtThisLevel; } + + // Ok, we are in view, but if we're in delta mode, then we also want to make sure we weren't already in view + // because we don't send nodes from the previously know in view frustum. + bool wasInView = false; + + if (params.deltaViewFrustum && params.lastViewFrustum) { + ViewFrustum::location location = node->inFrustum(*params.lastViewFrustum); + + // If we're a leaf, then either intersect or inside is considered "formerly in view" + if (node->isLeaf()) { + wasInView = location != ViewFrustum::OUTSIDE; + } else { + wasInView = location == ViewFrustum::INSIDE; + } + } + // If we were in view, then bail out early! + if (wasInView) { + return bytesAtThisLevel; + } // If the user also asked for occlusion culling, check if this node is occluded, but only if it's not a leaf. // leaf occlusion is handled down below when we check child nodes @@ -1200,16 +1219,9 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp CoverageMapStorageResult result = params.map->checkMap(voxelPolygon, false); delete voxelPolygon; // cleanup if (result == OCCLUDED) { - //node->printDebugDetails("upper section, non-Leaf is occluded!! node="); - //args->nonLeavesOccluded++; - - //args->subtreeVoxelsSkipped += (subArgs.voxelsTouched - 1); - //args->totalVoxels += (subArgs.voxelsTouched - 1); - return bytesAtThisLevel; } } else { - //node->printDebugDetails("upper section, shadow Not in view node="); // If this shadow wasn't "all in view" then we ignored it for occlusion culling, but // we do need to clean up memory and proceed as normal... delete voxelPolygon; diff --git a/voxel-server/src/VoxelNodeData.cpp b/voxel-server/src/VoxelNodeData.cpp index f2cce906cf..a9fc4a8620 100644 --- a/voxel-server/src/VoxelNodeData.cpp +++ b/voxel-server/src/VoxelNodeData.cpp @@ -17,7 +17,8 @@ VoxelNodeData::VoxelNodeData(Node* owningNode) : _voxelPacketAvailableBytes(MAX_VOXEL_PACKET_SIZE), _maxSearchLevel(1), _maxLevelReachedInLastSearch(1), - _lastTimeBagEmpty(0) + _lastTimeBagEmpty(0), + _viewFrustumChanging(false) { _voxelPacket = new unsigned char[MAX_VOXEL_PACKET_SIZE]; _voxelPacketAt = _voxelPacket; @@ -27,7 +28,8 @@ VoxelNodeData::VoxelNodeData(Node* owningNode) : void VoxelNodeData::resetVoxelPacket() { - _voxelPacket[0] = getWantColor() ? PACKET_HEADER_VOXEL_DATA : PACKET_HEADER_VOXEL_DATA_MONOCHROME; + bool wantColor = getWantColor(); + _voxelPacket[0] = wantColor ? PACKET_HEADER_VOXEL_DATA : PACKET_HEADER_VOXEL_DATA_MONOCHROME; _voxelPacketAt = &_voxelPacket[1]; _voxelPacketAvailableBytes = MAX_VOXEL_PACKET_SIZE - 1; _voxelPacketWaiting = false; @@ -63,6 +65,7 @@ bool VoxelNodeData::updateCurrentViewFrustum() { _currentViewFrustum.calculate(); currentViewFrustumChanged = true; } + _viewFrustumChanging = currentViewFrustumChanged; return currentViewFrustumChanged; } diff --git a/voxel-server/src/VoxelNodeData.h b/voxel-server/src/VoxelNodeData.h index bb30372f35..66fa096a3a 100644 --- a/voxel-server/src/VoxelNodeData.h +++ b/voxel-server/src/VoxelNodeData.h @@ -67,6 +67,7 @@ private: ViewFrustum _currentViewFrustum; ViewFrustum _lastKnownViewFrustum; long long _lastTimeBagEmpty; + bool _viewFrustumChanging; }; diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index e71e456359..b6a3833275 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -128,6 +128,8 @@ void deepestLevelVoxelDistributor(NodeList* nodeList, // FOR NOW... node tells us if it wants to receive only view frustum deltas bool wantDelta = viewFrustumChanged && nodeData->getWantDelta(); + bool wantColor = nodeData->getWantColor(); + const ViewFrustum* lastViewFrustum = wantDelta ? &nodeData->getLastKnownViewFrustum() : NULL; if (::debugVoxelSending) { @@ -227,7 +229,7 @@ void deepestLevelVoxelDistributor(NodeList* nodeList, bool wantOcclusionCulling = nodeData->getWantOcclusionCulling(); CoverageMap* coverageMap = wantOcclusionCulling ? &nodeData->map : IGNORE_COVERAGE_MAP; - EncodeBitstreamParams params(INT_MAX, &nodeData->getCurrentViewFrustum(), nodeData->getWantColor(), + EncodeBitstreamParams params(INT_MAX, &nodeData->getCurrentViewFrustum(), wantColor, WANT_EXISTS_BITS, DONT_CHOP, wantDelta, lastViewFrustum, wantOcclusionCulling, coverageMap); From 9aed3d3cc64411e133d8311e7c346d202fb84fca Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 11 Jul 2013 10:37:28 -0700 Subject: [PATCH 2/5] enable delta sending by default --- interface/src/Application.cpp | 6 +++--- interface/src/Application.h | 2 +- libraries/avatars/src/AvatarData.cpp | 2 +- voxel-server/src/main.cpp | 4 +++- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6cde05397c..27acfc3d38 100755 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1235,8 +1235,8 @@ void Application::setWantsMonochrome(bool wantsMonochrome) { _myAvatar.setWantColor(!wantsMonochrome); } -void Application::setWantsDelta(bool wantsDelta) { - _myAvatar.setWantDelta(wantsDelta); +void Application::disableDeltaSending(bool disableDeltaSending) { + _myAvatar.setWantDelta(!disableDeltaSending); } void Application::disableOcclusionCulling(bool disableOcclusionCulling) { @@ -1626,7 +1626,7 @@ void Application::initMenu() { renderDebugMenu->addAction("Show TRUE Colors", this, SLOT(doTrueVoxelColors()), Qt::CTRL | Qt::Key_T); debugMenu->addAction("Wants Monochrome", this, SLOT(setWantsMonochrome(bool)))->setCheckable(true); - debugMenu->addAction("Wants View Delta Sending", this, SLOT(setWantsDelta(bool)))->setCheckable(true); + debugMenu->addAction("Disable Delta Sending", this, SLOT(disableDeltaSending(bool)))->setCheckable(true); (_shouldLowPassFilter = debugMenu->addAction("Test: LowPass filter"))->setCheckable(true); debugMenu->addAction("Disable Occlusion Culling", this, SLOT(disableOcclusionCulling(bool)), Qt::SHIFT | Qt::Key_C)->setCheckable(true); diff --git a/interface/src/Application.h b/interface/src/Application.h index eede6d8cb2..0b65cba6bb 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -136,7 +136,7 @@ private slots: void doTrueVoxelColors(); void doTreeStats(); void setWantsMonochrome(bool wantsMonochrome); - void setWantsDelta(bool wantsDelta); + void disableDeltaSending(bool disableDeltaSending); void disableOcclusionCulling(bool disableOcclusionCulling); void updateVoxelModeActions(); void decreaseVoxelSize(); diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 997d528a5e..7d3c35029c 100755 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -33,7 +33,7 @@ AvatarData::AvatarData(Node* owningNode) : _cameraFarClip(0.0f), _keyState(NO_KEY_DOWN), _wantColor(true), - _wantDelta(false), + _wantDelta(true), _wantOcclusionCulling(true), _headData(NULL), _handData(NULL) diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index e6d8342eb6..608712d8f6 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -151,7 +151,9 @@ void deepestLevelVoxelDistributor(NodeList* nodeList, } else { printf("elapsed time to send scene = %f seconds", elapsedSceneSend); } - printf(" [occlusionCulling: %s]\n", debug::valueOf(nodeData->getWantOcclusionCulling())); + printf(" [occlusionCulling:%s, wantDelta:%s, wantColor:%s ]\n", + debug::valueOf(nodeData->getWantOcclusionCulling()), debug::valueOf(wantDelta), + debug::valueOf(wantColor)); } nodeData->setLastTimeBagEmpty(now); } From 04cd340f0ba32667d733301639b96141522c77b8 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 11 Jul 2013 10:50:17 -0700 Subject: [PATCH 3/5] add back in correct isViewChanging() --- interface/src/VoxelSystem.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 8c7cc40514..f84a1d9678 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -892,13 +892,11 @@ bool VoxelSystem::removeOutOfViewOperation(VoxelNode* node, void* extraData) { bool VoxelSystem::isViewChanging() { bool result = false; // assume the best -/** TEMPORARY HACK ****** // If our viewFrustum has changed since our _lastKnowViewFrustum - if (_viewFrustum && !_lastKnowViewFrustum.matches(_viewFrustum)) { + if (!_lastKnowViewFrustum.matches(Application::getInstance()->getViewFrustum())) { result = true; - _lastKnowViewFrustum = *_viewFrustum; // save last known + _lastKnowViewFrustum = *Application::getInstance()->getViewFrustum(); // save last known } -**/ return result; } From 57ce20d3ce463da3286fa89aac4a188017210b87 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 11 Jul 2013 12:43:43 -0700 Subject: [PATCH 4/5] add support for Low Res sending while moving --- interface/src/Application.cpp | 10 +++++-- interface/src/Application.h | 1 + libraries/avatars/src/AvatarData.cpp | 11 ++++--- libraries/avatars/src/AvatarData.h | 14 +++++---- voxel-server/src/VoxelNodeData.cpp | 10 +++++-- voxel-server/src/VoxelNodeData.h | 2 ++ voxel-server/src/main.cpp | 43 ++++++++++++++++++++++++---- 7 files changed, 72 insertions(+), 19 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 27acfc3d38..a6085c2343 100755 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1231,6 +1231,10 @@ void Application::doTreeStats() { _voxels.collectStatsForTreesAndVBOs(); } +void Application::setWantsLowResMoving(bool wantsLowResMoving) { + _myAvatar.setWantLowResMoving(wantsLowResMoving); +} + void Application::setWantsMonochrome(bool wantsMonochrome) { _myAvatar.setWantColor(!wantsMonochrome); } @@ -1625,9 +1629,11 @@ void Application::initMenu() { renderDebugMenu->addAction("FALSE Color Occluded V2 Voxels", this, SLOT(doFalseColorizeOccludedV2()), Qt::CTRL | Qt::Key_P); renderDebugMenu->addAction("Show TRUE Colors", this, SLOT(doTrueVoxelColors()), Qt::CTRL | Qt::Key_T); - debugMenu->addAction("Wants Monochrome", this, SLOT(setWantsMonochrome(bool)))->setCheckable(true); - debugMenu->addAction("Disable Delta Sending", this, SLOT(disableDeltaSending(bool)))->setCheckable(true); (_shouldLowPassFilter = debugMenu->addAction("Test: LowPass filter"))->setCheckable(true); + + debugMenu->addAction("Wants Monochrome", this, SLOT(setWantsMonochrome(bool)))->setCheckable(true); + debugMenu->addAction("Use Lower Resolution While Moving", this, SLOT(setWantsLowResMoving(bool)))->setCheckable(true); + debugMenu->addAction("Disable Delta Sending", this, SLOT(disableDeltaSending(bool)))->setCheckable(true); debugMenu->addAction("Disable Occlusion Culling", this, SLOT(disableOcclusionCulling(bool)), Qt::SHIFT | Qt::Key_C)->setCheckable(true); diff --git a/interface/src/Application.h b/interface/src/Application.h index 0b65cba6bb..0f80d6b6fd 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -136,6 +136,7 @@ private slots: void doTrueVoxelColors(); void doTreeStats(); void setWantsMonochrome(bool wantsMonochrome); + void setWantsLowResMoving(bool wantsLowResMoving); void disableDeltaSending(bool disableDeltaSending); void disableOcclusionCulling(bool disableOcclusionCulling); void updateVoxelModeActions(); diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index 7d3c35029c..497e3e149b 100755 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -34,6 +34,7 @@ AvatarData::AvatarData(Node* owningNode) : _keyState(NO_KEY_DOWN), _wantColor(true), _wantDelta(true), + _wantLowResMoving(false), _wantOcclusionCulling(true), _headData(NULL), _handData(NULL) @@ -112,8 +113,9 @@ int AvatarData::getBroadcastData(unsigned char* destinationBuffer) { // bitMask of less than byte wide items unsigned char bitItems = 0; - if (_wantColor) { setAtBit(bitItems, WANT_COLOR_AT_BIT); } - if (_wantDelta) { setAtBit(bitItems, WANT_DELTA_AT_BIT); } + if (_wantLowResMoving) { setAtBit(bitItems, WANT_LOW_RES_MOVING_BIT); } + if (_wantColor) { setAtBit(bitItems, WANT_COLOR_AT_BIT); } + if (_wantDelta) { setAtBit(bitItems, WANT_DELTA_AT_BIT); } if (_wantOcclusionCulling) { setAtBit(bitItems, WANT_OCCLUSION_CULLING_BIT); } // key state @@ -238,8 +240,9 @@ int AvatarData::parseData(unsigned char* sourceBuffer, int numBytes) { // voxel sending features... unsigned char bitItems = 0; bitItems = (unsigned char)*sourceBuffer++; - _wantColor = oneAtBit(bitItems, WANT_COLOR_AT_BIT); - _wantDelta = oneAtBit(bitItems, WANT_DELTA_AT_BIT); + _wantLowResMoving = oneAtBit(bitItems, WANT_LOW_RES_MOVING_BIT); + _wantColor = oneAtBit(bitItems, WANT_COLOR_AT_BIT); + _wantDelta = oneAtBit(bitItems, WANT_DELTA_AT_BIT); _wantOcclusionCulling = oneAtBit(bitItems, WANT_OCCLUSION_CULLING_BIT); // key state, stored as a semi-nibble in the bitItems diff --git a/libraries/avatars/src/AvatarData.h b/libraries/avatars/src/AvatarData.h index 218283999e..439ec9b5f8 100755 --- a/libraries/avatars/src/AvatarData.h +++ b/libraries/avatars/src/AvatarData.h @@ -20,7 +20,7 @@ #include "HeadData.h" #include "HandData.h" -const int UNUSED_BIT = 0; // this bit is available to use +const int WANT_LOW_RES_MOVING_BIT = 0; const int WANT_COLOR_AT_BIT = 1; const int WANT_DELTA_AT_BIT = 2; const int KEY_STATE_START_BIT = 3; // 4th and 5th bits @@ -91,11 +91,14 @@ public: const std::string& chatMessage () const { return _chatMessage; } // related to Voxel Sending strategies - bool getWantColor() const { return _wantColor; } - bool getWantDelta() const { return _wantDelta; } + bool getWantColor() const { return _wantColor; } + bool getWantDelta() const { return _wantDelta; } + bool getWantLowResMoving() const { return _wantLowResMoving; } bool getWantOcclusionCulling() const { return _wantOcclusionCulling; } - void setWantColor(bool wantColor) { _wantColor = wantColor; } - void setWantDelta(bool wantDelta) { _wantDelta = wantDelta; } + + void setWantColor(bool wantColor) { _wantColor = wantColor; } + void setWantDelta(bool wantDelta) { _wantDelta = wantDelta; } + void setWantLowResMoving(bool wantLowResMoving) { _wantLowResMoving = wantLowResMoving; } void setWantOcclusionCulling(bool wantOcclusionCulling) { _wantOcclusionCulling = wantOcclusionCulling; } void setHeadData(HeadData* headData) { _headData = headData; } @@ -130,6 +133,7 @@ protected: // voxel server sending items bool _wantColor; bool _wantDelta; + bool _wantLowResMoving; bool _wantOcclusionCulling; std::vector _joints; diff --git a/voxel-server/src/VoxelNodeData.cpp b/voxel-server/src/VoxelNodeData.cpp index a9fc4a8620..e6b721cc06 100644 --- a/voxel-server/src/VoxelNodeData.cpp +++ b/voxel-server/src/VoxelNodeData.cpp @@ -18,7 +18,8 @@ VoxelNodeData::VoxelNodeData(Node* owningNode) : _maxSearchLevel(1), _maxLevelReachedInLastSearch(1), _lastTimeBagEmpty(0), - _viewFrustumChanging(false) + _viewFrustumChanging(false), + _currentPacketIsColor(true) { _voxelPacket = new unsigned char[MAX_VOXEL_PACKET_SIZE]; _voxelPacketAt = _voxelPacket; @@ -28,8 +29,11 @@ VoxelNodeData::VoxelNodeData(Node* owningNode) : void VoxelNodeData::resetVoxelPacket() { - bool wantColor = getWantColor(); - _voxelPacket[0] = wantColor ? PACKET_HEADER_VOXEL_DATA : PACKET_HEADER_VOXEL_DATA_MONOCHROME; + + // If we're moving, and the client asked for low res, then we force monochrome, otherwise, use + // the clients requested color state. + _currentPacketIsColor = (getWantLowResMoving() && _viewFrustumChanging) ? false : getWantColor(); + _voxelPacket[0] = _currentPacketIsColor ? PACKET_HEADER_VOXEL_DATA : PACKET_HEADER_VOXEL_DATA_MONOCHROME; _voxelPacketAt = &_voxelPacket[1]; _voxelPacketAvailableBytes = MAX_VOXEL_PACKET_SIZE - 1; _voxelPacketWaiting = false; diff --git a/voxel-server/src/VoxelNodeData.h b/voxel-server/src/VoxelNodeData.h index c4f3d555cc..0f96a07c3d 100644 --- a/voxel-server/src/VoxelNodeData.h +++ b/voxel-server/src/VoxelNodeData.h @@ -53,6 +53,7 @@ public: uint64_t getLastTimeBagEmpty() const { return _lastTimeBagEmpty; }; void setLastTimeBagEmpty(uint64_t lastTimeBagEmpty) { _lastTimeBagEmpty = lastTimeBagEmpty; }; + bool getCurrentPacketIsColor() const { return _currentPacketIsColor; }; private: VoxelNodeData(const VoxelNodeData &); VoxelNodeData& operator= (const VoxelNodeData&); @@ -68,6 +69,7 @@ private: ViewFrustum _lastKnownViewFrustum; uint64_t _lastTimeBagEmpty; bool _viewFrustumChanging; + bool _currentPacketIsColor; }; #endif /* defined(__hifi__VoxelNodeData__) */ diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index 608712d8f6..e7bed711b2 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -123,11 +123,47 @@ void deepestLevelVoxelDistributor(NodeList* nodeList, int maxLevelReached = 0; uint64_t start = usecTimestampNow(); + int truePacketsSent = 0; + int trueBytesSent = 0; // FOR NOW... node tells us if it wants to receive only view frustum deltas bool wantDelta = viewFrustumChanged && nodeData->getWantDelta(); - bool wantColor = nodeData->getWantColor(); + + // If our packet already has content in it, then we must use the color choice of the waiting packet. + // If we're starting a fresh packet, then... + // If we're moving, and the client asked for low res, then we force monochrome, otherwise, use + // the clients requested color state. + bool wantColor = ((nodeData->getWantLowResMoving() && viewFrustumChanged) ? false : nodeData->getWantColor()); + + // If we have a packet waiting, and our desired want color, doesn't match the current waiting packets color + // then let's just send that waiting packet. + if (wantColor != nodeData->getCurrentPacketIsColor()) { + if (nodeData->isPacketWaiting()) { + if (::debugVoxelSending) { + printf("wantColor=%s --- SENDING PARTIAL PACKET! nodeData->getCurrentPacketIsColor()=%s\n", + debug::valueOf(wantColor), debug::valueOf(nodeData->getCurrentPacketIsColor())); + } + nodeList->getNodeSocket()->send(node->getActiveSocket(), + nodeData->getPacket(), nodeData->getPacketLength()); + trueBytesSent += nodeData->getPacketLength(); + truePacketsSent++; + nodeData->resetVoxelPacket(); + } else { + if (::debugVoxelSending) { + printf("wantColor=%s --- FIXING HEADER! nodeData->getCurrentPacketIsColor()=%s\n", + debug::valueOf(wantColor), debug::valueOf(nodeData->getCurrentPacketIsColor())); + } + nodeData->resetVoxelPacket(); + } + } + + if (::debugVoxelSending) { + printf("wantColor=%s getCurrentPacketIsColor()=%s, viewFrustumChanged=%s, getWantLowResMoving()=%s\n", + debug::valueOf(wantColor), debug::valueOf(nodeData->getCurrentPacketIsColor()), + debug::valueOf(viewFrustumChanged), debug::valueOf(nodeData->getWantLowResMoving())); + } + const ViewFrustum* lastViewFrustum = wantDelta ? &nodeData->getLastKnownViewFrustum() : NULL; if (::debugVoxelSending) { @@ -155,7 +191,7 @@ void deepestLevelVoxelDistributor(NodeList* nodeList, debug::valueOf(nodeData->getWantOcclusionCulling()), debug::valueOf(wantDelta), debug::valueOf(wantColor)); } - nodeData->setLastTimeBagEmpty(now); + nodeData->setLastTimeBagEmpty(now); // huh? why is this inside debug? probably not what we want } // if our view has changed, we need to reset these things... @@ -203,8 +239,6 @@ void deepestLevelVoxelDistributor(NodeList* nodeList, static unsigned char tempOutputBuffer[MAX_VOXEL_PACKET_SIZE - 1]; // save on allocs by making this static int bytesWritten = 0; int packetsSentThisInterval = 0; - int truePacketsSent = 0; - int trueBytesSent = 0; uint64_t start = usecTimestampNow(); bool shouldSendEnvironments = shouldDo(ENVIRONMENT_SEND_INTERVAL_USECS, VOXEL_SEND_INTERVAL_USECS); @@ -258,7 +292,6 @@ void deepestLevelVoxelDistributor(NodeList* nodeList, trueBytesSent += nodeData->getPacketLength(); truePacketsSent++; nodeData->resetVoxelPacket(); - } packetsSentThisInterval = PACKETS_PER_CLIENT_PER_INTERVAL; // done for now, no nodes left } From 241bd7ce377565a8255d999b7d13e23e10b95e26 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 11 Jul 2013 13:16:52 -0700 Subject: [PATCH 5/5] added support for lower LOD when moving with low res moving --- libraries/voxels/src/VoxelTree.cpp | 8 +++++--- libraries/voxels/src/VoxelTree.h | 29 +++++++++++++++++------------ voxel-server/src/main.cpp | 4 +++- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 3be28e9b93..ec93018ddd 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -1169,7 +1169,7 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp // caller can pass NULL as viewFrustum if they want everything if (params.viewFrustum) { float distance = node->distanceToCamera(*params.viewFrustum); - float boundaryDistance = boundaryDistanceForRenderLevel(*node->getOctalCode() + 1); + float boundaryDistance = boundaryDistanceForRenderLevel(node->getLevel() + params.boundaryLevelAdjust); // If we're too far away for our render level, then just return if (distance >= boundaryDistance) { @@ -1297,7 +1297,8 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp if (childIsInView) { // Before we determine consider this further, let's see if it's in our LOD scope... float distance = distancesToChildren[i]; // params.viewFrustum ? childNode->distanceToCamera(*params.viewFrustum) : 0; - float boundaryDistance = params.viewFrustum ? boundaryDistanceForRenderLevel(*childNode->getOctalCode() + 1) : 1; + float boundaryDistance = !params.viewFrustum ? 1 : + boundaryDistanceForRenderLevel(childNode->getLevel() + params.boundaryLevelAdjust); if (distance < boundaryDistance) { inViewCount++; @@ -1353,7 +1354,8 @@ int VoxelTree::encodeTreeBitstreamRecursion(VoxelNode* node, unsigned char* outp if (params.viewFrustum && childNode->isColored() && !childNode->isLeaf()) { int grandChildrenInView = 0; int grandChildrenInLOD = 0; - float grandChildBoundaryDistance = boundaryDistanceForRenderLevel(childNode->getLevel() + 2); + float grandChildBoundaryDistance = boundaryDistanceForRenderLevel(childNode->getLevel() + + 1 + params.boundaryLevelAdjust); for (int grandChildIndex = 0; grandChildIndex < NUMBER_OF_CHILDREN; grandChildIndex++) { VoxelNode* grandChild = childNode->getChildAtIndex(grandChildIndex); diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index a94afe0d79..61f2e13056 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -33,6 +33,8 @@ typedef enum {GRADIENT, RANDOM, NATURAL} creationMode; #define WANT_OCCLUSION_CULLING true #define IGNORE_COVERAGE_MAP NULL #define DONT_CHOP 0 +#define NO_BOUNDARY_ADJUST 0 +#define LOW_RES_MOVING_ADJUST 1 class EncodeBitstreamParams { public: @@ -46,6 +48,7 @@ public: const ViewFrustum* lastViewFrustum; bool wantOcclusionCulling; long childWasInViewDiscarded; + int boundaryLevelAdjust; CoverageMap* map; @@ -58,18 +61,20 @@ public: bool deltaViewFrustum = false, const ViewFrustum* lastViewFrustum = IGNORE_VIEW_FRUSTUM, bool wantOcclusionCulling= NO_OCCLUSION_CULLING, - CoverageMap* map = IGNORE_COVERAGE_MAP) : - maxEncodeLevel (maxEncodeLevel), - maxLevelReached (0), - viewFrustum (viewFrustum), - includeColor (includeColor), - includeExistsBits (includeExistsBits), - chopLevels (chopLevels), - deltaViewFrustum (deltaViewFrustum), - lastViewFrustum (lastViewFrustum), - wantOcclusionCulling(wantOcclusionCulling), - childWasInViewDiscarded(0), - map (map) + CoverageMap* map = IGNORE_COVERAGE_MAP, + int boundaryLevelAdjust = NO_BOUNDARY_ADJUST) : + maxEncodeLevel (maxEncodeLevel), + maxLevelReached (0), + viewFrustum (viewFrustum), + includeColor (includeColor), + includeExistsBits (includeExistsBits), + chopLevels (chopLevels), + deltaViewFrustum (deltaViewFrustum), + lastViewFrustum (lastViewFrustum), + wantOcclusionCulling (wantOcclusionCulling), + childWasInViewDiscarded (0), + boundaryLevelAdjust (boundaryLevelAdjust), + map (map) {} }; diff --git a/voxel-server/src/main.cpp b/voxel-server/src/main.cpp index e7bed711b2..87cf6af890 100644 --- a/voxel-server/src/main.cpp +++ b/voxel-server/src/main.cpp @@ -262,10 +262,12 @@ void deepestLevelVoxelDistributor(NodeList* nodeList, VoxelNode* subTree = nodeData->nodeBag.extract(); bool wantOcclusionCulling = nodeData->getWantOcclusionCulling(); CoverageMap* coverageMap = wantOcclusionCulling ? &nodeData->map : IGNORE_COVERAGE_MAP; + int boundaryLevelAdjust = viewFrustumChanged && nodeData->getWantLowResMoving() + ? LOW_RES_MOVING_ADJUST : NO_BOUNDARY_ADJUST; EncodeBitstreamParams params(INT_MAX, &nodeData->getCurrentViewFrustum(), wantColor, WANT_EXISTS_BITS, DONT_CHOP, wantDelta, lastViewFrustum, - wantOcclusionCulling, coverageMap); + wantOcclusionCulling, coverageMap, boundaryLevelAdjust); bytesWritten = serverTree.encodeTreeBitstream(subTree, &tempOutputBuffer[0], MAX_VOXEL_PACKET_SIZE - 1, nodeData->nodeBag, params);