From 5d18b68a2e8bf05744b9358dadd4c111f432e54b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 23 Oct 2013 10:14:41 -0700 Subject: [PATCH 1/2] added support for forceFullFrustum in hideOutOfView() this fixes inconcistancies with voxel hiding showing --- interface/src/Menu.cpp | 2 +- interface/src/Menu.h | 4 +- interface/src/VoxelSystem.cpp | 85 ++++++++++++++++++++++++----------- interface/src/VoxelSystem.h | 4 +- 4 files changed, 65 insertions(+), 30 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 9f7f3138c9..f4886aefde 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -289,8 +289,8 @@ Menu::Menu() : addDisabledActionAndSeparator(cullingOptionsMenu, "Individual Option Settings"); addCheckableActionToQMenuAndActionHash(cullingOptionsMenu, MenuOption::DisableFastVoxelPipeline, 0, false, appInstance->getVoxels(), SLOT(setDisableFastVoxelPipeline(bool))); - addCheckableActionToQMenuAndActionHash(cullingOptionsMenu, MenuOption::RemoveOutOfView); addCheckableActionToQMenuAndActionHash(cullingOptionsMenu, MenuOption::DisableHideOutOfView); + addCheckableActionToQMenuAndActionHash(cullingOptionsMenu, MenuOption::RemoveOutOfView); addCheckableActionToQMenuAndActionHash(cullingOptionsMenu, MenuOption::UseFullFrustumInHide); addCheckableActionToQMenuAndActionHash(cullingOptionsMenu, MenuOption::DisableConstantCulling); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index c11997d1ce..8783e0b497 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -147,7 +147,7 @@ namespace MenuOption { const QString DisableFastVoxelPipeline = "Disable Fast Voxel Pipeline"; const QString DisplayFrustum = "Display Frustum"; const QString DontRenderVoxels = "Don't call _voxels.render()"; - const QString DontCallOpenGLForVoxels = "Don't call glDrawElements()/glDrawRangeElementsEXT() for Voxels"; + const QString DontCallOpenGLForVoxels = "Don't call glDrawRangeElementsEXT() for Voxels"; const QString EchoAudio = "Echo Audio"; const QString ExportVoxels = "Export Voxels"; const QString HeadMouse = "Head Mouse"; @@ -196,7 +196,7 @@ namespace MenuOption { const QString PipelineWarnings = "Show Render Pipeline Warnings"; const QString Preferences = "Preferences..."; const QString RandomizeVoxelColors = "Randomize Voxel TRUE Colors"; - const QString RemoveOutOfView = "Remove Out of View Voxels"; + const QString RemoveOutOfView = "Instead of Hide Remove Out of View Voxels"; const QString ResetAvatarSize = "Reset Avatar Size"; const QString ResetSwatchColors = "Reset Swatch Colors"; const QString RunTimingTests = "Run Timing Tests"; diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 22e26b4027..0750af714e 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -753,25 +753,54 @@ void VoxelSystem::checkForCulling() { && !isViewChanging() ) ) { - _lastViewCulling = start; - // When we call removeOutOfView() voxels, we don't actually remove the voxels from the VBOs, but we do remove // them from tree, this makes our tree caclulations faster, but doesn't require us to fully rebuild the VBOs (which // can be expensive). if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableHideOutOfView)) { - hideOutOfView(); - } - if (Menu::getInstance()->isOptionChecked(MenuOption::RemoveOutOfView)) { + + // track how long its been since we were last moving. If we have recently moved then only use delta frustums, if + // it's been a long time since we last moved, then go ahead and do a full frustum cull. + if (isViewChanging()) { + _lastViewIsChanging = start; + } + uint64_t sinceLastMoving = (start - _lastViewIsChanging) / 1000; + + bool enoughTime = (sinceLastMoving >= std::max((float) _lastViewCullingElapsed, VIEW_CULLING_RATE_IN_MILLISECONDS)); + + // These has changed events will occur before we stop. So we need to remember this for when we finally have stopped + // moving long enough to be enoughTime + if (hasViewChanged()) { + _hasRecentlyChanged = true; + } + + // If we have recently changed, but it's been enough time since we last moved, then we will do a full frustum + // hide/show culling pass + bool forceFullFrustum = enoughTime && _hasRecentlyChanged; + + // in hide mode, we only track the full frustum culls, because we don't care about the partials. + if (forceFullFrustum) { + _lastViewCulling = start; + _hasRecentlyChanged = false; + } + + hideOutOfView(forceFullFrustum); + + if (forceFullFrustum) { + uint64_t endViewCulling = usecTimestampNow(); + _lastViewCullingElapsed = (endViewCulling - start) / 1000; + } + + } else if (Menu::getInstance()->isOptionChecked(MenuOption::RemoveOutOfView)) { + _lastViewCulling = start; removeOutOfView(); + uint64_t endViewCulling = usecTimestampNow(); + _lastViewCullingElapsed = (endViewCulling - start) / 1000; } // Once we call cleanupRemovedVoxels() we do need to rebuild our VBOs (if anything was actually removed). So, // we should consider putting this someplace else... as this might be able to occur less frequently, and save us on // VBO reubuilding. Possibly we should do this only if our actual VBO usage crosses some lower boundary. cleanupRemovedVoxels(); - - uint64_t endViewCulling = usecTimestampNow(); - _lastViewCullingElapsed = (endViewCulling - start) / 1000; } uint64_t sinceLastAudit = (start - _lastAudit) / 1000; @@ -1047,7 +1076,8 @@ void VoxelSystem::init() { _callsToTreesToArrays = 0; _setupNewVoxelsForDrawingLastFinished = 0; _setupNewVoxelsForDrawingLastElapsed = 0; - _lastViewCullingElapsed = _lastViewCulling = _lastAudit = 0; + _lastViewCullingElapsed = _lastViewCulling = _lastAudit = _lastViewIsChanging = 0; + _hasRecentlyChanged = false; _voxelsDirty = false; _voxelsInWriteArrays = 0; @@ -1807,11 +1837,27 @@ public: } }; -void VoxelSystem::hideOutOfView() { +void VoxelSystem::hideOutOfView(bool forceFullFrustum) { + printf("VoxelSystem::hideOutOfView(bool forceFullFrustum=%s)\n",debug::valueOf(forceFullFrustum)); bool showDebugDetails = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showDebugDetails, "hideOutOfView()", showDebugDetails); bool widenFrustum = true; - bool wantDeltaFrustums = !Menu::getInstance()->isOptionChecked(MenuOption::UseFullFrustumInHide); + + // When using "delta" view frustums and only hide/show items that are in the difference + // between the two view frustums. There are some potential problems with this mode. + // + // 1) This work well for rotating, but what about moving forward? + // In the move forward case, you'll get new voxel details, but those + // new voxels will be in the last view. + // + // 2) Also, voxels will arrive from the network that are OUTSIDE of the view + // frustum... these won't get hidden... and so we can't assume they are correctly + // hidden... + // + // Both these problems are solved by intermittently calling this with forceFullFrustum set + // to true. This will essentially clean up the improperly hidden or shown voxels. + // + bool wantDeltaFrustums = !forceFullFrustum && !Menu::getInstance()->isOptionChecked(MenuOption::UseFullFrustumInHide); hideOutOfViewArgs args(this, this->_tree, _culledOnce, widenFrustum, wantDeltaFrustums); const bool wantViewFrustumDebugging = false; // change to true for additional debugging @@ -1822,24 +1868,11 @@ void VoxelSystem::hideOutOfView() { } } - if (_culledOnce && args.lastViewFrustum.matches(args.thisViewFrustum)) { - //printf("view frustum hasn't changed BAIL!!!\n"); + if (!forceFullFrustum && _culledOnce && args.lastViewFrustum.matches(args.thisViewFrustum)) { + printf("view frustum hasn't changed BAIL!!!\n"); return; } - // Changed hideOutOfView() to support "delta" view frustums and only hide/show items that are in the difference - // between the two view frustums. There are some potential problems with this idea... - // - // 1) This might work well for rotating, but what about moving forward? - // in the move forward case, you'll get new voxel details, but those - // new voxels will be in the last view... does that work? This works - // ok for now because voxel server resends them and so they get redisplayed, - // but this will not work if we update the voxel server to send less data. - // - // 2) what about voxels coming in from the network that are OUTSIDE of the view - // frustum... they don't get hidden... and so we can't assume they are correctly - // hidden... we could solve this with checking in view on voxelUpdated... - // _tree->recurseTreeWithOperation(hideOutOfViewOperation,(void*)&args); _lastCulledViewFrustum = args.thisViewFrustum; // save last stable _culledOnce = true; diff --git a/interface/src/VoxelSystem.h b/interface/src/VoxelSystem.h index cf8e8b3e17..d5434ec7f7 100644 --- a/interface/src/VoxelSystem.h +++ b/interface/src/VoxelSystem.h @@ -85,7 +85,7 @@ public: void killLocalVoxels(); virtual void removeOutOfView(); - virtual void hideOutOfView(); + virtual void hideOutOfView(bool forceFullFrustum = false); bool hasViewChanged(); bool isViewChanging(); @@ -228,8 +228,10 @@ private: int _setupNewVoxelsForDrawingLastElapsed; uint64_t _setupNewVoxelsForDrawingLastFinished; uint64_t _lastViewCulling; + uint64_t _lastViewIsChanging; uint64_t _lastAudit; int _lastViewCullingElapsed; + bool _hasRecentlyChanged; void initVoxelMemory(); void cleanupVoxelMemory(); From b05d6e25e3b9aa7034bbdea59f17b40b99fb71f1 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Wed, 23 Oct 2013 10:23:07 -0700 Subject: [PATCH 2/2] remove two debug outs --- interface/src/VoxelSystem.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/VoxelSystem.cpp b/interface/src/VoxelSystem.cpp index 0750af714e..c166c57f3a 100644 --- a/interface/src/VoxelSystem.cpp +++ b/interface/src/VoxelSystem.cpp @@ -1838,7 +1838,6 @@ public: }; void VoxelSystem::hideOutOfView(bool forceFullFrustum) { - printf("VoxelSystem::hideOutOfView(bool forceFullFrustum=%s)\n",debug::valueOf(forceFullFrustum)); bool showDebugDetails = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showDebugDetails, "hideOutOfView()", showDebugDetails); bool widenFrustum = true; @@ -1869,7 +1868,7 @@ void VoxelSystem::hideOutOfView(bool forceFullFrustum) { } if (!forceFullFrustum && _culledOnce && args.lastViewFrustum.matches(args.thisViewFrustum)) { - printf("view frustum hasn't changed BAIL!!!\n"); + //printf("view frustum hasn't changed BAIL!!!\n"); return; }