diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index dbc409bac2..efbf429ab4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -80,6 +80,7 @@ #include "Application.h" #include "InterfaceVersion.h" +#include "LODManager.h" #include "Menu.h" #include "ModelUploader.h" #include "Util.h" @@ -173,6 +174,7 @@ bool setupEssentials(int& argc, char** argv) { auto ddeFaceTracker = DependencyManager::set(); auto modelBlender = DependencyManager::set(); auto audioToolBox = DependencyManager::set(); + auto lodManager = DependencyManager::set(); return true; } @@ -1772,9 +1774,9 @@ void Application::updateLOD() { PerformanceTimer perfTimer("LOD"); // adjust it unless we were asked to disable this feature, or if we're currently in throttleRendering mode if (!Menu::getInstance()->isOptionChecked(MenuOption::DisableAutoAdjustLOD) && !isThrottleRendering()) { - Menu::getInstance()->autoAdjustLOD(_fps); + DependencyManager::get()->autoAdjustLOD(_fps); } else { - Menu::getInstance()->resetLODAdjust(); + DependencyManager::get()->resetLODAdjust(); } } @@ -2246,8 +2248,9 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node _octreeQuery.setCameraNearClip(_viewFrustum.getNearClip()); _octreeQuery.setCameraFarClip(_viewFrustum.getFarClip()); _octreeQuery.setCameraEyeOffsetPosition(_viewFrustum.getEyeOffsetPosition()); - _octreeQuery.setOctreeSizeScale(Menu::getInstance()->getOctreeSizeScale()); - _octreeQuery.setBoundaryLevelAdjust(Menu::getInstance()->getBoundaryLevelAdjust()); + auto lodManager = DependencyManager::get(); + _octreeQuery.setOctreeSizeScale(lodManager->getOctreeSizeScale()); + _octreeQuery.setBoundaryLevelAdjust(lodManager->getBoundaryLevelAdjust()); unsigned char queryPacket[MAX_PACKET_SIZE]; @@ -2649,11 +2652,11 @@ bool Application::shouldRenderMesh(float largestDimension, float distanceToCamer } float Application::getSizeScale() const { - return Menu::getInstance()->getOctreeSizeScale(); + return DependencyManager::get()->getOctreeSizeScale(); } int Application::getBoundaryLevelAdjust() const { - return Menu::getInstance()->getBoundaryLevelAdjust(); + return DependencyManager::get()->getBoundaryLevelAdjust(); } PickRay Application::computePickRay(float x, float y) { diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp new file mode 100644 index 0000000000..837020dc36 --- /dev/null +++ b/interface/src/LODManager.cpp @@ -0,0 +1,181 @@ +// +// LODManager.cpp +// +// +// Created by Clement on 1/16/15. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include + +#include "Application.h" + +#include "LODManager.h" + +void LODManager::autoAdjustLOD(float currentFPS) { + // NOTE: our first ~100 samples at app startup are completely all over the place, and we don't + // really want to count them in our average, so we will ignore the real frame rates and stuff + // our moving average with simulated good data + const int IGNORE_THESE_SAMPLES = 100; + const float ASSUMED_FPS = 60.0f; + if (_fpsAverage.getSampleCount() < IGNORE_THESE_SAMPLES) { + currentFPS = ASSUMED_FPS; + } + _fpsAverage.updateAverage(currentFPS); + _fastFPSAverage.updateAverage(currentFPS); + + quint64 now = usecTimestampNow(); + + const quint64 ADJUST_AVATAR_LOD_DOWN_DELAY = 1000 * 1000; + if (_automaticAvatarLOD) { + if (_fastFPSAverage.getAverage() < _avatarLODDecreaseFPS) { + if (now - _lastAvatarDetailDrop > ADJUST_AVATAR_LOD_DOWN_DELAY) { + // attempt to lower the detail in proportion to the fps difference + float targetFps = (_avatarLODDecreaseFPS + _avatarLODIncreaseFPS) * 0.5f; + float averageFps = _fastFPSAverage.getAverage(); + const float MAXIMUM_MULTIPLIER_SCALE = 2.0f; + _avatarLODDistanceMultiplier = qMin(MAXIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER, _avatarLODDistanceMultiplier * + (averageFps < EPSILON ? MAXIMUM_MULTIPLIER_SCALE : + qMin(MAXIMUM_MULTIPLIER_SCALE, targetFps / averageFps))); + _lastAvatarDetailDrop = now; + } + } else if (_fastFPSAverage.getAverage() > _avatarLODIncreaseFPS) { + // let the detail level creep slowly upwards + const float DISTANCE_DECREASE_RATE = 0.05f; + _avatarLODDistanceMultiplier = qMax(MINIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER, + _avatarLODDistanceMultiplier - DISTANCE_DECREASE_RATE); + } + } + + bool changed = false; + quint64 elapsed = now - _lastAdjust; + + if (elapsed > ADJUST_LOD_DOWN_DELAY && _fpsAverage.getAverage() < ADJUST_LOD_DOWN_FPS + && _octreeSizeScale > ADJUST_LOD_MIN_SIZE_SCALE) { + + _octreeSizeScale *= ADJUST_LOD_DOWN_BY; + + if (_octreeSizeScale < ADJUST_LOD_MIN_SIZE_SCALE) { + _octreeSizeScale = ADJUST_LOD_MIN_SIZE_SCALE; + } + changed = true; + _lastAdjust = now; + qDebug() << "adjusting LOD down... average fps for last approximately 5 seconds=" << _fpsAverage.getAverage() + << "_octreeSizeScale=" << _octreeSizeScale; + } + + if (elapsed > ADJUST_LOD_UP_DELAY && _fpsAverage.getAverage() > ADJUST_LOD_UP_FPS + && _octreeSizeScale < ADJUST_LOD_MAX_SIZE_SCALE) { + _octreeSizeScale *= ADJUST_LOD_UP_BY; + if (_octreeSizeScale > ADJUST_LOD_MAX_SIZE_SCALE) { + _octreeSizeScale = ADJUST_LOD_MAX_SIZE_SCALE; + } + changed = true; + _lastAdjust = now; + qDebug() << "adjusting LOD up... average fps for last approximately 5 seconds=" << _fpsAverage.getAverage() + << "_octreeSizeScale=" << _octreeSizeScale; + } + + if (changed) { + _shouldRenderTableNeedsRebuilding = true; + // TODO: reactivate lodToolsDialog here +// if (_lodToolsDialog) { +// _lodToolsDialog->reloadSliders(); +// } + } +} + +void LODManager::resetLODAdjust() { + _fpsAverage.reset(); + _fastFPSAverage.reset(); + _lastAvatarDetailDrop = _lastAdjust = usecTimestampNow(); +} + +QString LODManager::getLODFeedbackText() { + // determine granularity feedback + int boundaryLevelAdjust = getBoundaryLevelAdjust(); + QString granularityFeedback; + + switch (boundaryLevelAdjust) { + case 0: { + granularityFeedback = QString("at standard granularity."); + } break; + case 1: { + granularityFeedback = QString("at half of standard granularity."); + } break; + case 2: { + granularityFeedback = QString("at a third of standard granularity."); + } break; + default: { + granularityFeedback = QString("at 1/%1th of standard granularity.").arg(boundaryLevelAdjust + 1); + } break; + } + + // distance feedback + float octreeSizeScale = getOctreeSizeScale(); + float relativeToDefault = octreeSizeScale / DEFAULT_OCTREE_SIZE_SCALE; + QString result; + if (relativeToDefault > 1.01) { + result = QString("%1 further %2").arg(relativeToDefault,8,'f',2).arg(granularityFeedback); + } else if (relativeToDefault > 0.99) { + result = QString("the default distance %1").arg(granularityFeedback); + } else { + result = QString("%1 of default %2").arg(relativeToDefault,8,'f',3).arg(granularityFeedback); + } + return result; +} + +void LODManager::setOctreeSizeScale(float sizeScale) { + _octreeSizeScale = sizeScale; + _shouldRenderTableNeedsRebuilding = true; +} + +void LODManager::setBoundaryLevelAdjust(int boundaryLevelAdjust) { + _boundaryLevelAdjust = boundaryLevelAdjust; + _shouldRenderTableNeedsRebuilding = true; +} + + +void LODManager::loadSettings(QSettings* settings) { + bool lockedSettings = false; + if (!settings) { + settings = qApp->lockSettings(); + lockedSettings = true; + } + + _automaticAvatarLOD = settings->value("automaticAvatarLOD", true).toBool(); + _avatarLODDecreaseFPS = loadSetting(settings, "avatarLODDecreaseFPS", DEFAULT_ADJUST_AVATAR_LOD_DOWN_FPS); + _avatarLODIncreaseFPS = loadSetting(settings, "avatarLODIncreaseFPS", ADJUST_LOD_UP_FPS); + _avatarLODDistanceMultiplier = loadSetting(settings, "avatarLODDistanceMultiplier", + DEFAULT_AVATAR_LOD_DISTANCE_MULTIPLIER); + _octreeSizeScale = loadSetting(settings, "octreeSizeScale", DEFAULT_OCTREE_SIZE_SCALE); + _boundaryLevelAdjust = loadSetting(settings, "boundaryLevelAdjust", 0); + + if (lockedSettings) { + qApp->unlockSettings(); + } +} + +void LODManager::saveSettings(QSettings* settings) { + bool lockedSettings = false; + if (!settings) { + settings = qApp->lockSettings(); + lockedSettings = true; + } + + settings->setValue("automaticAvatarLOD", _automaticAvatarLOD); + settings->setValue("avatarLODDecreaseFPS", _avatarLODDecreaseFPS); + settings->setValue("avatarLODIncreaseFPS", _avatarLODIncreaseFPS); + settings->setValue("avatarLODDistanceMultiplier", _avatarLODDistanceMultiplier); + settings->setValue("octreeSizeScale", _octreeSizeScale); + settings->setValue("boundaryLevelAdjust", _boundaryLevelAdjust); + + if (lockedSettings) { + qApp->unlockSettings(); + } +} + + diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h new file mode 100644 index 0000000000..1b02a931ed --- /dev/null +++ b/interface/src/LODManager.h @@ -0,0 +1,98 @@ +// +// LODManager.h +// +// +// Created by Clement on 1/16/15. +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_LODManager_h +#define hifi_LODManager_h + +#include + +#include +#include +#include +#include + +const float ADJUST_LOD_DOWN_FPS = 40.0; +const float ADJUST_LOD_UP_FPS = 55.0; +const float DEFAULT_ADJUST_AVATAR_LOD_DOWN_FPS = 30.0f; + +const quint64 ADJUST_LOD_DOWN_DELAY = 1000 * 1000 * 5; +const quint64 ADJUST_LOD_UP_DELAY = ADJUST_LOD_DOWN_DELAY * 2; + +const float ADJUST_LOD_DOWN_BY = 0.9f; +const float ADJUST_LOD_UP_BY = 1.1f; + +const float ADJUST_LOD_MIN_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE * 0.25f; +const float ADJUST_LOD_MAX_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE; + +const float MINIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER = 0.1f; +const float MAXIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER = 15.0f; +const float DEFAULT_AVATAR_LOD_DISTANCE_MULTIPLIER = 1.0f; + +const int ONE_SECOND_OF_FRAMES = 60; +const int FIVE_SECONDS_OF_FRAMES = 5 * ONE_SECOND_OF_FRAMES; + +class LODManager : public Dependency { + SINGLETON_DEPENDENCY + +public: + // TODO: actually use them + bool shouldRenderTableNeedsRebuilding() const { return _shouldRenderTableNeedsRebuilding; } + void setShouldRenderTableNeedsRebuilding(bool shouldRenderTableNeedsRebuilding) { + _shouldRenderTableNeedsRebuilding = shouldRenderTableNeedsRebuilding; + } + + // TODO: replace bumpSettings() + void setAutomaticAvatarLOD(bool automaticAvatarLOD) { _automaticAvatarLOD = automaticAvatarLOD; } + bool getAutomaticAvatarLOD() const { return _automaticAvatarLOD; } + void setAvatarLODDecreaseFPS(float avatarLODDecreaseFPS) { _avatarLODDecreaseFPS = avatarLODDecreaseFPS; } + float getAvatarLODDecreaseFPS() const { return _avatarLODDecreaseFPS; } + void setAvatarLODIncreaseFPS(float avatarLODIncreaseFPS) { _avatarLODIncreaseFPS = avatarLODIncreaseFPS; } + float getAvatarLODIncreaseFPS() const { return _avatarLODIncreaseFPS; } + void setAvatarLODDistanceMultiplier(float multiplier) { _avatarLODDistanceMultiplier = multiplier; } + float getAvatarLODDistanceMultiplier() const { return _avatarLODDistanceMultiplier; } + + // User Tweakable LOD Items + QString getLODFeedbackText(); + void setOctreeSizeScale(float sizeScale); + float getOctreeSizeScale() const { return _octreeSizeScale; } + + void setBoundaryLevelAdjust(int boundaryLevelAdjust); + int getBoundaryLevelAdjust() const { return _boundaryLevelAdjust; } + + void autoAdjustLOD(float currentFPS); + void resetLODAdjust(); + +private: + LODManager(); + + void loadSettings(QSettings* settings); + void saveSettings(QSettings* settings); + + bool _automaticAvatarLOD = true; + float _avatarLODDecreaseFPS = DEFAULT_ADJUST_AVATAR_LOD_DOWN_FPS; + float _avatarLODIncreaseFPS = ADJUST_LOD_UP_FPS; + float _avatarLODDistanceMultiplier = DEFAULT_AVATAR_LOD_DISTANCE_MULTIPLIER; + + float _octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE; + int _boundaryLevelAdjust = 0; + + quint64 _lastAdjust = 0; + quint64 _lastAvatarDetailDrop = 0; + SimpleMovingAverage _fpsAverage = FIVE_SECONDS_OF_FRAMES; + SimpleMovingAverage _fastFPSAverage = ONE_SECOND_OF_FRAMES; + + + // TODO: actually use them + bool _shouldRenderTableNeedsRebuilding = true; + QMap _shouldRenderTable; +}; + +#endif // hifi_LODManager_h \ No newline at end of file diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 6531344f9b..7f8e1b82ae 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -86,10 +86,7 @@ Menu* Menu::getInstance() { return _instance; } -Menu::Menu() : - _lastAdjust(usecTimestampNow()), - _lastAvatarDetailDrop(usecTimestampNow()) -{ +Menu::Menu() { Application *appInstance = Application::getInstance(); QMenu* fileMenu = addMenu("File"); @@ -606,13 +603,6 @@ void Menu::loadSettings(QSettings* settings) { _faceshiftEyeDeflection = loadSetting(settings, "faceshiftEyeDeflection", DEFAULT_FACESHIFT_EYE_DEFLECTION); _faceshiftHostname = settings->value("faceshiftHostname", DEFAULT_FACESHIFT_HOSTNAME).toString(); _maxOctreePacketsPerSecond = loadSetting(settings, "maxOctreePPS", DEFAULT_MAX_OCTREE_PPS); - _octreeSizeScale = loadSetting(settings, "octreeSizeScale", DEFAULT_OCTREE_SIZE_SCALE); - _automaticAvatarLOD = settings->value("automaticAvatarLOD", true).toBool(); - _avatarLODDecreaseFPS = loadSetting(settings, "avatarLODDecreaseFPS", DEFAULT_ADJUST_AVATAR_LOD_DOWN_FPS); - _avatarLODIncreaseFPS = loadSetting(settings, "avatarLODIncreaseFPS", ADJUST_LOD_UP_FPS); - _avatarLODDistanceMultiplier = loadSetting(settings, "avatarLODDistanceMultiplier", - DEFAULT_AVATAR_LOD_DISTANCE_MULTIPLIER); - _boundaryLevelAdjust = loadSetting(settings, "boundaryLevelAdjust", 0); _snapshotsLocation = settings->value("snapshotsLocation", QStandardPaths::writableLocation(QStandardPaths::DesktopLocation)).toString(); setScriptsLocation(settings->value("scriptsLocation", QString()).toString()); @@ -669,12 +659,6 @@ void Menu::saveSettings(QSettings* settings) { settings->setValue("faceshiftEyeDeflection", _faceshiftEyeDeflection); settings->setValue("faceshiftHostname", _faceshiftHostname); settings->setValue("maxOctreePPS", _maxOctreePacketsPerSecond); - settings->setValue("octreeSizeScale", _octreeSizeScale); - settings->setValue("automaticAvatarLOD", _automaticAvatarLOD); - settings->setValue("avatarLODDecreaseFPS", _avatarLODDecreaseFPS); - settings->setValue("avatarLODIncreaseFPS", _avatarLODIncreaseFPS); - settings->setValue("avatarLODDistanceMultiplier", _avatarLODDistanceMultiplier); - settings->setValue("boundaryLevelAdjust", _boundaryLevelAdjust); settings->setValue("snapshotsLocation", _snapshotsLocation); settings->setValue("scriptsLocation", _scriptsLocation); #if defined(Q_OS_MAC) || defined(Q_OS_WIN) @@ -1404,130 +1388,6 @@ void Menu::octreeStatsDetails() { _octreeStatsDialog->raise(); } -QString Menu::getLODFeedbackText() { - // determine granularity feedback - int boundaryLevelAdjust = getBoundaryLevelAdjust(); - QString granularityFeedback; - - switch (boundaryLevelAdjust) { - case 0: { - granularityFeedback = QString("at standard granularity."); - } break; - case 1: { - granularityFeedback = QString("at half of standard granularity."); - } break; - case 2: { - granularityFeedback = QString("at a third of standard granularity."); - } break; - default: { - granularityFeedback = QString("at 1/%1th of standard granularity.").arg(boundaryLevelAdjust + 1); - } break; - } - - // distance feedback - float octreeSizeScale = getOctreeSizeScale(); - float relativeToDefault = octreeSizeScale / DEFAULT_OCTREE_SIZE_SCALE; - QString result; - if (relativeToDefault > 1.01) { - result = QString("%1 further %2").arg(relativeToDefault,8,'f',2).arg(granularityFeedback); - } else if (relativeToDefault > 0.99) { - result = QString("the default distance %1").arg(granularityFeedback); - } else { - result = QString("%1 of default %2").arg(relativeToDefault,8,'f',3).arg(granularityFeedback); - } - return result; -} - -void Menu::autoAdjustLOD(float currentFPS) { - // NOTE: our first ~100 samples at app startup are completely all over the place, and we don't - // really want to count them in our average, so we will ignore the real frame rates and stuff - // our moving average with simulated good data - const int IGNORE_THESE_SAMPLES = 100; - const float ASSUMED_FPS = 60.0f; - if (_fpsAverage.getSampleCount() < IGNORE_THESE_SAMPLES) { - currentFPS = ASSUMED_FPS; - } - _fpsAverage.updateAverage(currentFPS); - _fastFPSAverage.updateAverage(currentFPS); - - quint64 now = usecTimestampNow(); - - const quint64 ADJUST_AVATAR_LOD_DOWN_DELAY = 1000 * 1000; - if (_automaticAvatarLOD) { - if (_fastFPSAverage.getAverage() < _avatarLODDecreaseFPS) { - if (now - _lastAvatarDetailDrop > ADJUST_AVATAR_LOD_DOWN_DELAY) { - // attempt to lower the detail in proportion to the fps difference - float targetFps = (_avatarLODDecreaseFPS + _avatarLODIncreaseFPS) * 0.5f; - float averageFps = _fastFPSAverage.getAverage(); - const float MAXIMUM_MULTIPLIER_SCALE = 2.0f; - _avatarLODDistanceMultiplier = qMin(MAXIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER, _avatarLODDistanceMultiplier * - (averageFps < EPSILON ? MAXIMUM_MULTIPLIER_SCALE : - qMin(MAXIMUM_MULTIPLIER_SCALE, targetFps / averageFps))); - _lastAvatarDetailDrop = now; - } - } else if (_fastFPSAverage.getAverage() > _avatarLODIncreaseFPS) { - // let the detail level creep slowly upwards - const float DISTANCE_DECREASE_RATE = 0.05f; - _avatarLODDistanceMultiplier = qMax(MINIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER, - _avatarLODDistanceMultiplier - DISTANCE_DECREASE_RATE); - } - } - - bool changed = false; - quint64 elapsed = now - _lastAdjust; - - if (elapsed > ADJUST_LOD_DOWN_DELAY && _fpsAverage.getAverage() < ADJUST_LOD_DOWN_FPS - && _octreeSizeScale > ADJUST_LOD_MIN_SIZE_SCALE) { - - _octreeSizeScale *= ADJUST_LOD_DOWN_BY; - - if (_octreeSizeScale < ADJUST_LOD_MIN_SIZE_SCALE) { - _octreeSizeScale = ADJUST_LOD_MIN_SIZE_SCALE; - } - changed = true; - _lastAdjust = now; - qDebug() << "adjusting LOD down... average fps for last approximately 5 seconds=" << _fpsAverage.getAverage() - << "_octreeSizeScale=" << _octreeSizeScale; - } - - if (elapsed > ADJUST_LOD_UP_DELAY && _fpsAverage.getAverage() > ADJUST_LOD_UP_FPS - && _octreeSizeScale < ADJUST_LOD_MAX_SIZE_SCALE) { - _octreeSizeScale *= ADJUST_LOD_UP_BY; - if (_octreeSizeScale > ADJUST_LOD_MAX_SIZE_SCALE) { - _octreeSizeScale = ADJUST_LOD_MAX_SIZE_SCALE; - } - changed = true; - _lastAdjust = now; - qDebug() << "adjusting LOD up... average fps for last approximately 5 seconds=" << _fpsAverage.getAverage() - << "_octreeSizeScale=" << _octreeSizeScale; - } - - if (changed) { - _shouldRenderTableNeedsRebuilding = true; - if (_lodToolsDialog) { - _lodToolsDialog->reloadSliders(); - } - } -} - -void Menu::resetLODAdjust() { - _fpsAverage.reset(); - _fastFPSAverage.reset(); - _lastAvatarDetailDrop = _lastAdjust = usecTimestampNow(); -} - -void Menu::setOctreeSizeScale(float sizeScale) { - _octreeSizeScale = sizeScale; - _shouldRenderTableNeedsRebuilding = true; - bumpSettings(); -} - -void Menu::setBoundaryLevelAdjust(int boundaryLevelAdjust) { - _boundaryLevelAdjust = boundaryLevelAdjust; - _shouldRenderTableNeedsRebuilding = true; - bumpSettings(); -} - // TODO: This is essentially the same logic used to render octree cells, but since models are more detailed then octree cells // I've added a voxelToModelRatio that adjusts how much closer to a model you have to be to see it. bool Menu::shouldRenderMesh(float largestDimension, float distanceToCamera) { diff --git a/interface/src/Menu.h b/interface/src/Menu.h index bafcf401c9..0b12bb5066 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -21,7 +21,6 @@ #include #include -#include #if defined(Q_OS_MAC) || defined(Q_OS_WIN) #include "SpeechRecognizer.h" @@ -29,32 +28,11 @@ #include "devices/Faceshift.h" #include "devices/SixenseManager.h" +#include "LODManager.h" #include "ui/ChatWindow.h" #include "ui/JSConsole.h" #include "ui/ScriptEditorWindow.h" -// Make an LOD handler class and move everything overthere -const float ADJUST_LOD_DOWN_FPS = 40.0; -const float ADJUST_LOD_UP_FPS = 55.0; -const float DEFAULT_ADJUST_AVATAR_LOD_DOWN_FPS = 30.0f; - -const quint64 ADJUST_LOD_DOWN_DELAY = 1000 * 1000 * 5; -const quint64 ADJUST_LOD_UP_DELAY = ADJUST_LOD_DOWN_DELAY * 2; - -const float ADJUST_LOD_DOWN_BY = 0.9f; -const float ADJUST_LOD_UP_BY = 1.1f; - -const float ADJUST_LOD_MIN_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE * 0.25f; -const float ADJUST_LOD_MAX_SIZE_SCALE = DEFAULT_OCTREE_SIZE_SCALE; - -const float MINIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER = 0.1f; -const float MAXIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER = 15.0f; -const float DEFAULT_AVATAR_LOD_DISTANCE_MULTIPLIER = 1.0f; - -const int ONE_SECOND_OF_FRAMES = 60; -const int FIVE_SECONDS_OF_FRAMES = 5 * ONE_SECOND_OF_FRAMES; -////////////////////////////////////////////////////////// - const float DEFAULT_OCULUS_UI_ANGULAR_SIZE = 72.0f; const QString SETTINGS_ADDRESS_KEY = "address"; @@ -187,23 +165,6 @@ public: bool getShadowsEnabled() const; - // User Tweakable LOD Items - QString getLODFeedbackText(); - void autoAdjustLOD(float currentFPS); - void resetLODAdjust(); - void setOctreeSizeScale(float sizeScale); - float getOctreeSizeScale() const { return _octreeSizeScale; } - void setAutomaticAvatarLOD(bool automaticAvatarLOD) { _automaticAvatarLOD = automaticAvatarLOD; bumpSettings(); } - bool getAutomaticAvatarLOD() const { return _automaticAvatarLOD; } - void setAvatarLODDecreaseFPS(float avatarLODDecreaseFPS) { _avatarLODDecreaseFPS = avatarLODDecreaseFPS; bumpSettings(); } - float getAvatarLODDecreaseFPS() const { return _avatarLODDecreaseFPS; } - void setAvatarLODIncreaseFPS(float avatarLODIncreaseFPS) { _avatarLODIncreaseFPS = avatarLODIncreaseFPS; bumpSettings(); } - float getAvatarLODIncreaseFPS() const { return _avatarLODIncreaseFPS; } - void setAvatarLODDistanceMultiplier(float multiplier) { _avatarLODDistanceMultiplier = multiplier; bumpSettings(); } - float getAvatarLODDistanceMultiplier() const { return _avatarLODDistanceMultiplier; } - void setBoundaryLevelAdjust(int boundaryLevelAdjust); - int getBoundaryLevelAdjust() const { return _boundaryLevelAdjust; } - bool shouldRenderMesh(float largestDimension, float distanceToCamera); #if defined(Q_OS_MAC) || defined(Q_OS_WIN) @@ -271,26 +232,13 @@ private: #if defined(Q_OS_MAC) || defined(Q_OS_WIN) SpeechRecognizer _speechRecognizer; #endif - float _octreeSizeScale = DEFAULT_OCTREE_SIZE_SCALE; float _oculusUIAngularSize = DEFAULT_OCULUS_UI_ANGULAR_SIZE; float _sixenseReticleMoveSpeed = DEFAULT_SIXENSE_RETICLE_MOVE_SPEED; bool _invertSixenseButtons = DEFAULT_INVERT_SIXENSE_MOUSE_BUTTONS; bool _hasLoginDialogDisplayed = false; - bool _automaticAvatarLOD = true; - float _avatarLODDecreaseFPS = DEFAULT_ADJUST_AVATAR_LOD_DOWN_FPS; - float _avatarLODIncreaseFPS = ADJUST_LOD_UP_FPS; - float _avatarLODDistanceMultiplier = DEFAULT_AVATAR_LOD_DISTANCE_MULTIPLIER; - - int _boundaryLevelAdjust = 0; int _maxOctreePacketsPerSecond = DEFAULT_MAX_OCTREE_PPS; - quint64 _lastAdjust; - quint64 _lastAvatarDetailDrop; - - SimpleMovingAverage _fpsAverage = FIVE_SECONDS_OF_FRAMES; - SimpleMovingAverage _fastFPSAverage = ONE_SECOND_OF_FRAMES; - QPointer _addressBarDialog; QPointer _animationsDialog; QPointer _attachmentsDialog; diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 7ad81d7bf5..b395fcadae 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -114,8 +114,8 @@ glm::quat Avatar::getWorldAlignedOrientation () const { } float Avatar::getLODDistance() const { - return Menu::getInstance()->getAvatarLODDistanceMultiplier() * - glm::distance(Application::getInstance()->getCamera()->getPosition(), _position) / _scale; + return DependencyManager::get()->getAvatarLODDistanceMultiplier() * + glm::distance(Application::getInstance()->getCamera()->getPosition(), _position) / _scale; } void Avatar::simulate(float deltaTime) { diff --git a/interface/src/ui/LodToolsDialog.cpp b/interface/src/ui/LodToolsDialog.cpp index 8ff9eadc51..5d079e840f 100644 --- a/interface/src/ui/LodToolsDialog.cpp +++ b/interface/src/ui/LodToolsDialog.cpp @@ -28,6 +28,7 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) : QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint) { this->setWindowTitle("LOD Tools"); + auto lodManager = DependencyManager::get(); // Create layouter QFormLayout* form = new QFormLayout(this); @@ -45,7 +46,7 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) : _lodSize->setTickPosition(QSlider::TicksBelow); _lodSize->setFixedWidth(SLIDER_WIDTH); _lodSize->setPageStep(PAGE_STEP_LOD_SIZE); - int sliderValue = Menu::getInstance()->getOctreeSizeScale() / TREE_SCALE; + int sliderValue = lodManager->getOctreeSizeScale() / TREE_SCALE; _lodSize->setValue(sliderValue); form->addRow("LOD Size Scale:", _lodSize); connect(_lodSize,SIGNAL(valueChanged(int)),this,SLOT(sizeScaleValueChanged(int))); @@ -60,7 +61,7 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) : _boundaryLevelAdjust->setTickInterval(STEP_ADJUST); _boundaryLevelAdjust->setTickPosition(QSlider::TicksBelow); _boundaryLevelAdjust->setFixedWidth(SLIDER_WIDTH); - sliderValue = Menu::getInstance()->getBoundaryLevelAdjust(); + sliderValue = lodManager->getBoundaryLevelAdjust(); _boundaryLevelAdjust->setValue(sliderValue); form->addRow("Boundary Level Adjust:", _boundaryLevelAdjust); connect(_boundaryLevelAdjust,SIGNAL(valueChanged(int)),this,SLOT(boundaryLevelValueChanged(int))); @@ -71,22 +72,22 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) : const unsigned redish = 0xfff00000; palette.setColor(QPalette::WindowText, QColor::fromRgb(redish)); _feedback->setPalette(palette); - _feedback->setText(Menu::getInstance()->getLODFeedbackText()); + _feedback->setText(lodManager->getLODFeedbackText()); const int FEEDBACK_WIDTH = 350; _feedback->setFixedWidth(FEEDBACK_WIDTH); form->addRow("You can see... ", _feedback); - + form->addRow("Automatic Avatar LOD Adjustment:", _automaticAvatarLOD = new QCheckBox(this)); - _automaticAvatarLOD->setChecked(Menu::getInstance()->getAutomaticAvatarLOD()); + _automaticAvatarLOD->setChecked(lodManager->getAutomaticAvatarLOD()); connect(_automaticAvatarLOD, SIGNAL(toggled(bool)), SLOT(updateAvatarLODControls())); form->addRow("Decrease Avatar LOD Below FPS:", _avatarLODDecreaseFPS = new QDoubleSpinBox(this)); - _avatarLODDecreaseFPS->setValue(Menu::getInstance()->getAvatarLODDecreaseFPS()); + _avatarLODDecreaseFPS->setValue(lodManager->getAvatarLODDecreaseFPS()); _avatarLODDecreaseFPS->setDecimals(0); connect(_avatarLODDecreaseFPS, SIGNAL(valueChanged(double)), SLOT(updateAvatarLODValues())); form->addRow("Increase Avatar LOD Above FPS:", _avatarLODIncreaseFPS = new QDoubleSpinBox(this)); - _avatarLODIncreaseFPS->setValue(Menu::getInstance()->getAvatarLODIncreaseFPS()); + _avatarLODIncreaseFPS->setValue(lodManager->getAvatarLODIncreaseFPS()); _avatarLODIncreaseFPS->setDecimals(0); connect(_avatarLODIncreaseFPS, SIGNAL(valueChanged(double)), SLOT(updateAvatarLODValues())); @@ -94,7 +95,7 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) : _avatarLOD->setDecimals(3); _avatarLOD->setRange(1.0 / MAXIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER, 1.0 / MINIMUM_AVATAR_LOD_DISTANCE_MULTIPLIER); _avatarLOD->setSingleStep(0.001); - _avatarLOD->setValue(1.0 / Menu::getInstance()->getAvatarLODDistanceMultiplier()); + _avatarLOD->setValue(1.0 / lodManager->getAvatarLODDistanceMultiplier()); connect(_avatarLOD, SIGNAL(valueChanged(double)), SLOT(updateAvatarLODValues())); // Add a button to reset @@ -108,15 +109,17 @@ LodToolsDialog::LodToolsDialog(QWidget* parent) : } void LodToolsDialog::reloadSliders() { - _lodSize->setValue(Menu::getInstance()->getOctreeSizeScale() / TREE_SCALE); - _boundaryLevelAdjust->setValue(Menu::getInstance()->getBoundaryLevelAdjust()); - _feedback->setText(Menu::getInstance()->getLODFeedbackText()); + auto lodManager = DependencyManager::get(); + _lodSize->setValue(lodManager->getOctreeSizeScale() / TREE_SCALE); + _boundaryLevelAdjust->setValue(lodManager->getBoundaryLevelAdjust()); + _feedback->setText(lodManager->getLODFeedbackText()); } void LodToolsDialog::updateAvatarLODControls() { QFormLayout* form = static_cast(layout()); - Menu::getInstance()->setAutomaticAvatarLOD(_automaticAvatarLOD->isChecked()); + auto lodManager = DependencyManager::get(); + lodManager->setAutomaticAvatarLOD(_automaticAvatarLOD->isChecked()); _avatarLODDecreaseFPS->setVisible(_automaticAvatarLOD->isChecked()); form->labelForField(_avatarLODDecreaseFPS)->setVisible(_automaticAvatarLOD->isChecked()); @@ -128,7 +131,7 @@ void LodToolsDialog::updateAvatarLODControls() { form->labelForField(_avatarLOD)->setVisible(!_automaticAvatarLOD->isChecked()); if (!_automaticAvatarLOD->isChecked()) { - _avatarLOD->setValue(1.0 / Menu::getInstance()->getAvatarLODDistanceMultiplier()); + _avatarLOD->setValue(1.0 / lodManager->getAvatarLODDistanceMultiplier()); } if (isVisible()) { @@ -137,25 +140,28 @@ void LodToolsDialog::updateAvatarLODControls() { } void LodToolsDialog::updateAvatarLODValues() { + auto lodManager = DependencyManager::get(); if (_automaticAvatarLOD->isChecked()) { - Menu::getInstance()->setAvatarLODDecreaseFPS(_avatarLODDecreaseFPS->value()); - Menu::getInstance()->setAvatarLODIncreaseFPS(_avatarLODIncreaseFPS->value()); + lodManager->setAvatarLODDecreaseFPS(_avatarLODDecreaseFPS->value()); + lodManager->setAvatarLODIncreaseFPS(_avatarLODIncreaseFPS->value()); } else { - Menu::getInstance()->setAvatarLODDistanceMultiplier(1.0 / _avatarLOD->value()); + lodManager->setAvatarLODDistanceMultiplier(1.0 / _avatarLOD->value()); } } void LodToolsDialog::sizeScaleValueChanged(int value) { + auto lodManager = DependencyManager::get(); float realValue = value * TREE_SCALE; - Menu::getInstance()->setOctreeSizeScale(realValue); + lodManager->setOctreeSizeScale(realValue); - _feedback->setText(Menu::getInstance()->getLODFeedbackText()); + _feedback->setText(lodManager->getLODFeedbackText()); } void LodToolsDialog::boundaryLevelValueChanged(int value) { - Menu::getInstance()->setBoundaryLevelAdjust(value); - _feedback->setText(Menu::getInstance()->getLODFeedbackText()); + auto lodManager = DependencyManager::get(); + lodManager->setBoundaryLevelAdjust(value); + _feedback->setText(lodManager->getLODFeedbackText()); } void LodToolsDialog::resetClicked(bool checked) { diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 486a4621af..182cdce0cc 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -623,7 +623,7 @@ void Stats::display( // LOD Details if (_expanded) { octreeStats.str(""); - QString displayLODDetails = Menu::getInstance()->getLODFeedbackText(); + QString displayLODDetails = DependencyManager::get()->getLODFeedbackText(); octreeStats << "LOD: You can see " << qPrintable(displayLODDetails.trimmed()); verticalOffset += STATS_PELS_PER_LINE; drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 8f9f54c591..0c2279e22b 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -83,10 +83,13 @@ void Overlays::update(float deltatime) { void Overlays::renderHUD() { QReadLocker lock(&_lock); - + + auto lodManager = DependencyManager::get(); RenderArgs args = { NULL, Application::getInstance()->getViewFrustum(), - Menu::getInstance()->getOctreeSizeScale(), Menu::getInstance()->getBoundaryLevelAdjust(), - RenderArgs::DEFAULT_RENDER_MODE, RenderArgs::MONO, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + lodManager->getOctreeSizeScale(), + lodManager->getBoundaryLevelAdjust(), + RenderArgs::DEFAULT_RENDER_MODE, RenderArgs::MONO, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; foreach(Overlay* thisOverlay, _overlaysHUD) { if (thisOverlay->is3D()) { @@ -116,9 +119,12 @@ void Overlays::renderWorld(bool drawFront, RenderArgs::RenderMode renderMode, Re glm::vec3 axis(0.0f, 1.0f, 0.0f); float myAvatarScale = 1.0f; + auto lodManager = DependencyManager::get(); RenderArgs args = { NULL, Application::getInstance()->getViewFrustum(), - Menu::getInstance()->getOctreeSizeScale(), Menu::getInstance()->getBoundaryLevelAdjust(), - renderMode, renderSide, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; + lodManager->getOctreeSizeScale(), + lodManager->getBoundaryLevelAdjust(), + renderMode, renderSide, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; foreach(Overlay* thisOverlay, _overlaysWorld) {