diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index 56d4f9c14b..7048efe55c 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -258,14 +258,14 @@ Item { Text { color: root.fontColor; font.pixelSize: root.fontSize - visible: root.expanded + visible: root.showAcuity text: "LOD: " + root.lodStatus; } Text { color: root.fontColor; font.pixelSize: root.fontSize visible: root.expanded - text: "Renderable avatars: " + root.avatarRenderableCount + " w/in " + root.avatarRenderDistance + "m"; + text: root.lodStatsRenderText; } } } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 608f4cd388..f6350cb8d5 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2990,7 +2990,11 @@ void Application::update(float deltaTime) { bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::update()"); - updateLOD(); + if (DependencyManager::get()->getUseAcuity()) { + updateLOD(); + } else { + DependencyManager::get()->updatePIDRenderDistance(getTargetFrameRate(), getLastInstanteousFps(), deltaTime, isThrottleRendering()); + } { PerformanceTimer perfTimer("devices"); diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index 368143e36e..10a288a44e 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -9,6 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include #include #include @@ -20,9 +21,30 @@ Setting::Handle desktopLODDecreaseFPS("desktopLODDecreaseFPS", DEFAULT_DESKTOP_LOD_DOWN_FPS); Setting::Handle hmdLODDecreaseFPS("hmdLODDecreaseFPS", DEFAULT_HMD_LOD_DOWN_FPS); +// There are two different systems in use, based on lodPreference: +// pid: renderDistance is adjusted by a PID such that frame rate targets are met. +// acuity: a pseudo-acuity target is held, or adjusted to match minimum frame rates (and a PID controlls avatar rendering distance) +// If unspecified, acuity is used only if user has specified non-default minumum frame rates. +Setting::Handle lodPreference("lodPreference", (int)LODManager::LODPreference::unspecified); +const float SMALLEST_REASONABLE_HORIZON = 50.0f; // meters +Setting::Handle renderDistanceInverseHighLimit("renderDistanceInverseHighLimit", 1.0f / SMALLEST_REASONABLE_HORIZON); +void LODManager::setRenderDistanceInverseHighLimit(float newValue) { + renderDistanceInverseHighLimit.set(newValue); // persist it, and tell all the controllers that use it + _renderDistanceController.setControlledValueHighLimit(newValue); +} LODManager::LODManager() { calculateAvatarLODDistanceMultiplier(); + + setRenderDistanceInverseHighLimit(renderDistanceInverseHighLimit.get()); + setRenderDistanceInverseLowLimit(1.0f / (float)TREE_SCALE); + // Advice for tuning parameters: + // See PIDController.h. There's a section on tuning in the reference. + // Turn on logging with the following (or from js with LODManager.setRenderDistanceControllerHistory("render pid", 240)) + //setRenderDistanceControllerHistory("render pid", 60 * 4); + // Note that extra logging/hysteresis is turned off in Avatar.cpp when the above logging is on. + setRenderDistanceKP(0.000012f); // Usually about 0.6 of largest that doesn't oscillate when other parameters 0. + setRenderDistanceKI(0.00002f); // Big enough to bring us to target with the above KP. } float LODManager::getLODDecreaseFPS() { @@ -39,7 +61,6 @@ float LODManager::getLODIncreaseFPS() { return getDesktopLODIncreaseFPS(); } - void LODManager::autoAdjustLOD(float currentFPS) { // NOTE: our first ~100 samples at app startup are completely all over the place, and we don't @@ -217,15 +238,58 @@ QString LODManager::getLODFeedbackText() { return result; } +static float renderDistance = (float)TREE_SCALE; +static int renderedCount = 0; +static int lastRenderedCount = 0; +bool LODManager::getUseAcuity() { return lodPreference.get() == (int)LODManager::LODPreference::acuity; } +void LODManager::setUseAcuity(bool newValue) { lodPreference.set(newValue ? (int)LODManager::LODPreference::acuity : (int)LODManager::LODPreference::pid); } +float LODManager::getRenderDistance() { + return renderDistance; +} +int LODManager::getRenderedCount() { + return lastRenderedCount; +} +QString LODManager::getLODStatsRenderText() { + QString label = getUseAcuity() ? "Renderable avatars: " : "Rendered objects: "; + return label + QString::number(getRenderedCount()) + " w/in " + QString::number((int)getRenderDistance()) + "m"; +} +// compare audoAdjustLOD() +void LODManager::updatePIDRenderDistance(float targetFps, float measuredFps, float deltaTime, bool isThrottled) { + float distance; + if (!isThrottled) { + _renderDistanceController.setMeasuredValueSetpoint(targetFps / 2.0f); // No problem updating in flight. + // The PID controller raises the controlled value when the measured value goes up. + // The measured value is frame rate. When the controlled value (1 / render cutoff distance) + // goes up, the render cutoff distance gets closer, the number of rendered avatars is less, and frame rate + // goes up. + distance = 1.0f / _renderDistanceController.update(measuredFps, deltaTime); + } else { + // Here we choose to just use the maximum render cutoff distance if throttled. + distance = 1.0f / _renderDistanceController.getControlledValueLowLimit(); + } + _renderDistanceAverage.updateAverage(distance); + renderDistance = _renderDistanceAverage.getAverage(); // average only once per cycle + lastRenderedCount = renderedCount; + renderedCount = 0; +} + bool LODManager::shouldRender(const RenderArgs* args, const AABox& bounds) { + float distanceToCamera = glm::length(bounds.calcCenter() - args->_viewFrustum->getPosition()); + float largestDimension = bounds.getLargestDimension(); + if (!getUseAcuity()) { + const float scenerySize = 300; // meters + bool isRendered = (largestDimension > scenerySize) || // render scenery regardless of distance + (fabsf(distanceToCamera - largestDimension) < renderDistance); + renderedCount += isRendered ? 1 : 0; + return isRendered; + } + const float maxScale = (float)TREE_SCALE; const float octreeToMeshRatio = 4.0f; // must be this many times closer to a mesh than a voxel to see it. float octreeSizeScale = args->_sizeScale; int boundaryLevelAdjust = args->_boundaryLevelAdjust; float visibleDistanceAtMaxScale = boundaryDistanceForRenderLevel(boundaryLevelAdjust, octreeSizeScale) / octreeToMeshRatio; - float distanceToCamera = glm::length(bounds.calcCenter() - args->_viewFrustum->getPosition()); - float largestDimension = bounds.getLargestDimension(); - + static bool shouldRenderTableNeedsBuilding = true; static QMap shouldRenderTable; if (shouldRenderTableNeedsBuilding) { @@ -315,6 +379,12 @@ void LODManager::setBoundaryLevelAdjust(int boundaryLevelAdjust) { void LODManager::loadSettings() { setDesktopLODDecreaseFPS(desktopLODDecreaseFPS.get()); setHMDLODDecreaseFPS(hmdLODDecreaseFPS.get()); + + if (lodPreference.get() == (int)LODManager::LODPreference::unspecified) { + setUseAcuity((getDesktopLODDecreaseFPS() != DEFAULT_DESKTOP_LOD_DOWN_FPS) || (getHMDLODDecreaseFPS() != DEFAULT_HMD_LOD_DOWN_FPS)); + } + Menu::getInstance()->getActionForOption(MenuOption::LodTools)->setEnabled(getUseAcuity()); + Menu::getInstance()->getSubMenuFromName(MenuOption::RenderResolution, Menu::getInstance()->getSubMenuFromName("Render", Menu::getInstance()->getMenu("Developer")))->setEnabled(getUseAcuity()); } void LODManager::saveSettings() { diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h index b0185b528f..6b141004e5 100644 --- a/interface/src/LODManager.h +++ b/interface/src/LODManager.h @@ -15,6 +15,7 @@ #include #include #include +#include #include const float DEFAULT_DESKTOP_LOD_DOWN_FPS = 15.0; @@ -81,6 +82,27 @@ public: Q_INVOKABLE float getLODDecreaseFPS(); Q_INVOKABLE float getLODIncreaseFPS(); + enum class LODPreference { + pid = 0, + acuity, + unspecified + }; + static bool getUseAcuity(); + static void setUseAcuity(bool newValue); + Q_INVOKABLE void setRenderDistanceKP(float newValue) { _renderDistanceController.setKP(newValue); } + Q_INVOKABLE void setRenderDistanceKI(float newValue) { _renderDistanceController.setKI(newValue); } + Q_INVOKABLE void setRenderDistanceKD(float newValue) { _renderDistanceController.setKD(newValue); } + Q_INVOKABLE bool getRenderDistanceControllerIsLogging() { return _renderDistanceController.getIsLogging(); } + Q_INVOKABLE void setRenderDistanceControllerHistory(QString label, int size) { return _renderDistanceController.setHistorySize(label, size); } + Q_INVOKABLE float getRenderDistanceInverseLowLimit() { return _renderDistanceController.getControlledValueLowLimit(); } + Q_INVOKABLE void setRenderDistanceInverseLowLimit(float newValue) { _renderDistanceController.setControlledValueLowLimit(newValue); } + Q_INVOKABLE float getRenderDistanceInverseHighLimit() { return _renderDistanceController.getControlledValueHighLimit(); } + Q_INVOKABLE void setRenderDistanceInverseHighLimit(float newValue); + void updatePIDRenderDistance(float targetFps, float measuredFps, float deltaTime, bool isThrottled); + float getRenderDistance(); + int getRenderedCount(); + QString getLODStatsRenderText(); + static bool shouldRender(const RenderArgs* args, const AABox& bounds); bool shouldRenderMesh(float largestDimension, float distanceToCamera); void autoAdjustLOD(float currentFPS); @@ -116,6 +138,9 @@ private: bool _shouldRenderTableNeedsRebuilding = true; QMap _shouldRenderTable; + + PIDController _renderDistanceController{}; + SimpleMovingAverage _renderDistanceAverage{ 10 }; }; #endif // hifi_LODManager_h diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 4b77e96f79..4d898caefc 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -64,6 +64,7 @@ public: void saveSettings(); MenuWrapper* getMenu(const QString& menuName); + MenuWrapper* getSubMenuFromName(const QString& menuName, MenuWrapper* menu); void triggerOption(const QString& menuOption); QAction* getActionForOption(const QString& menuOption); @@ -130,7 +131,6 @@ private: const QString& grouping = QString()); QAction* getActionFromName(const QString& menuName, MenuWrapper* menu); - MenuWrapper* getSubMenuFromName(const QString& menuName, MenuWrapper* menu); MenuWrapper* getMenuParent(const QString& menuName, QString& finalMenuPart); QAction* getMenuAction(const QString& menuName); diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 7bec752d96..d9e2159df7 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -184,26 +184,6 @@ void Avatar::simulate(float deltaTime) { qCDebug(interfaceapp) << "Billboarding" << (isMyAvatar() ? "myself" : getSessionUUID()) << "for LOD" << getLODDistance(); } - const bool isControllerLogging = DependencyManager::get()->getRenderDistanceControllerIsLogging(); - float renderDistance = DependencyManager::get()->getRenderDistance(); - const float SKIP_HYSTERESIS_PROPORTION = isControllerLogging ? 0.0f : BILLBOARD_HYSTERESIS_PROPORTION; - float distance = glm::distance(qApp->getCamera()->getPosition(), getPosition()); - if (_shouldSkipRender) { - if (distance < renderDistance * (1.0f - SKIP_HYSTERESIS_PROPORTION)) { - _shouldSkipRender = false; - _skeletonModel.setVisibleInScene(true, qApp->getMain3DScene()); - if (!isControllerLogging) { // Test for isMyAvatar is prophylactic. Never occurs in current code. - qCDebug(interfaceapp) << "Rerendering" << (isMyAvatar() ? "myself" : getSessionUUID()) << "for distance" << renderDistance; - } - } - } else if (distance > renderDistance * (1.0f + SKIP_HYSTERESIS_PROPORTION)) { - _shouldSkipRender = true; - _skeletonModel.setVisibleInScene(false, qApp->getMain3DScene()); - if (!isControllerLogging) { - qCDebug(interfaceapp) << "Unrendering" << (isMyAvatar() ? "myself" : getSessionUUID()) << "for distance" << renderDistance; - } - } - // simple frustum check float boundingRadius = getBillboardSize(); bool inViewFrustum = qApp->getViewFrustum()->sphereInFrustum(getPosition(), boundingRadius) != diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 217cd28e61..7d8d5e4c9b 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -76,13 +76,6 @@ AvatarManager::AvatarManager(QObject* parent) : packetReceiver.registerListener(PacketType::AvatarBillboard, this, "processAvatarBillboardPacket"); } -const float SMALLEST_REASONABLE_HORIZON = 5.0f; // meters -Setting::Handle avatarRenderDistanceInverseHighLimit("avatarRenderDistanceHighLimit", 1.0f / SMALLEST_REASONABLE_HORIZON); -void AvatarManager::setRenderDistanceInverseHighLimit(float newValue) { - avatarRenderDistanceInverseHighLimit.set(newValue); - _renderDistanceController.setControlledValueHighLimit(newValue); -} - void AvatarManager::init() { _myAvatar->init(); { @@ -98,19 +91,6 @@ void AvatarManager::init() { _myAvatar->addToScene(_myAvatar, scene, pendingChanges); } scene->enqueuePendingChanges(pendingChanges); - - const float target_fps = qApp->getTargetFrameRate(); - _renderDistanceController.setMeasuredValueSetpoint(target_fps); - _renderDistanceController.setControlledValueHighLimit(avatarRenderDistanceInverseHighLimit.get()); - _renderDistanceController.setControlledValueLowLimit(1.0f / (float) TREE_SCALE); - // Advice for tuning parameters: - // See PIDController.h. There's a section on tuning in the reference. - // Turn on logging with the following (or from js with AvatarList.setRenderDistanceControllerHistory("avatar render", 300)) - //_renderDistanceController.setHistorySize("avatar render", target_fps * 4); - // Note that extra logging/hysteresis is turned off in Avatar.cpp when the above logging is on. - _renderDistanceController.setKP(0.0008f); // Usually about 0.6 of largest that doesn't oscillate when other parameters 0. - _renderDistanceController.setKI(0.0006f); // Big enough to bring us to target with the above KP. - _renderDistanceController.setKD(0.000001f); // A touch of kd increases the speed by which we get there. } void AvatarManager::updateMyAvatar(float deltaTime) { @@ -145,23 +125,6 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { PerformanceTimer perfTimer("otherAvatars"); - float distance; - if (!qApp->isThrottleRendering()) { - _renderDistanceController.setMeasuredValueSetpoint(qApp->getTargetFrameRate()); // No problem updating in flight. - // The PID controller raises the controlled value when the measured value goes up. - // The measured value is frame rate. When the controlled value (1 / render cutoff distance) - // goes up, the render cutoff distance gets closer, the number of rendered avatars is less, and frame rate - // goes up. - const float deduced = qApp->getLastUnsynchronizedFps(); - distance = 1.0f / _renderDistanceController.update(deduced, deltaTime); - } else { - // Here we choose to just use the maximum render cutoff distance if throttled. - distance = 1.0f / _renderDistanceController.getControlledValueLowLimit(); - } - _renderDistanceAverage.updateAverage(distance); - _renderDistance = _renderDistanceAverage.getAverage(); - int renderableCount = 0; - // simulate avatars auto hashCopy = getHashCopy(); @@ -179,14 +142,10 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { } else { avatar->startUpdate(); avatar->simulate(deltaTime); - if (avatar->getShouldRender()) { - renderableCount++; - } avatar->endUpdate(); ++avatarIterator; } } - _renderedAvatarCount = renderableCount; // simulate avatar fades simulateAvatarFades(deltaTime); diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index 1b165495c3..f34a784ba5 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -45,7 +45,6 @@ public: void clearOtherAvatars(); bool shouldShowReceiveStats() const { return _shouldShowReceiveStats; } - PIDController& getRenderDistanceController() { return _renderDistanceController; } class LocalLight { public: @@ -68,19 +67,6 @@ public: void addAvatarToSimulation(Avatar* avatar); - // Expose results and parameter-tuning operations to other systems, such as stats and javascript. - Q_INVOKABLE float getRenderDistance() { return _renderDistance; } - Q_INVOKABLE float getRenderDistanceInverseLowLimit() { return _renderDistanceController.getControlledValueLowLimit(); } - Q_INVOKABLE float getRenderDistanceInverseHighLimit() { return _renderDistanceController.getControlledValueHighLimit(); } - Q_INVOKABLE int getNumberInRenderRange() { return _renderedAvatarCount; } - Q_INVOKABLE bool getRenderDistanceControllerIsLogging() { return _renderDistanceController.getIsLogging(); } - Q_INVOKABLE void setRenderDistanceControllerHistory(QString label, int size) { return _renderDistanceController.setHistorySize(label, size); } - Q_INVOKABLE void setRenderDistanceKP(float newValue) { _renderDistanceController.setKP(newValue); } - Q_INVOKABLE void setRenderDistanceKI(float newValue) { _renderDistanceController.setKI(newValue); } - Q_INVOKABLE void setRenderDistanceKD(float newValue) { _renderDistanceController.setKD(newValue); } - Q_INVOKABLE void setRenderDistanceInverseLowLimit(float newValue) { _renderDistanceController.setControlledValueLowLimit(newValue); } - Q_INVOKABLE void setRenderDistanceInverseHighLimit(float newValue); - public slots: void setShouldShowReceiveStats(bool shouldShowReceiveStats) { _shouldShowReceiveStats = shouldShowReceiveStats; } void updateAvatarRenderStatus(bool shouldRenderAvatars); @@ -106,10 +92,6 @@ private: QVector _localLights; bool _shouldShowReceiveStats = false; - float _renderDistance { (float) TREE_SCALE }; - int _renderedAvatarCount { 0 }; - PIDController _renderDistanceController { }; - SimpleMovingAverage _renderDistanceAverage { 10 }; SetOfAvatarMotionStates _avatarMotionStates; SetOfMotionStates _motionStatesToAdd; diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index a38cc13100..dfdfedb50d 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -48,6 +48,7 @@ PreferencesDialog::PreferencesDialog(QWidget* parent) : connect(ui.buttonChangeAppearance, &QPushButton::clicked, this, &PreferencesDialog::openFullAvatarModelBrowser); connect(ui.appearanceDescription, &QLineEdit::editingFinished, this, &PreferencesDialog::changeFullAvatarURL); + connect(ui.useAcuityCheckBox, &QCheckBox::clicked, this, &PreferencesDialog::changeUseAcuity); connect(qApp, &Application::fullAvatarURLChanged, this, &PreferencesDialog::fullAvatarURLChanged); @@ -58,6 +59,16 @@ PreferencesDialog::PreferencesDialog(QWidget* parent) : UIUtil::scaleWidgetFontSizes(this); } +void PreferencesDialog::changeUseAcuity() { + bool useAcuity = ui.useAcuityCheckBox->isChecked(); + ui.label_desktopMinimumFPSSpin->setEnabled(useAcuity); + ui.desktopMinimumFPSSpin->setEnabled(useAcuity); + ui.label_hmdMinimumFPSSpin->setEnabled(useAcuity); + ui.hmdMinimumFPSSpin->setEnabled(useAcuity); + ui.label_smallestReasonableRenderHorizon->setText(useAcuity ? "Minimum Avatar Display Distance (@half speed)" : "Minimum Display Distance (@half speed)"); + Menu::getInstance()->getActionForOption(MenuOption::LodTools)->setEnabled(useAcuity); + Menu::getInstance()->getSubMenuFromName(MenuOption::RenderResolution, Menu::getInstance()->getSubMenuFromName("Render", Menu::getInstance()->getMenu("Developer")))->setEnabled(useAcuity); +} void PreferencesDialog::changeFullAvatarURL() { DependencyManager::get()->getMyAvatar()->useFullAvatarURL(ui.appearanceDescription->text(), ""); this->fullAvatarURLChanged(ui.appearanceDescription->text(), ""); @@ -212,9 +223,11 @@ void PreferencesDialog::loadPreferences() { // LOD items auto lodManager = DependencyManager::get(); + ui.useAcuityCheckBox->setChecked(lodManager->getUseAcuity()); ui.desktopMinimumFPSSpin->setValue(lodManager->getDesktopLODDecreaseFPS()); ui.hmdMinimumFPSSpin->setValue(lodManager->getHMDLODDecreaseFPS()); - ui.avatarRenderSmallestReasonableHorizon->setValue(1.0f / DependencyManager::get()->getRenderDistanceInverseHighLimit()); + ui.smallestReasonableRenderHorizon->setValue(1.0f / lodManager->getRenderDistanceInverseHighLimit()); + changeUseAcuity(); } void PreferencesDialog::savePreferences() { @@ -303,7 +316,8 @@ void PreferencesDialog::savePreferences() { // LOD items auto lodManager = DependencyManager::get(); + lodManager->setUseAcuity(ui.useAcuityCheckBox->isChecked()); lodManager->setDesktopLODDecreaseFPS(ui.desktopMinimumFPSSpin->value()); lodManager->setHMDLODDecreaseFPS(ui.hmdMinimumFPSSpin->value()); - DependencyManager::get()->setRenderDistanceInverseHighLimit(1.0f / ui.avatarRenderSmallestReasonableHorizon->value()); + lodManager->setRenderDistanceInverseHighLimit(1.0f / ui.smallestReasonableRenderHorizon->value()); } diff --git a/interface/src/ui/PreferencesDialog.h b/interface/src/ui/PreferencesDialog.h index 1536eca3ee..a6c27dee08 100644 --- a/interface/src/ui/PreferencesDialog.h +++ b/interface/src/ui/PreferencesDialog.h @@ -51,6 +51,7 @@ private slots: void openScriptsLocationBrowser(); void changeFullAvatarURL(); void fullAvatarURLChanged(const QString& newValue, const QString& modelName); + void changeUseAcuity(); }; #endif // hifi_PreferencesDialog_h diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 6acacee41d..b82ab93068 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -116,8 +116,6 @@ void Stats::updateStats(bool force) { auto avatarManager = DependencyManager::get(); // we need to take one avatar out so we don't include ourselves STAT_UPDATE(avatarCount, avatarManager->size() - 1); - STAT_UPDATE(avatarRenderableCount, avatarManager->getNumberInRenderRange()); - STAT_UPDATE(avatarRenderDistance, (int) round(avatarManager->getRenderDistance())); // deliberately truncating STAT_UPDATE(serverCount, (int)nodeList->size()); STAT_UPDATE(renderrate, (int)qApp->getFps()); if (qApp->getActiveDisplayPlugin()) { @@ -285,7 +283,9 @@ void Stats::updateStats(bool force) { STAT_UPDATE(localLeaves, (int)OctreeElement::getLeafNodeCount()); // LOD Details STAT_UPDATE(lodStatus, "You can see " + DependencyManager::get()->getLODFeedbackText()); + STAT_UPDATE(lodStatsRenderText, DependencyManager::get()->getLODStatsRenderText()); } + STAT_UPDATE(showAcuity, (_expanded || force) && DependencyManager::get()->getUseAcuity()); bool performanceTimerIsActive = PerformanceTimer::isActive(); bool displayPerf = _expanded && Menu::getInstance()->isOptionChecked(MenuOption::DisplayDebugTimingDetails); diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index eb28883001..5e948ce0f0 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -30,6 +30,7 @@ class Stats : public QQuickItem { Q_PROPERTY(QString monospaceFont READ monospaceFont CONSTANT) Q_PROPERTY(float audioPacketlossUpstream READ getAudioPacketLossUpstream) Q_PROPERTY(float audioPacketlossDownstream READ getAudioPacketLossDownstream) + Q_PROPERTY(bool showAcuity READ getShowAcuity WRITE setShowAcuity NOTIFY showAcuityChanged) STATS_PROPERTY(int, serverCount, 0) STATS_PROPERTY(int, renderrate, 0) @@ -37,8 +38,6 @@ class Stats : public QQuickItem { STATS_PROPERTY(int, simrate, 0) STATS_PROPERTY(int, avatarSimrate, 0) STATS_PROPERTY(int, avatarCount, 0) - STATS_PROPERTY(int, avatarRenderableCount, 0) - STATS_PROPERTY(int, avatarRenderDistance, 0) STATS_PROPERTY(int, packetInCount, 0) STATS_PROPERTY(int, packetOutCount, 0) STATS_PROPERTY(float, mbpsIn, 0) @@ -77,6 +76,7 @@ class Stats : public QQuickItem { STATS_PROPERTY(QString, packetStats, QString()) STATS_PROPERTY(QString, lodStatus, QString()) STATS_PROPERTY(QString, timingStats, QString()) + STATS_PROPERTY(QString, lodStatsRenderText, QString()) STATS_PROPERTY(int, serverElements, 0) STATS_PROPERTY(int, serverInternal, 0) STATS_PROPERTY(int, serverLeaves, 0) @@ -108,12 +108,15 @@ public: emit expandedChanged(); } } + bool getShowAcuity() { return _showAcuity; } + void setShowAcuity(bool newValue) { _showAcuity = newValue; } public slots: void forceUpdateStats() { updateStats(true); } signals: void expandedChanged(); + void showAcuityChanged(); void timingExpandedChanged(); void serverCountChanged(); void renderrateChanged(); @@ -121,8 +124,7 @@ signals: void simrateChanged(); void avatarSimrateChanged(); void avatarCountChanged(); - void avatarRenderableCountChanged(); - void avatarRenderDistanceChanged(); + void lodStatsRenderTextChanged(); void packetInCountChanged(); void packetOutCountChanged(); void mbpsInChanged(); @@ -172,6 +174,7 @@ private: int _recentMaxPackets{ 0 } ; // recent max incoming voxel packets to process bool _resetRecentMaxPacketsSoon{ true }; bool _expanded{ false }; + bool _showAcuity{ false }; bool _timingExpanded{ false }; QString _monospaceFont; const AudioIOStats* _audioStats; diff --git a/interface/ui/preferencesDialog.ui b/interface/ui/preferencesDialog.ui index e6a5e2228d..a66c4bf7ee 100644 --- a/interface/ui/preferencesDialog.ui +++ b/interface/ui/preferencesDialog.ui @@ -742,6 +742,43 @@ + + + + + 0 + 0 + + + + + 32 + 28 + + + + + 0 + 0 + + + + + Arial + + + + Render based on visual acuity + + + + 0 + 0 + + + + + @@ -757,7 +794,7 @@ 7 - + Arial @@ -842,7 +879,7 @@ 7 - + Arial @@ -927,7 +964,7 @@ 7 - + Arial @@ -963,7 +1000,7 @@ - + 100 diff --git a/libraries/shared/src/PIDController.h b/libraries/shared/src/PIDController.h index 0b2411530a..0a376872cc 100644 --- a/libraries/shared/src/PIDController.h +++ b/libraries/shared/src/PIDController.h @@ -31,7 +31,7 @@ public: float update(float measuredValue, float dt, bool resetAccumulator = false); // returns the new computedValue void setHistorySize(QString label = QString(""), int size = 0) { _history.reserve(size); _history.resize(0); _label = label; } // non-empty does logging - bool getIsLogging() { return _history.capacity(); } + bool getIsLogging() { return !_label.isEmpty(); } float getMeasuredValueSetpoint() const { return _measuredValueSetpoint; } // In normal operation (where we can easily reach setpoint), controlledValue is typcially pinned at max. // Defaults to [0, max float], but for 1/LODdistance, it might be, say, [0, 0.2 or 0.1]