diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index d9f1caa794..f1ca392a99 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -290,8 +290,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 80c739b6ca..0b5f6fcdce 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"; @@ -197,7 +197,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..c166c57f3a 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,26 @@ public: } }; -void VoxelSystem::hideOutOfView() { +void VoxelSystem::hideOutOfView(bool 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 +1867,11 @@ void VoxelSystem::hideOutOfView() { } } - if (_culledOnce && args.lastViewFrustum.matches(args.thisViewFrustum)) { + 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();