From 069199554ccee24f98fcbc8229dc6e67e124c069 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Tue, 15 Dec 2015 16:07:37 -0800 Subject: [PATCH 01/21] checkpoint --- interface/src/Application.cpp | 6 ++- interface/src/LODManager.cpp | 66 ++++++++++++++++++++++++-- interface/src/LODManager.h | 22 +++++++++ interface/src/ui/PreferencesDialog.cpp | 17 ++++++- interface/src/ui/PreferencesDialog.h | 1 + interface/src/ui/Stats.cpp | 4 +- interface/ui/preferencesDialog.ui | 45 ++++++++++++++++-- 7 files changed, 148 insertions(+), 13 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4494203a49..97bc3f3689 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2801,7 +2801,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..dfe03137d5 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -20,9 +20,25 @@ 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 automatically adjusted such that frame rate targets are met. +// acuity: a pseudo-acuity target is held, or adjusted to match minimum frame rates. +// If unspecified, acuity is used only if user has specified non-default minumum frame rates. +Setting::Handle lodPreference("lodPreference", (int)LODManager::LODPreference::unspecified); LODManager::LODManager() { calculateAvatarLODDistanceMultiplier(); + + _renderDistanceController.setControlledValueHighLimit(20.0f); + _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.000012f); // Usually about 0.6 of largest that doesn't oscillate when other parameters 0. + _renderDistanceController.setKI(0.00002f); // Big enough to bring us to target with the above KP. + _renderDistanceController.setHistorySize("FIXME", 240); } float LODManager::getLODDecreaseFPS() { @@ -39,7 +55,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 +232,53 @@ 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; +} +// compare audoAdjustLOD() +void LODManager::updatePIDRenderDistance(float targetFps, float measuredFps, float deltaTime, bool isThrottled) { + float distance; + if (!isThrottled) { + _renderDistanceController.setMeasuredValueSetpoint(targetFps); // 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()) { + bool isRendered = 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 +368,11 @@ 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()); } void LODManager::saveSettings() { diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h index b0185b528f..21a30bceaf 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,24 @@ 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 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) { _renderDistanceController.setControlledValueHighLimit(newValue); } + void updatePIDRenderDistance(float targetFps, float measuredFps, float deltaTime, bool isThrottled); + float getRenderDistance(); + int getRenderedCount(); + static bool shouldRender(const RenderArgs* args, const AABox& bounds); bool shouldRenderMesh(float largestDimension, float distanceToCamera); void autoAdjustLOD(float currentFPS); @@ -116,6 +135,9 @@ private: bool _shouldRenderTableNeedsRebuilding = true; QMap _shouldRenderTable; + + PIDController _renderDistanceController{}; + SimpleMovingAverage _renderDistanceAverage{ 10 }; }; #endif // hifi_LODManager_h diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 9a995263cd..bc08391bbe 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,15 @@ 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); +} void PreferencesDialog::changeFullAvatarURL() { DependencyManager::get()->getMyAvatar()->useFullAvatarURL(ui.appearanceDescription->text(), ""); this->fullAvatarURLChanged(ui.appearanceDescription->text(), ""); @@ -212,9 +222,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 / DependencyManager::get()->getRenderDistanceInverseHighLimit()); + changeUseAcuity(); } void PreferencesDialog::savePreferences() { @@ -303,7 +315,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()); + DependencyManager::get()->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..e391d5c40a 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -116,8 +116,8 @@ 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(avatarRenderableCount, DependencyManager::get()->getRenderedCount()); //FIXME avatarManager->getNumberInRenderRange()); + STAT_UPDATE(avatarRenderDistance, (int)round(DependencyManager::get()->getRenderDistance())); // FIXME avatarManager->getRenderDistance())); // deliberately truncating STAT_UPDATE(serverCount, (int)nodeList->size()); STAT_UPDATE(renderrate, (int)qApp->getFps()); if (qApp->getActiveDisplayPlugin()) { 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 From f47873bac3b581609a88e73b322f20051b1a8d52 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Tue, 15 Dec 2015 17:00:49 -0800 Subject: [PATCH 02/21] stats checkpoint --- interface/src/LODManager.cpp | 2 +- interface/src/ui/Stats.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index dfe03137d5..5ac2f687c7 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -247,7 +247,7 @@ int LODManager::getRenderedCount() { void LODManager::updatePIDRenderDistance(float targetFps, float measuredFps, float deltaTime, bool isThrottled) { float distance; if (!isThrottled) { - _renderDistanceController.setMeasuredValueSetpoint(targetFps); // No problem updating in flight. + _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 diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index e391d5c40a..a86ed97f0c 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, DependencyManager::get()->getRenderedCount()); //FIXME avatarManager->getNumberInRenderRange()); - STAT_UPDATE(avatarRenderDistance, (int)round(DependencyManager::get()->getRenderDistance())); // FIXME avatarManager->getRenderDistance())); // deliberately truncating STAT_UPDATE(serverCount, (int)nodeList->size()); STAT_UPDATE(renderrate, (int)qApp->getFps()); if (qApp->getActiveDisplayPlugin()) { @@ -285,6 +283,8 @@ void Stats::updateStats(bool force) { STAT_UPDATE(localLeaves, (int)OctreeElement::getLeafNodeCount()); // LOD Details STAT_UPDATE(lodStatus, "You can see " + DependencyManager::get()->getLODFeedbackText()); + STAT_UPDATE(avatarRenderableCount, DependencyManager::get()->getRenderedCount()); //FIXME avatarManager->getNumberInRenderRange()); + STAT_UPDATE(avatarRenderDistance, (int)round(DependencyManager::get()->getRenderDistance())); // FIXME avatarManager->getRenderDistance())); // deliberately truncating } bool performanceTimerIsActive = PerformanceTimer::isActive(); From 09d4a06ad4dbe8c1adbe093d66757efcb475fbe4 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Wed, 16 Dec 2015 15:30:48 -0800 Subject: [PATCH 03/21] LODManager-centric stats and preferences. --- interface/resources/qml/Stats.qml | 4 ++-- interface/src/LODManager.cpp | 30 ++++++++++++++++++++------ interface/src/LODManager.h | 9 +++++--- interface/src/avatar/AvatarManager.cpp | 12 +++-------- interface/src/avatar/AvatarManager.h | 2 +- interface/src/ui/PreferencesDialog.cpp | 4 ++-- interface/src/ui/Stats.cpp | 4 ++-- interface/src/ui/Stats.h | 11 ++++++---- 8 files changed, 46 insertions(+), 30 deletions(-) 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/LODManager.cpp b/interface/src/LODManager.cpp index 5ac2f687c7..9d61a1c02c 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 @@ -21,24 +22,31 @@ 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 automatically adjusted such that frame rate targets are met. -// acuity: a pseudo-acuity target is held, or adjusted to match minimum frame rates. +// 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); + DependencyManager::get()->setRenderDistanceInverseHighLimit(newValue); +} LODManager::LODManager() { calculateAvatarLODDistanceMultiplier(); - _renderDistanceController.setControlledValueHighLimit(20.0f); - _renderDistanceController.setControlledValueLowLimit(1.0f / (float)TREE_SCALE); + 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 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.000012f); // Usually about 0.6 of largest that doesn't oscillate when other parameters 0. - _renderDistanceController.setKI(0.00002f); // Big enough to bring us to target with the above KP. - _renderDistanceController.setHistorySize("FIXME", 240); + 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. + //setRenderDistanceControllerHistory("FIXME", 240); } float LODManager::getLODDecreaseFPS() { @@ -243,6 +251,14 @@ float LODManager::getRenderDistance() { int LODManager::getRenderedCount() { return lastRenderedCount; } +QString LODManager::getLODStatsRenderText() { + if (getUseAcuity()) { + auto avatarManager = DependencyManager::get(); + return QString("Renderable avatars: ") + QString::number(avatarManager->getNumberInRenderRange()) + " w/in " + QString::number((int)avatarManager->getRenderDistance()) + "m"; + } else { + return QString("Rendered objects: ") + 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; diff --git a/interface/src/LODManager.h b/interface/src/LODManager.h index 21a30bceaf..6b141004e5 100644 --- a/interface/src/LODManager.h +++ b/interface/src/LODManager.h @@ -89,16 +89,19 @@ public: }; static bool getUseAcuity(); static void setUseAcuity(bool newValue); - 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 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 void setRenderDistanceInverseHighLimit(float newValue) { _renderDistanceController.setControlledValueHighLimit(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); diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 7c1a52f1b3..4f59e21cda 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -34,6 +34,7 @@ #include "Application.h" #include "Avatar.h" #include "AvatarManager.h" +#include "LODManager.h" #include "Menu.h" #include "MyAvatar.h" #include "SceneScriptingInterface.h" @@ -76,13 +77,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(); { @@ -100,8 +94,8 @@ void AvatarManager::init() { scene->enqueuePendingChanges(pendingChanges); const float target_fps = qApp->getTargetFrameRate(); - _renderDistanceController.setMeasuredValueSetpoint(target_fps); - _renderDistanceController.setControlledValueHighLimit(avatarRenderDistanceInverseHighLimit.get()); + _renderDistanceController.setMeasuredValueSetpoint(target_fps / 2.0f); + _renderDistanceController.setControlledValueHighLimit(DependencyManager::get()->getRenderDistanceInverseHighLimit()); _renderDistanceController.setControlledValueLowLimit(1.0f / (float) TREE_SCALE); // Advice for tuning parameters: // See PIDController.h. There's a section on tuning in the reference. diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index 84a4bc44b8..290dda3668 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -79,7 +79,7 @@ public: 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); + Q_INVOKABLE void setRenderDistanceInverseHighLimit(float newValue) { _renderDistanceController.setControlledValueHighLimit(newValue); } public slots: void setShouldShowReceiveStats(bool shouldShowReceiveStats) { _shouldShowReceiveStats = shouldShowReceiveStats; } diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index bc08391bbe..133fc409fb 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -225,7 +225,7 @@ void PreferencesDialog::loadPreferences() { ui.useAcuityCheckBox->setChecked(lodManager->getUseAcuity()); ui.desktopMinimumFPSSpin->setValue(lodManager->getDesktopLODDecreaseFPS()); ui.hmdMinimumFPSSpin->setValue(lodManager->getHMDLODDecreaseFPS()); - ui.smallestReasonableRenderHorizon->setValue(1.0f / DependencyManager::get()->getRenderDistanceInverseHighLimit()); + ui.smallestReasonableRenderHorizon->setValue(1.0f / lodManager->getRenderDistanceInverseHighLimit()); changeUseAcuity(); } @@ -318,5 +318,5 @@ void PreferencesDialog::savePreferences() { lodManager->setUseAcuity(ui.useAcuityCheckBox->isChecked()); lodManager->setDesktopLODDecreaseFPS(ui.desktopMinimumFPSSpin->value()); lodManager->setHMDLODDecreaseFPS(ui.hmdMinimumFPSSpin->value()); - DependencyManager::get()->setRenderDistanceInverseHighLimit(1.0f / ui.smallestReasonableRenderHorizon->value()); + lodManager->setRenderDistanceInverseHighLimit(1.0f / ui.smallestReasonableRenderHorizon->value()); } diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index a86ed97f0c..b82ab93068 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -283,9 +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(avatarRenderableCount, DependencyManager::get()->getRenderedCount()); //FIXME avatarManager->getNumberInRenderRange()); - STAT_UPDATE(avatarRenderDistance, (int)round(DependencyManager::get()->getRenderDistance())); // FIXME avatarManager->getRenderDistance())); // deliberately truncating + 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; From e058057e3da120b2b183faa5605b8948f85136f6 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Wed, 16 Dec 2015 15:41:23 -0800 Subject: [PATCH 04/21] fix logging --- libraries/shared/src/PIDController.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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] From 23ffcdca3e354259e3afbd8dc9c5cd829b315745 Mon Sep 17 00:00:00 2001 From: howard-stearns Date: Wed, 16 Dec 2015 17:01:14 -0800 Subject: [PATCH 05/21] big sweep --- interface/src/LODManager.cpp | 9 ++----- interface/src/Menu.h | 2 +- interface/src/avatar/Avatar.cpp | 20 --------------- interface/src/avatar/AvatarManager.cpp | 34 -------------------------- interface/src/avatar/AvatarManager.h | 20 +-------------- interface/src/ui/PreferencesDialog.cpp | 1 + 6 files changed, 5 insertions(+), 81 deletions(-) diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index 9d61a1c02c..eafc3b29f2 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -31,7 +31,6 @@ Setting::Handle renderDistanceInverseHighLimit("renderDistanceInverseHigh void LODManager::setRenderDistanceInverseHighLimit(float newValue) { renderDistanceInverseHighLimit.set(newValue); // persist it, and tell all the controllers that use it _renderDistanceController.setControlledValueHighLimit(newValue); - DependencyManager::get()->setRenderDistanceInverseHighLimit(newValue); } LODManager::LODManager() { @@ -252,12 +251,8 @@ int LODManager::getRenderedCount() { return lastRenderedCount; } QString LODManager::getLODStatsRenderText() { - if (getUseAcuity()) { - auto avatarManager = DependencyManager::get(); - return QString("Renderable avatars: ") + QString::number(avatarManager->getNumberInRenderRange()) + " w/in " + QString::number((int)avatarManager->getRenderDistance()) + "m"; - } else { - return QString("Rendered objects: ") + QString::number(getRenderedCount()) + " w/in " + QString::number((int)getRenderDistance()) + "m"; - } + 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) { diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 55266cf062..22da7d9127 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); @@ -128,7 +129,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 7a234f2b47..9cede63ab0 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -164,26 +164,6 @@ void Avatar::simulate(float deltaTime) { _shouldRenderBillboard = true; 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(); diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 4f59e21cda..a6fa611914 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -92,19 +92,6 @@ void AvatarManager::init() { _myAvatar->addToScene(_myAvatar, scene, pendingChanges); } scene->enqueuePendingChanges(pendingChanges); - - const float target_fps = qApp->getTargetFrameRate(); - _renderDistanceController.setMeasuredValueSetpoint(target_fps / 2.0f); - _renderDistanceController.setControlledValueHighLimit(DependencyManager::get()->getRenderDistanceInverseHighLimit()); - _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) { @@ -139,23 +126,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(); @@ -173,14 +143,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 290dda3668..0e3dab109d 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: @@ -67,20 +66,7 @@ public: void handleCollisionEvents(const CollisionEvents& collisionEvents); void updateAvatarPhysicsShape(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) { _renderDistanceController.setControlledValueHighLimit(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 133fc409fb..c561aa1b36 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -67,6 +67,7 @@ void PreferencesDialog::changeUseAcuity() { 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(), ""); From 7e54e1f7536694f3a7f3107e8dd7592815740ee7 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Wed, 16 Dec 2015 20:25:37 -0800 Subject: [PATCH 06/21] missed menu --- interface/src/LODManager.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index eafc3b29f2..5f55e0fed0 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -384,6 +384,7 @@ void LODManager::loadSettings() { 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() { From 5ac5ecfc224b7695bfa1bc11e54d37ead8bf45a4 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Wed, 16 Dec 2015 20:35:56 -0800 Subject: [PATCH 07/21] drop obsolete include --- interface/src/avatar/AvatarManager.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index a6fa611914..b550ce131f 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -34,7 +34,6 @@ #include "Application.h" #include "Avatar.h" #include "AvatarManager.h" -#include "LODManager.h" #include "Menu.h" #include "MyAvatar.h" #include "SceneScriptingInterface.h" From 75814e712c9ed4804b36d4dcc7919dc371b8307b Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Wed, 16 Dec 2015 20:56:54 -0800 Subject: [PATCH 08/21] compiler warning --- interface/src/ui/ApplicationCompositor.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/ui/ApplicationCompositor.cpp b/interface/src/ui/ApplicationCompositor.cpp index e5ecdfe217..abc3520c83 100644 --- a/interface/src/ui/ApplicationCompositor.cpp +++ b/interface/src/ui/ApplicationCompositor.cpp @@ -34,7 +34,6 @@ static const quint64 MSECS_TO_USECS = 1000ULL; static const quint64 TOOLTIP_DELAY = 500 * MSECS_TO_USECS; -static const float RETICLE_COLOR[] = { 0.0f, 198.0f / 255.0f, 244.0f / 255.0f }; static const float reticleSize = TWO_PI / 100.0f; static const float CURSOR_PIXEL_SIZE = 32.0f; From 41052083c3fd141747c6ef4f7bd86c9582c0cb4e Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Fri, 18 Dec 2015 17:05:58 -0800 Subject: [PATCH 09/21] Render scenery even if it is far away. --- interface/src/LODManager.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index 5f55e0fed0..1dff1da0a7 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -40,12 +40,11 @@ LODManager::LODManager() { 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 AvatarList.setRenderDistanceControllerHistory("avatar render", 300)) - //_renderDistanceController.setHistorySize("avatar render", target_fps * 4); + // 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. - //setRenderDistanceControllerHistory("FIXME", 240); } float LODManager::getLODDecreaseFPS() { @@ -279,7 +278,9 @@ bool LODManager::shouldRender(const RenderArgs* args, const AABox& bounds) { float distanceToCamera = glm::length(bounds.calcCenter() - args->_viewFrustum->getPosition()); float largestDimension = bounds.getLargestDimension(); if (!getUseAcuity()) { - bool isRendered = fabsf(distanceToCamera - largestDimension) < renderDistance; + const float scenerySize = 300; // meters + bool isRendered = (largestDimension > scenerySize) || // render scenery regardless of distance + (fabsf(distanceToCamera - largestDimension) < renderDistance); renderedCount += isRendered ? 1 : 0; return isRendered; } From cc35eaf4be5cf306fb7a1627c7c269e18d78caaf Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Mon, 28 Dec 2015 17:32:10 -0800 Subject: [PATCH 10/21] Added glow effect to ravestick --- examples/flowArts/raveStick/raveStick.js | 91 ++++++++++++++++++++---- unpublishedScripts/hiddenEntityReset.js | 64 ++++++++++++++++- unpublishedScripts/masterReset.js | 66 ++++++++++++++++- 3 files changed, 206 insertions(+), 15 deletions(-) diff --git a/examples/flowArts/raveStick/raveStick.js b/examples/flowArts/raveStick/raveStick.js index 5fb019bf97..5021559824 100644 --- a/examples/flowArts/raveStick/raveStick.js +++ b/examples/flowArts/raveStick/raveStick.js @@ -24,6 +24,9 @@ RaveStick = function(spawnPosition) { green: 10, blue: 40 }]; + + + var stick = Entities.addEntity({ type: "Model", name: "raveStick", @@ -40,23 +43,25 @@ RaveStick = function(spawnPosition) { userData: JSON.stringify({ grabbableKey: { spatialKey: { - rightRelativePosition: { - x: 0.02, - y: 0, - z: 0 - }, - leftRelativePosition: { - x: -0.02, - y: 0, - z: 0 - }, - relativeRotation: Quat.fromPitchYawRollDegrees(90, 90, 0) + rightRelativePosition: { + x: 0.02, + y: 0, + z: 0 }, + leftRelativePosition: { + x: -0.02, + y: 0, + z: 0 + }, + relativeRotation: Quat.fromPitchYawRollDegrees(90, 90, 0) + }, invertSolidWhileHeld: true } }) }); + var glowEmitter = createGlowEmitter(); + var light = Entities.addEntity({ type: 'Light', name: "raveLight", @@ -82,14 +87,76 @@ RaveStick = function(spawnPosition) { green: 200, blue: 40 }; - function cleanup() { Entities.deleteEntity(stick); Entities.deleteEntity(light); + Entities.deleteEntity(glowEmitter); } this.cleanup = cleanup; + + function createGlowEmitter() { + var props = Entities.getEntityProperties(stick, ["position", "rotation"]); + var forwardVec = Quat.getFront(props.rotation); + var forwardQuat = Quat.rotationBetween(Vec3.UNIT_Z, forwardVec); + var position = props.position; + var color = { + red: 150, + green: 20, + blue: 100 + } + var props = { + type: "ParticleEffect", + name: "Rave Stick Glow Emitter", + position: position, + parentID: stick, + isEmitting: true, + colorStart: color, + color: { + red: 200, + green: 200, + blue: 255 + }, + colorFinish: color, + maxParticles: 100000, + lifespan: 0.8, + emitRate: 1000, + emitOrientation: forwardQuat, + emitSpeed: 0.2, + speedSpread: 0.0, + emitDimensions: { + x: 0, + y: 0, + z: 0 + }, + polarStart: 0, + polarFinish: 0, + azimuthStart: 0.1, + azimuthFinish: 0.01, + emitAcceleration: { + x: 0, + y: 0, + z: 0 + }, + accelerationSpread: { + x: .00, + y: .00, + z: .00 + }, + radiusStart: 0.01, + radiusFinish: 0.005, + alpha: 0.7, + alphaSpread: 0.1, + alphaStart: 0.1, + alphaFinish: 0.1, + textures: "https://s3.amazonaws.com/hifi-public/eric/textures/particleSprites/beamParticle.png", + emitterShouldTrail: false + } + var glowEmitter = Entities.addEntity(props); + return glowEmitter; + + } } \ No newline at end of file diff --git a/unpublishedScripts/hiddenEntityReset.js b/unpublishedScripts/hiddenEntityReset.js index a53d6e721f..6d29858fb9 100644 --- a/unpublishedScripts/hiddenEntityReset.js +++ b/unpublishedScripts/hiddenEntityReset.js @@ -170,10 +170,12 @@ function createRaveStick(position) { var modelURL = "http://hifi-content.s3.amazonaws.com/eric/models/raveStick.fbx"; + var rotation = Quat.fromPitchYawRollDegrees(0, 0, 0); var stick = Entities.addEntity({ type: "Model", name: "raveStick", modelURL: modelURL, + rotation: rotation, position: position, shapeType: 'box', collisionsWillMove: true, @@ -206,6 +208,66 @@ }) }); + var forwardVec = Quat.getFront(rotation); + var forwardQuat = Quat.rotationBetween(Vec3.UNIT_Z, forwardVec); + var color = { + red: 150, + green: 20, + blue: 100 + } + var raveGlowEmitter = Entities.addEntity({ + type: "ParticleEffect", + name: "Rave Stick Glow Emitter", + position: position, + parentID: stick, + isEmitting: true, + colorStart: color, + color: { + red: 200, + green: 200, + blue: 255 + }, + colorFinish: color, + maxParticles: 100000, + lifespan: 0.8, + emitRate: 1000, + emitOrientation: forwardQuat, + emitSpeed: 0.2, + speedSpread: 0.0, + emitDimensions: { + x: 0, + y: 0, + z: 0 + }, + polarStart: 0, + polarFinish: 0, + azimuthStart: 0.1, + azimuthFinish: 0.01, + emitAcceleration: { + x: 0, + y: 0, + z: 0 + }, + accelerationSpread: { + x: .00, + y: .00, + z: .00 + }, + radiusStart: 0.01, + radiusFinish: 0.005, + alpha: 0.7, + alphaSpread: 0.1, + alphaStart: 0.1, + alphaFinish: 0.1, + textures: "https://s3.amazonaws.com/hifi-public/eric/textures/particleSprites/beamParticle.png", + emitterShouldTrail: false, + userData: JSON.stringify({ + resetMe: { + resetMe: true + } + }) + }); + } function createGun(position) { @@ -1447,4 +1509,4 @@ }; // entity scripts always need to return a newly constructed object of our type return new ResetSwitch(); -}); +}); \ No newline at end of file diff --git a/unpublishedScripts/masterReset.js b/unpublishedScripts/masterReset.js index 2d6d9a0d01..3f1025eb5e 100644 --- a/unpublishedScripts/masterReset.js +++ b/unpublishedScripts/masterReset.js @@ -149,10 +149,12 @@ MasterReset = function() { function createRaveStick(position) { var modelURL = "http://hifi-content.s3.amazonaws.com/eric/models/raveStick.fbx"; + var rotation = Quat.fromPitchYawRollDegrees(0, 0, 0); var stick = Entities.addEntity({ type: "Model", name: "raveStick", modelURL: modelURL, + rotation: rotation, position: position, shapeType: 'box', collisionsWillMove: true, @@ -189,6 +191,66 @@ MasterReset = function() { } }) }); + + var forwardVec = Quat.getFront(rotation); + var forwardQuat = Quat.rotationBetween(Vec3.UNIT_Z, forwardVec); + var color = { + red: 150, + green: 20, + blue: 100 + } + var raveGlowEmitter = Entities.addEntity({ + type: "ParticleEffect", + name: "Rave Stick Glow Emitter", + position: position, + parentID: stick, + isEmitting: true, + colorStart: color, + color: { + red: 200, + green: 200, + blue: 255 + }, + colorFinish: color, + maxParticles: 100000, + lifespan: 0.8, + emitRate: 1000, + emitOrientation: forwardQuat, + emitSpeed: 0.2, + speedSpread: 0.0, + emitDimensions: { + x: 0, + y: 0, + z: 0 + }, + polarStart: 0, + polarFinish: 0, + azimuthStart: 0.1, + azimuthFinish: 0.01, + emitAcceleration: { + x: 0, + y: 0, + z: 0 + }, + accelerationSpread: { + x: .00, + y: .00, + z: .00 + }, + radiusStart: 0.01, + radiusFinish: 0.005, + alpha: 0.7, + alphaSpread: 0.1, + alphaStart: 0.1, + alphaFinish: 0.1, + textures: "https://s3.amazonaws.com/hifi-public/eric/textures/particleSprites/beamParticle.png", + emitterShouldTrail: false, + userData: JSON.stringify({ + resetMe: { + resetMe: true + } + }) + }); } function createGun(position) { @@ -1084,7 +1146,7 @@ MasterReset = function() { y: 0, z: 0.06 }, - relativeRotation: Quat.fromPitchYawRollDegrees(0,-90, -90) + relativeRotation: Quat.fromPitchYawRollDegrees(0, -90, -90) }, invertSolidWhileHeld: true } @@ -1432,4 +1494,4 @@ MasterReset = function() { Script.scriptEnding.connect(cleanup); } -}; +}; \ No newline at end of file From 3a6478aac1e7548e44d24f0d690c95ac56c1bdb1 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 28 Dec 2015 21:15:52 -0800 Subject: [PATCH 11/21] Update raveStick.js leading zeroes --- examples/flowArts/raveStick/raveStick.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/flowArts/raveStick/raveStick.js b/examples/flowArts/raveStick/raveStick.js index 5021559824..d1180e2b34 100644 --- a/examples/flowArts/raveStick/raveStick.js +++ b/examples/flowArts/raveStick/raveStick.js @@ -142,9 +142,9 @@ RaveStick = function(spawnPosition) { z: 0 }, accelerationSpread: { - x: .00, - y: .00, - z: .00 + x: 0.00, + y: 0.00, + z: 0.00 }, radiusStart: 0.01, radiusFinish: 0.005, @@ -159,4 +159,4 @@ RaveStick = function(spawnPosition) { return glowEmitter; } -} \ No newline at end of file +} From 79a60c06484a090ad3e58b8d049dbb7d8a06925e Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 28 Dec 2015 21:16:15 -0800 Subject: [PATCH 12/21] Update hiddenEntityReset.js leading zeroes --- unpublishedScripts/hiddenEntityReset.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/unpublishedScripts/hiddenEntityReset.js b/unpublishedScripts/hiddenEntityReset.js index 6d29858fb9..4352a5d562 100644 --- a/unpublishedScripts/hiddenEntityReset.js +++ b/unpublishedScripts/hiddenEntityReset.js @@ -249,9 +249,9 @@ z: 0 }, accelerationSpread: { - x: .00, - y: .00, - z: .00 + x: 0.00, + y: 0.00, + z: 0.00 }, radiusStart: 0.01, radiusFinish: 0.005, @@ -1509,4 +1509,4 @@ }; // entity scripts always need to return a newly constructed object of our type return new ResetSwitch(); -}); \ No newline at end of file +}); From 74badfb667813560db45c0ef406167c70ef3485f Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 28 Dec 2015 21:16:38 -0800 Subject: [PATCH 13/21] Update masterReset.js leading zeroes --- unpublishedScripts/masterReset.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/unpublishedScripts/masterReset.js b/unpublishedScripts/masterReset.js index 3f1025eb5e..8aedd1c650 100644 --- a/unpublishedScripts/masterReset.js +++ b/unpublishedScripts/masterReset.js @@ -233,9 +233,9 @@ MasterReset = function() { z: 0 }, accelerationSpread: { - x: .00, - y: .00, - z: .00 + x: 0.00, + y: 0.00, + z: 0.00 }, radiusStart: 0.01, radiusFinish: 0.005, @@ -1494,4 +1494,4 @@ MasterReset = function() { Script.scriptEnding.connect(cleanup); } -}; \ No newline at end of file +}; From c6e6aceb8527fb35753c0d603db069916dfb71df Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Wed, 30 Dec 2015 15:37:28 -0800 Subject: [PATCH 14/21] Optimize getVertexStream() by using a const& --- libraries/model/src/model/Geometry.h | 2 +- libraries/render-utils/src/DeferredLightingEffect.cpp | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/model/src/model/Geometry.h b/libraries/model/src/model/Geometry.h index fa29faff5f..f9d9b0eeb4 100755 --- a/libraries/model/src/model/Geometry.h +++ b/libraries/model/src/model/Geometry.h @@ -58,7 +58,7 @@ public: const gpu::Stream::FormatPointer getVertexFormat() const { return _vertexFormat; } // BufferStream on the mesh vertices and attributes matching the vertex format - const gpu::BufferStream getVertexStream() const { return _vertexStream; } + const gpu::BufferStream& getVertexStream() const { return _vertexStream; } // Index Buffer void setIndexBuffer(const BufferView& buffer); diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index db0e47de5e..e6892b95f4 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -819,8 +819,6 @@ model::MeshPointer DeferredLightingEffect::getSpotLightMesh() { //DEBUG: model::Mesh::Part part(0, indices, 0, model::Mesh::LINE_STRIP); _spotLightMesh->setPartBuffer(gpu::BufferView(new gpu::Buffer(sizeof(part), (gpu::Byte*) &part), gpu::Element::PART_DRAWCALL)); - - _spotLightMesh->getVertexStream(); } return _spotLightMesh; } From bfa9213a10faaec206b064979993f701aeb24f18 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Sun, 3 Jan 2016 20:22:39 -0800 Subject: [PATCH 15/21] Allow keyboard navigation of 'vr menu' --- interface/resources/qml/VrMenu.qml | 143 ++++++++++++++----------- interface/resources/qml/VrMenuItem.qml | 84 ++------------- interface/resources/qml/VrMenuView.qml | 78 ++++++++++++++ 3 files changed, 167 insertions(+), 138 deletions(-) create mode 100644 interface/resources/qml/VrMenuView.qml diff --git a/interface/resources/qml/VrMenu.qml b/interface/resources/qml/VrMenu.qml index 14a4a449fd..eef87ed943 100644 --- a/interface/resources/qml/VrMenu.qml +++ b/interface/resources/qml/VrMenu.qml @@ -1,7 +1,9 @@ import Hifi 1.0 as Hifi + import QtQuick 2.4 import QtQuick.Controls 1.3 import QtQuick.Controls.Styles 1.3 + import "controls" import "styles" @@ -21,15 +23,18 @@ Hifi.VrMenu { property var models: [] property var columns: [] - onEnabledChanged: { + console.log("Activating menu " + enabled); if (enabled && columns.length == 0) { + console.log(rootMenu) + console.log(rootMenu.items) pushColumn(rootMenu.items); } opacity = enabled ? 1.0 : 0.0 - if (enabled) { - forceActiveFocus() - } + offscreenFlags.navigationFocused = enabled; +// if (enabled) { + //forceActiveFocus() +// } } // The actual animator @@ -49,13 +54,12 @@ Hifi.VrMenu { } property var menuBuilder: Component { - Border { - HifiConstants { id: hifi } - property int menuDepth + VrMenuView { + property int menuDepth: root.models.length - 1 + model: root.models[menuDepth] Component.onCompleted: { - menuDepth = root.models.length - 1 - if (menuDepth == 0) { + if (menuDepth === 0) { x = lastMousePosition.x - 20 y = lastMousePosition.y - 20 } else { @@ -63,50 +67,11 @@ Hifi.VrMenu { x = lastColumn.x + 64; y = lastMousePosition.y - height / 2; } + //recalcSize(); } - border.color: hifi.colors.hifiBlue - color: hifi.colors.window - implicitHeight: listView.implicitHeight + 16 - implicitWidth: listView.implicitWidth + 16 - - Column { - id: listView - property real minWidth: 0 - anchors { - top: parent.top - topMargin: 8 - left: parent.left - leftMargin: 8 - right: parent.right - rightMargin: 8 - } - - Repeater { - model: root.models[menuDepth] - delegate: Loader { - id: loader - source: "VrMenuItem.qml" - Binding { - target: loader.item - property: "menuContainer" - value: root - when: loader.status == Loader.Ready - } - Binding { - target: loader.item - property: "source" - value: modelData - when: loader.status == Loader.Ready - } - Binding { - target: loader.item - property: "listView" - value: listView - when: loader.status == Loader.Ready - } - } - } + onSelected: { + root.selectItem(menuDepth, item) } } } @@ -116,14 +81,14 @@ Hifi.VrMenu { } function pushColumn(items) { - models.push(items) + models.push(itemsToModel(items)) if (columns.length) { var oldColumn = lastColumn(); //oldColumn.enabled = false } var newColumn = menuBuilder.createObject(root); columns.push(newColumn); - newColumn.forceActiveFocus(); + forceActiveFocus(); } function popColumn() { @@ -145,13 +110,41 @@ Hifi.VrMenu { curColumn.forceActiveFocus(); } - function selectItem(source) { + function itemsToModel(items) { + var newListModel = Qt.createQmlObject('import QtQuick 2.2; ListModel {}', root); + console.log(items) + console.log(items.length) + for (var i = 0; i < items.length; ++i) { + var item = items[i]; + switch (item.type) { + case 2: + newListModel.append({"type":item.type, "name": item.title, "item": item}) + break; + case 1: + newListModel.append({"type":item.type, "name": item.text, "item": item}) + break; + case 0: + newListModel.append({"type":item.type, "name": "-----", "item": item}) + break; + } + } + return newListModel; + } + + function selectItem(depth, source) { + var popped = false; + while (depth + 1 < columns.length) { + popColumn() + popped = true + } + switch (source.type) { case 2: + lastColumn().enabled = false pushColumn(source.items) break; case 1: - source.trigger() + if (!popped) source.trigger() enabled = false break; case 0: @@ -165,14 +158,6 @@ Hifi.VrMenu { } } - Keys.onPressed: { - switch (event.key) { - case Qt.Key_Escape: - root.popColumn() - event.accepted = true; - } - } - MouseArea { anchors.fill: parent id: mouseArea @@ -206,4 +191,36 @@ Hifi.VrMenu { function removeItem(menu, menuItem) { menu.removeItem(menuItem); } + + function previousItem() { + if (columns.length) { + lastColumn().incrementCurrentIndex() + } + } + + function nextItem() { + if (columns.length) { + lastColumn().decrementCurrentIndex() + } + } + + function selectCurrentItem() { + if (columns.length) { + var depth = columns.length - 1; + var index = lastColumn().currentIndex; + if (index >= 0) { + var model = models[depth]; + var item = model.get(index).item; + selectItem(depth, item); + } + } + } + + Keys.onDownPressed: previousItem(); + Keys.onUpPressed: nextItem(); + Keys.onSpacePressed: selectCurrentItem(); + Keys.onReturnPressed: selectCurrentItem(); + Keys.onRightPressed: selectCurrentItem(); + Keys.onLeftPressed: popColumn(); + Keys.onEscapePressed: popColumn(); } diff --git a/interface/resources/qml/VrMenuItem.qml b/interface/resources/qml/VrMenuItem.qml index fbde35059d..4dcde0e2ae 100644 --- a/interface/resources/qml/VrMenuItem.qml +++ b/interface/resources/qml/VrMenuItem.qml @@ -1,62 +1,23 @@ import QtQuick 2.4 import QtQuick.Controls 1.3 import QtQuick.Controls.Styles 1.3 -import "controls" + import "styles" +import "controls" Item { id: root - HifiConstants { - id: hifi - } + HifiConstants { id: hifi } + // The model object + property alias text: label.text property var source - property var menuContainer - property var listView - MouseArea { - anchors.left: parent.left - anchors.right: tag.right - anchors.rightMargin: -4 - anchors.top: parent.top - anchors.bottom: parent.bottom - acceptedButtons: Qt.LeftButton - hoverEnabled: true - - Rectangle { - id: highlight - visible: false - anchors.fill: parent - color: "#7f0e7077" - } - - onEntered: { - //if (source.type == 2 && enabled) { - // timer.start() - //} - highlight.visible = source.enabled - } - - onExited: { - timer.stop() - highlight.visible = false - } - - onClicked: { - select() - } - } implicitHeight: source.visible ? label.implicitHeight * 1.5 : 0 - implicitWidth: label.implicitWidth + label.height * 2.5 + implicitWidth: label.width + label.height * 2.5 visible: source.visible - - Timer { - id: timer - interval: 1000 - onTriggered: parent.select() - } - + width: parent.width FontAwesome { clip: true @@ -84,32 +45,18 @@ Item { Text { id: label - text: typedText() anchors.left: check.right anchors.leftMargin: 4 anchors.verticalCenter: parent.verticalCenter verticalAlignment: Text.AlignVCenter color: source.enabled ? hifi.colors.text : hifi.colors.disabledText - enabled: source.enabled && source.visible + enabled: source.visible && (source.type !== 0 ? source.enabled : false) visible: source.visible - function typedText() { - if (source) { - switch (source.type) { - case 2: - return source.title - case 1: - return source.text - case 0: - return "-----" - } - } - return "" - } } FontAwesome { id: tag - x: listView.width - width - 4 + x: root.parent.width - width size: label.height width: implicitWidth visible: source.visible && (source.type == 2) @@ -117,17 +64,4 @@ Item { anchors.verticalCenter: parent.verticalCenter color: label.color } - - function select() { - //timer.stop(); - var popped = false - while (columns.length - 1 > listView.parent.menuDepth) { - popColumn() - popped = true - } - - if (!popped || source.type != 1) { - root.menuContainer.selectItem(source) - } - } } diff --git a/interface/resources/qml/VrMenuView.qml b/interface/resources/qml/VrMenuView.qml new file mode 100644 index 0000000000..6758031491 --- /dev/null +++ b/interface/resources/qml/VrMenuView.qml @@ -0,0 +1,78 @@ +import QtQuick 2.4 +import QtQuick.Controls 1.3 +import QtQuick.Controls.Styles 1.3 + +import "styles" + +ListView { + id: root + HifiConstants { id: hifi } + width: 128 + height: count * 32 + onEnabledChanged: root.recalcSize(); + onVisibleChanged: root.recalcSize(); + signal selected(var item) + + highlight: Rectangle { + width: root.currentItem ? root.currentItem.width : 0 + height: root.currentItem ? root.currentItem.height : 0 + color: "lightsteelblue"; radius: 3 +// y: root.currentItem ? root.currentItem.y : 0 + } + + delegate: VrMenuItem { + text: name + source: item + onImplicitHeightChanged: root.recalcSize() + onImplicitWidthChanged: root.recalcSize() + + MouseArea { + anchors.fill: parent + hoverEnabled: true + onEntered: root.currentIndex = index + onClicked: root.selected(item) + } + } + + onCountChanged: recalcSize(); + + function recalcSize() { + if (model.count !== count || !visible) { + return; + } + + var originalIndex = currentIndex; + var maxWidth = width; + var newHeight = 0; + for (var i = 0; i < count; ++i) { + currentIndex = i; + if (!currentItem) { + continue; + } + if (currentItem && currentItem.implicitWidth > maxWidth) { + maxWidth = currentItem.implicitWidth + } + if (currentItem.visible) { + newHeight += currentItem.implicitHeight + } + } + if (maxWidth > width) { + width = maxWidth; + } + if (newHeight > height) { + height = newHeight + } + currentIndex = originalIndex; + } + + Border { + id: border + anchors.fill: parent + anchors.margins: -8 + z: parent.z - 1 + border.color: hifi.colors.hifiBlue + color: hifi.colors.window + } +} + + From 435ab8c4e8dd7f60f28df34d0da83dffa530e228 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Sun, 3 Jan 2016 20:22:55 -0800 Subject: [PATCH 16/21] Fix possible log spam issue --- interface/resources/qml/QmlWebWindow.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/QmlWebWindow.qml b/interface/resources/qml/QmlWebWindow.qml index c2076c93e3..188351c113 100644 --- a/interface/resources/qml/QmlWebWindow.qml +++ b/interface/resources/qml/QmlWebWindow.qml @@ -49,7 +49,7 @@ VrDialog { onUrlChanged: { var currentUrl = url.toString(); - var newUrl = urlHandler.fixupUrl(currentUrl); + var newUrl = urlHandler.fixupUrl(currentUrl).toString(); if (newUrl != currentUrl) { url = newUrl; } From 297e58fbc6db05b2d43f6a7bffd2e10b329c7ac4 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Sun, 3 Jan 2016 20:29:31 -0800 Subject: [PATCH 17/21] Cleanup --- interface/resources/qml/VrMenu.qml | 9 --------- interface/resources/qml/VrMenuItem.qml | 8 ++++---- interface/resources/qml/VrMenuView.qml | 9 ++++----- 3 files changed, 8 insertions(+), 18 deletions(-) diff --git a/interface/resources/qml/VrMenu.qml b/interface/resources/qml/VrMenu.qml index eef87ed943..738ec34a02 100644 --- a/interface/resources/qml/VrMenu.qml +++ b/interface/resources/qml/VrMenu.qml @@ -24,17 +24,11 @@ Hifi.VrMenu { property var columns: [] onEnabledChanged: { - console.log("Activating menu " + enabled); if (enabled && columns.length == 0) { - console.log(rootMenu) - console.log(rootMenu.items) pushColumn(rootMenu.items); } opacity = enabled ? 1.0 : 0.0 offscreenFlags.navigationFocused = enabled; -// if (enabled) { - //forceActiveFocus() -// } } // The actual animator @@ -67,7 +61,6 @@ Hifi.VrMenu { x = lastColumn.x + 64; y = lastMousePosition.y - height / 2; } - //recalcSize(); } onSelected: { @@ -112,8 +105,6 @@ Hifi.VrMenu { function itemsToModel(items) { var newListModel = Qt.createQmlObject('import QtQuick 2.2; ListModel {}', root); - console.log(items) - console.log(items.length) for (var i = 0; i < items.length; ++i) { var item = items[i]; switch (item.type) { diff --git a/interface/resources/qml/VrMenuItem.qml b/interface/resources/qml/VrMenuItem.qml index 4dcde0e2ae..2b1a4a3b5a 100644 --- a/interface/resources/qml/VrMenuItem.qml +++ b/interface/resources/qml/VrMenuItem.qml @@ -1,19 +1,19 @@ import QtQuick 2.4 import QtQuick.Controls 1.3 import QtQuick.Controls.Styles 1.3 - -import "styles" import "controls" +import "styles" Item { id: root - HifiConstants { id: hifi } + HifiConstants { + id: hifi + } // The model object property alias text: label.text property var source - implicitHeight: source.visible ? label.implicitHeight * 1.5 : 0 implicitWidth: label.width + label.height * 2.5 visible: source.visible diff --git a/interface/resources/qml/VrMenuView.qml b/interface/resources/qml/VrMenuView.qml index 6758031491..b00e21ba93 100644 --- a/interface/resources/qml/VrMenuView.qml +++ b/interface/resources/qml/VrMenuView.qml @@ -9,15 +9,16 @@ ListView { HifiConstants { id: hifi } width: 128 height: count * 32 - onEnabledChanged: root.recalcSize(); - onVisibleChanged: root.recalcSize(); + onEnabledChanged: recalcSize(); + onVisibleChanged: recalcSize(); + onCountChanged: recalcSize(); + signal selected(var item) highlight: Rectangle { width: root.currentItem ? root.currentItem.width : 0 height: root.currentItem ? root.currentItem.height : 0 color: "lightsteelblue"; radius: 3 -// y: root.currentItem ? root.currentItem.y : 0 } delegate: VrMenuItem { @@ -34,8 +35,6 @@ ListView { } } - onCountChanged: recalcSize(); - function recalcSize() { if (model.count !== count || !visible) { return; From 342d3e80bc87be9d00eb22b4582d4c6df132d9f1 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Mon, 4 Jan 2016 09:49:25 -0800 Subject: [PATCH 18/21] fix MSVC formatting --- interface/src/LODManager.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/LODManager.cpp b/interface/src/LODManager.cpp index 1dff1da0a7..10a288a44e 100644 --- a/interface/src/LODManager.cpp +++ b/interface/src/LODManager.cpp @@ -263,8 +263,7 @@ void LODManager::updatePIDRenderDistance(float targetFps, float measuredFps, flo // 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 { + } else { // Here we choose to just use the maximum render cutoff distance if throttled. distance = 1.0f / _renderDistanceController.getControlledValueLowLimit(); } From 4360595ed673a268c06fc0fb2f2e9e9cc8306d49 Mon Sep 17 00:00:00 2001 From: ericrius1 Date: Mon, 4 Jan 2016 11:29:57 -0800 Subject: [PATCH 19/21] Fix to pistol.js so muzzle flash particle system doesn't stick around forever --- examples/toybox/pistol/pistol.js | 68 +++++++++++++------------------- 1 file changed, 27 insertions(+), 41 deletions(-) diff --git a/examples/toybox/pistol/pistol.js b/examples/toybox/pistol/pistol.js index 7fb05d992f..e0f063d463 100644 --- a/examples/toybox/pistol/pistol.js +++ b/examples/toybox/pistol/pistol.js @@ -37,6 +37,13 @@ this.bulletForce = 10; this.showLaser = false; + this.laserOffsets = { + y: 0.095 + }; + this.firingOffsets = { + z: 0.16 + } + }; Pistol.prototype = { @@ -272,46 +279,12 @@ }); }, 100); - Entities.editEntity(this.flash, { - isEmitting: true - }); - Script.setTimeout(function() { - Entities.editEntity(_this.flash, { - isEmitting: false - }); - }, 100) - - }, - - preload: function(entityID) { - this.entityID = entityID; - this.laser = Overlays.addOverlay("line3d", { - start: ZERO_VECTOR, - end: ZERO_VECTOR, - color: COLORS.RED, - alpha: 1, - visible: true, - lineWidth: 2 - }); - this.laserOffsets = { - y: 0.095 - }; - this.firingOffsets = { - z: 0.16 - } - var gunProps = Entities.getEntityProperties(this.entityID, ['position', 'rotation']); - var position = gunProps.position; - var rotation = Quat.fromPitchYawRollDegrees(0, 0, 0); - this.firingDirection = Quat.getFront(rotation); - var upVec = Quat.getUp(rotation); - this.barrelPoint = Vec3.sum(position, Vec3.multiply(upVec, this.laserOffsets.y)); - this.barrelPoint = Vec3.sum(this.barrelPoint, Vec3.multiply(this.firingDirection, this.firingOffsets.z)) - - this.flash = Entities.addEntity({ + var flash = Entities.addEntity({ type: "ParticleEffect", position: this.barrelPoint, "name": "Muzzle Flash", - isEmitting: false, + lifetime: 4, + parentID: this.entityID, "color": { red: 228, green: 128, @@ -363,14 +336,27 @@ "additiveBlending": true, "textures": "http://ericrius1.github.io/PartiArt/assets/star.png" }); + Script.setTimeout(function() { + Entities.editEntity(flash, { + isEmitting: false + }); + }, 100) - Script.setTimeout(function() { - Entities.editEntity(_this.flash, {parentID: _this.entityID}); - }, 500) + }, + preload: function(entityID) { + this.entityID = entityID; + this.laser = Overlays.addOverlay("line3d", { + start: ZERO_VECTOR, + end: ZERO_VECTOR, + color: COLORS.RED, + alpha: 1, + visible: true, + lineWidth: 2 + }); }, }; // entity scripts always need to return a newly constructed object of our type return new Pistol(); -}); +}); \ No newline at end of file From 4bb03f8c2d34a288ba469060381ccf3a76dd1f00 Mon Sep 17 00:00:00 2001 From: "James B. Pollack" Date: Mon, 4 Jan 2016 12:34:08 -0800 Subject: [PATCH 20/21] add beam visualization if sphere doesnt actually hit anything --- examples/controllers/handControllerGrab.js | 38 +++++++++++++++------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/examples/controllers/handControllerGrab.js b/examples/controllers/handControllerGrab.js index ed02bd3709..9a12550b43 100644 --- a/examples/controllers/handControllerGrab.js +++ b/examples/controllers/handControllerGrab.js @@ -23,14 +23,14 @@ var WANT_DEBUG = false; // these tune time-averaging and "on" value for analog trigger // -var TRIGGER_SMOOTH_RATIO = 0.1; // Time averaging of trigger - 0.0 disables smoothing -var TRIGGER_ON_VALUE = 0.4; // Squeezed just enough to activate search or near grab -var TRIGGER_GRAB_VALUE = 0.85; // Squeezed far enough to complete distant grab +var TRIGGER_SMOOTH_RATIO = 0.1; // Time averaging of trigger - 0.0 disables smoothing +var TRIGGER_ON_VALUE = 0.4; // Squeezed just enough to activate search or near grab +var TRIGGER_GRAB_VALUE = 0.85; // Squeezed far enough to complete distant grab var TRIGGER_OFF_VALUE = 0.15; var BUMPER_ON_VALUE = 0.5; -var HAND_HEAD_MIX_RATIO = 0.0; // 0 = only use hands for search/move. 1 = only use head for search/move. +var HAND_HEAD_MIX_RATIO = 0.0; // 0 = only use hands for search/move. 1 = only use head for search/move. // // distant manipulation @@ -421,7 +421,7 @@ function MyController(hand) { this.searchSphereOn = function(location, size, color) { if (this.searchSphere === null) { var sphereProperties = { - position: location, + position: location, size: size, color: color, alpha: SEARCH_SPHERE_ALPHA, @@ -429,10 +429,15 @@ function MyController(hand) { visible: true } this.searchSphere = Overlays.addOverlay("sphere", sphereProperties); - } else { - Overlays.editOverlay(this.searchSphere, { position: location, size: size, color: color, visible: true }); + } else { + Overlays.editOverlay(this.searchSphere, { + position: location, + size: size, + color: color, + visible: true + }); } - } + } this.overlayLineOn = function(closePoint, farPoint, color) { if (this.overlayLine === null) { @@ -765,7 +770,7 @@ function MyController(hand) { if (this.triggerSmoothedSqueezed() || this.bumperSqueezed()) { this.lastPickTime = 0; var controllerHandInput = (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand; - this.startingHandRotation = Controller.getPoseValue(controllerHandInput).rotation; + this.startingHandRotation = Controller.getPoseValue(controllerHandInput).rotation; if (this.triggerSmoothedSqueezed()) { this.setState(STATE_SEARCHING); } else { @@ -788,13 +793,19 @@ function MyController(hand) { var controllerHandInput = (this.hand === RIGHT_HAND) ? Controller.Standard.RightHand : Controller.Standard.LeftHand; var currentHandRotation = Controller.getPoseValue(controllerHandInput).rotation; var handDeltaRotation = Quat.multiply(currentHandRotation, Quat.inverse(this.startingHandRotation)); - + var distantPickRay = { - origin: Camera.position, + origin: Camera.position, direction: Vec3.mix(Quat.getUp(this.getHandRotation()), Quat.getFront(Camera.orientation), HAND_HEAD_MIX_RATIO), length: PICK_MAX_DISTANCE }; + var searchVisualizationPickRay = { + origin: handPosition, + direction: Quat.getUp(this.getHandRotation()), + length: PICK_MAX_DISTANCE + }; + // Pick at some maximum rate, not always var pickRays = []; var now = Date.now(); @@ -1015,6 +1026,11 @@ function MyController(hand) { if (USE_PARTICLE_BEAM_FOR_SEARCHING === true) { this.handleParticleBeam(distantPickRay.origin, this.getHandRotation(), NO_INTERSECT_COLOR); } + + if (USE_OVERLAY_LINES_FOR_SEARCHING === true) { + this.overlayLineOn(searchVisualizationPickRay.origin, Vec3.sum(searchVisualizationPickRay.origin, Vec3.multiply(searchVisualizationPickRay.direction, LINE_LENGTH)), NO_INTERSECT_COLOR); + } + if (this.intersectionDistance > 0) { var SPHERE_INTERSECTION_SIZE = 0.011; var SEARCH_SPHERE_FOLLOW_RATE = 0.50; From f719f4a1cc82a820c609a381f6d4a9115ae4521a Mon Sep 17 00:00:00 2001 From: Brad Hefta-Gaub Date: Mon, 4 Jan 2016 13:31:01 -0800 Subject: [PATCH 21/21] hide the rear view mirror and the audio in the HMD --- interface/resources/qml/AvatarInputs.qml | 1 + interface/src/ui/ApplicationOverlay.cpp | 4 ++-- interface/src/ui/AvatarInputs.cpp | 1 + interface/src/ui/AvatarInputs.h | 2 ++ 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/AvatarInputs.qml b/interface/resources/qml/AvatarInputs.qml index 7888ffd967..49aeee3074 100644 --- a/interface/resources/qml/AvatarInputs.qml +++ b/interface/resources/qml/AvatarInputs.qml @@ -84,6 +84,7 @@ Hifi.AvatarInputs { Item { width: root.mirrorWidth height: 44 + visible: !root.isHMD x: root.mirrorLeftPad y: root.mirrorVisible ? root.mirrorTopPad + root.mirrorHeight : 5 diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 03d6432104..b11e4c7a95 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -86,7 +86,7 @@ void ApplicationOverlay::renderOverlay(RenderArgs* renderArgs) { // Now render the overlay components together into a single texture renderDomainConnectionStatusBorder(renderArgs); // renders the connected domain line - renderAudioScope(renderArgs); // audio scope in the very back + renderAudioScope(renderArgs); // audio scope in the very back - NOTE: this is the debug audio scope, not the VU meter renderRearView(renderArgs); // renders the mirror view selfie renderQmlUi(renderArgs); // renders a unit quad with the QML UI texture, and the text overlays from scripts renderOverlays(renderArgs); // renders Scripts Overlay and AudioScope @@ -158,7 +158,7 @@ void ApplicationOverlay::renderRearViewToFbo(RenderArgs* renderArgs) { } void ApplicationOverlay::renderRearView(RenderArgs* renderArgs) { - if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { + if (!qApp->isHMDMode() && Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { gpu::Batch& batch = *renderArgs->_batch; auto geometryCache = DependencyManager::get(); diff --git a/interface/src/ui/AvatarInputs.cpp b/interface/src/ui/AvatarInputs.cpp index a9827a23c2..7b5f80ee80 100644 --- a/interface/src/ui/AvatarInputs.cpp +++ b/interface/src/ui/AvatarInputs.cpp @@ -66,6 +66,7 @@ void AvatarInputs::update() { && !Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)); AI_UPDATE(cameraEnabled, !Menu::getInstance()->isOptionChecked(MenuOption::NoFaceTracking)); AI_UPDATE(cameraMuted, Menu::getInstance()->isOptionChecked(MenuOption::MuteFaceTracking)); + AI_UPDATE(isHMD, qApp->isHMDMode()); auto audioIO = DependencyManager::get(); const float AUDIO_METER_AVERAGING = 0.5; diff --git a/interface/src/ui/AvatarInputs.h b/interface/src/ui/AvatarInputs.h index 8ed4e8f163..36d3027a42 100644 --- a/interface/src/ui/AvatarInputs.h +++ b/interface/src/ui/AvatarInputs.h @@ -30,6 +30,7 @@ class AvatarInputs : public QQuickItem { AI_PROPERTY(float, audioLevel, 0) AI_PROPERTY(bool, mirrorVisible, false) AI_PROPERTY(bool, mirrorZoomed, true) + AI_PROPERTY(bool, isHMD, false) public: static AvatarInputs* getInstance(); @@ -44,6 +45,7 @@ signals: void audioLevelChanged(); void mirrorVisibleChanged(); void mirrorZoomedChanged(); + void isHMDChanged(); protected: Q_INVOKABLE void resetSensors();