From 60048a231f1409e21857c66a0651bdb397613a47 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 2 Jun 2017 10:26:54 -0700 Subject: [PATCH 01/54] god view controller --- scripts/system/controllers/godView.js | 117 ++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 scripts/system/controllers/godView.js diff --git a/scripts/system/controllers/godView.js b/scripts/system/controllers/godView.js new file mode 100644 index 0000000000..f4990b7921 --- /dev/null +++ b/scripts/system/controllers/godView.js @@ -0,0 +1,117 @@ +"use strict"; +// +// godView.js +// scripts/system/ +// +// Created by Brad Hefta-Gaub on 1 Jun 2017 +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +/* globals HMD, Script, Menu, Tablet, Camera */ +/* eslint indent: ["error", 4, { "outerIIFEBody": 0 }] */ + +(function() { // BEGIN LOCAL_SCOPE + +var godView = false; + +var GOD_CAMERA_OFFSET = -1; // 1 meter below the avatar +var GOD_VIEW_HEIGHT = 300; // 300 meter above the ground +var ABOVE_GROUND_DROP = 2; +var MOVE_BY = 1; + +function moveTo(position) { + if (godView) { + MyAvatar.position = position; + Camera.position = Vec3.sum(MyAvatar.position, {x:0, y: GOD_CAMERA_OFFSET, z: 0}); + } else { + MyAvatar.position = position; + } +} + +function keyPressEvent(event) { + if (godView) { + switch(event.text) { + case "UP": + moveTo(Vec3.sum(MyAvatar.position, {x:0.0, y: 0, z: -1 * MOVE_BY})); + break; + case "DOWN": + moveTo(Vec3.sum(MyAvatar.position, {x:0, y: 0, z: MOVE_BY})); + break; + case "LEFT": + moveTo(Vec3.sum(MyAvatar.position, {x:-1 * MOVE_BY, y: 0, z: 0})); + break; + case "RIGHT": + moveTo(Vec3.sum(MyAvatar.position, {x:MOVE_BY, y: 0, z: 0})); + break; + } + } +} + +function mousePress(event) { + if (godView) { + var pickRay = Camera.computePickRay(event.x, event.y); + Vec3.print("pr.o:", pickRay.origin); + Vec3.print("pr.d:", pickRay.direction); + Vec3.print("c.p:", Camera.position); + var pointingAt = Vec3.sum(pickRay.origin, Vec3.multiply(pickRay.direction,300)); + var moveToPosition = { x: pointingAt.x, y: MyAvatar.position.y, z: pointingAt.z }; + moveTo(moveToPosition); + } +} + + +function startGodView() { + if (!godView) { + Camera.mode = "first person"; + MyAvatar.position = Vec3.sum(MyAvatar.position, {x:0, y: GOD_VIEW_HEIGHT, z: 0}); + Camera.mode = "independent"; + Camera.position = Vec3.sum(MyAvatar.position, {x:0, y: GOD_CAMERA_OFFSET, z: 0}); + Camera.orientation = Quat.fromPitchYawRollDegrees(-90,0,0); + godView = true; + } +} + +function endGodView() { + if (godView) { + Camera.mode = "first person"; + MyAvatar.position = Vec3.sum(MyAvatar.position, {x:0, y: (-1 * GOD_VIEW_HEIGHT) + ABOVE_GROUND_DROP, z: 0}); + godView = false; + } +} + +var button; +var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + +function onClicked() { + if (godView) { + endGodView(); + } else { + startGodView(); + } +} + +button = tablet.addButton({ + icon: "icons/tablet-icons/switch-desk-i.svg", // FIXME - consider a better icon from Alan + text: "God View" +}); + +button.clicked.connect(onClicked); +Controller.keyPressEvent.connect(keyPressEvent); +Controller.mousePressEvent.connect(mousePress); + + +Script.scriptEnding.connect(function () { + if (godView) { + endGodView(); + } + button.clicked.disconnect(onClicked); + if (tablet) { + tablet.removeButton(button); + } + Controller.keyPressEvent.disconnect(keyPressEvent); + Controller.mousePressEvent.disconnect(mousePress); +}); + +}()); // END LOCAL_SCOPE From d8380923f0c54cd07b89dc266dfc50431536234c Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 14 Jun 2017 18:06:42 -0700 Subject: [PATCH 02/54] Introducing the SCeneUpdtate job to the engine to take care of performing transactions and introducing the stages --- interface/src/Application.cpp | 3 -- libraries/render/src/render/Engine.cpp | 3 ++ libraries/render/src/render/Scene.h | 6 +++- libraries/render/src/render/SceneTask.cpp | 21 ++++++++++++ libraries/render/src/render/SceneTask.h | 41 +++++++++++++++++++++++ libraries/render/src/render/Stage.cpp | 26 ++++++++++++++ libraries/render/src/render/Stage.h | 38 +++++++++++++++++++++ 7 files changed, 134 insertions(+), 4 deletions(-) create mode 100644 libraries/render/src/render/SceneTask.cpp create mode 100644 libraries/render/src/render/SceneTask.h create mode 100644 libraries/render/src/render/Stage.cpp create mode 100644 libraries/render/src/render/Stage.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9ce6cc9b25..cd3875521a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5140,10 +5140,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se } { - PerformanceTimer perfTimer("SceneProcessTransaction"); _main3DScene->enqueueTransaction(transaction); - - _main3DScene->processTransactionQueue(); } // For now every frame pass the renderContext diff --git a/libraries/render/src/render/Engine.cpp b/libraries/render/src/render/Engine.cpp index b3372a9305..19fececa4b 100644 --- a/libraries/render/src/render/Engine.cpp +++ b/libraries/render/src/render/Engine.cpp @@ -18,6 +18,8 @@ #include #include "EngineStats.h" +#include "SceneTask.h" + #include "Logging.h" using namespace render; @@ -31,6 +33,7 @@ public: void build(JobModel& task, const Varying& in, Varying& out) { task.addJob("Stats"); + task.addJob("PerformSceneTransaction"); } }; diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index fc0a8c1fca..48d09a9d52 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -128,7 +128,6 @@ protected: void removeItems(const ItemIDs& ids); void updateItems(const ItemIDs& ids, UpdateFunctors& functors); - // The Selection map mutable std::mutex _selectionsMutex; // mutable so it can be used in the thread safe getSelection const method SelectionMap _selections; @@ -139,6 +138,11 @@ protected: // void appendToSelection(const Selection& selection); // void mergeWithSelection(const Selection& selection); + // The Stages + StageMap _stages; + + + friend class Engine; }; diff --git a/libraries/render/src/render/SceneTask.cpp b/libraries/render/src/render/SceneTask.cpp new file mode 100644 index 0000000000..56010f246e --- /dev/null +++ b/libraries/render/src/render/SceneTask.cpp @@ -0,0 +1,21 @@ +// +// SceneTask.cpp +// render/src/render +// +// Created by Sam Gateau on 6/14/2017. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "SceneTask.h" + + +using namespace render; + +void PerformSceneTransaction::configure(const Config& config) { +} + +void PerformSceneTransaction::run(const RenderContextPointer& renderContext) { + renderContext->_scene->processTransactionQueue(); +} diff --git a/libraries/render/src/render/SceneTask.h b/libraries/render/src/render/SceneTask.h new file mode 100644 index 0000000000..0cf2dda395 --- /dev/null +++ b/libraries/render/src/render/SceneTask.h @@ -0,0 +1,41 @@ +// +// SceneTask.h +// render/src/render +// +// Created by Sam Gateau on 6/14/2017. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_render_SceneTask_h +#define hifi_render_SceneTask_h + +#include "Engine.h" + +namespace render { + + class PerformSceneTransactionConfig : public Job::Config { + Q_OBJECT + public: + signals: + void dirty(); + + protected: + }; + + class PerformSceneTransaction { + public: + using Config = PerformSceneTransactionConfig; + using JobModel = Job::Model; + + void configure(const Config& config); + void run(const RenderContextPointer& renderContext); + protected: + }; + + +} + +#endif // hifi_render_SceneTask_h diff --git a/libraries/render/src/render/Stage.cpp b/libraries/render/src/render/Stage.cpp new file mode 100644 index 0000000000..1ee9b1d6ff --- /dev/null +++ b/libraries/render/src/render/Stage.cpp @@ -0,0 +1,26 @@ +// +// Stage.cpp +// render/src/render +// +// Created by Sam Gateau on 6/14/2017. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "Stage.h" + + +using namespace render; + + + +Stage::~Stage() { + +} + +Stage::Stage() : + _name() +{ +} + diff --git a/libraries/render/src/render/Stage.h b/libraries/render/src/render/Stage.h new file mode 100644 index 0000000000..5145810671 --- /dev/null +++ b/libraries/render/src/render/Stage.h @@ -0,0 +1,38 @@ +// +// Stage.h +// render/src/render +// +// Created by Sam Gateau on 6/14/2017. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_render_Stage_h +#define hifi_render_Stage_h + +#include +#include +#include + +namespace render { + + class Stage { + public: + using Name = std::string; + + Stage(); + virtual ~Stage(); + + protected: + Name _name; + }; + + using StagePointer = std::shared_ptr; + + using StageMap = std::map; + +} + +#endif // hifi_render_Stage_h From df340a5b55fad72e7c504967a8b41b2e81dbde8b Mon Sep 17 00:00:00 2001 From: Sam Cake Date: Wed, 14 Jun 2017 22:39:47 -0700 Subject: [PATCH 03/54] COmpiling --- libraries/render/src/render/Scene.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index 48d09a9d52..6c536be34a 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -14,6 +14,7 @@ #include "Item.h" #include "SpatialTree.h" +#include "Stage.h" #include "Selection.h" namespace render { From 9ae2861ee6c020e86b56237cb86c44586fbdad44 Mon Sep 17 00:00:00 2001 From: samcake Date: Wed, 21 Jun 2017 18:29:38 -0700 Subject: [PATCH 04/54] Moving the stage objects under the scene umbrella and creating a cear task to update the scene elements --- interface/src/Application.cpp | 6 ++-- .../render-utils/src/BackgroundStage.cpp | 13 +++++++- libraries/render-utils/src/BackgroundStage.h | 12 +++++++- libraries/render-utils/src/LightStage.cpp | 10 +++++++ libraries/render-utils/src/LightStage.h | 23 ++++++++++---- .../render-utils/src/UpdateSceneTask.cpp | 24 +++++++++++++++ libraries/render-utils/src/UpdateSceneTask.h | 30 +++++++++++++++++++ libraries/render/src/render/Engine.cpp | 1 - libraries/render/src/render/Scene.cpp | 23 ++++++++++++++ libraries/render/src/render/Scene.h | 12 ++++++-- 10 files changed, 140 insertions(+), 14 deletions(-) create mode 100644 libraries/render-utils/src/UpdateSceneTask.cpp create mode 100644 libraries/render-utils/src/UpdateSceneTask.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index c5ba7be12b..d44ca58a89 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -111,10 +111,7 @@ #include #include #include -#include -#include -#include -#include +#include #include #include #include @@ -1902,6 +1899,7 @@ void Application::initializeGL() { render::CullFunctor cullFunctor = LODManager::shouldRender; static const QString RENDER_FORWARD = "HIFI_RENDER_FORWARD"; bool isDeferred = !QProcessEnvironment::systemEnvironment().contains(RENDER_FORWARD); + _renderEngine->addJob("UpdateScene"); _renderEngine->addJob("SecondaryCameraFrame", cullFunctor); _renderEngine->addJob("RenderMainView", cullFunctor, isDeferred); _renderEngine->load(); diff --git a/libraries/render-utils/src/BackgroundStage.cpp b/libraries/render-utils/src/BackgroundStage.cpp index 5c2f55954a..1d1aa877e4 100644 --- a/libraries/render-utils/src/BackgroundStage.cpp +++ b/libraries/render-utils/src/BackgroundStage.cpp @@ -137,4 +137,15 @@ void DrawBackgroundStage::run(const render::RenderContextPointer& renderContext, } */ -} \ No newline at end of file +} + +BackgroundStageSetup::BackgroundStageSetup() { +} + +void BackgroundStageSetup::run(const render::RenderContextPointer& renderContext) { + auto stage = renderContext->_scene->getStage("BACKGROUND_STAGE"); + if (!stage) { + renderContext->_scene->resetStage("BACKGROUND_STAGE", std::make_shared()); + } +} + diff --git a/libraries/render-utils/src/BackgroundStage.h b/libraries/render-utils/src/BackgroundStage.h index 1dd1651c98..2f0231b071 100644 --- a/libraries/render-utils/src/BackgroundStage.h +++ b/libraries/render-utils/src/BackgroundStage.h @@ -15,12 +15,13 @@ #include #include #include +#include #include "LightingModel.h" // Background stage to set up background-related rendering tasks -class BackgroundStage { +class BackgroundStage : public render::Stage { public: using Index = render::indexed_container::Index; static const Index INVALID_INDEX { render::indexed_container::INVALID_INDEX }; @@ -66,6 +67,15 @@ public: }; using BackgroundStagePointer = std::shared_ptr; +class BackgroundStageSetup { +public: + using JobModel = render::Job::Model; + + BackgroundStageSetup(); + void run(const render::RenderContextPointer& renderContext); + +protected: +}; class DrawBackgroundStage { public: diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index dd6a046dea..14abc746d4 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -165,3 +165,13 @@ void LightStage::updateLightArrayBuffer(Index lightId) { } } +LightStageSetup::LightStageSetup() { +} + +void LightStageSetup::run(const render::RenderContextPointer& renderContext) { + auto stage = renderContext->_scene->getStage("LIGHT_STAGE"); + if (!stage) { + renderContext->_scene->resetStage("LIGHT_STAGE", std::make_shared()); + } +} + diff --git a/libraries/render-utils/src/LightStage.h b/libraries/render-utils/src/LightStage.h index edbdff28fd..90501056e4 100644 --- a/libraries/render-utils/src/LightStage.h +++ b/libraries/render-utils/src/LightStage.h @@ -14,16 +14,19 @@ #include #include + +#include + +#include + #include - -#include "gpu/Framebuffer.h" - -#include "model/Light.h" +#include +#include class ViewFrustum; // Light stage to set up light-related rendering tasks -class LightStage { +class LightStage : public render::Stage { public: using Index = render::indexed_container::Index; static const Index INVALID_INDEX { render::indexed_container::INVALID_INDEX }; @@ -149,5 +152,15 @@ using LightStagePointer = std::shared_ptr; +class LightStageSetup { +public: + using JobModel = render::Job::Model; + + LightStageSetup(); + void run(const render::RenderContextPointer& renderContext); + +protected: +}; + #endif diff --git a/libraries/render-utils/src/UpdateSceneTask.cpp b/libraries/render-utils/src/UpdateSceneTask.cpp new file mode 100644 index 0000000000..4fd46b215f --- /dev/null +++ b/libraries/render-utils/src/UpdateSceneTask.cpp @@ -0,0 +1,24 @@ +// +// UpdateSceneTask.cpp +// render-utils/src/ +// +// Created by Sam Gateau on 6/21/2017. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "UpdateSceneTask.h" + +#include +#include "LightStage.h" +#include "BackgroundStage.h" + +void UpdateSceneTask::build(JobModel& task, const render::Varying& input, render::Varying& output) { + + task.addJob("PerformSceneTransaction"); + + task.addJob("LightStageSetup"); + +} + diff --git a/libraries/render-utils/src/UpdateSceneTask.h b/libraries/render-utils/src/UpdateSceneTask.h new file mode 100644 index 0000000000..227ede8ea3 --- /dev/null +++ b/libraries/render-utils/src/UpdateSceneTask.h @@ -0,0 +1,30 @@ +// +// UpdateSceneTask.h +// render-utils/src/ +// +// Created by Sam Gateau on 6/21/2017. +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#pragma once +#ifndef hifi_UpdateSceneTask_h +#define hifi_UpdateSceneTask_h + +#include +#include + + +class UpdateSceneTask { +public: + using JobModel = render::Task::Model; + + UpdateSceneTask() {} + + void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs); + +}; + + +#endif // hifi_UpdateSceneTask_h diff --git a/libraries/render/src/render/Engine.cpp b/libraries/render/src/render/Engine.cpp index 19fececa4b..5f67d40d17 100644 --- a/libraries/render/src/render/Engine.cpp +++ b/libraries/render/src/render/Engine.cpp @@ -33,7 +33,6 @@ public: void build(JobModel& task, const Varying& in, Varying& out) { task.addJob("Stats"); - task.addJob("PerformSceneTransaction"); } }; diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index 0e77b389a0..b8f93c52c3 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -237,3 +237,26 @@ void Scene::resetSelections(const Selections& selections) { } } } + +// Access a particular Stage (empty if doesn't exist) +// Thread safe +StagePointer Scene::getStage(const Stage::Name& name) const { + std::unique_lock lock(_stagesMutex); + auto found = _stages.find(name); + if (found == _stages.end()) { + return StagePointer(); + } else { + return (*found).second; + } + +} + +void Scene::resetStage(const Stage::Name& name, const StagePointer& stage) { + std::unique_lock lock(_stagesMutex); + auto found = _stages.find(name); + if (found == _stages.end()) { + _stages.insert(StageMap::value_type(name, stage)); + } else { + (*found).second = stage; + } +} \ No newline at end of file diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index 6c536be34a..09f6140618 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -111,6 +111,14 @@ public: // Access non-spatialized items (overlays, backgrounds) const ItemIDSet& getNonspatialSet() const { return _masterNonspatialSet; } + + + // Access a particular Stage (empty if doesn't exist) + // Thread safe + StagePointer getStage(const Stage::Name& name) const; + void resetStage(const Stage::Name& name, const StagePointer& stage); + + protected: // Thread safe elements that can be accessed from anywhere std::atomic _IDAllocator{ 1 }; // first valid itemID will be One @@ -139,11 +147,11 @@ protected: // void appendToSelection(const Selection& selection); // void mergeWithSelection(const Selection& selection); - // The Stages + // The Stage map + mutable std::mutex _stagesMutex; // mutable so it can be used in the thread safe getStage const method StageMap _stages; - friend class Engine; }; From 07e18eb3a8a29efee23015e3ba83a5ca6622e19c Mon Sep 17 00:00:00 2001 From: Sam Cake Date: Thu, 22 Jun 2017 01:12:32 -0700 Subject: [PATCH 05/54] Keep cleaning up the DeferredLightingEffect , removing stage s from there... --- .../src/RenderableZoneEntityItem.cpp | 6 +- .../render-utils/src/BackgroundStage.cpp | 5 +- .../render-utils/src/DebugDeferredBuffer.cpp | 9 ++- .../src/DeferredLightingEffect.cpp | 71 ++++++++++++++++--- .../render-utils/src/DeferredLightingEffect.h | 41 +++++++---- libraries/render-utils/src/LightClusters.cpp | 5 +- libraries/render-utils/src/LightPayload.cpp | 6 +- libraries/render-utils/src/LightStage.cpp | 6 +- libraries/render-utils/src/LightStage.h | 2 + .../render-utils/src/RenderShadowTask.cpp | 6 +- .../render-utils/src/SubsurfaceScattering.cpp | 7 +- .../render-utils/src/UpdateSceneTask.cpp | 2 + libraries/render-utils/src/ZoneRenderer.cpp | 17 +++-- libraries/render/src/render/Scene.h | 5 ++ 14 files changed, 142 insertions(+), 46 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index 2d4dd50e88..da0aef75aa 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -554,11 +554,13 @@ void RenderableZoneEntityItemMeta::setProceduralUserData(QString userData) { void RenderableZoneEntityItemMeta::render(RenderArgs* args) { if (!_stage) { - _stage = DependencyManager::get()->getLightStage(); + // _stage = DependencyManager::get()->getLightStage(); + _stage = args->_scene->getStage("LIGHT_STAGE"); } if (!_backgroundStage) { - _backgroundStage = DependencyManager::get()->getBackgroundStage(); + //_backgroundStage = DependencyManager::get()->getBackgroundStage(); + _backgroundStage = args->_scene->getStage("BACKGROUND_STAGE"); } { // Sun diff --git a/libraries/render-utils/src/BackgroundStage.cpp b/libraries/render-utils/src/BackgroundStage.cpp index 1d1aa877e4..b980887471 100644 --- a/libraries/render-utils/src/BackgroundStage.cpp +++ b/libraries/render-utils/src/BackgroundStage.cpp @@ -60,7 +60,8 @@ void DrawBackgroundStage::run(const render::RenderContextPointer& renderContext, // Background rendering decision - auto backgroundStage = DependencyManager::get()->getBackgroundStage(); + // auto backgroundStage = DependencyManager::get()->getBackgroundStage(); + auto backgroundStage = renderContext->_scene->getStage("BACKGROUND_STAGE"); model::SunSkyStagePointer background; model::SkyboxPointer skybox; if (backgroundStage->_currentFrame._backgrounds.size()) { @@ -70,7 +71,7 @@ void DrawBackgroundStage::run(const render::RenderContextPointer& renderContext, skybox = background->getSkybox(); } } else { - skybox = DependencyManager::get()->getDefaultSkybox(); + // skybox = DependencyManager::get()->getDefaultSkybox(); } /* auto backgroundMode = skyStage->getBackgroundMode(); diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index 3359b3a12d..e83789252c 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -432,9 +432,12 @@ void DebugDeferredBuffer::run(const RenderContextPointer& renderContext, const I batch.setResourceTexture(Lighting, deferredFramebuffer->getLightingTexture()); } - auto deferredLightingEffect = DependencyManager::get(); - assert(deferredLightingEffect->getLightStage()->getNumLights() > 0); - auto lightAndShadow = deferredLightingEffect->getLightStage()->getLightAndShadow(0); + // auto deferredLightingEffect = DependencyManager::get(); + auto lightStage = renderContext->_scene->getStage("LIGHT_STAGE"); + // assert(deferredLightingEffect->getLightStage()->getNumLights() > 0); + assert(lightStage->getNumLights() > 0); + // auto lightAndShadow = deferredLightingEffect->getLightStage()->getLightAndShadow(0); + auto lightAndShadow = lightStage->getLightAndShadow(0); const auto& globalShadow = lightAndShadow.second; if (globalShadow) { batch.setResourceTexture(Shadow, globalShadow->map); diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 0b4eee125b..374487a79d 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -101,7 +101,7 @@ void DeferredLightingEffect::init() { loadLightProgram(deferred_light_vert, local_lights_drawOutline_frag, true, _localLightOutline, _localLightOutlineLocations); // Light Stage and clusters - _lightStage = std::make_shared(); + /* _lightStage = std::make_shared(); // Allocate a global light representing the Global Directional light casting shadow (the sun) and the ambient light _allocatedLights.push_back(std::make_shared()); @@ -140,7 +140,7 @@ void DeferredLightingEffect::init() { auto irradianceSH = _defaultSkyboxAmbientTexture->getIrradiance(); if (irradianceSH) { lp->setAmbientSphere((*irradianceSH)); - } + }*/ } void DeferredLightingEffect::setupKeyLightBatch(gpu::Batch& batch, int lightBufferUnit, int ambientBufferUnit, int skyboxCubemapUnit) { @@ -275,11 +275,11 @@ void DeferredLightingEffect::setGlobalLight(const model::LightPointer& light) { globalLight->setAmbientSphere(light->getAmbientSphere()); globalLight->setAmbientMap(light->getAmbientMap());*/ } - +/* const model::LightPointer& DeferredLightingEffect::getGlobalLight() const { return _allocatedLights.front(); } - +*/ #include @@ -483,8 +483,10 @@ void PrepareDeferred::run(const RenderContextPointer& renderContext, const Input // Prepare a fresh Light Frame - auto deferredLightingEffect = DependencyManager::get(); - deferredLightingEffect->getLightStage()->_currentFrame.clear(); + //auto deferredLightingEffect = DependencyManager::get(); + //deferredLightingEffect->getLightStage()->_currentFrame.clear(); + auto lightStage = renderContext->_scene->getStage("LIGHT_STAGE"); + lightStage->_currentFrame.clear(); } @@ -547,8 +549,11 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext, // Global directional light and ambient pass - assert(deferredLightingEffect->getLightStage()->getNumLights() > 0); - auto lightAndShadow = deferredLightingEffect->getLightStage()->getLightAndShadow(0); + auto lightStage = renderContext->_scene->getStage("LIGHT_STAGE"); + // assert(deferredLightingEffect->getLightStage()->getNumLights() > 0); + assert(lightStage->getNumLights() > 0); + // auto lightAndShadow = deferredLightingEffect->getLightStage()->getLightAndShadow(0); + auto lightAndShadow = lightStage->getLightAndShadow(0); const auto& globalShadow = lightAndShadow.second; // Bind the shadow buffer @@ -749,3 +754,53 @@ void RenderDeferred::run(const RenderContextPointer& renderContext, const Inputs auto config = std::static_pointer_cast(renderContext->jobConfig); config->setGPUBatchRunTime(_gpuTimer->getGPUAverage(), _gpuTimer->getBatchAverage()); } + + + +void DefaultLightingSetup::run(const RenderContextPointer& renderContext) { + + if (!_defaultLight) { + if (!_defaultSkyboxTexture) { + auto textureCache = DependencyManager::get(); + { + PROFILE_RANGE(render, "Process Default Skybox"); + auto textureCache = DependencyManager::get(); + + auto skyboxUrl = PathUtils::resourcesPath().toStdString() + "images/Default-Sky-9-cubemap.ktx"; + + _defaultSkyboxTexture = gpu::Texture::unserialize(skyboxUrl); + _defaultSkyboxAmbientTexture = _defaultSkyboxTexture; + + _defaultSkybox->setCubemap(_defaultSkyboxTexture); + } + } + + auto lightStage = renderContext->_scene->getStage("LIGHT_STAGE"); + if (lightStage) { + + // Allocate a default global light directional and ambient + model::LightPointer lp = std::make_shared(); + lp->setType(model::Light::SUN); + lp->setDirection(glm::vec3(-1.0f)); + lp->setColor(glm::vec3(1.0f)); + lp->setIntensity(1.0f); + lp->setType(model::Light::SUN); + lp->setAmbientSpherePreset(gpu::SphericalHarmonics::Preset::OLD_TOWN_SQUARE); + + lp->setAmbientIntensity(0.5f); + lp->setAmbientMap(_defaultSkyboxAmbientTexture); + auto irradianceSH = _defaultSkyboxAmbientTexture->getIrradiance(); + if (irradianceSH) { + lp->setAmbientSphere((*irradianceSH)); + } + + // capture default light + _defaultLight = lp; + + // Add the global light to the light stage (for later shadow rendering) + auto defaultLightID = lightStage->addLight(lp); + lightStage->addShadow(defaultLightID); + } + } +} + diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index d69c72e97d..0e1b365149 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -51,25 +51,25 @@ public: void unsetKeyLightBatch(gpu::Batch& batch, int lightBufferUnit, int ambientBufferUnit, int skyboxCubemapUnit); // update global lighting - void setGlobalLight(const model::LightPointer& light); - const model::LightPointer& getGlobalLight() const; + // void setGlobalLight(const model::LightPointer& light); + // const model::LightPointer& getGlobalLight() const; - const LightStagePointer& getLightStage() { return _lightStage; } - const BackgroundStagePointer& getBackgroundStage() { return _backgroundStage; } + // const LightStagePointer& getLightStage() { return _lightStage; } + // const BackgroundStagePointer& getBackgroundStage() { return _backgroundStage; } void setShadowMapEnabled(bool enable) { _shadowMapEnabled = enable; }; void setAmbientOcclusionEnabled(bool enable) { _ambientOcclusionEnabled = enable; } bool isAmbientOcclusionEnabled() const { return _ambientOcclusionEnabled; } - model::SkyboxPointer getDefaultSkybox() const { return _defaultSkybox; } - gpu::TexturePointer getDefaultSkyboxTexture() const { return _defaultSkyboxTexture; } - gpu::TexturePointer getDefaultSkyboxAmbientTexture() const { return _defaultSkyboxAmbientTexture; } + // model::SkyboxPointer getDefaultSkybox() const { return _defaultSkybox; } + // gpu::TexturePointer getDefaultSkyboxTexture() const { return _defaultSkyboxTexture; } + // gpu::TexturePointer getDefaultSkyboxAmbientTexture() const { return _defaultSkyboxAmbientTexture; } private: DeferredLightingEffect() = default; - LightStagePointer _lightStage; - BackgroundStagePointer _backgroundStage; + // LightStagePointer _lightStage; + // BackgroundStagePointer _backgroundStage; bool _shadowMapEnabled{ false }; bool _ambientOcclusionEnabled{ false }; @@ -97,14 +97,14 @@ private: LightLocationsPtr _localLightLocations; LightLocationsPtr _localLightOutlineLocations; - using Lights = std::vector; + // using Lights = std::vector; - Lights _allocatedLights; - std::vector _globalLights; + // Lights _allocatedLights; + // std::vector _globalLights; - model::SkyboxPointer _defaultSkybox { new ProceduralSkybox() }; - gpu::TexturePointer _defaultSkyboxTexture; - gpu::TexturePointer _defaultSkyboxAmbientTexture; + // model::SkyboxPointer _defaultSkybox { new ProceduralSkybox() }; + // gpu::TexturePointer _defaultSkyboxTexture; + // gpu::TexturePointer _defaultSkyboxAmbientTexture; friend class LightClusteringPass; friend class RenderDeferredSetup; @@ -195,6 +195,17 @@ protected: gpu::RangeTimerPointer _gpuTimer; }; +class DefaultLightingSetup { +public: + using JobModel = render::Job::Model; + void run(const render::RenderContextPointer& renderContext); + +protected: + model::LightPointer _defaultLight; + model::SkyboxPointer _defaultSkybox { new ProceduralSkybox() }; + gpu::TexturePointer _defaultSkyboxTexture; + gpu::TexturePointer _defaultSkyboxAmbientTexture; +}; #endif // hifi_DeferredLightingEffect_h diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index e35120eb5b..79b755f310 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -574,8 +574,9 @@ void LightClusteringPass::run(const render::RenderContextPointer& renderContext, } // From the LightStage and the current frame, update the light cluster Grid - auto deferredLightingEffect = DependencyManager::get(); - auto lightStage = deferredLightingEffect->getLightStage(); + // auto deferredLightingEffect = DependencyManager::get(); + // auto lightStage = deferredLightingEffect->getLightStage(); + auto lightStage = renderContext->_scene->getStage("LIGHT_STAGE"); _lightClusters->updateLightStage(lightStage); _lightClusters->updateLightFrame(lightStage->_currentFrame, lightingModel->isPointLightEnabled(), lightingModel->isSpotLightEnabled()); diff --git a/libraries/render-utils/src/LightPayload.cpp b/libraries/render-utils/src/LightPayload.cpp index dbdf7129ef..d0cc8dfd18 100644 --- a/libraries/render-utils/src/LightPayload.cpp +++ b/libraries/render-utils/src/LightPayload.cpp @@ -55,7 +55,8 @@ LightPayload::~LightPayload() { void LightPayload::render(RenderArgs* args) { if (!_stage) { - _stage = DependencyManager::get()->getLightStage(); + // _stage = DependencyManager::get()->getLightStage(); + _stage = args->_scene->getStage("LIGHT_STAGE"); } // Do we need to allocate the light in the stage ? if (LightStage::isIndexInvalid(_index)) { @@ -123,7 +124,8 @@ KeyLightPayload::~KeyLightPayload() { void KeyLightPayload::render(RenderArgs* args) { if (!_stage) { - _stage = DependencyManager::get()->getLightStage(); + // _stage = DependencyManager::get()->getLightStage(); + _stage = args->_scene->getStage("LIGHT_STAGE"); } // Do we need to allocate the light in the stage ? if (LightStage::isIndexInvalid(_index)) { diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index 14abc746d4..10c99bf008 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -13,6 +13,9 @@ #include "LightStage.h" +LightStage::LightStage() { +} + LightStage::Shadow::Shadow(model::LightPointer light) : _light{ light}, _frustum{ std::make_shared() } { framebuffer = gpu::FramebufferPointer(gpu::Framebuffer::createShadowmap(MAP_SIZE)); map = framebuffer->getDepthStencilBuffer(); @@ -171,7 +174,8 @@ LightStageSetup::LightStageSetup() { void LightStageSetup::run(const render::RenderContextPointer& renderContext) { auto stage = renderContext->_scene->getStage("LIGHT_STAGE"); if (!stage) { - renderContext->_scene->resetStage("LIGHT_STAGE", std::make_shared()); + stage = std::make_shared(); + renderContext->_scene->resetStage("LIGHT_STAGE", stage); } } diff --git a/libraries/render-utils/src/LightStage.h b/libraries/render-utils/src/LightStage.h index 90501056e4..8273118f0c 100644 --- a/libraries/render-utils/src/LightStage.h +++ b/libraries/render-utils/src/LightStage.h @@ -96,6 +96,7 @@ public: LightPointer getLight(Index lightId) const { return _lights.get(lightId); } + Index getShadowId(Index lightId) const { if (checkLightId(lightId)) { return _descs[lightId].shadowId; @@ -112,6 +113,7 @@ public: return LightAndShadow(getLight(lightId), getShadow(lightId)); } + LightStage(); Lights _lights; LightMap _lightMap; Descs _descs; diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index ddb64bc69e..2d8f6c0cab 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -35,7 +35,8 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext, assert(renderContext->args); assert(renderContext->args->hasViewFrustum()); - auto lightStage = DependencyManager::get()->getLightStage(); + // auto lightStage = DependencyManager::get()->getLightStage(); + auto lightStage = renderContext->_scene->getStage("LIGHT_STAGE"); LightStage::Index globalLightIndex { 0 }; @@ -140,7 +141,8 @@ void RenderShadowTask::configure(const Config& configuration) { } void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, Output& output) { - auto lightStage = DependencyManager::get()->getLightStage(); + // auto lightStage = DependencyManager::get()->getLightStage(); + auto lightStage = renderContext->_scene->getStage("LIGHT_STAGE"); const auto globalShadow = lightStage->getShadow(0); // Cache old render args diff --git a/libraries/render-utils/src/SubsurfaceScattering.cpp b/libraries/render-utils/src/SubsurfaceScattering.cpp index 40b3c85675..d67369774c 100644 --- a/libraries/render-utils/src/SubsurfaceScattering.cpp +++ b/libraries/render-utils/src/SubsurfaceScattering.cpp @@ -532,9 +532,10 @@ void DebugSubsurfaceScattering::run(const render::RenderContextPointer& renderCo - - const auto light = DependencyManager::get()->getLightStage()->getLight(0); - + auto lightStage = renderContext->_scene->getStage("LIGHT_STAGE"); + // const auto light = DependencyManager::get()->getLightStage()->getLight(0); + const auto light = lightStage->getLight(0); + gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { batch.enableStereo(false); diff --git a/libraries/render-utils/src/UpdateSceneTask.cpp b/libraries/render-utils/src/UpdateSceneTask.cpp index 4fd46b215f..1a9beb4bed 100644 --- a/libraries/render-utils/src/UpdateSceneTask.cpp +++ b/libraries/render-utils/src/UpdateSceneTask.cpp @@ -13,6 +13,7 @@ #include #include "LightStage.h" #include "BackgroundStage.h" +#include "DeferredLightingEffect.h" void UpdateSceneTask::build(JobModel& task, const render::Varying& input, render::Varying& output) { @@ -20,5 +21,6 @@ void UpdateSceneTask::build(JobModel& task, const render::Varying& input, render task.addJob("LightStageSetup"); + task.addJob("DefaultLightingSetup"); } diff --git a/libraries/render-utils/src/ZoneRenderer.cpp b/libraries/render-utils/src/ZoneRenderer.cpp index 8f04265226..e20e7d9ed8 100644 --- a/libraries/render-utils/src/ZoneRenderer.cpp +++ b/libraries/render-utils/src/ZoneRenderer.cpp @@ -53,7 +53,8 @@ void ZoneRendererTask::build(JobModel& task, const Varying& input, Varying& oupu void SetupZones::run(const RenderContextPointer& context, const Inputs& inputs) { - auto backgroundStage = DependencyManager::get()->getBackgroundStage(); + // auto backgroundStage = DependencyManager::get()->getBackgroundStage(); + auto backgroundStage = context->_scene->getStage("BACKGROUND_STAGE"); backgroundStage->_currentFrame.clear(); // call render in the correct order first... @@ -130,14 +131,16 @@ void DebugZoneLighting::run(const render::RenderContextPointer& context, const I auto deferredTransform = inputs; - auto lightStage = DependencyManager::get()->getLightStage(); + // auto lightStage = DependencyManager::get()->getLightStage(); + auto lightStage = context->_scene->getStage("LIGHT_STAGE"); std::vector keyLightStack; if (lightStage && lightStage->_currentFrame._sunLights.size()) { for (auto index : lightStage->_currentFrame._sunLights) { keyLightStack.push_back(lightStage->getLight(index)); } } - keyLightStack.push_back(DependencyManager::get()->getGlobalLight()); + // keyLightStack.push_back(DependencyManager::get()->getGlobalLight()); + keyLightStack.push_back(lightStage->getLight(0)); std::vector ambientLightStack; if (lightStage && lightStage->_currentFrame._ambientLights.size()) { @@ -145,10 +148,12 @@ void DebugZoneLighting::run(const render::RenderContextPointer& context, const I ambientLightStack.push_back(lightStage->getLight(index)); } } - ambientLightStack.push_back(DependencyManager::get()->getGlobalLight()); + // ambientLightStack.push_back(DependencyManager::get()->getGlobalLight()); + ambientLightStack.push_back(lightStage->getLight(0)); - auto backgroundStage = DependencyManager::get()->getBackgroundStage(); + // auto backgroundStage = DependencyManager::get()->getBackgroundStage(); + auto backgroundStage = context->_scene->getStage("BACKGROUND_STAGE"); std::vector skyboxStack; if (backgroundStage && backgroundStage->_currentFrame._backgrounds.size()) { for (auto index : backgroundStage->_currentFrame._backgrounds) { @@ -158,7 +163,7 @@ void DebugZoneLighting::run(const render::RenderContextPointer& context, const I } } } - skyboxStack.push_back(DependencyManager::get()->getDefaultSkybox()); + // skyboxStack.push_back(DependencyManager::get()->getDefaultSkybox()); gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index 09f6140618..f0c5e7a3f0 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -116,6 +116,11 @@ public: // Access a particular Stage (empty if doesn't exist) // Thread safe StagePointer getStage(const Stage::Name& name) const; + template + std::shared_ptr getStage(const Stage::Name& name) const { + auto stage = getStage(name); + return (stage ? std::static_pointer_cast(stage) : std::shared_ptr()); + } void resetStage(const Stage::Name& name, const StagePointer& stage); From 20d8c11e28f84c2d2df66d81bd7ac6abe4b94e6d Mon Sep 17 00:00:00 2001 From: samcake Date: Thu, 22 Jun 2017 17:54:16 -0700 Subject: [PATCH 06/54] ALmost there, getting eback everything to work with the light and background stages in the scene, not in deferredLighting Effect anymore --- interface/src/Application.cpp | 2 +- interface/src/Util.cpp | 14 +-- interface/src/Util.h | 3 +- interface/src/ui/overlays/Cube3DOverlay.cpp | 4 +- interface/src/ui/overlays/Shape3DOverlay.cpp | 4 +- interface/src/ui/overlays/Sphere3DOverlay.cpp | 4 +- interface/src/ui/overlays/Text3DOverlay.cpp | 2 +- .../src/avatars-renderer/Avatar.cpp | 2 +- .../src/avatars-renderer/SkeletonModel.cpp | 6 +- .../src/avatars-renderer/SkeletonModel.h | 2 +- .../src/RenderableModelEntityItem.cpp | 2 +- .../src/RenderableShapeEntityItem.cpp | 4 +- .../src/RenderableZoneEntityItem.cpp | 4 +- .../render-utils/src/BackgroundStage.cpp | 5 +- .../src/DeferredLightingEffect.cpp | 98 +++++-------------- .../render-utils/src/DeferredLightingEffect.h | 3 +- libraries/render-utils/src/GeometryCache.cpp | 36 +++---- libraries/render-utils/src/GeometryCache.h | 36 +++---- .../render-utils/src/RenderPipelines.cpp | 12 +-- .../render-utils/src/UpdateSceneTask.cpp | 6 +- libraries/render-utils/src/ZoneRenderer.cpp | 20 ++-- libraries/render/src/render/ShapePipeline.cpp | 6 +- libraries/render/src/render/ShapePipeline.h | 4 +- tests/gpu-test/src/TestWindow.cpp | 2 +- tests/render-perf/src/main.cpp | 4 +- 25 files changed, 120 insertions(+), 165 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 690a833c3b..27361d0bd0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -5110,7 +5110,7 @@ namespace render { auto& batch = *args->_batch; DependencyManager::get()->bindSimpleProgram(batch); - renderWorldBox(batch); + renderWorldBox(args, batch); } } } diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index 78a503bc71..7822b78244 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -34,7 +34,7 @@ using namespace std; -void renderWorldBox(gpu::Batch& batch) { +void renderWorldBox(RenderArgs* args, gpu::Batch& batch) { auto geometryCache = DependencyManager::get(); // Show center of world @@ -115,7 +115,7 @@ void renderWorldBox(gpu::Batch& batch) { geometryIds[17]); - geometryCache->renderWireCubeInstance(batch, GREY4); + geometryCache->renderWireCubeInstance(args, batch, GREY4); // Draw meter markers along the 3 axis to help with measuring things const float MARKER_DISTANCE = 1.0f; @@ -123,23 +123,23 @@ void renderWorldBox(gpu::Batch& batch) { transform = Transform().setScale(MARKER_RADIUS); batch.setModelTransform(transform); - geometryCache->renderSolidSphereInstance(batch, RED); + geometryCache->renderSolidSphereInstance(args, batch, RED); transform = Transform().setTranslation(glm::vec3(MARKER_DISTANCE, 0.0f, 0.0f)).setScale(MARKER_RADIUS); batch.setModelTransform(transform); - geometryCache->renderSolidSphereInstance(batch, RED); + geometryCache->renderSolidSphereInstance(args, batch, RED); transform = Transform().setTranslation(glm::vec3(0.0f, MARKER_DISTANCE, 0.0f)).setScale(MARKER_RADIUS); batch.setModelTransform(transform); - geometryCache->renderSolidSphereInstance(batch, GREEN); + geometryCache->renderSolidSphereInstance(args, batch, GREEN); transform = Transform().setTranslation(glm::vec3(0.0f, 0.0f, MARKER_DISTANCE)).setScale(MARKER_RADIUS); batch.setModelTransform(transform); - geometryCache->renderSolidSphereInstance(batch, BLUE); + geometryCache->renderSolidSphereInstance(args, batch, BLUE); transform = Transform().setTranslation(glm::vec3(MARKER_DISTANCE, 0.0f, MARKER_DISTANCE)).setScale(MARKER_RADIUS); batch.setModelTransform(transform); - geometryCache->renderSolidSphereInstance(batch, GREY); + geometryCache->renderSolidSphereInstance(args, batch, GREY); } // Do some basic timing tests and report the results diff --git a/interface/src/Util.h b/interface/src/Util.h index b1b4c78bcb..48acb53936 100644 --- a/interface/src/Util.h +++ b/interface/src/Util.h @@ -16,8 +16,9 @@ #include #include +#include -void renderWorldBox(gpu::Batch& batch); +void renderWorldBox(RenderArgs* args, gpu::Batch& batch); void runTimingTests(); void runUnitTests(); diff --git a/interface/src/ui/overlays/Cube3DOverlay.cpp b/interface/src/ui/overlays/Cube3DOverlay.cpp index 8af4c1d908..707aabc241 100644 --- a/interface/src/ui/overlays/Cube3DOverlay.cpp +++ b/interface/src/ui/overlays/Cube3DOverlay.cpp @@ -73,7 +73,7 @@ void Cube3DOverlay::render(RenderArgs* args) { if (_isSolid) { transform.setScale(dimensions); batch->setModelTransform(transform); - geometryCache->renderSolidCubeInstance(*batch, cubeColor, pipeline); + geometryCache->renderSolidCubeInstance(args, *batch, cubeColor, pipeline); } else { geometryCache->bindSimpleProgram(*batch, false, false, false, true, true); if (getIsDashedLine()) { @@ -109,7 +109,7 @@ void Cube3DOverlay::render(RenderArgs* args) { } else { transform.setScale(dimensions); batch->setModelTransform(transform); - geometryCache->renderWireCubeInstance(*batch, cubeColor, pipeline); + geometryCache->renderWireCubeInstance(args, *batch, cubeColor, pipeline); } } } diff --git a/interface/src/ui/overlays/Shape3DOverlay.cpp b/interface/src/ui/overlays/Shape3DOverlay.cpp index 2556bc84aa..72c57565d4 100644 --- a/interface/src/ui/overlays/Shape3DOverlay.cpp +++ b/interface/src/ui/overlays/Shape3DOverlay.cpp @@ -53,9 +53,9 @@ void Shape3DOverlay::render(RenderArgs* args) { transform.setScale(dimensions); batch->setModelTransform(transform); if (_isSolid) { - geometryCache->renderSolidShapeInstance(*batch, _shape, cubeColor, pipeline); + geometryCache->renderSolidShapeInstance(args, *batch, _shape, cubeColor, pipeline); } else { - geometryCache->renderWireShapeInstance(*batch, _shape, cubeColor, pipeline); + geometryCache->renderWireShapeInstance(args, *batch, _shape, cubeColor, pipeline); } } } diff --git a/interface/src/ui/overlays/Sphere3DOverlay.cpp b/interface/src/ui/overlays/Sphere3DOverlay.cpp index 07c2861f16..67e11cf1d8 100644 --- a/interface/src/ui/overlays/Sphere3DOverlay.cpp +++ b/interface/src/ui/overlays/Sphere3DOverlay.cpp @@ -50,9 +50,9 @@ void Sphere3DOverlay::render(RenderArgs* args) { } if (_isSolid) { - geometryCache->renderSolidSphereInstance(*batch, sphereColor, pipeline); + geometryCache->renderSolidSphereInstance(args, *batch, sphereColor, pipeline); } else { - geometryCache->renderWireSphereInstance(*batch, sphereColor, pipeline); + geometryCache->renderWireSphereInstance(args, *batch, sphereColor, pipeline); } } } diff --git a/interface/src/ui/overlays/Text3DOverlay.cpp b/interface/src/ui/overlays/Text3DOverlay.cpp index ebc28ca86a..ed29bc4e1b 100644 --- a/interface/src/ui/overlays/Text3DOverlay.cpp +++ b/interface/src/ui/overlays/Text3DOverlay.cpp @@ -138,7 +138,7 @@ void Text3DOverlay::render(RenderArgs* args) { _textRenderer->draw(batch, 0, 0, getText(), textColor, glm::vec2(-1.0f), getDrawInFront()); // so before we continue, we must reset the pipeline batch.setPipeline(args->_pipeline->pipeline); - args->_pipeline->prepare(batch); + args->_pipeline->prepare(batch, args); } const render::ShapeKey Text3DOverlay::getShapeKey() { diff --git a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp index a0a348388e..6cdffff844 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/Avatar.cpp @@ -609,7 +609,7 @@ void Avatar::render(RenderArgs* renderArgs) { if (showCollisionShapes && shouldRenderHead(renderArgs) && _skeletonModel->isRenderable()) { PROFILE_RANGE_BATCH(batch, __FUNCTION__":skeletonBoundingCollisionShapes"); const float BOUNDING_SHAPE_ALPHA = 0.7f; - _skeletonModel->renderBoundingCollisionShapes(*renderArgs->_batch, getUniformScale(), BOUNDING_SHAPE_ALPHA); + _skeletonModel->renderBoundingCollisionShapes(renderArgs, *renderArgs->_batch, getUniformScale(), BOUNDING_SHAPE_ALPHA); } if (showReceiveStats || showNamesAboveHeads) { diff --git a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp index 2a2817e68b..9651951b46 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp +++ b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.cpp @@ -322,20 +322,20 @@ void SkeletonModel::computeBoundingShape() { _boundingCapsuleLocalOffset = invScale * offset; } -void SkeletonModel::renderBoundingCollisionShapes(gpu::Batch& batch, float scale, float alpha) { +void SkeletonModel::renderBoundingCollisionShapes(RenderArgs* args, gpu::Batch& batch, float scale, float alpha) { auto geometryCache = DependencyManager::get(); // draw a blue sphere at the capsule top point glm::vec3 topPoint = _translation + getRotation() * (scale * (_boundingCapsuleLocalOffset + (0.5f * _boundingCapsuleHeight) * Vectors::UNIT_Y)); batch.setModelTransform(Transform().setTranslation(topPoint).postScale(scale * _boundingCapsuleRadius)); - geometryCache->renderSolidSphereInstance(batch, glm::vec4(0.6f, 0.6f, 0.8f, alpha)); + geometryCache->renderSolidSphereInstance(args, batch, glm::vec4(0.6f, 0.6f, 0.8f, alpha)); // draw a yellow sphere at the capsule bottom point glm::vec3 bottomPoint = topPoint - glm::vec3(0.0f, scale * _boundingCapsuleHeight, 0.0f); glm::vec3 axis = topPoint - bottomPoint; batch.setModelTransform(Transform().setTranslation(bottomPoint).postScale(scale * _boundingCapsuleRadius)); - geometryCache->renderSolidSphereInstance(batch, glm::vec4(0.8f, 0.8f, 0.6f, alpha)); + geometryCache->renderSolidSphereInstance(args, batch, glm::vec4(0.8f, 0.8f, 0.6f, alpha)); // draw a green cylinder between the two points glm::vec3 origin(0.0f); diff --git a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.h b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.h index db87a37477..e48884c581 100644 --- a/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.h +++ b/libraries/avatars-renderer/src/avatars-renderer/SkeletonModel.h @@ -96,7 +96,7 @@ public: /// \return whether or not the head was found. glm::vec3 getDefaultEyeModelPosition() const; - void renderBoundingCollisionShapes(gpu::Batch& batch, float scale, float alpha); + void renderBoundingCollisionShapes(RenderArgs* args, gpu::Batch& batch, float scale, float alpha); float getBoundingCapsuleRadius() const { return _boundingCapsuleRadius; } float getBoundingCapsuleHeight() const { return _boundingCapsuleHeight; } const glm::vec3 getBoundingCapsuleOffset() const { return _boundingCapsuleLocalOffset; } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index f343fdb155..e94a965156 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -380,7 +380,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) { auto shapeTransform = getTransformToCenter(success); if (success) { batch.setModelTransform(shapeTransform); // we want to include the scale as well - DependencyManager::get()->renderWireCubeInstance(batch, greenColor); + DependencyManager::get()->renderWireCubeInstance(args, batch, greenColor); } return; } diff --git a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp index 27dd678d91..62ab3377a8 100644 --- a/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableShapeEntityItem.cpp @@ -128,9 +128,9 @@ void RenderableShapeEntityItem::render(RenderArgs* args) { auto pipeline = color.a < 1.0f ? geometryCache->getTransparentShapePipeline() : geometryCache->getOpaqueShapePipeline(); if (render::ShapeKey(args->_globalShapeKey).isWireframe()) { - geometryCache->renderWireShapeInstance(batch, MAPPING[_shape], color, pipeline); + geometryCache->renderWireShapeInstance(args, batch, MAPPING[_shape], color, pipeline); } else { - geometryCache->renderSolidShapeInstance(batch, MAPPING[_shape], color, pipeline); + geometryCache->renderSolidShapeInstance(args, batch, MAPPING[_shape], color, pipeline); } } diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index da0aef75aa..bb07454992 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -221,10 +221,10 @@ void RenderableZoneEntityItem::render(RenderArgs* args) { if (getShapeType() == SHAPE_TYPE_SPHERE) { shapeTransform.postScale(SPHERE_ENTITY_SCALE); batch.setModelTransform(shapeTransform); - geometryCache->renderWireSphereInstance(batch, DEFAULT_COLOR); + geometryCache->renderWireSphereInstance(args, batch, DEFAULT_COLOR); } else { batch.setModelTransform(shapeTransform); - geometryCache->renderWireCubeInstance(batch, DEFAULT_COLOR); + geometryCache->renderWireCubeInstance(args, batch, DEFAULT_COLOR); } break; } diff --git a/libraries/render-utils/src/BackgroundStage.cpp b/libraries/render-utils/src/BackgroundStage.cpp index b980887471..c164b584a9 100644 --- a/libraries/render-utils/src/BackgroundStage.cpp +++ b/libraries/render-utils/src/BackgroundStage.cpp @@ -60,7 +60,6 @@ void DrawBackgroundStage::run(const render::RenderContextPointer& renderContext, // Background rendering decision - // auto backgroundStage = DependencyManager::get()->getBackgroundStage(); auto backgroundStage = renderContext->_scene->getStage("BACKGROUND_STAGE"); model::SunSkyStagePointer background; model::SkyboxPointer skybox; @@ -69,9 +68,9 @@ void DrawBackgroundStage::run(const render::RenderContextPointer& renderContext, auto background = backgroundStage->getBackground(backgroundId); if (background) { skybox = background->getSkybox(); - } + } } else { - // skybox = DependencyManager::get()->getDefaultSkybox(); + skybox = backgroundStage->getBackground(0)->getSkybox(); } /* auto backgroundMode = skyStage->getBackgroundMode(); diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 374487a79d..84c972bab3 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -99,64 +99,23 @@ void DeferredLightingEffect::init() { loadLightProgram(deferred_light_vert, local_lights_shading_frag, true, _localLight, _localLightLocations); loadLightProgram(deferred_light_vert, local_lights_drawOutline_frag, true, _localLightOutline, _localLightOutlineLocations); - - // Light Stage and clusters - /* _lightStage = std::make_shared(); - - // Allocate a global light representing the Global Directional light casting shadow (the sun) and the ambient light - _allocatedLights.push_back(std::make_shared()); - model::LightPointer lp = _allocatedLights[0]; - lp->setType(model::Light::SUN); - lp->setDirection(glm::vec3(-1.0f)); - lp->setColor(glm::vec3(1.0f)); - lp->setIntensity(1.0f); - lp->setType(model::Light::SUN); - lp->setAmbientSpherePreset(gpu::SphericalHarmonics::Preset::OLD_TOWN_SQUARE); - - // Add the global light to the light stage (for later shadow rendering) - _globalLights.push_back(_lightStage->addLight(lp)); - _lightStage->addShadow(_globalLights[0]); - - - _backgroundStage = std::make_shared(); - - auto textureCache = DependencyManager::get(); - - { - PROFILE_RANGE(render, "Process Default Skybox"); - auto textureCache = DependencyManager::get(); - - auto skyboxUrl = PathUtils::resourcesPath().toStdString() + "images/Default-Sky-9-cubemap.ktx"; - - _defaultSkyboxTexture = gpu::Texture::unserialize(skyboxUrl); - _defaultSkyboxAmbientTexture = _defaultSkyboxTexture; - - _defaultSkybox->setCubemap(_defaultSkyboxTexture); - } - - - lp->setAmbientIntensity(0.5f); - lp->setAmbientMap(_defaultSkyboxAmbientTexture); - auto irradianceSH = _defaultSkyboxAmbientTexture->getIrradiance(); - if (irradianceSH) { - lp->setAmbientSphere((*irradianceSH)); - }*/ } -void DeferredLightingEffect::setupKeyLightBatch(gpu::Batch& batch, int lightBufferUnit, int ambientBufferUnit, int skyboxCubemapUnit) { +void DeferredLightingEffect::setupKeyLightBatch(const RenderArgs* args, gpu::Batch& batch, int lightBufferUnit, int ambientBufferUnit, int skyboxCubemapUnit) { PerformanceTimer perfTimer("DLE->setupBatch()"); model::LightPointer keySunLight; - if (_lightStage && _lightStage->_currentFrame._sunLights.size()) { - keySunLight = _lightStage->getLight(_lightStage->_currentFrame._sunLights.front()); + auto lightStage = args->_scene->getStage("LIGHT_STAGE"); + if (lightStage && lightStage->_currentFrame._sunLights.size()) { + keySunLight = lightStage->getLight(lightStage->_currentFrame._sunLights.front()); } else { - keySunLight = _allocatedLights[_globalLights.front()]; + keySunLight = lightStage->getLight(0); } model::LightPointer keyAmbiLight; - if (_lightStage && _lightStage->_currentFrame._ambientLights.size()) { - keyAmbiLight = _lightStage->getLight(_lightStage->_currentFrame._ambientLights.front()); + if (lightStage && lightStage->_currentFrame._ambientLights.size()) { + keyAmbiLight = lightStage->getLight(lightStage->_currentFrame._ambientLights.front()); } else { - keyAmbiLight = _allocatedLights[_globalLights.front()]; + keyAmbiLight = lightStage->getLight(0); } if (lightBufferUnit >= 0) { @@ -266,21 +225,6 @@ static void loadLightProgram(const char* vertSource, const char* fragSource, boo } -void DeferredLightingEffect::setGlobalLight(const model::LightPointer& light) { - /* auto globalLight = _allocatedLights.front(); - globalLight->setDirection(light->getDirection()); - globalLight->setColor(light->getColor()); - globalLight->setIntensity(light->getIntensity()); - globalLight->setAmbientIntensity(light->getAmbientIntensity()); - globalLight->setAmbientSphere(light->getAmbientSphere()); - globalLight->setAmbientMap(light->getAmbientMap());*/ -} -/* -const model::LightPointer& DeferredLightingEffect::getGlobalLight() const { - return _allocatedLights.front(); -} -*/ - #include model::MeshPointer DeferredLightingEffect::getPointLightMesh() { @@ -483,8 +427,6 @@ void PrepareDeferred::run(const RenderContextPointer& renderContext, const Input // Prepare a fresh Light Frame - //auto deferredLightingEffect = DependencyManager::get(); - //deferredLightingEffect->getLightStage()->_currentFrame.clear(); auto lightStage = renderContext->_scene->getStage("LIGHT_STAGE"); lightStage->_currentFrame.clear(); } @@ -550,9 +492,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext, // Global directional light and ambient pass auto lightStage = renderContext->_scene->getStage("LIGHT_STAGE"); - // assert(deferredLightingEffect->getLightStage()->getNumLights() > 0); assert(lightStage->getNumLights() > 0); - // auto lightAndShadow = deferredLightingEffect->getLightStage()->getLightAndShadow(0); auto lightAndShadow = lightStage->getLightAndShadow(0); const auto& globalShadow = lightAndShadow.second; @@ -563,7 +503,8 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext, auto& program = deferredLightingEffect->_directionalSkyboxLight; LightLocationsPtr locations = deferredLightingEffect->_directionalSkyboxLightLocations; - const auto& keyLight = deferredLightingEffect->_allocatedLights[deferredLightingEffect->_globalLights.front()]; + + auto keyLight = lightStage->getLight(0); // Setup the global directional pass pipeline { @@ -602,7 +543,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext, batch._glUniform4fv(locations->texcoordFrameTransform, 1, reinterpret_cast< const float* >(&textureFrameTransform)); // Setup the global lighting - deferredLightingEffect->setupKeyLightBatch(batch, locations->lightBufferUnit, locations->ambientBufferUnit, SKYBOX_MAP_UNIT); + deferredLightingEffect->setupKeyLightBatch(args, batch, locations->lightBufferUnit, locations->ambientBufferUnit, SKYBOX_MAP_UNIT); batch.draw(gpu::TRIANGLE_STRIP, 4); @@ -759,7 +700,7 @@ void RenderDeferred::run(const RenderContextPointer& renderContext, const Inputs void DefaultLightingSetup::run(const RenderContextPointer& renderContext) { - if (!_defaultLight) { + if (!_defaultLight || !_defaultBackground) { if (!_defaultSkyboxTexture) { auto textureCache = DependencyManager::get(); { @@ -779,7 +720,7 @@ void DefaultLightingSetup::run(const RenderContextPointer& renderContext) { if (lightStage) { // Allocate a default global light directional and ambient - model::LightPointer lp = std::make_shared(); + auto lp = std::make_shared(); lp->setType(model::Light::SUN); lp->setDirection(glm::vec3(-1.0f)); lp->setColor(glm::vec3(1.0f)); @@ -801,6 +742,19 @@ void DefaultLightingSetup::run(const RenderContextPointer& renderContext) { auto defaultLightID = lightStage->addLight(lp); lightStage->addShadow(defaultLightID); } + + auto backgroundStage = renderContext->_scene->getStage("BACKGROUND_STAGE"); + if (backgroundStage) { + + auto background = std::make_shared(); + background->setSkybox(_defaultSkybox); + + // capture deault background + _defaultBackground = background; + + // Add the global light to the light stage (for later shadow rendering) + auto defaultBackgroundID = backgroundStage->addBackground(_defaultBackground); + } } } diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 0e1b365149..fcbb8acf25 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -47,7 +47,7 @@ class DeferredLightingEffect : public Dependency { public: void init(); - void setupKeyLightBatch(gpu::Batch& batch, int lightBufferUnit, int ambientBufferUnit, int skyboxCubemapUnit); + void setupKeyLightBatch(const RenderArgs* args, gpu::Batch& batch, int lightBufferUnit, int ambientBufferUnit, int skyboxCubemapUnit); void unsetKeyLightBatch(gpu::Batch& batch, int lightBufferUnit, int ambientBufferUnit, int skyboxCubemapUnit); // update global lighting @@ -203,6 +203,7 @@ public: protected: model::LightPointer _defaultLight; + model::SunSkyStagePointer _defaultBackground; model::SkyboxPointer _defaultSkybox { new ProceduralSkybox() }; gpu::TexturePointer _defaultSkyboxTexture; gpu::TexturePointer _defaultSkyboxAmbientTexture; diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index dcf90012c1..49b844efb0 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -455,7 +455,7 @@ _nextID(0) { buildShapes(); GeometryCache::_simpleOpaquePipeline = std::make_shared(getSimplePipeline(false, false, true, false), nullptr, - [](const render::ShapePipeline&, gpu::Batch& batch) { + [](const render::ShapePipeline&, gpu::Batch& batch, RenderArgs* args) { // Set the defaults needed for a simple program batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO, DependencyManager::get()->getWhiteTexture()); @@ -463,7 +463,7 @@ _nextID(0) { ); GeometryCache::_simpleTransparentPipeline = std::make_shared(getSimplePipeline(false, true, true, false), nullptr, - [](const render::ShapePipeline&, gpu::Batch& batch) { + [](const render::ShapePipeline&, gpu::Batch& batch, RenderArgs* args) { // Set the defaults needed for a simple program batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO, DependencyManager::get()->getWhiteTexture()); @@ -471,7 +471,7 @@ _nextID(0) { ); GeometryCache::_simpleWirePipeline = std::make_shared(getSimplePipeline(false, false, true, true), nullptr, - [](const render::ShapePipeline&, gpu::Batch& batch) {}); + [](const render::ShapePipeline&, gpu::Batch& batch, RenderArgs* args) {}); } GeometryCache::~GeometryCache() { @@ -1938,7 +1938,7 @@ uint32_t toCompactColor(const glm::vec4& color) { static const size_t INSTANCE_COLOR_BUFFER = 0; -void renderInstances(gpu::Batch& batch, const glm::vec4& color, bool isWire, +void renderInstances(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, bool isWire, const render::ShapePipelinePointer& pipeline, GeometryCache::Shape shape) { // Add pipeline to name std::string instanceName = (isWire ? "wire_shapes_" : "solid_shapes_") + std::to_string(shape) + "_" + std::to_string(std::hash()(pipeline)); @@ -1951,9 +1951,9 @@ void renderInstances(gpu::Batch& batch, const glm::vec4& color, bool isWire, } // Add call to named buffer - batch.setupNamedCalls(instanceName, [isWire, pipeline, shape](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) { + batch.setupNamedCalls(instanceName, [args, isWire, pipeline, shape](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) { batch.setPipeline(pipeline->pipeline); - pipeline->prepare(batch); + pipeline->prepare(batch, args); if (isWire) { DependencyManager::get()->renderWireShapeInstances(batch, shape, data.count(), data.buffers[INSTANCE_COLOR_BUFFER]); @@ -1963,28 +1963,28 @@ void renderInstances(gpu::Batch& batch, const glm::vec4& color, bool isWire, }); } -void GeometryCache::renderSolidShapeInstance(gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) { - renderInstances(batch, color, false, pipeline, shape); +void GeometryCache::renderSolidShapeInstance(RenderArgs* args, gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) { + renderInstances(args, batch, color, false, pipeline, shape); } -void GeometryCache::renderWireShapeInstance(gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) { - renderInstances(batch, color, true, pipeline, shape); +void GeometryCache::renderWireShapeInstance(RenderArgs* args, gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) { + renderInstances(args, batch, color, true, pipeline, shape); } -void GeometryCache::renderSolidSphereInstance(gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) { - renderInstances(batch, color, false, pipeline, GeometryCache::Sphere); +void GeometryCache::renderSolidSphereInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) { + renderInstances(args, batch, color, false, pipeline, GeometryCache::Sphere); } -void GeometryCache::renderWireSphereInstance(gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) { - renderInstances(batch, color, true, pipeline, GeometryCache::Sphere); +void GeometryCache::renderWireSphereInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) { + renderInstances(args, batch, color, true, pipeline, GeometryCache::Sphere); } // Enable this in a debug build to cause 'box' entities to iterate through all the // available shape types, both solid and wireframes //#define DEBUG_SHAPES -void GeometryCache::renderSolidCubeInstance(gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) { +void GeometryCache::renderSolidCubeInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) { #ifdef DEBUG_SHAPES static auto startTime = usecTimestampNow(); renderInstances(INSTANCE_NAME, batch, color, pipeline, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) { @@ -2018,11 +2018,11 @@ void GeometryCache::renderSolidCubeInstance(gpu::Batch& batch, const glm::vec4& } }); #else - renderInstances(batch, color, false, pipeline, GeometryCache::Cube); + renderInstances(args, batch, color, false, pipeline, GeometryCache::Cube); #endif } -void GeometryCache::renderWireCubeInstance(gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) { +void GeometryCache::renderWireCubeInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) { static const std::string INSTANCE_NAME = __FUNCTION__; - renderInstances(batch, color, true, pipeline, GeometryCache::Cube); + renderInstances(args, batch, color, true, pipeline, GeometryCache::Cube); } diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index 9853269280..fa558a1151 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -172,46 +172,46 @@ public: void renderShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer); void renderWireShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer); - void renderSolidShapeInstance(gpu::Batch& batch, Shape shape, const glm::vec4& color = glm::vec4(1), + void renderSolidShapeInstance(RenderArgs* args, gpu::Batch& batch, Shape shape, const glm::vec4& color = glm::vec4(1), const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline); - void renderSolidShapeInstance(gpu::Batch& batch, Shape shape, const glm::vec3& color, + void renderSolidShapeInstance(RenderArgs* args, gpu::Batch& batch, Shape shape, const glm::vec3& color, const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline) { - renderSolidShapeInstance(batch, shape, glm::vec4(color, 1.0f), pipeline); + renderSolidShapeInstance(args, batch, shape, glm::vec4(color, 1.0f), pipeline); } - void renderWireShapeInstance(gpu::Batch& batch, Shape shape, const glm::vec4& color = glm::vec4(1), + void renderWireShapeInstance(RenderArgs* args, gpu::Batch& batch, Shape shape, const glm::vec4& color = glm::vec4(1), const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline); - void renderWireShapeInstance(gpu::Batch& batch, Shape shape, const glm::vec3& color, + void renderWireShapeInstance(RenderArgs* args, gpu::Batch& batch, Shape shape, const glm::vec3& color, const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline) { - renderWireShapeInstance(batch, shape, glm::vec4(color, 1.0f), pipeline); + renderWireShapeInstance(args, batch, shape, glm::vec4(color, 1.0f), pipeline); } - void renderSolidSphereInstance(gpu::Batch& batch, const glm::vec4& color, + void renderSolidSphereInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline); - void renderSolidSphereInstance(gpu::Batch& batch, const glm::vec3& color, + void renderSolidSphereInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec3& color, const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline) { - renderSolidSphereInstance(batch, glm::vec4(color, 1.0f), pipeline); + renderSolidSphereInstance(args, batch, glm::vec4(color, 1.0f), pipeline); } - void renderWireSphereInstance(gpu::Batch& batch, const glm::vec4& color, + void renderWireSphereInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline = _simpleWirePipeline); - void renderWireSphereInstance(gpu::Batch& batch, const glm::vec3& color, + void renderWireSphereInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec3& color, const render::ShapePipelinePointer& pipeline = _simpleWirePipeline) { - renderWireSphereInstance(batch, glm::vec4(color, 1.0f), pipeline); + renderWireSphereInstance(args, batch, glm::vec4(color, 1.0f), pipeline); } - void renderSolidCubeInstance(gpu::Batch& batch, const glm::vec4& color, + void renderSolidCubeInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline); - void renderSolidCubeInstance(gpu::Batch& batch, const glm::vec3& color, + void renderSolidCubeInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec3& color, const render::ShapePipelinePointer& pipeline = _simpleOpaquePipeline) { - renderSolidCubeInstance(batch, glm::vec4(color, 1.0f), pipeline); + renderSolidCubeInstance(args, batch, glm::vec4(color, 1.0f), pipeline); } - void renderWireCubeInstance(gpu::Batch& batch, const glm::vec4& color, + void renderWireCubeInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline = _simpleWirePipeline); - void renderWireCubeInstance(gpu::Batch& batch, const glm::vec3& color, + void renderWireCubeInstance(RenderArgs* args, gpu::Batch& batch, const glm::vec3& color, const render::ShapePipelinePointer& pipeline = _simpleWirePipeline) { - renderWireCubeInstance(batch, glm::vec4(color, 1.0f), pipeline); + renderWireCubeInstance(args, batch, glm::vec4(color, 1.0f), pipeline); } // Dynamic geometry diff --git a/libraries/render-utils/src/RenderPipelines.cpp b/libraries/render-utils/src/RenderPipelines.cpp index 42ed0bdad9..6c3a58b7e5 100644 --- a/libraries/render-utils/src/RenderPipelines.cpp +++ b/libraries/render-utils/src/RenderPipelines.cpp @@ -76,8 +76,8 @@ void initForwardPipelines(ShapePlumber& plumber); void addPlumberPipeline(ShapePlumber& plumber, const ShapeKey& key, const gpu::ShaderPointer& vertex, const gpu::ShaderPointer& pixel); -void batchSetter(const ShapePipeline& pipeline, gpu::Batch& batch); -void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch); +void batchSetter(const ShapePipeline& pipeline, gpu::Batch& batch, RenderArgs* args); +void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch, RenderArgs* args); void initOverlay3DPipelines(ShapePlumber& plumber) { auto vertex = gpu::Shader::createVertex(std::string(overlay3D_vert)); @@ -359,7 +359,7 @@ void addPlumberPipeline(ShapePlumber& plumber, } } -void batchSetter(const ShapePipeline& pipeline, gpu::Batch& batch) { +void batchSetter(const ShapePipeline& pipeline, gpu::Batch& batch, RenderArgs* args) { // Set a default albedo map batch.setResourceTexture(render::ShapePipeline::Slot::MAP::ALBEDO, DependencyManager::get()->getWhiteTexture()); @@ -382,13 +382,13 @@ void batchSetter(const ShapePipeline& pipeline, gpu::Batch& batch) { } } -void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch) { +void lightBatchSetter(const ShapePipeline& pipeline, gpu::Batch& batch, RenderArgs* args) { // Set the batch - batchSetter(pipeline, batch); + batchSetter(pipeline, batch, args); // Set the light if (pipeline.locations->lightBufferUnit >= 0) { - DependencyManager::get()->setupKeyLightBatch(batch, + DependencyManager::get()->setupKeyLightBatch(args, batch, pipeline.locations->lightBufferUnit, pipeline.locations->lightAmbientBufferUnit, pipeline.locations->lightAmbientMapUnit); diff --git a/libraries/render-utils/src/UpdateSceneTask.cpp b/libraries/render-utils/src/UpdateSceneTask.cpp index 1a9beb4bed..2daee5fb5a 100644 --- a/libraries/render-utils/src/UpdateSceneTask.cpp +++ b/libraries/render-utils/src/UpdateSceneTask.cpp @@ -16,11 +16,11 @@ #include "DeferredLightingEffect.h" void UpdateSceneTask::build(JobModel& task, const render::Varying& input, render::Varying& output) { - - task.addJob("PerformSceneTransaction"); - task.addJob("LightStageSetup"); + task.addJob("BackgroundStageSetup"); task.addJob("DefaultLightingSetup"); + + task.addJob("PerformSceneTransaction"); } diff --git a/libraries/render-utils/src/ZoneRenderer.cpp b/libraries/render-utils/src/ZoneRenderer.cpp index e20e7d9ed8..80be123f0f 100644 --- a/libraries/render-utils/src/ZoneRenderer.cpp +++ b/libraries/render-utils/src/ZoneRenderer.cpp @@ -52,14 +52,19 @@ void ZoneRendererTask::build(JobModel& task, const Varying& input, Varying& oupu } void SetupZones::run(const RenderContextPointer& context, const Inputs& inputs) { - - // auto backgroundStage = DependencyManager::get()->getBackgroundStage(); auto backgroundStage = context->_scene->getStage("BACKGROUND_STAGE"); backgroundStage->_currentFrame.clear(); // call render in the correct order first... render::renderItems(context, inputs); + // Finally add the default lights and background: + auto lightStage = context->_scene->getStage("LIGHT_STAGE"); + lightStage->_currentFrame.pushSunLight(0); + lightStage->_currentFrame.pushAmbientLight(0); + + backgroundStage->_currentFrame.pushBackground(0); + } const gpu::PipelinePointer& DebugZoneLighting::getKeyLightPipeline() { @@ -131,7 +136,6 @@ void DebugZoneLighting::run(const render::RenderContextPointer& context, const I auto deferredTransform = inputs; - // auto lightStage = DependencyManager::get()->getLightStage(); auto lightStage = context->_scene->getStage("LIGHT_STAGE"); std::vector keyLightStack; if (lightStage && lightStage->_currentFrame._sunLights.size()) { @@ -139,8 +143,7 @@ void DebugZoneLighting::run(const render::RenderContextPointer& context, const I keyLightStack.push_back(lightStage->getLight(index)); } } - // keyLightStack.push_back(DependencyManager::get()->getGlobalLight()); - keyLightStack.push_back(lightStage->getLight(0)); + // keyLightStack.push_back(lightStage->getLight(0)); std::vector ambientLightStack; if (lightStage && lightStage->_currentFrame._ambientLights.size()) { @@ -148,11 +151,8 @@ void DebugZoneLighting::run(const render::RenderContextPointer& context, const I ambientLightStack.push_back(lightStage->getLight(index)); } } - // ambientLightStack.push_back(DependencyManager::get()->getGlobalLight()); - ambientLightStack.push_back(lightStage->getLight(0)); + // ambientLightStack.push_back(lightStage->getLight(0)); - - // auto backgroundStage = DependencyManager::get()->getBackgroundStage(); auto backgroundStage = context->_scene->getStage("BACKGROUND_STAGE"); std::vector skyboxStack; if (backgroundStage && backgroundStage->_currentFrame._backgrounds.size()) { @@ -163,7 +163,7 @@ void DebugZoneLighting::run(const render::RenderContextPointer& context, const I } } } - // skyboxStack.push_back(DependencyManager::get()->getDefaultSkybox()); + // skyboxStack.push_back(backgroundStage->getBackground(0)->getSkybox()); gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { diff --git a/libraries/render/src/render/ShapePipeline.cpp b/libraries/render/src/render/ShapePipeline.cpp index d51d7f8cb6..79ac5c0990 100644 --- a/libraries/render/src/render/ShapePipeline.cpp +++ b/libraries/render/src/render/ShapePipeline.cpp @@ -17,9 +17,9 @@ using namespace render; -void ShapePipeline::prepare(gpu::Batch& batch) { +void ShapePipeline::prepare(gpu::Batch& batch, RenderArgs* args) { if (batchSetter) { - batchSetter(*this, batch); + batchSetter(*this, batch, args); } } @@ -119,7 +119,7 @@ const ShapePipelinePointer ShapePlumber::pickPipeline(RenderArgs* args, const Ke // Run the pipeline's BatchSetter on the passed in batch if (shapePipeline->batchSetter) { - shapePipeline->batchSetter(*shapePipeline, *batch); + shapePipeline->batchSetter(*shapePipeline, *batch, args); } return shapePipeline; diff --git a/libraries/render/src/render/ShapePipeline.h b/libraries/render/src/render/ShapePipeline.h index 434c909198..1b97baae7c 100644 --- a/libraries/render/src/render/ShapePipeline.h +++ b/libraries/render/src/render/ShapePipeline.h @@ -240,14 +240,14 @@ public: }; using LocationsPointer = std::shared_ptr; - using BatchSetter = std::function; + using BatchSetter = std::function; ShapePipeline(gpu::PipelinePointer pipeline, LocationsPointer locations, BatchSetter batchSetter) : pipeline(pipeline), locations(locations), batchSetter(batchSetter) {} // Normally, a pipeline is accessed thorugh pickPipeline. If it needs to be set manually, // after calling setPipeline this method should be called to prepare the pipeline with default buffers. - void prepare(gpu::Batch& batch); + void prepare(gpu::Batch& batch, RenderArgs* args); gpu::PipelinePointer pipeline; std::shared_ptr locations; diff --git a/tests/gpu-test/src/TestWindow.cpp b/tests/gpu-test/src/TestWindow.cpp index 6436ff1ef4..5b5102701a 100644 --- a/tests/gpu-test/src/TestWindow.cpp +++ b/tests/gpu-test/src/TestWindow.cpp @@ -77,7 +77,7 @@ void TestWindow::initGl() { #ifdef DEFERRED_LIGHTING auto deferredLightingEffect = DependencyManager::get(); deferredLightingEffect->init(); - deferredLightingEffect->setGlobalLight(_light); + // deferredLightingEffect->setGlobalLight(_light); initDeferredPipelines(*_shapePlumber); #endif } diff --git a/tests/render-perf/src/main.cpp b/tests/render-perf/src/main.cpp index 52592cd202..f725e1f09d 100644 --- a/tests/render-perf/src/main.cpp +++ b/tests/render-perf/src/main.cpp @@ -891,7 +891,7 @@ private: // Setup the current Zone Entity lighting { auto stage = DependencyManager::get()->getSkyStage(); - DependencyManager::get()->setGlobalLight(stage->getSunLight()); + // DependencyManager::get()->setGlobalLight(stage->getSunLight()); } { @@ -914,7 +914,7 @@ private: // The pending changes collecting the changes here render::Transaction transaction; // Setup the current Zone Entity lighting - DependencyManager::get()->setGlobalLight(_sunSkyStage.getSunLight()); + // DependencyManager::get()->setGlobalLight(_sunSkyStage.getSunLight()); { PerformanceTimer perfTimer("SceneProcessTransaction"); _main3DScene->enqueueTransaction(transaction); From 77644e7e9dbf890e760d54a8a5a20b30d3e877b7 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 26 Jun 2017 14:34:09 +0200 Subject: [PATCH 07/54] Removing commented objects from deferredlighting effect --- .../render-utils/src/DeferredLightingEffect.h | 23 ------------------- 1 file changed, 23 deletions(-) diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index fcbb8acf25..7fc9600d18 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -50,27 +50,13 @@ public: void setupKeyLightBatch(const RenderArgs* args, gpu::Batch& batch, int lightBufferUnit, int ambientBufferUnit, int skyboxCubemapUnit); void unsetKeyLightBatch(gpu::Batch& batch, int lightBufferUnit, int ambientBufferUnit, int skyboxCubemapUnit); - // update global lighting - // void setGlobalLight(const model::LightPointer& light); - // const model::LightPointer& getGlobalLight() const; - - // const LightStagePointer& getLightStage() { return _lightStage; } - // const BackgroundStagePointer& getBackgroundStage() { return _backgroundStage; } - void setShadowMapEnabled(bool enable) { _shadowMapEnabled = enable; }; void setAmbientOcclusionEnabled(bool enable) { _ambientOcclusionEnabled = enable; } bool isAmbientOcclusionEnabled() const { return _ambientOcclusionEnabled; } - // model::SkyboxPointer getDefaultSkybox() const { return _defaultSkybox; } - // gpu::TexturePointer getDefaultSkyboxTexture() const { return _defaultSkyboxTexture; } - // gpu::TexturePointer getDefaultSkyboxAmbientTexture() const { return _defaultSkyboxAmbientTexture; } - private: DeferredLightingEffect() = default; - // LightStagePointer _lightStage; - // BackgroundStagePointer _backgroundStage; - bool _shadowMapEnabled{ false }; bool _ambientOcclusionEnabled{ false }; @@ -97,15 +83,6 @@ private: LightLocationsPtr _localLightLocations; LightLocationsPtr _localLightOutlineLocations; - // using Lights = std::vector; - - // Lights _allocatedLights; - // std::vector _globalLights; - - // model::SkyboxPointer _defaultSkybox { new ProceduralSkybox() }; - // gpu::TexturePointer _defaultSkyboxTexture; - // gpu::TexturePointer _defaultSkyboxAmbientTexture; - friend class LightClusteringPass; friend class RenderDeferredSetup; friend class RenderDeferredLocals; From 904f22985c4840c3412308cb6a52393ac75fd8be Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 26 Jun 2017 16:43:04 +0200 Subject: [PATCH 08/54] CLeaning up comments --- .../entities-renderer/src/RenderableZoneEntityItem.cpp | 6 ++---- libraries/render-utils/src/BackgroundStage.cpp | 6 ++++-- libraries/render-utils/src/BackgroundStage.h | 3 +++ libraries/render-utils/src/DeferredLightingEffect.cpp | 10 +++++----- libraries/render-utils/src/LightStage.cpp | 6 ++++-- libraries/render-utils/src/LightStage.h | 3 +++ libraries/render/src/render/Scene.h | 2 +- 7 files changed, 22 insertions(+), 14 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp index bb07454992..a57a6e5d52 100644 --- a/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableZoneEntityItem.cpp @@ -554,13 +554,11 @@ void RenderableZoneEntityItemMeta::setProceduralUserData(QString userData) { void RenderableZoneEntityItemMeta::render(RenderArgs* args) { if (!_stage) { - // _stage = DependencyManager::get()->getLightStage(); - _stage = args->_scene->getStage("LIGHT_STAGE"); + _stage = args->_scene->getStage(); } if (!_backgroundStage) { - //_backgroundStage = DependencyManager::get()->getBackgroundStage(); - _backgroundStage = args->_scene->getStage("BACKGROUND_STAGE"); + _backgroundStage = args->_scene->getStage(); } { // Sun diff --git a/libraries/render-utils/src/BackgroundStage.cpp b/libraries/render-utils/src/BackgroundStage.cpp index c164b584a9..8599ec64e0 100644 --- a/libraries/render-utils/src/BackgroundStage.cpp +++ b/libraries/render-utils/src/BackgroundStage.cpp @@ -13,6 +13,8 @@ #include +std::string BackgroundStage::_stageName { "BACKGROUND_STAGE"}; + BackgroundStage::Index BackgroundStage::findBackground(const BackgroundPointer& background) const { auto found = _backgroundMap.find(background); if (found != _backgroundMap.end()) { @@ -143,9 +145,9 @@ BackgroundStageSetup::BackgroundStageSetup() { } void BackgroundStageSetup::run(const render::RenderContextPointer& renderContext) { - auto stage = renderContext->_scene->getStage("BACKGROUND_STAGE"); + auto stage = renderContext->_scene->getStage(BackgroundStage::getName()); if (!stage) { - renderContext->_scene->resetStage("BACKGROUND_STAGE", std::make_shared()); + renderContext->_scene->resetStage(BackgroundStage::getName(), std::make_shared()); } } diff --git a/libraries/render-utils/src/BackgroundStage.h b/libraries/render-utils/src/BackgroundStage.h index 2f0231b071..eab7c94f0d 100644 --- a/libraries/render-utils/src/BackgroundStage.h +++ b/libraries/render-utils/src/BackgroundStage.h @@ -23,6 +23,9 @@ // Background stage to set up background-related rendering tasks class BackgroundStage : public render::Stage { public: + static std::string _stageName; + static const std::string& getName() { return _stageName; } + using Index = render::indexed_container::Index; static const Index INVALID_INDEX { render::indexed_container::INVALID_INDEX }; static bool isIndexInvalid(Index index) { return index == INVALID_INDEX; } diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 84c972bab3..399225ac3b 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -104,7 +104,7 @@ void DeferredLightingEffect::init() { void DeferredLightingEffect::setupKeyLightBatch(const RenderArgs* args, gpu::Batch& batch, int lightBufferUnit, int ambientBufferUnit, int skyboxCubemapUnit) { PerformanceTimer perfTimer("DLE->setupBatch()"); model::LightPointer keySunLight; - auto lightStage = args->_scene->getStage("LIGHT_STAGE"); + auto lightStage = args->_scene->getStage(); if (lightStage && lightStage->_currentFrame._sunLights.size()) { keySunLight = lightStage->getLight(lightStage->_currentFrame._sunLights.front()); } else { @@ -427,7 +427,7 @@ void PrepareDeferred::run(const RenderContextPointer& renderContext, const Input // Prepare a fresh Light Frame - auto lightStage = renderContext->_scene->getStage("LIGHT_STAGE"); + auto lightStage = renderContext->_scene->getStage(); lightStage->_currentFrame.clear(); } @@ -491,7 +491,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext, // Global directional light and ambient pass - auto lightStage = renderContext->_scene->getStage("LIGHT_STAGE"); + auto lightStage = renderContext->_scene->getStage(); assert(lightStage->getNumLights() > 0); auto lightAndShadow = lightStage->getLightAndShadow(0); const auto& globalShadow = lightAndShadow.second; @@ -716,7 +716,7 @@ void DefaultLightingSetup::run(const RenderContextPointer& renderContext) { } } - auto lightStage = renderContext->_scene->getStage("LIGHT_STAGE"); + auto lightStage = renderContext->_scene->getStage(); if (lightStage) { // Allocate a default global light directional and ambient @@ -743,7 +743,7 @@ void DefaultLightingSetup::run(const RenderContextPointer& renderContext) { lightStage->addShadow(defaultLightID); } - auto backgroundStage = renderContext->_scene->getStage("BACKGROUND_STAGE"); + auto backgroundStage = renderContext->_scene->getStage(); if (backgroundStage) { auto background = std::make_shared(); diff --git a/libraries/render-utils/src/LightStage.cpp b/libraries/render-utils/src/LightStage.cpp index 10c99bf008..d0e9f2467e 100644 --- a/libraries/render-utils/src/LightStage.cpp +++ b/libraries/render-utils/src/LightStage.cpp @@ -13,6 +13,8 @@ #include "LightStage.h" +std::string LightStage::_stageName { "LIGHT_STAGE"}; + LightStage::LightStage() { } @@ -172,10 +174,10 @@ LightStageSetup::LightStageSetup() { } void LightStageSetup::run(const render::RenderContextPointer& renderContext) { - auto stage = renderContext->_scene->getStage("LIGHT_STAGE"); + auto stage = renderContext->_scene->getStage(LightStage::getName()); if (!stage) { stage = std::make_shared(); - renderContext->_scene->resetStage("LIGHT_STAGE", stage); + renderContext->_scene->resetStage(LightStage::getName(), stage); } } diff --git a/libraries/render-utils/src/LightStage.h b/libraries/render-utils/src/LightStage.h index 8273118f0c..f946cf699e 100644 --- a/libraries/render-utils/src/LightStage.h +++ b/libraries/render-utils/src/LightStage.h @@ -28,6 +28,9 @@ class ViewFrustum; // Light stage to set up light-related rendering tasks class LightStage : public render::Stage { public: + static std::string _stageName; + static const std::string& getName() { return _stageName; } + using Index = render::indexed_container::Index; static const Index INVALID_INDEX { render::indexed_container::INVALID_INDEX }; static bool isIndexInvalid(Index index) { return index == INVALID_INDEX; } diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index f0c5e7a3f0..199d9ce224 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -117,7 +117,7 @@ public: // Thread safe StagePointer getStage(const Stage::Name& name) const; template - std::shared_ptr getStage(const Stage::Name& name) const { + std::shared_ptr getStage(const Stage::Name& name = T::getName()) const { auto stage = getStage(name); return (stage ? std::static_pointer_cast(stage) : std::shared_ptr()); } From a2fc44703d4be82b9b10982e2834c6aeece07b5a Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 26 Jun 2017 16:45:54 +0200 Subject: [PATCH 09/54] One less constant --- libraries/render-utils/src/BackgroundStage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/BackgroundStage.cpp b/libraries/render-utils/src/BackgroundStage.cpp index 8599ec64e0..5275331696 100644 --- a/libraries/render-utils/src/BackgroundStage.cpp +++ b/libraries/render-utils/src/BackgroundStage.cpp @@ -62,7 +62,7 @@ void DrawBackgroundStage::run(const render::RenderContextPointer& renderContext, // Background rendering decision - auto backgroundStage = renderContext->_scene->getStage("BACKGROUND_STAGE"); + auto backgroundStage = renderContext->_scene->getStage(); model::SunSkyStagePointer background; model::SkyboxPointer skybox; if (backgroundStage->_currentFrame._backgrounds.size()) { From 7cbeabfc2991949ec18eed4c8ec16c4c1f59a7a5 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 26 Jun 2017 16:49:20 +0200 Subject: [PATCH 10/54] less comments & constant --- libraries/render-utils/src/LightClusters.cpp | 2 +- libraries/render-utils/src/LightPayload.cpp | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index 79b755f310..1f99f190af 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -576,7 +576,7 @@ void LightClusteringPass::run(const render::RenderContextPointer& renderContext, // From the LightStage and the current frame, update the light cluster Grid // auto deferredLightingEffect = DependencyManager::get(); // auto lightStage = deferredLightingEffect->getLightStage(); - auto lightStage = renderContext->_scene->getStage("LIGHT_STAGE"); + auto lightStage = renderContext->_scene->getStage(); _lightClusters->updateLightStage(lightStage); _lightClusters->updateLightFrame(lightStage->_currentFrame, lightingModel->isPointLightEnabled(), lightingModel->isSpotLightEnabled()); diff --git a/libraries/render-utils/src/LightPayload.cpp b/libraries/render-utils/src/LightPayload.cpp index d0cc8dfd18..5f7f7236f2 100644 --- a/libraries/render-utils/src/LightPayload.cpp +++ b/libraries/render-utils/src/LightPayload.cpp @@ -55,8 +55,7 @@ LightPayload::~LightPayload() { void LightPayload::render(RenderArgs* args) { if (!_stage) { - // _stage = DependencyManager::get()->getLightStage(); - _stage = args->_scene->getStage("LIGHT_STAGE"); + _stage = args->_scene->getStage(); } // Do we need to allocate the light in the stage ? if (LightStage::isIndexInvalid(_index)) { @@ -124,8 +123,7 @@ KeyLightPayload::~KeyLightPayload() { void KeyLightPayload::render(RenderArgs* args) { if (!_stage) { - // _stage = DependencyManager::get()->getLightStage(); - _stage = args->_scene->getStage("LIGHT_STAGE"); + _stage = args->_scene->getStage(); } // Do we need to allocate the light in the stage ? if (LightStage::isIndexInvalid(_index)) { From 6ab2dccd3830dbe013337cbbf51b7693c19f7cb4 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 26 Jun 2017 16:52:04 +0200 Subject: [PATCH 11/54] less comments & constant --- libraries/render-utils/src/LightClusters.cpp | 2 -- libraries/render-utils/src/RenderShadowTask.cpp | 6 ++---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/libraries/render-utils/src/LightClusters.cpp b/libraries/render-utils/src/LightClusters.cpp index 1f99f190af..74209ce951 100644 --- a/libraries/render-utils/src/LightClusters.cpp +++ b/libraries/render-utils/src/LightClusters.cpp @@ -574,8 +574,6 @@ void LightClusteringPass::run(const render::RenderContextPointer& renderContext, } // From the LightStage and the current frame, update the light cluster Grid - // auto deferredLightingEffect = DependencyManager::get(); - // auto lightStage = deferredLightingEffect->getLightStage(); auto lightStage = renderContext->_scene->getStage(); _lightClusters->updateLightStage(lightStage); _lightClusters->updateLightFrame(lightStage->_currentFrame, lightingModel->isPointLightEnabled(), lightingModel->isSpotLightEnabled()); diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index 2d8f6c0cab..a817a6abff 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -35,8 +35,7 @@ void RenderShadowMap::run(const render::RenderContextPointer& renderContext, assert(renderContext->args); assert(renderContext->args->hasViewFrustum()); - // auto lightStage = DependencyManager::get()->getLightStage(); - auto lightStage = renderContext->_scene->getStage("LIGHT_STAGE"); + auto lightStage = renderContext->_scene->getStage(); LightStage::Index globalLightIndex { 0 }; @@ -141,8 +140,7 @@ void RenderShadowTask::configure(const Config& configuration) { } void RenderShadowSetup::run(const render::RenderContextPointer& renderContext, Output& output) { - // auto lightStage = DependencyManager::get()->getLightStage(); - auto lightStage = renderContext->_scene->getStage("LIGHT_STAGE"); + auto lightStage = renderContext->_scene->getStage(); const auto globalShadow = lightStage->getShadow(0); // Cache old render args From 5e05c41980c9248f67b33ccd3fb6e20cded4dc2a Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 26 Jun 2017 16:56:04 +0200 Subject: [PATCH 12/54] less comments & constant --- libraries/render-utils/src/DebugDeferredBuffer.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/libraries/render-utils/src/DebugDeferredBuffer.cpp b/libraries/render-utils/src/DebugDeferredBuffer.cpp index e83789252c..8887de81ef 100644 --- a/libraries/render-utils/src/DebugDeferredBuffer.cpp +++ b/libraries/render-utils/src/DebugDeferredBuffer.cpp @@ -432,11 +432,8 @@ void DebugDeferredBuffer::run(const RenderContextPointer& renderContext, const I batch.setResourceTexture(Lighting, deferredFramebuffer->getLightingTexture()); } - // auto deferredLightingEffect = DependencyManager::get(); - auto lightStage = renderContext->_scene->getStage("LIGHT_STAGE"); - // assert(deferredLightingEffect->getLightStage()->getNumLights() > 0); + auto lightStage = renderContext->_scene->getStage(); assert(lightStage->getNumLights() > 0); - // auto lightAndShadow = deferredLightingEffect->getLightStage()->getLightAndShadow(0); auto lightAndShadow = lightStage->getLightAndShadow(0); const auto& globalShadow = lightAndShadow.second; if (globalShadow) { From 7687bdc0600880b40fc5b7d13fe6b877afa4e080 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 26 Jun 2017 17:02:45 +0200 Subject: [PATCH 13/54] less comments & constant --- .../src/DeferredLightingEffect.cpp | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 399225ac3b..5f18916a92 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -107,26 +107,27 @@ void DeferredLightingEffect::setupKeyLightBatch(const RenderArgs* args, gpu::Bat auto lightStage = args->_scene->getStage(); if (lightStage && lightStage->_currentFrame._sunLights.size()) { keySunLight = lightStage->getLight(lightStage->_currentFrame._sunLights.front()); - } else { - keySunLight = lightStage->getLight(0); } model::LightPointer keyAmbiLight; if (lightStage && lightStage->_currentFrame._ambientLights.size()) { keyAmbiLight = lightStage->getLight(lightStage->_currentFrame._ambientLights.front()); - } else { - keyAmbiLight = lightStage->getLight(0); } - if (lightBufferUnit >= 0) { - batch.setUniformBuffer(lightBufferUnit, keySunLight->getLightSchemaBuffer()); - } - if (ambientBufferUnit >= 0) { - batch.setUniformBuffer(ambientBufferUnit, keyAmbiLight->getAmbientSchemaBuffer()); + if (keySunLight) { + if (lightBufferUnit >= 0) { + batch.setUniformBuffer(lightBufferUnit, keySunLight->getLightSchemaBuffer()); + } } - if (keyAmbiLight->getAmbientMap() && (skyboxCubemapUnit >= 0)) { - batch.setResourceTexture(skyboxCubemapUnit, keyAmbiLight->getAmbientMap()); + if (keyAmbiLight) { + if (ambientBufferUnit >= 0) { + batch.setUniformBuffer(ambientBufferUnit, keyAmbiLight->getAmbientSchemaBuffer()); + } + + if (keyAmbiLight->getAmbientMap() && (skyboxCubemapUnit >= 0)) { + batch.setResourceTexture(skyboxCubemapUnit, keyAmbiLight->getAmbientMap()); + } } } From 76dae279cf4f9381796016fd6b4ef3546208e915 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 27 Jun 2017 14:24:34 +0200 Subject: [PATCH 14/54] Removing the default case from the renderer --- libraries/render-utils/src/BackgroundStage.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/libraries/render-utils/src/BackgroundStage.cpp b/libraries/render-utils/src/BackgroundStage.cpp index 5275331696..5d04f188f1 100644 --- a/libraries/render-utils/src/BackgroundStage.cpp +++ b/libraries/render-utils/src/BackgroundStage.cpp @@ -54,13 +54,11 @@ BackgroundStage::BackgroundPointer BackgroundStage::removeBackground(Index index void DrawBackgroundStage::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) { - const auto& lightingModel = inputs; if (!lightingModel->isBackgroundEnabled()) { return; } - // Background rendering decision auto backgroundStage = renderContext->_scene->getStage(); model::SunSkyStagePointer background; @@ -71,10 +69,7 @@ void DrawBackgroundStage::run(const render::RenderContextPointer& renderContext, if (background) { skybox = background->getSkybox(); } - } else { - skybox = backgroundStage->getBackground(0)->getSkybox(); } - /* auto backgroundMode = skyStage->getBackgroundMode(); switch (backgroundMode) { From 86eb5b14ca977fe236d34f4d5a6df73c8a805b48 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 28 Jun 2017 13:18:34 -0700 Subject: [PATCH 15/54] disable the user activity logger in DS/AC/ac-client --- assignment-client/src/AssignmentClientApp.cpp | 6 +++++- domain-server/src/DomainServer.cpp | 8 ++++++-- tools/ac-client/src/ACClientApp.cpp | 4 ++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/assignment-client/src/AssignmentClientApp.cpp b/assignment-client/src/AssignmentClientApp.cpp index 7e9042e609..91554d915b 100644 --- a/assignment-client/src/AssignmentClientApp.cpp +++ b/assignment-client/src/AssignmentClientApp.cpp @@ -13,9 +13,10 @@ #include #include -#include #include +#include #include +#include #include "Assignment.h" #include "AssignmentClient.h" @@ -207,6 +208,9 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : DependencyManager::registerInheritance(); + // the ACs should not send any user activity events so disable the logger ASAP + UserActivityLogger::getInstance().disable(true); + if (numForks || minForks || maxForks) { AssignmentClientMonitor* monitor = new AssignmentClientMonitor(numForks, minForks, maxForks, requestAssignmentType, assignmentPool, diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 8e3d04897b..545484d79d 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -40,11 +40,12 @@ #include #include #include +#include +#include +#include #include "DomainServerNodeData.h" #include "NodeConnectionData.h" -#include -#include int const DomainServer::EXIT_CODE_REBOOT = 234923; @@ -75,6 +76,9 @@ DomainServer::DomainServer(int argc, char* argv[]) : { parseCommandLine(); + // the DS should not send any user activity events so disable the logger ASAP + UserActivityLogger::getInstance().disable(true); + DependencyManager::set(); DependencyManager::set(); diff --git a/tools/ac-client/src/ACClientApp.cpp b/tools/ac-client/src/ACClientApp.cpp index b81d092662..34b7d5b049 100644 --- a/tools/ac-client/src/ACClientApp.cpp +++ b/tools/ac-client/src/ACClientApp.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include "ACClientApp.h" @@ -42,6 +43,8 @@ ACClientApp::ACClientApp(int argc, char* argv[]) : const QCommandLineOption listenPortOption("listenPort", "listen port", QString::number(INVALID_PORT)); parser.addOption(listenPortOption); + // the AC client should not send any user activity events so disable the logger ASAP + UserActivityLogger::getInstance().disable(true); if (!parser.parse(QCoreApplication::arguments())) { qCritical() << parser.errorText() << endl; @@ -66,6 +69,7 @@ ACClientApp::ACClientApp(int argc, char* argv[]) : const_cast(&shared())->setEnabled(QtInfoMsg, false); const_cast(&shared())->setEnabled(QtWarningMsg, false); } + QString domainServerAddress = "127.0.0.1:40103"; if (parser.isSet(domainAddressOption)) { From cf921447489d06aa82f183049519d63804c5e7f7 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Wed, 28 Jun 2017 14:13:09 -0700 Subject: [PATCH 16/54] fix for OAuth OPTIONS firing on XHR 302 --- domain-server/resources/web/js/tables.js | 42 ++++++++++++++++-------- domain-server/src/DomainServer.cpp | 29 ++++++++++------ 2 files changed, 47 insertions(+), 24 deletions(-) diff --git a/domain-server/resources/web/js/tables.js b/domain-server/resources/web/js/tables.js index 09f85a7047..600e5a5f8e 100644 --- a/domain-server/resources/web/js/tables.js +++ b/domain-server/resources/web/js/tables.js @@ -2,11 +2,11 @@ $(document).ready(function(){ // setup the underscore templates var nodeTemplate = _.template($('#nodes-template').html()); var queuedTemplate = _.template($('#queued-template').html()); - + // setup a function to grab the assignments function getNodesAndAssignments() { $.getJSON("nodes.json", function(json){ - + json.nodes.sort(function(a, b){ if (a.type === b.type) { if (a.uptime < b.uptime) { @@ -16,36 +16,50 @@ $(document).ready(function(){ } else { return 0; } - } - + } + if (a.type === "agent" && b.type !== "agent") { return 1; } else if (b.type === "agent" && a.type !== "agent") { return -1; } - + if (a.type > b.type) { return 1; } - + if (a.type < b.type) { return -1; - } + } }); - + $('#nodes-table tbody').html(nodeTemplate(json)); + }).fail(function(jqXHR, textStatus, errorThrown) { + // we assume a 401 means the DS has restarted + // and no longer has our OAuth produced uuid + // so just reload and re-auth + if (jqXHR.status == 401) { + location.reload(); + } }); - - $.getJSON("assignments.json", function(json){ + + $.getJSON("assignments.json", function(json){ $('#assignments-table tbody').html(queuedTemplate(json)); + }).fail(function(jqXHR, textStatus, errorThrown) { + // we assume a 401 means the DS has restarted + // and no longer has our OAuth produced uuid + // so just reload and re-auth + if (jqXHR.status == 401) { + location.reload(); + } }); } - + // do the first GET on page load getNodesAndAssignments(); // grab the new assignments JSON every two seconds var getNodesAndAssignmentsInterval = setInterval(getNodesAndAssignments, 2000); - + // hook the node delete to the X button $(document.body).on('click', '.glyphicon-remove', function(){ // fire off a delete for this node @@ -57,10 +71,10 @@ $(document).ready(function(){ } }); }); - + $(document.body).on('click', '#kill-all-btn', function() { var confirmed_kill = confirm("Are you sure?"); - + if (confirmed_kill == true) { $.ajax({ url: "/nodes/", diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 8e3d04897b..9303bed2b5 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -2091,22 +2091,31 @@ bool DomainServer::isAuthenticatedRequest(HTTPConnection* connection, const QUrl // the user does not have allowed username or role, return 401 return false; } else { - // re-direct this user to OAuth page + static const QByteArray REQUESTED_WITH_HEADER = "X-Requested-With"; + static const QString XML_REQUESTED_WITH = "XMLHttpRequest"; - // generate a random state UUID to use - QUuid stateUUID = QUuid::createUuid(); + if (connection->requestHeaders().value(REQUESTED_WITH_HEADER) == XML_REQUESTED_WITH) { + // unauthorized XHR requests get a 401 and not a 302, since there isn't an XHR + // path to OAuth authorize + connection->respond(HTTPConnection::StatusCode401, UNAUTHENTICATED_BODY); + } else { + // re-direct this user to OAuth page - // add it to the set so we can handle the callback from the OAuth provider - _webAuthenticationStateSet.insert(stateUUID); + // generate a random state UUID to use + QUuid stateUUID = QUuid::createUuid(); - QUrl authURL = oauthAuthorizationURL(stateUUID); + // add it to the set so we can handle the callback from the OAuth provider + _webAuthenticationStateSet.insert(stateUUID); - Headers redirectHeaders; + QUrl authURL = oauthAuthorizationURL(stateUUID); - redirectHeaders.insert("Location", authURL.toEncoded()); + Headers redirectHeaders; - connection->respond(HTTPConnection::StatusCode302, - QByteArray(), HTTPConnection::DefaultContentType, redirectHeaders); + redirectHeaders.insert("Location", authURL.toEncoded()); + + connection->respond(HTTPConnection::StatusCode302, + QByteArray(), HTTPConnection::DefaultContentType, redirectHeaders); + } // we don't know about this user yet, so they are not yet authenticated return false; From 8ec20ef0423204f530f066cc8986d6c0a626ddab Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Sun, 25 Jun 2017 20:04:49 -0700 Subject: [PATCH 17/54] Additional tracing of CPU cores --- interface/src/Application.cpp | 441 ++++++++++++++++++++++++---------- 1 file changed, 315 insertions(+), 126 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 75bcee0703..602495d165 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -2154,48 +2155,74 @@ void Application::paintGL() { return; } - auto displayPlugin = getActiveDisplayPlugin(); - // FIXME not needed anymore? - _offscreenContext->makeCurrent(); + DisplayPluginPointer displayPlugin; + { + PROFILE_RANGE(render, "/getActiveDisplayPlugin"); + displayPlugin = getActiveDisplayPlugin(); + } - // If a display plugin loses it's underlying support, it - // needs to be able to signal us to not use it - if (!displayPlugin->beginFrameRender(_frameCount)) { - _inPaint = false; - updateDisplayMode(); - return; + { + PROFILE_RANGE(render, "/offscreenMakeCurrent"); + // FIXME not needed anymore? + _offscreenContext->makeCurrent(); + } + + { + PROFILE_RANGE(render, "/pluginBeginFrameRender"); + // If a display plugin loses it's underlying support, it + // needs to be able to signal us to not use it + if (!displayPlugin->beginFrameRender(_frameCount)) { + _inPaint = false; + updateDisplayMode(); + return; + } } // update the avatar with a fresh HMD pose - getMyAvatar()->updateFromHMDSensorMatrix(getHMDSensorPose()); + { + PROFILE_RANGE(render, "/updateAvatar"); + getMyAvatar()->updateFromHMDSensorMatrix(getHMDSensorPose()); + } auto lodManager = DependencyManager::get(); + RenderArgs renderArgs; { - QMutexLocker viewLocker(&_viewMutex); - _viewFrustum.calculate(); - } - RenderArgs renderArgs(_gpuContext, getEntities(), lodManager->getOctreeSizeScale(), - lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE, - RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE); - { - QMutexLocker viewLocker(&_viewMutex); - renderArgs.setViewFrustum(_viewFrustum); + PROFILE_RANGE(render, "/buildFrustrumAndArgs"); + { + QMutexLocker viewLocker(&_viewMutex); + _viewFrustum.calculate(); + } + renderArgs = RenderArgs(_gpuContext, getEntities(), lodManager->getOctreeSizeScale(), + lodManager->getBoundaryLevelAdjust(), RenderArgs::DEFAULT_RENDER_MODE, + RenderArgs::MONO, RenderArgs::RENDER_DEBUG_NONE); + { + QMutexLocker viewLocker(&_viewMutex); + renderArgs.setViewFrustum(_viewFrustum); + } } - PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings)); - bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); - PerformanceWarning warn(showWarnings, "Application::paintGL()"); - resizeGL(); - - _gpuContext->beginFrame(getHMDSensorPose()); - // Reset the gpu::Context Stages - // Back to the default framebuffer; - gpu::doInBatch(_gpuContext, [&](gpu::Batch& batch) { - batch.resetStages(); - }); + { + PROFILE_RANGE(render, "/resizeGL"); + PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings)); + bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); + PerformanceWarning warn(showWarnings, "Application::paintGL()"); + resizeGL(); + } { + PROFILE_RANGE(render, "/gpuContextReset"); + _gpuContext->beginFrame(getHMDSensorPose()); + // Reset the gpu::Context Stages + // Back to the default framebuffer; + gpu::doInBatch(_gpuContext, [&](gpu::Batch& batch) { + batch.resetStages(); + }); + } + + + { + PROFILE_RANGE(render, "/renderOverlay"); PerformanceTimer perfTimer("renderOverlay"); // NOTE: There is no batch associated with this renderArgs // the ApplicationOverlay class assumes it's viewport is setup to be the device size @@ -2206,114 +2233,127 @@ void Application::paintGL() { glm::vec3 boomOffset; { - PerformanceTimer perfTimer("CameraUpdates"); + PROFILE_RANGE(render, "/updateCamera"); + { + PerformanceTimer perfTimer("CameraUpdates"); - auto myAvatar = getMyAvatar(); - boomOffset = myAvatar->getScale() * myAvatar->getBoomLength() * -IDENTITY_FORWARD; + auto myAvatar = getMyAvatar(); + boomOffset = myAvatar->getScale() * myAvatar->getBoomLength() * -IDENTITY_FORWARD; - if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON || _myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) { - Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, myAvatar->getBoomLength() <= MyAvatar::ZOOM_MIN); - Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, !(myAvatar->getBoomLength() <= MyAvatar::ZOOM_MIN)); - cameraMenuChanged(); - } - - // The render mode is default or mirror if the camera is in mirror mode, assigned further below - renderArgs._renderMode = RenderArgs::DEFAULT_RENDER_MODE; - - // Always use the default eye position, not the actual head eye position. - // Using the latter will cause the camera to wobble with idle animations, - // or with changes from the face tracker - if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) { - if (isHMDMode()) { - mat4 camMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix(); - _myCamera.setPosition(extractTranslation(camMat)); - _myCamera.setOrientation(glm::quat_cast(camMat)); - } else { - _myCamera.setPosition(myAvatar->getDefaultEyePosition()); - _myCamera.setOrientation(myAvatar->getMyHead()->getHeadOrientation()); + if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON || _myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) { + Menu::getInstance()->setIsOptionChecked(MenuOption::FirstPerson, myAvatar->getBoomLength() <= MyAvatar::ZOOM_MIN); + Menu::getInstance()->setIsOptionChecked(MenuOption::ThirdPerson, !(myAvatar->getBoomLength() <= MyAvatar::ZOOM_MIN)); + cameraMenuChanged(); } - } else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) { - if (isHMDMode()) { - auto hmdWorldMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix(); - _myCamera.setOrientation(glm::normalize(glm::quat_cast(hmdWorldMat))); - _myCamera.setPosition(extractTranslation(hmdWorldMat) + - myAvatar->getOrientation() * boomOffset); - } else { - _myCamera.setOrientation(myAvatar->getHead()->getOrientation()); - if (Menu::getInstance()->isOptionChecked(MenuOption::CenterPlayerInView)) { - _myCamera.setPosition(myAvatar->getDefaultEyePosition() - + _myCamera.getOrientation() * boomOffset); - } else { - _myCamera.setPosition(myAvatar->getDefaultEyePosition() - + myAvatar->getOrientation() * boomOffset); - } - } - } else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { - if (isHMDMode()) { - auto mirrorBodyOrientation = myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)); - glm::quat hmdRotation = extractRotation(myAvatar->getHMDSensorMatrix()); - // Mirror HMD yaw and roll - glm::vec3 mirrorHmdEulers = glm::eulerAngles(hmdRotation); - mirrorHmdEulers.y = -mirrorHmdEulers.y; - mirrorHmdEulers.z = -mirrorHmdEulers.z; - glm::quat mirrorHmdRotation = glm::quat(mirrorHmdEulers); + // The render mode is default or mirror if the camera is in mirror mode, assigned further below + renderArgs._renderMode = RenderArgs::DEFAULT_RENDER_MODE; - glm::quat worldMirrorRotation = mirrorBodyOrientation * mirrorHmdRotation; - - _myCamera.setOrientation(worldMirrorRotation); - - glm::vec3 hmdOffset = extractTranslation(myAvatar->getHMDSensorMatrix()); - // Mirror HMD lateral offsets - hmdOffset.x = -hmdOffset.x; - - _myCamera.setPosition(myAvatar->getDefaultEyePosition() - + glm::vec3(0, _raiseMirror * myAvatar->getUniformScale(), 0) - + mirrorBodyOrientation * glm::vec3(0.0f, 0.0f, 1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror - + mirrorBodyOrientation * hmdOffset); - } else { - _myCamera.setOrientation(myAvatar->getWorldAlignedOrientation() - * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f))); - _myCamera.setPosition(myAvatar->getDefaultEyePosition() - + glm::vec3(0, _raiseMirror * myAvatar->getUniformScale(), 0) - + (myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) * - glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror); - } - renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE; - } else if (_myCamera.getMode() == CAMERA_MODE_ENTITY) { - EntityItemPointer cameraEntity = _myCamera.getCameraEntityPointer(); - if (cameraEntity != nullptr) { + // Always use the default eye position, not the actual head eye position. + // Using the latter will cause the camera to wobble with idle animations, + // or with changes from the face tracker + if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) { if (isHMDMode()) { - glm::quat hmdRotation = extractRotation(myAvatar->getHMDSensorMatrix()); - _myCamera.setOrientation(cameraEntity->getRotation() * hmdRotation); - glm::vec3 hmdOffset = extractTranslation(myAvatar->getHMDSensorMatrix()); - _myCamera.setPosition(cameraEntity->getPosition() + (hmdRotation * hmdOffset)); + mat4 camMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix(); + _myCamera.setPosition(extractTranslation(camMat)); + _myCamera.setOrientation(glm::quat_cast(camMat)); } else { - _myCamera.setOrientation(cameraEntity->getRotation()); - _myCamera.setPosition(cameraEntity->getPosition()); + _myCamera.setPosition(myAvatar->getDefaultEyePosition()); + _myCamera.setOrientation(myAvatar->getMyHead()->getHeadOrientation()); + } + } else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) { + if (isHMDMode()) { + auto hmdWorldMat = myAvatar->getSensorToWorldMatrix() * myAvatar->getHMDSensorMatrix(); + _myCamera.setOrientation(glm::normalize(glm::quat_cast(hmdWorldMat))); + _myCamera.setPosition(extractTranslation(hmdWorldMat) + + myAvatar->getOrientation() * boomOffset); + } else { + _myCamera.setOrientation(myAvatar->getHead()->getOrientation()); + if (Menu::getInstance()->isOptionChecked(MenuOption::CenterPlayerInView)) { + _myCamera.setPosition(myAvatar->getDefaultEyePosition() + + _myCamera.getOrientation() * boomOffset); + } else { + _myCamera.setPosition(myAvatar->getDefaultEyePosition() + + myAvatar->getOrientation() * boomOffset); + } + } + } else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { + if (isHMDMode()) { + auto mirrorBodyOrientation = myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)); + + glm::quat hmdRotation = extractRotation(myAvatar->getHMDSensorMatrix()); + // Mirror HMD yaw and roll + glm::vec3 mirrorHmdEulers = glm::eulerAngles(hmdRotation); + mirrorHmdEulers.y = -mirrorHmdEulers.y; + mirrorHmdEulers.z = -mirrorHmdEulers.z; + glm::quat mirrorHmdRotation = glm::quat(mirrorHmdEulers); + + glm::quat worldMirrorRotation = mirrorBodyOrientation * mirrorHmdRotation; + + _myCamera.setOrientation(worldMirrorRotation); + + glm::vec3 hmdOffset = extractTranslation(myAvatar->getHMDSensorMatrix()); + // Mirror HMD lateral offsets + hmdOffset.x = -hmdOffset.x; + + _myCamera.setPosition(myAvatar->getDefaultEyePosition() + + glm::vec3(0, _raiseMirror * myAvatar->getUniformScale(), 0) + + mirrorBodyOrientation * glm::vec3(0.0f, 0.0f, 1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror + + mirrorBodyOrientation * hmdOffset); + } else { + _myCamera.setOrientation(myAvatar->getWorldAlignedOrientation() + * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f))); + _myCamera.setPosition(myAvatar->getDefaultEyePosition() + + glm::vec3(0, _raiseMirror * myAvatar->getUniformScale(), 0) + + (myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) * + glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror); + } + renderArgs._renderMode = RenderArgs::MIRROR_RENDER_MODE; + } else if (_myCamera.getMode() == CAMERA_MODE_ENTITY) { + EntityItemPointer cameraEntity = _myCamera.getCameraEntityPointer(); + if (cameraEntity != nullptr) { + if (isHMDMode()) { + glm::quat hmdRotation = extractRotation(myAvatar->getHMDSensorMatrix()); + _myCamera.setOrientation(cameraEntity->getRotation() * hmdRotation); + glm::vec3 hmdOffset = extractTranslation(myAvatar->getHMDSensorMatrix()); + _myCamera.setPosition(cameraEntity->getPosition() + (hmdRotation * hmdOffset)); + } else { + _myCamera.setOrientation(cameraEntity->getRotation()); + _myCamera.setPosition(cameraEntity->getPosition()); + } } } - } - // Update camera position - if (!isHMDMode()) { - _myCamera.update(1.0f / _frameCounter.rate()); + // Update camera position + if (!isHMDMode()) { + _myCamera.update(1.0f / _frameCounter.rate()); + } } } - getApplicationCompositor().setFrameInfo(_frameCount, _myCamera.getTransform()); + { + PROFILE_RANGE(render, "/updateCompositor"); + getApplicationCompositor().setFrameInfo(_frameCount, _myCamera.getTransform()); + } - // Primary rendering pass - auto framebufferCache = DependencyManager::get(); - const QSize size = framebufferCache->getFrameBufferSize(); - // Final framebuffer that will be handled to the display-plugin - auto finalFramebuffer = framebufferCache->getFramebuffer(); + gpu::FramebufferPointer finalFramebuffer; + QSize finalFramebufferSize; + { + PROFILE_RANGE(render, "/getOutputFramebuffer"); + // Primary rendering pass + auto framebufferCache = DependencyManager::get(); + finalFramebufferSize = framebufferCache->getFrameBufferSize(); + // Final framebuffer that will be handled to the display-plugin + finalFramebuffer = framebufferCache->getFramebuffer(); + } { PROFILE_RANGE(render, "/mainRender"); PerformanceTimer perfTimer("mainRender"); renderArgs._boomOffset = boomOffset; + // FIXME is this ever going to be different from the size previously set in the render args + // in the overlay render? // Viewport is assigned to the size of the framebuffer - renderArgs._viewport = ivec4(0, 0, size.width(), size.height()); + renderArgs._viewport = ivec4(0, 0, finalFramebufferSize.width(), finalFramebufferSize.height()); if (displayPlugin->isStereo()) { // Stereo modes will typically have a larger projection matrix overall, // so we ask for the 'mono' projection matrix, which for stereo and HMD @@ -3613,6 +3653,133 @@ bool Application::shouldPaint(float nsecsElapsed) { #include #include #pragma comment(lib, "pdh.lib") +#pragma comment(lib, "ntdll.lib") + +extern "C" { + enum SYSTEM_INFORMATION_CLASS { + SystemBasicInformation = 0, + SystemProcessorPerformanceInformation = 8, + }; + + struct SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION { + LARGE_INTEGER IdleTime; + LARGE_INTEGER KernelTime; + LARGE_INTEGER UserTime; + LARGE_INTEGER DpcTime; + LARGE_INTEGER InterruptTime; + ULONG InterruptCount; + }; + + struct SYSTEM_BASIC_INFORMATION { + ULONG Reserved; + ULONG TimerResolution; + ULONG PageSize; + ULONG NumberOfPhysicalPages; + ULONG LowestPhysicalPageNumber; + ULONG HighestPhysicalPageNumber; + ULONG AllocationGranularity; + ULONG_PTR MinimumUserModeAddress; + ULONG_PTR MaximumUserModeAddress; + ULONG_PTR ActiveProcessorsAffinityMask; + CCHAR NumberOfProcessors; + }; + + NTSYSCALLAPI NTSTATUS NTAPI NtQuerySystemInformation( + _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, + _Out_writes_bytes_opt_(SystemInformationLength) PVOID SystemInformation, + _In_ ULONG SystemInformationLength, + _Out_opt_ PULONG ReturnLength + ); + +} +template +NTSTATUS NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClass, T& t) { + return NtQuerySystemInformation(SystemInformationClass, &t, (ULONG)sizeof(T), nullptr); +} + +template +NTSTATUS NtQuerySystemInformation(SYSTEM_INFORMATION_CLASS SystemInformationClass, std::vector& t) { + return NtQuerySystemInformation(SystemInformationClass, t.data(), (ULONG)(sizeof(T) * t.size()), nullptr); +} + + +template +void updateValueAndDelta(std::pair& pair, T newValue) { + auto& value = pair.first; + auto& delta = pair.second; + delta = (value != 0) ? newValue - value : 0; + value = newValue; +} + +struct MyCpuInfo { + using ValueAndDelta = std::pair; + std::string name; + ValueAndDelta kernel { 0, 0 }; + ValueAndDelta user { 0, 0 }; + ValueAndDelta idle { 0, 0 }; + float kernelUsage { 0.0f }; + float userUsage { 0.0f }; + + void update(const SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION& cpuInfo) { + updateValueAndDelta(kernel, cpuInfo.KernelTime.QuadPart); + updateValueAndDelta(user, cpuInfo.UserTime.QuadPart); + updateValueAndDelta(idle, cpuInfo.IdleTime.QuadPart); + auto totalTime = kernel.second + user.second + idle.second; + if (totalTime != 0) { + kernelUsage = (FLOAT)kernel.second / totalTime; + userUsage = (FLOAT)user.second / totalTime; + } else { + kernelUsage = userUsage = 0.0f; + } + } +}; + +void updateCpuInformation() { + static std::once_flag once; + static SYSTEM_BASIC_INFORMATION systemInfo {}; + static SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION cpuTotals; + static std::vector cpuInfos; + static std::vector myCpuInfos; + static MyCpuInfo myCpuTotals; + std::call_once(once, [&] { + NtQuerySystemInformation( SystemBasicInformation, systemInfo); + cpuInfos.resize(systemInfo.NumberOfProcessors); + myCpuInfos.resize(systemInfo.NumberOfProcessors); + for (size_t i = 0; i < systemInfo.NumberOfProcessors; ++i) { + myCpuInfos[i].name = "cpu." + std::to_string(i); + } + myCpuTotals.name = "cpu.total"; + }); + NtQuerySystemInformation(SystemProcessorPerformanceInformation, cpuInfos); + + // Zero the CPU totals. + memset(&cpuTotals, 0, sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)); + for (size_t i = 0; i < systemInfo.NumberOfProcessors; ++i) { + auto& cpuInfo = cpuInfos[i]; + // KernelTime includes IdleTime. + cpuInfo.KernelTime.QuadPart -= cpuInfo.IdleTime.QuadPart; + + // Update totals + cpuTotals.IdleTime.QuadPart += cpuInfo.IdleTime.QuadPart; + cpuTotals.KernelTime.QuadPart += cpuInfo.KernelTime.QuadPart; + cpuTotals.UserTime.QuadPart += cpuInfo.UserTime.QuadPart; + + // Update friendly structure + auto& myCpuInfo = myCpuInfos[i]; + myCpuInfo.update(cpuInfo); + PROFILE_COUNTER(app, myCpuInfo.name.c_str(), { + { "kernel", myCpuInfo.kernelUsage }, + { "user", myCpuInfo.userUsage } + }); + } + + myCpuTotals.update(cpuTotals); + PROFILE_COUNTER(app, myCpuTotals.name.c_str(), { + { "kernel", myCpuTotals.kernelUsage }, + { "user", myCpuTotals.userUsage } + }); +} + static ULARGE_INTEGER lastCPU, lastSysCPU, lastUserCPU; static int numProcessors; @@ -3665,6 +3832,26 @@ void getCpuUsage(vec3& systemAndUser) { systemAndUser.z = (float)counterVal.doubleValue; } +void setupCpuMonitorThread() { + initCpuUsage(); + auto cpuMonitorThread = QThread::currentThread(); + + QTimer* timer = new QTimer(); + timer->setInterval(50); + QObject::connect(timer, &QTimer::timeout, [] { + updateCpuInformation(); + vec3 kernelUserAndSystem; + getCpuUsage(kernelUserAndSystem); + PROFILE_COUNTER(app, "cpuProcess", { { "system", kernelUserAndSystem.x }, { "user", kernelUserAndSystem.y } }); + PROFILE_COUNTER(app, "cpuSystem", { { "system", kernelUserAndSystem.z } }); + }); + QObject::connect(cpuMonitorThread, &QThread::finished, [=] { + timer->deleteLater(); + cpuMonitorThread->deleteLater(); + }); + timer->start(); +} + #endif @@ -3685,15 +3872,17 @@ void Application::idle(float nsecsElapsed) { } #ifdef Q_OS_WIN + // If tracing is enabled then monitor the CPU in a separate thread static std::once_flag once; - std::call_once(once, [] { - initCpuUsage(); + std::call_once(once, [&] { + if (trace_app().isDebugEnabled()) { + QThread* cpuMonitorThread = new QThread(qApp); + cpuMonitorThread->setObjectName("cpuMonitorThread"); + QObject::connect(cpuMonitorThread, &QThread::started, [this] { setupCpuMonitorThread(); }); + QObject::connect(qApp, &QCoreApplication::aboutToQuit, cpuMonitorThread, &QThread::quit); + cpuMonitorThread->start(); + } }); - - vec3 kernelUserAndSystem; - getCpuUsage(kernelUserAndSystem); - PROFILE_COUNTER(app, "cpuProcess", { { "system", kernelUserAndSystem.x }, { "user", kernelUserAndSystem.y } }); - PROFILE_COUNTER(app, "cpuSystem", { { "system", kernelUserAndSystem.z } }); #endif From 3e1aee4d8a6e9876f2ca0a08d4ff5d0b451d6448 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 30 Jun 2017 19:07:34 +0100 Subject: [PATCH 18/54] saving work --- plugins/openvr/src/ViveControllerManager.cpp | 13 +++++++++++++ plugins/openvr/src/ViveControllerManager.h | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 648373ccc2..40e33a26dd 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include #include @@ -121,6 +123,13 @@ static QString deviceTrackingResultToString(vr::ETrackingResult trackingResult) return result; } +bool ViveControllerManager::isDesktopMode() { + if (_container) { + return !_container->getActiveDisplayPlugin()->isHmd(); + } + return false; +} + void ViveControllerManager::calibrate() { if (isSupported()) { _inputDevice->calibrateNextFrame(); @@ -218,6 +227,10 @@ void ViveControllerManager::pluginUpdate(float deltaTime, const controller::Inpu return; } + if (isDesktopMode()) { + qDebug() << "In desktop mode"; + } + auto userInputMapper = DependencyManager::get(); handleOpenVrEvents(); if (openVrQuitRequested()) { diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index 0b0406bb60..f1fcb8403e 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -189,7 +189,7 @@ private: }; void renderHand(const controller::Pose& pose, gpu::Batch& batch, int sign); - + bool isDesktopMode(); bool _registeredWithInputMapper { false }; bool _modelLoaded { false }; model::Geometry _modelGeometry; From 577969481da2b54341cd59ead3705a9fbdd1103e Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Fri, 30 Jun 2017 23:43:12 +0100 Subject: [PATCH 19/54] head puck working --- interface/resources/controllers/vive.json | 22 ++++++++---------- interface/src/avatar/MyAvatar.cpp | 3 ++- plugins/openvr/src/OpenVrDisplayPlugin.cpp | 2 +- plugins/openvr/src/ViveControllerManager.cpp | 24 +++++++++++++++++++- plugins/openvr/src/ViveControllerManager.h | 3 +++ 5 files changed, 38 insertions(+), 16 deletions(-) diff --git a/interface/resources/controllers/vive.json b/interface/resources/controllers/vive.json index a0e9bd30d4..8f58ef3c98 100644 --- a/interface/resources/controllers/vive.json +++ b/interface/resources/controllers/vive.json @@ -34,36 +34,32 @@ { "from": "Vive.RSCenter", "to": "Standard.RightPrimaryThumb" }, { "from": "Vive.RightApplicationMenu", "to": "Standard.RightSecondaryThumb" }, - { "from": "Vive.LeftHand", "to": "Standard.LeftHand", "when": [ "Application.InHMD" ] }, - { "from": "Vive.RightHand", "to": "Standard.RightHand", "when": [ "Application.InHMD" ] }, + { "from": "Vive.LeftHand", "to": "Standard.LeftHand"}, + { "from": "Vive.RightHand", "to": "Standard.RightHand"}, { "from": "Vive.LeftFoot", "to" : "Standard.LeftFoot", - "filters" : [{"type" : "lowVelocity", "rotation" : 1.0, "translation": 1.0}], - "when": [ "Application.InHMD" ] + "filters" : [{"type" : "lowVelocity", "rotation" : 1.0, "translation": 1.0}] }, { "from": "Vive.RightFoot", "to" : "Standard.RightFoot", - "filters" : [{"type" : "lowVelocity", "rotation" : 1.0, "translation": 1.0}], - "when": [ "Application.InHMD" ] + "filters" : [{"type" : "lowVelocity", "rotation" : 1.0, "translation": 1.0}] }, { "from": "Vive.Hips", "to" : "Standard.Hips", - "filters" : [{"type" : "lowVelocity", "rotation" : 0.01, "translation": 0.01}], - "when": [ "Application.InHMD" ] + "filters" : [{"type" : "lowVelocity", "rotation" : 0.01, "translation": 0.01}] }, { "from": "Vive.Spine2", "to" : "Standard.Spine2", - "filters" : [{"type" : "lowVelocity", "rotation" : 0.01, "translation": 0.01}], - "when": [ "Application.InHMD" ] + "filters" : [{"type" : "lowVelocity", "rotation" : 0.01, "translation": 0.01}] }, - { "from": "Vive.Head", "to" : "Standard.Head", "when": [ "Application.InHMD" ] }, + { "from": "Vive.Head", "to" : "Standard.Head"}, - { "from": "Vive.RightArm", "to" : "Standard.RightArm", "when": [ "Application.InHMD" ] }, - { "from": "Vive.LeftArm", "to" : "Standard.LeftArm", "when": [ "Application.InHMD" ] } + { "from": "Vive.RightArm", "to" : "Standard.RightArm"}, + { "from": "Vive.LeftArm", "to" : "Standard.LeftArm"} ] } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index e5c4f4b972..d676f473e0 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1620,7 +1620,8 @@ void MyAvatar::prepareForPhysicsSimulation() { _characterController.setParentVelocity(parentVelocity); _characterController.setPositionAndOrientation(getPosition(), getOrientation()); - if (qApp->isHMDMode()) { + auto headPose = getHeadControllerPoseInAvatarFrame(); + if (headPose.isValid()) { _follow.prePhysicsUpdate(*this, deriveBodyFromHMDSensor(), _bodySensorMatrix, hasDriveInput()); } else { _follow.deactivate(); diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index 7a73c91c7d..c2bb349146 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -525,7 +525,7 @@ void OpenVrDisplayPlugin::resetSensors() { _sensorResetMat = glm::inverse(cancelOutRollAndPitch(m)); } -static bool isBadPose(vr::HmdMatrix34_t* mat) { +/static bool isBadPose(vr::HmdMatrix34_t* mat) { if (mat->m[1][3] < -0.2f) { return true; } diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 40e33a26dd..a0ad41615d 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -123,6 +123,22 @@ static QString deviceTrackingResultToString(vr::ETrackingResult trackingResult) return result; } +static glm::mat4 calculateResetMat() { + auto chaperone = vr::VRChaperone(); + if (chaperone) { + float const UI_RADIUS = 1.0f; + float const UI_HEIGHT = 1.6f; + float const UI_Z_OFFSET = 0.5; + + float xSize, zSize; + chaperone->GetPlayAreaSize(&xSize, &zSize); + glm::vec3 uiPos(0.0f, UI_HEIGHT, UI_RADIUS - (0.5f * zSize) - UI_Z_OFFSET); + + return glm::inverse(createMatFromQuatAndPos(glm::quat(), uiPos)); + } + return glm::mat4(); +} + bool ViveControllerManager::isDesktopMode() { if (_container) { return !_container->getActiveDisplayPlugin()->isHmd(); @@ -228,7 +244,13 @@ void ViveControllerManager::pluginUpdate(float deltaTime, const controller::Inpu } if (isDesktopMode()) { - qDebug() << "In desktop mode"; + if (!_resetMatCalculated) { + _resetMat = calculateResetMat(); + _resetMatCalculated = true; + } + + _system->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseStanding, 0, _nextSimPoseData.vrPoses, vr::k_unMaxTrackedDeviceCount); + _nextSimPoseData.update(_resetMat); } auto userInputMapper = DependencyManager::get(); diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index f1fcb8403e..50ea8aef47 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -192,6 +192,9 @@ private: bool isDesktopMode(); bool _registeredWithInputMapper { false }; bool _modelLoaded { false }; + bool _resetMatCalculated { false }; + bool _pullInputData { false }; + glm::mat4 _resetMat { glm::mat4() }; model::Geometry _modelGeometry; gpu::TexturePointer _texture; From 51792769b5fc737c255c74f2efc82364fe23dfd7 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Sat, 1 Jul 2017 00:48:36 +0100 Subject: [PATCH 20/54] finished vive in desktop mode --- .../qml/hifi/tablet/OpenVrConfiguration.qml | 57 ++++++++++++++++++- plugins/openvr/src/OpenVrDisplayPlugin.cpp | 2 +- plugins/openvr/src/OpenVrHelpers.h | 6 ++ plugins/openvr/src/ViveControllerManager.cpp | 12 +++- plugins/openvr/src/ViveControllerManager.h | 2 +- 5 files changed, 74 insertions(+), 5 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml b/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml index 96413534c3..49a73a6e38 100644 --- a/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml +++ b/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml @@ -642,6 +642,57 @@ Rectangle { } } + Separator { + id: advanceSeperator + width: parent.width + anchors.top: timeToCalibrate.bottom + anchors.topMargin: 10 + } + + RalewayBold { + id: advanceSettings + + text: "Advance Settings" + size: 12 + + color: hifi.colors.white + + anchors.top: advanceSeperator.bottom + anchors.topMargin: 10 + anchors.left: parent.left + anchors.leftMargin: leftMargin + } + + + HifiControls.CheckBox { + id: viveInDesktop + width: 15 + height: 15 + boxRadius: 7 + + anchors.top: advanceSettings.bottom + anchors.topMargin: 5 + anchors.left: openVrConfiguration.left + anchors.leftMargin: leftMargin + 10 + + onClicked: { + sendConfigurationSettings(); + } + } + + RalewayBold { + id: viveDesktopText + size: 10 + text: "Use vive devices in desktop mode" + color: hifi.colors.white + + anchors { + left: viveInDesktop.right + leftMargin: 5 + verticalCenter: viveInDesktop.verticalCenter + } + } + NumberAnimation { id: numberAnimation target: openVrConfiguration @@ -728,6 +779,7 @@ Rectangle { var HmdHead = settings["HMDHead"]; var viveController = settings["handController"]; + var desktopMode = settings["desktopMode"]; if (HmdHead) { headBox.checked = true; @@ -745,6 +797,8 @@ Rectangle { handBox.checked = false; } + viveInDesktop.checked = desktopMode; + initializeButtonState(); updateCalibrationText(); @@ -901,7 +955,8 @@ Rectangle { var settingsObject = { "bodyConfiguration": trackerConfiguration, "headConfiguration": headObject, - "handConfiguration": handObject + "handConfiguration": handObject, + "desktopMode": viveInDesktop.checked } return settingsObject; diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index c2bb349146..7a73c91c7d 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -525,7 +525,7 @@ void OpenVrDisplayPlugin::resetSensors() { _sensorResetMat = glm::inverse(cancelOutRollAndPitch(m)); } -/static bool isBadPose(vr::HmdMatrix34_t* mat) { +static bool isBadPose(vr::HmdMatrix34_t* mat) { if (mat->m[1][3] < -0.2f) { return true; } diff --git a/plugins/openvr/src/OpenVrHelpers.h b/plugins/openvr/src/OpenVrHelpers.h index f4253899a2..c54f2326c2 100644 --- a/plugins/openvr/src/OpenVrHelpers.h +++ b/plugins/openvr/src/OpenVrHelpers.h @@ -82,6 +82,12 @@ struct PoseData { angularVelocities[i] = transformVectorFast(resetMat, toGlm(vrPoses[i].vAngularVelocity)); } } + + void resetToInvalid() { + for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) { + vrPoses[i].bPoseIsValid = false; + } + } }; // FIXME remove once OpenVR header is updated diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index c1fcb78fa7..f14085f9a0 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -166,13 +166,19 @@ bool ViveControllerManager::isSupported() const { void ViveControllerManager::setConfigurationSettings(const QJsonObject configurationSettings) { if (isSupported()) { + if (configurationSettings.contains("desktopMode")) { + qDebug() << configurationSettings["desktopMode"].toBool(); + _desktopMode = configurationSettings["desktopMode"].toBool(); + } _inputDevice->configureCalibrationSettings(configurationSettings); } } QJsonObject ViveControllerManager::configurationSettings() { if (isSupported()) { - return _inputDevice->configurationSettings(); + QJsonObject configurationSettings = _inputDevice->configurationSettings(); + configurationSettings["desktopMode"] = _desktopMode; + return configurationSettings; } return QJsonObject(); @@ -243,7 +249,7 @@ void ViveControllerManager::pluginUpdate(float deltaTime, const controller::Inpu return; } - if (isDesktopMode()) { + if (isDesktopMode() && _desktopMode) { if (!_resetMatCalculated) { _resetMat = calculateResetMat(); _resetMatCalculated = true; @@ -251,6 +257,8 @@ void ViveControllerManager::pluginUpdate(float deltaTime, const controller::Inpu _system->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseStanding, 0, _nextSimPoseData.vrPoses, vr::k_unMaxTrackedDeviceCount); _nextSimPoseData.update(_resetMat); + } else if (isDesktopMode()) { + _nextSimPoseData.resetToInvalid(); } auto userInputMapper = DependencyManager::get(); diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index 50cce6a2ce..275c064a04 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -194,7 +194,7 @@ private: bool _registeredWithInputMapper { false }; bool _modelLoaded { false }; bool _resetMatCalculated { false }; - bool _pullInputData { false }; + bool _desktopMode { false }; glm::mat4 _resetMat { glm::mat4() }; model::Geometry _modelGeometry; gpu::TexturePointer _texture; From 691b59fffff8e92c79912fd4cc95844fe4e88e91 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 5 Jul 2017 18:26:58 +0100 Subject: [PATCH 21/54] remove debug statments --- plugins/openvr/src/ViveControllerManager.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 1b2a7892d1..95a2ab7161 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -167,7 +167,6 @@ bool ViveControllerManager::isSupported() const { void ViveControllerManager::setConfigurationSettings(const QJsonObject configurationSettings) { if (isSupported()) { if (configurationSettings.contains("desktopMode")) { - qDebug() << configurationSettings["desktopMode"].toBool(); _desktopMode = configurationSettings["desktopMode"].toBool(); } _inputDevice->configureCalibrationSettings(configurationSettings); From 27a9880eff2fc7d9b4e24578ab0794bfddc8f033 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 5 Jul 2017 18:34:33 +0100 Subject: [PATCH 22/54] removed double add of head offset --- plugins/openvr/src/ViveControllerManager.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 95a2ab7161..a1e6e929e1 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -760,10 +760,6 @@ glm::mat4 ViveControllerManager::InputDevice::calculateDefaultToReferenceForHead glm::mat4 finalHeadPuck = newHeadPuck * headPuckOffset; - glm::mat4 defaultHeadOffset = glm::inverse(inputCalibration.defaultCenterEyeMat) * inputCalibration.defaultHeadMat; - - glm::mat4 currentHead = finalHeadPuck * defaultHeadOffset; - // calculate the defaultToRefrenceXform glm::mat4 defaultToReferenceMat = currentHead * glm::inverse(inputCalibration.defaultHeadMat); return defaultToReferenceMat; From e567cf019671c0b910852b6a4bd2a6e1d217043d Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 5 Jul 2017 19:04:34 +0100 Subject: [PATCH 23/54] made requested changes --- plugins/openvr/src/ViveControllerManager.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index a1e6e929e1..acabd850ef 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -168,6 +168,9 @@ void ViveControllerManager::setConfigurationSettings(const QJsonObject configura if (isSupported()) { if (configurationSettings.contains("desktopMode")) { _desktopMode = configurationSettings["desktopMode"].toBool(); + if (!_desktopMode) { + _resetMatCalculated = false; + } } _inputDevice->configureCalibrationSettings(configurationSettings); } @@ -761,7 +764,7 @@ glm::mat4 ViveControllerManager::InputDevice::calculateDefaultToReferenceForHead glm::mat4 finalHeadPuck = newHeadPuck * headPuckOffset; // calculate the defaultToRefrenceXform - glm::mat4 defaultToReferenceMat = currentHead * glm::inverse(inputCalibration.defaultHeadMat); + glm::mat4 defaultToReferenceMat = finalHeadPuck * glm::inverse(inputCalibration.defaultHeadMat); return defaultToReferenceMat; } From 275f48b65aa77fe9a698c2a43cd6ef0f841ae3e8 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 5 Jul 2017 19:22:19 +0100 Subject: [PATCH 24/54] another requested change made --- plugins/openvr/src/ViveControllerManager.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index acabd850ef..3d4f4e0ce5 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -62,10 +62,10 @@ static const int SECOND_FOOT = 1; static const int HIP = 2; static const int CHEST = 3; -static float HEAD_PUCK_Y_OFFSET = -0.0254f; -static float HEAD_PUCK_Z_OFFSET = -0.152f; -static float HAND_PUCK_Y_OFFSET = -0.0508f; -static float HAND_PUCK_Z_OFFSET = 0.0254f; +static float HEAD_PUCK_Y_OFFSET = 0.0f; +static float HEAD_PUCK_Z_OFFSET = 0.0f; +static float HAND_PUCK_Y_OFFSET = 0.0f; +static float HAND_PUCK_Z_OFFSET = 0.0f; const char* ViveControllerManager::NAME { "OpenVR" }; @@ -763,8 +763,12 @@ glm::mat4 ViveControllerManager::InputDevice::calculateDefaultToReferenceForHead glm::mat4 finalHeadPuck = newHeadPuck * headPuckOffset; + glm::mat4 defaultHeadOffset = glm::inverse(inputCalibration.defaultCenterEyeMat) * inputCalibration.defaultHeadMat; + + glm::mat4 currentHead = finalHeadPuck * defaultHeadOffset; + // calculate the defaultToRefrenceXform - glm::mat4 defaultToReferenceMat = finalHeadPuck * glm::inverse(inputCalibration.defaultHeadMat); + glm::mat4 defaultToReferenceMat = currentHead * glm::inverse(inputCalibration.defaultHeadMat); return defaultToReferenceMat; } From 07d098b95beb28d4b3993884113f47158fee785f Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Wed, 5 Jul 2017 19:45:52 +0100 Subject: [PATCH 25/54] coding standard fix --- plugins/openvr/src/ViveControllerManager.cpp | 19 +++++++------------ plugins/openvr/src/ViveControllerManager.h | 4 ++++ 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 3d4f4e0ce5..b0e7297879 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -62,11 +62,6 @@ static const int SECOND_FOOT = 1; static const int HIP = 2; static const int CHEST = 3; -static float HEAD_PUCK_Y_OFFSET = 0.0f; -static float HEAD_PUCK_Z_OFFSET = 0.0f; -static float HAND_PUCK_Y_OFFSET = 0.0f; -static float HAND_PUCK_Z_OFFSET = 0.0f; - const char* ViveControllerManager::NAME { "OpenVR" }; const std::map TRACKING_RESULT_TO_STRING = { @@ -389,8 +384,8 @@ void ViveControllerManager::InputDevice::configureCalibrationSettings(const QJso bool overrideHead = headObject["override"].toBool(); if (overrideHead) { _headConfig = HeadConfig::Puck; - HEAD_PUCK_Y_OFFSET = headObject["Y"].toDouble(); - HEAD_PUCK_Z_OFFSET = headObject["Z"].toDouble(); + _headPuckYOffset = headObject["Y"].toDouble(); + _headPuckZOffset = headObject["Z"].toDouble(); } else { _headConfig = HeadConfig::HMD; } @@ -399,8 +394,8 @@ void ViveControllerManager::InputDevice::configureCalibrationSettings(const QJso bool overrideHands = handsObject["override"].toBool(); if (overrideHands) { _handConfig = HandConfig::Pucks; - HAND_PUCK_Y_OFFSET = handsObject["Y"].toDouble(); - HAND_PUCK_Z_OFFSET = handsObject["Z"].toDouble(); + _handPuckYOffset = handsObject["Y"].toDouble(); + _handPuckZOffset = handsObject["Z"].toDouble(); } else { _handConfig = HandConfig::HandController; } @@ -759,7 +754,7 @@ glm::mat4 ViveControllerManager::InputDevice::calculateDefaultToReferenceForHead glm::vec4(zPrime, 0.0f), glm::vec4(headPuckTranslation, 1.0f)); glm::mat4 headPuckOffset = glm::mat4(glm::vec4(1.0f, 0.0f, 0.0f, 0.0f), glm::vec4(0.0f, 1.0f, 0.0f, 0.0f), - glm::vec4(0.0f, 0.0f, 1.0f, 0.0f), glm::vec4(0.0f, HEAD_PUCK_Y_OFFSET, HEAD_PUCK_Z_OFFSET, 1.0f)); + glm::vec4(0.0f, 0.0f, 1.0f, 0.0f), glm::vec4(0.0f, _headPuckYOffset, _headPuckZOffset, 1.0f)); glm::mat4 finalHeadPuck = newHeadPuck * headPuckOffset; @@ -959,7 +954,7 @@ void ViveControllerManager::InputDevice::calibrateLeftHand(glm::mat4& defaultToR glm::vec4(zPrime, 0.0f), glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)); - glm::vec3 translationOffset = glm::vec3(0.0f, HAND_PUCK_Y_OFFSET, HAND_PUCK_Z_OFFSET); + glm::vec3 translationOffset = glm::vec3(0.0f, _handPuckYOffset, _handPuckZOffset); glm::quat initialRotation = glmExtractRotation(handPoseAvatarMat); glm::quat finalRotation = glmExtractRotation(newHandMat); @@ -990,7 +985,7 @@ void ViveControllerManager::InputDevice::calibrateRightHand(glm::mat4& defaultTo - glm::vec3 translationOffset = glm::vec3(0.0f, HAND_PUCK_Y_OFFSET, HAND_PUCK_Z_OFFSET); + glm::vec3 translationOffset = glm::vec3(0.0f, _handPuckYOffset, _handPuckZOffset); glm::quat initialRotation = glmExtractRotation(handPoseAvatarMat); glm::quat finalRotation = glmExtractRotation(newHandMat); diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index 275c064a04..d94320dfb2 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -177,6 +177,10 @@ private: float _leftHapticDuration { 0.0f }; float _rightHapticStrength { 0.0f }; float _rightHapticDuration { 0.0f }; + float _headPuckYOffset { 0.0f }; + float _headPuckZOffset { 0.0f }; + float _handPuckYOffset { 0.0f }; + float _handPuckZOffset { 0.0f }; bool _triggersPressedHandled { false }; bool _calibrated { false }; bool _timeTilCalibrationSet { false }; From 7b79e8c41ede7880ab879e47a300702d5b8351d2 Mon Sep 17 00:00:00 2001 From: utkarshgautamnyu Date: Wed, 5 Jul 2017 13:53:04 -0700 Subject: [PATCH 26/54] Update describe-settings.json --- domain-server/resources/describe-settings.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index bc67a31c02..d9d6abc840 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -50,11 +50,12 @@ { "label": "Places / Paths", "html_id": "places_paths", + "restart": false, "settings": [ { "name": "paths", "label": "Paths", - "help": "Clients can enter a path to reach an exact viewpoint in your domain.
Add rows to the table below to map a path to a viewpoint.
The index path ( / ) is where clients will enter if they do not enter an explicit path.", + "help": "Clients can enter a path to reach an exact viewpoint in your domain.
Add rows to the table below to map a path to a viewpoint.
The index path ( / ) is where clients will enter if they do not enter an explicit path.", "type": "table", "can_add_new_rows": true, "key": { From 1385ef80a7d961886c64e3a35091ef834b9a6df1 Mon Sep 17 00:00:00 2001 From: utkarshgautamnyu Date: Wed, 5 Jul 2017 13:56:40 -0700 Subject: [PATCH 27/54] Update DomainServerSettingsManager.cpp --- domain-server/src/DomainServerSettingsManager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index 9279648319..1bba9690c1 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -1198,6 +1198,7 @@ bool DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJ static const QString SECURITY_ROOT_KEY = "security"; static const QString AC_SUBNET_WHITELIST_KEY = "ac_subnet_whitelist"; static const QString BROADCASTING_KEY = "broadcasting"; + static const QString PATHS_ROOT_KEY = "Places / Paths"; auto& settingsVariant = _configMap.getConfig(); bool needRestart = false; @@ -1249,7 +1250,7 @@ bool DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJ if (!matchingDescriptionObject.isEmpty()) { updateSetting(rootKey, rootValue, *thisMap, matchingDescriptionObject); - if (rootKey != SECURITY_ROOT_KEY && rootKey != BROADCASTING_KEY) { + if (rootKey != SECURITY_ROOT_KEY && rootKey != BROADCASTING_KEY && rootKey != SETTINGS_PATHS_KEY ) { needRestart = true; } } else { From c069c13ebb29a2ff7fb2863194513770398f2cd6 Mon Sep 17 00:00:00 2001 From: utkarshgautamnyu Date: Wed, 5 Jul 2017 14:12:18 -0700 Subject: [PATCH 28/54] Update DomainServerSettingsManager.cpp --- domain-server/src/DomainServerSettingsManager.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index 1bba9690c1..e0054a5a00 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -1198,8 +1198,7 @@ bool DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJ static const QString SECURITY_ROOT_KEY = "security"; static const QString AC_SUBNET_WHITELIST_KEY = "ac_subnet_whitelist"; static const QString BROADCASTING_KEY = "broadcasting"; - static const QString PATHS_ROOT_KEY = "Places / Paths"; - + auto& settingsVariant = _configMap.getConfig(); bool needRestart = false; From 872751bb1611d2b480bede9592e27efe3ec7dc50 Mon Sep 17 00:00:00 2001 From: utkarshgautamnyu Date: Wed, 5 Jul 2017 14:30:48 -0700 Subject: [PATCH 29/54] Update describe-settings.json --- domain-server/resources/describe-settings.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index d9d6abc840..638c52a64d 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -50,12 +50,12 @@ { "label": "Places / Paths", "html_id": "places_paths", - "restart": false, + "restart": false, "settings": [ { "name": "paths", "label": "Paths", - "help": "Clients can enter a path to reach an exact viewpoint in your domain.
Add rows to the table below to map a path to a viewpoint.
The index path ( / ) is where clients will enter if they do not enter an explicit path.", + "help": "Clients can enter a path to reach an exact viewpoint in your domain.
Add rows to the table below to map a path to a viewpoint.
The index path ( / ) is where clients will enter if they do not enter an explicit path.", "type": "table", "can_add_new_rows": true, "key": { From 25773fcf5ab26ae25a7dc1367ea1d782c66ee230 Mon Sep 17 00:00:00 2001 From: utkarshgautamnyu Date: Wed, 5 Jul 2017 14:36:17 -0700 Subject: [PATCH 30/54] Update describe-settings.json --- domain-server/resources/describe-settings.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index 638c52a64d..f42b56b56d 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -50,12 +50,12 @@ { "label": "Places / Paths", "html_id": "places_paths", - "restart": false, + "restart": false, "settings": [ { "name": "paths", "label": "Paths", - "help": "Clients can enter a path to reach an exact viewpoint in your domain.
Add rows to the table below to map a path to a viewpoint.
The index path ( / ) is where clients will enter if they do not enter an explicit path.", + "help": "Clients can enter a path to reach an exact viewpoint in your domain.
Add rows to the table below to map a path to a viewpoint.
The index path ( / ) is where clients will enter if they do not enter an explicit path.", "type": "table", "can_add_new_rows": true, "key": { From f824290a4cdc5ec34ce9a372afae7ff477989fa5 Mon Sep 17 00:00:00 2001 From: utkarshgautamnyu Date: Wed, 5 Jul 2017 14:38:06 -0700 Subject: [PATCH 31/54] Update describe-settings.json --- domain-server/resources/describe-settings.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index f42b56b56d..638c52a64d 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -50,12 +50,12 @@ { "label": "Places / Paths", "html_id": "places_paths", - "restart": false, + "restart": false, "settings": [ { "name": "paths", "label": "Paths", - "help": "Clients can enter a path to reach an exact viewpoint in your domain.
Add rows to the table below to map a path to a viewpoint.
The index path ( / ) is where clients will enter if they do not enter an explicit path.", + "help": "Clients can enter a path to reach an exact viewpoint in your domain.
Add rows to the table below to map a path to a viewpoint.
The index path ( / ) is where clients will enter if they do not enter an explicit path.", "type": "table", "can_add_new_rows": true, "key": { From 6c15dffb9d0d3737aaae3cac9af01d4061ae3b5b Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 6 Jul 2017 00:45:59 +0100 Subject: [PATCH 32/54] added new glyph --- interface/resources/fonts/hifi-glyphs.ttf | Bin 28952 -> 29160 bytes .../resources/images/calibration-help.png | Bin 0 -> 50683 bytes .../qml/controls-uit/ImageMessageBox.qml | 32 ++++++++++++++++++ .../qml/hifi/tablet/CalibratingScreen.qml | 2 +- .../qml/hifi/tablet/OpenVrConfiguration.qml | 23 +++++++++++++ .../qml/styles-uit/HifiConstants.qml | 1 + 6 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 interface/resources/images/calibration-help.png create mode 100644 interface/resources/qml/controls-uit/ImageMessageBox.qml diff --git a/interface/resources/fonts/hifi-glyphs.ttf b/interface/resources/fonts/hifi-glyphs.ttf index ddb0743bf84edd1b9d4d0ae538cee3e050ff201e..8733349227646b207ec15315e9eab9ee7ae9e252 100644 GIT binary patch delta 760 zcmYL{O=uHA6vzK>c6YLyO_MgZnY}y2^ zhuX9rdhz65Ja`bl4kAU&L6Cws@lX*3J&6>(1i_1-NChLC1{@gP@4?J_??3;!{e?9*v$ndUasvE-=3dplNh?B#L!#VEze!w%BB6Ft#y14bT|?r>8PTc7eZp z4X_P>9ZMLwY`F{pn1293PNc70QkO=z0bUDCUr5G{X-CV}8vvgGgp1V|2m#Eh|+#b-JPP>(gxWg`>M1eTrwsjPJ;JD1CM zZ2tZTq}u@LMnxO}3Hg+C-gWpVR0eB(D8x!Tk;O{4sGnBM0Xj>q#XHnYp|Q#t0jTVz zN)gZz2o-9ANCzx+kg-$k`c`YP#5_cW;$Oizb{eH*lX+xixb~0B2>JpvIG_1s?4F1)7+lf zqmSc|^+ciq5gOL3EJ4HjDsyP~W%kXsn~Btf6hZ(I^JQwk5DG-h@2Q+=%(l_W{nc4w zv{YP8Pl%H>#uX!PEClj_>|8Ex`9kF~Sf#fUKx4%!D;H1zK?JI%Sl=3({rBEl@xR}( F(myDUigEw| delta 553 zcmXw%F=!J}7{`C#sBD7_0f(K=%4+U+HVg6!B<(FX z?UAb71VabWI`*p17pa3BR}EdaJFR%?-8@`-4ifpx!OD86I0fzk7(pT@;N|ZRHTIwU zgQcO?)?z*GpISYBAk)$fPstS-iyq0Slu!oA&LsgzjZ{K8beT|Qr0FN!*&d62X~Pm3 zdPc%S#*PNj0rP1yywN^VC~&WzfR4q70UKDv12(bbVEDd0UO2}IRYl*6PL|gLHpsFy zV3RC6VZ$8`N8QGrNy-$dgm>KueX?AvgfHD7%zNX~eSF%JsM@)p&nQRf_0W=P8DJ#w aSN9a^?R6NKsDHr6>Gh5NVEzxN9{&S4W^f7s diff --git a/interface/resources/images/calibration-help.png b/interface/resources/images/calibration-help.png new file mode 100644 index 0000000000000000000000000000000000000000..e3734a7d9c9fbc6ed450b136ce1cd71c16cd3852 GIT binary patch literal 50683 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%0AgD`I+yh72OZXOcS3 zw7)+O*A5J}S-j2@?|K(xEud+rnk>No+y7T<@M>dpV7_~%nFI}&w<_KK`8}O_OPTb? zw)`K@5A1G!&cGmm12POWmQ2Iw64KImI9=d%xLK6yfBsilqnh@#QhDjg`@*Ar!J%i@ zqjVNeu1h-Hex*udmoOPHzuiW!M;s-}>r}nwAbeW29@ss8*~a_%RY7&1f-DZ3bt*$lhHR|0r>0O$uyW6ZAF7K+z;z;XR`b5Ir&fdZX zRGPLt%auG+8nPee;|WVSYfkkF;C%k2ktVQv=N!51aZP+P~kHtj!noor%RHiFua6 zmH~EdZo%)iBmF<5msfJr1Sl^>LI|807}lwJ{tiV+Q^{b)g7ZIHGhH>DIer(-ui*D^ zLSsf_L*947(XDd6D1Pu@esDoF&8k>zTyKO!I6s$DLL*?Ih=~ zDCHI$+l%B~w!iMEQ~GRQ!Di-n?@)Y!q(=QaPThKmmojnmcZk-%>|bV;$DbdMH0OMM z`)Ry!=Mq!9fP|!QflxHUGU*`tAr~(hks5?RUVzk6u=JCV%?UQ5!;y!Cx#=Y*WudlR z?>>(Z5QHulmiK7#X)eY!_0pQSZlt_E^EB&K+y9($Y4CH(*x|335vf0oSChpKphrT; zVdzE=nuwPTqDdmTEtVi@erp$=ZD>oSaR2F#kIa!-qPA(Lao5jIeG0jGTlFZ_*0`Ggc01{(ih!GINe=j+>Eic_9TDZ*3ytNjn% zYF60tI|zMUhP$<&EP0pYyJ_8ii0LBsc)6oWug6T zzRYV9*aVYDPb$5`w8T1XtgX0ZndCb6HPkcl`QSdqP{opd{*$E`?Z$T-+5@+reVpQ$ z*14iwo!7Xgmp9clqaixutx9*wc*1llMc11qX&O43g+Ty)Fv**CiSbhec0CHl6Dy-e0Rc2^s%v6>pr=BYEKid#`VeO*4g^PkV1QYSeJHvt1{k2#Wgt-$Kyv zOSp`T3?bJ{1A5CkrDOVzB^g4K)1+1m`W5W137?b zMdz+NXLl1YaF14JNpc2@y7`|TGC=xV&YRGDfiz=*P!%+6^=>yy0AHn#_Z#9lH68jS~=eo(hZFfuA=R6ojQQ0)CvFoZ>G&f6la@s1l~; zXOMyXK(yj^*In_eIBdg7uJ_@l%^06JP2w@J#xTkL`j}S7FzwDN4z>dGJ5EnJ?tUGL z*?4Hg&39EEhX6C!u$VB3E3#&Hk@`fip!s82S(&or6%yKyt|t3U9wwEk4J@_p8{^8; z_omXNE)9KpA~TewMD8}Ip^%;P-Js(6he+Yy)Nm$NShc2M*!Rv)mJ3#!leN0vDVgu+ zU;J;!;6;wT2%5W$gMTImFo{Xo^Pw;SfDTE;6fMg@0PK$qCV#nBRDD&@97o_8{+|c` zojN?ezdVQ~bt3Nw@_bmMq zIs_Ie)0QdHrwKP)+7&JIX&o=!HliNG}MWvTCei&oR&k zkgI;3@0quRWjoq!tMO2TMiM6jMZzXT3*8lRkWA5Re|0F|WvQoUzrk^)33fp%H!=^_ z&Jt1sysRxK&4`$XBM_b$o{FnE-xlSO-}U7cu~zxBUU^#KIQ{_DtFYuF+WMFf7lf`k zUM(1ky{lEYX@7RSKg8{~P2_es;-C+*B|2%8@CHDDkJp zTek!q3Sp+)ZN%6k`(UD+3j@INFBDIJHZI^23IjQSn+>~a`#)u_%S{)NGRc4ZAoDuE zptw%CW0@2_TWJWOF^w^pn9EUs? zOiU*4NV=^K<_R4X^FRNI>2TF|b}qGy|8FuU%vyc9?Ph+2|{*5`bcksn{m? zk5e0qB?pg|BFU{875{N=V-etg`E|Mf-F^>Y|1ppf{`-pm^BvHNYFVMszwU1yB?Qhg zTA=B_yx(Z20K`9zQs#f%;QujTf2aC)TMdnYgx|6T1R?&jr-c~_Mk|dU!Cr6JKi)zJ zpqSbEW%2OGgZCuBu_sD2rvGjWNg;3xvPmd1;J^07z%FjKKJ literal 0 HcmV?d00001 diff --git a/interface/resources/qml/controls-uit/ImageMessageBox.qml b/interface/resources/qml/controls-uit/ImageMessageBox.qml new file mode 100644 index 0000000000..492f520d2a --- /dev/null +++ b/interface/resources/qml/controls-uit/ImageMessageBox.qml @@ -0,0 +1,32 @@ +// +// ImageMessageBox.qml +// +// Created by Dante Ruiz on 7/5/2017 +// Copyright 2017 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +import QtQuick 2.5 +import QtQuick.Controls 1.4 +import "../styles-uit" + +Item { + id: imageBox + visible: false + anchors.fill: parent + property alias source: image.source + property alias imageWidth: image.width + proeprty alias imageHeight: image.height + Rectangle { + acnhors.fill: parent + color: "black" + opacity: 0.5 + } + + Image { + id: image + } + +} diff --git a/interface/resources/qml/hifi/tablet/CalibratingScreen.qml b/interface/resources/qml/hifi/tablet/CalibratingScreen.qml index 8053673e9c..dd56bc96ab 100644 --- a/interface/resources/qml/hifi/tablet/CalibratingScreen.qml +++ b/interface/resources/qml/hifi/tablet/CalibratingScreen.qml @@ -65,7 +65,7 @@ Rectangle { HiFiGlyphs { id: image - text: hifi.glyphs.avatar1 + text: hifi.glyphs.avatarTPose size: 190 color: hifi.colors.white diff --git a/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml b/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml index 96413534c3..2fe8a69321 100644 --- a/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml +++ b/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml @@ -290,6 +290,27 @@ Rectangle { anchors.leftMargin: leftMargin } + RalewayRegular { + id: info + + text: "See Recommended Tracker Placement" + color: hifi.colors.blueHighlight + size: 10 + anchors { + left: additional.right + leftMargin: 10 + verticalCenter: additional.verticalCenter + } + + MouseArea { + anchors.fill: parent; + + onEntered: info.color = hifi.colors.blueAccent + onExited: info.color = hifi.colors.blueHighlight + onClicked: console.log("text clicked"); + } + } + Row { id: feetConfig anchors.top: additional.bottom @@ -379,6 +400,7 @@ Rectangle { if (checked) { hipBox.checked = true; feetBox.checked = true; + shoulderBox.checked = false; } sendConfigurationSettings(); } @@ -416,6 +438,7 @@ Rectangle { if (checked) { hipBox.checked = true; feetBox.checked = true; + chestBox.checked = false; } sendConfigurationSettings(); } diff --git a/interface/resources/qml/styles-uit/HifiConstants.qml b/interface/resources/qml/styles-uit/HifiConstants.qml index ca39326102..aa968c85ef 100644 --- a/interface/resources/qml/styles-uit/HifiConstants.qml +++ b/interface/resources/qml/styles-uit/HifiConstants.qml @@ -336,5 +336,6 @@ Item { readonly property string source: "\ue01c" readonly property string playback_play: "\ue01d" readonly property string stop_square: "\ue01e" + readonly property string avatarTPose: "\ue01f" } } From 9b7a561c28abe764bed04dc0fcc5f36f3acffc87 Mon Sep 17 00:00:00 2001 From: utkarshgautamnyu Date: Wed, 5 Jul 2017 16:56:21 -0700 Subject: [PATCH 33/54] Update describe-settings.json --- domain-server/resources/describe-settings.json | 1 + 1 file changed, 1 insertion(+) diff --git a/domain-server/resources/describe-settings.json b/domain-server/resources/describe-settings.json index bc67a31c02..e8b5bb2878 100644 --- a/domain-server/resources/describe-settings.json +++ b/domain-server/resources/describe-settings.json @@ -75,6 +75,7 @@ { "name": "descriptors", "label": "Description", + "restart": false, "help": "This data will be queryable from your server. It may be collected by High Fidelity and used to share your domain with others.", "settings": [ { From 8c96d00f14bf1bb7677bf7b5e1e8285da3f96418 Mon Sep 17 00:00:00 2001 From: utkarshgautamnyu Date: Wed, 5 Jul 2017 16:59:47 -0700 Subject: [PATCH 34/54] Update DomainServerSettingsManager.cpp --- domain-server/src/DomainServerSettingsManager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/domain-server/src/DomainServerSettingsManager.cpp b/domain-server/src/DomainServerSettingsManager.cpp index 9279648319..138ed7d8e8 100644 --- a/domain-server/src/DomainServerSettingsManager.cpp +++ b/domain-server/src/DomainServerSettingsManager.cpp @@ -1198,6 +1198,7 @@ bool DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJ static const QString SECURITY_ROOT_KEY = "security"; static const QString AC_SUBNET_WHITELIST_KEY = "ac_subnet_whitelist"; static const QString BROADCASTING_KEY = "broadcasting"; + static const QString DESCRIPTION_ROOT_KEY = "descriptors"; auto& settingsVariant = _configMap.getConfig(); bool needRestart = false; @@ -1265,7 +1266,7 @@ bool DomainServerSettingsManager::recurseJSONObjectAndOverwriteSettings(const QJ if (!matchingDescriptionObject.isEmpty()) { const QJsonValue& settingValue = rootValue.toObject()[settingKey]; updateSetting(settingKey, settingValue, *thisMap, matchingDescriptionObject); - if ((rootKey != SECURITY_ROOT_KEY && rootKey != BROADCASTING_KEY) + if ((rootKey != SECURITY_ROOT_KEY && rootKey != BROADCASTING_KEY && rootKey != DESCRIPTION_ROOT_KEY) || settingKey == AC_SUBNET_WHITELIST_KEY) { needRestart = true; } From 4a22fbca1bedcbe1e37cbf37cf776f2e364725f2 Mon Sep 17 00:00:00 2001 From: David Kelly Date: Wed, 5 Jul 2017 17:01:31 -0700 Subject: [PATCH 35/54] redo cache switch --- interface/src/Application.cpp | 10 ++++- interface/src/main.cpp | 16 +------- libraries/networking/src/AssetClient.cpp | 39 ++++++++++--------- libraries/networking/src/AssetClient.h | 2 +- libraries/networking/src/ResourceManager.cpp | 6 +-- libraries/networking/src/ResourceManager.h | 1 - libraries/shared/src/PathUtils.cpp | 9 ++--- libraries/shared/src/PathUtils.h | 2 +- .../shared/src/shared/GlobalAppProperties.cpp | 1 + .../shared/src/shared/GlobalAppProperties.h | 1 + 10 files changed, 38 insertions(+), 49 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 377819c0a0..f9f43757d0 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -480,6 +480,12 @@ bool setupEssentials(int& argc, char** argv, bool runningMarkerExisted) { static const auto SUPPRESS_SETTINGS_RESET = "--suppress-settings-reset"; bool suppressPrompt = cmdOptionExists(argc, const_cast(argv), SUPPRESS_SETTINGS_RESET); bool previousSessionCrashed = CrashHandler::checkForResetSettings(runningMarkerExisted, suppressPrompt); + // get dir to use for cache + static const auto CACHE_SWITCH = "--cache"; + QString cacheDir = getCmdOption(argc, const_cast(argv), CACHE_SWITCH); + if (!cacheDir.isEmpty()) { + qApp->setProperty(hifi::properties::APP_LOCAL_DATA_PATH, cacheDir); + } Setting::init(); @@ -1218,8 +1224,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo settingsTimer->stop(); // Delete it (this will trigger the thread destruction settingsTimer->deleteLater(); - // Mark the settings thread as finished, so we know we can safely save in the main application - // shutdown code + // Mark the settings thread as finished, so we know we can safely save in the main application + // shutdown code _settingsGuard.trigger(); }); diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 42ceb756b9..a19055d4da 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -101,7 +101,7 @@ int main(int argc, const char* argv[]) { if (allowMultipleInstances) { instanceMightBeRunning = false; } - // this needs to be done here in main, as the mechanism for setting the + // this needs to be done here in main, as the mechanism for setting the // scripts directory appears not to work. See the bug report // https://highfidelity.fogbugz.com/f/cases/5759/Issues-changing-scripts-directory-in-ScriptsEngine if (parser.isSet(overrideScriptsPathOption)) { @@ -111,20 +111,6 @@ int main(int argc, const char* argv[]) { } } - if (parser.isSet(overrideAppLocalDataPathOption)) { - // get dir to use for cache - QString cacheDir = parser.value(overrideAppLocalDataPathOption); - if (!cacheDir.isEmpty()) { - // tell everyone to use the right cache location - // - // this handles data8 and prepared - DependencyManager::get()->setCacheDir(cacheDir); - - // this does the ktx_cache - PathUtils::getAppLocalDataPath(cacheDir); - } - } - if (instanceMightBeRunning) { // Try to connect and send message to existing interface instance QLocalSocket socket; diff --git a/libraries/networking/src/AssetClient.cpp b/libraries/networking/src/AssetClient.cpp index e97660da4c..cb0b620a54 100644 --- a/libraries/networking/src/AssetClient.cpp +++ b/libraries/networking/src/AssetClient.cpp @@ -19,6 +19,8 @@ #include #include +#include + #include "AssetRequest.h" #include "AssetUpload.h" #include "AssetUtils.h" @@ -31,11 +33,12 @@ MessageID AssetClient::_currentID = 0; -AssetClient::AssetClient(const QString& cacheDir) : _cacheDir(cacheDir) { +AssetClient::AssetClient() { + _cacheDir = qApp->property(hifi::properties::APP_LOCAL_DATA_PATH).toString(); setCustomDeleter([](Dependency* dependency){ static_cast(dependency)->deleteLater(); }); - + auto nodeList = DependencyManager::get(); auto& packetReceiver = nodeList->getPacketReceiver(); @@ -105,7 +108,7 @@ void AssetClient::handleAssetMappingOperationReply(QSharedPointerreadPrimitive(&messageID); - + AssetServerError error; message->readPrimitive(&error); @@ -132,13 +135,13 @@ void AssetClient::handleAssetMappingOperationReply(QSharedPointer(); SharedNodePointer assetServer = nodeList->soloNodeOfType(NodeType::AssetServer); - + if (!assetServer) { qCWarning(asset_client) << "Could not complete AssetClient operation " << "since you are not currently connected to an asset-server."; return false; } - + return true; } @@ -220,14 +223,14 @@ MessageID AssetClient::getAsset(const QString& hash, DataOffset start, DataOffse SharedNodePointer assetServer = nodeList->soloNodeOfType(NodeType::AssetServer); if (assetServer) { - + auto messageID = ++_currentID; - + auto payloadSize = sizeof(messageID) + SHA256_HASH_LENGTH + sizeof(start) + sizeof(end); auto packet = NLPacket::create(PacketType::AssetGet, payloadSize, true); - + qCDebug(asset_client) << "Requesting data from" << start << "to" << end << "of" << hash << "from asset-server."; - + packet->writePrimitive(messageID); packet->write(QByteArray::fromHex(hash.toLatin1())); @@ -254,10 +257,10 @@ MessageID AssetClient::getAssetInfo(const QString& hash, GetInfoCallback callbac if (assetServer) { auto messageID = ++_currentID; - + auto payloadSize = sizeof(messageID) + SHA256_HASH_LENGTH; auto packet = NLPacket::create(PacketType::AssetGetInfo, payloadSize, true); - + packet->writePrimitive(messageID); packet->write(QByteArray::fromHex(hash.toLatin1())); @@ -278,7 +281,7 @@ void AssetClient::handleAssetGetInfoReply(QSharedPointer messag MessageID messageID; message->readPrimitive(&messageID); auto assetHash = message->read(SHA256_HASH_LENGTH); - + AssetServerError error; message->readPrimitive(&error); @@ -367,7 +370,7 @@ void AssetClient::handleAssetGetReply(QSharedPointer message, S callbacks.completeCallback(true, error, message->readAll()); } - + messageCallbackMap.erase(requestIt); } } @@ -478,7 +481,7 @@ MessageID AssetClient::getAllAssetMappings(MappingOperationCallback callback) { auto nodeList = DependencyManager::get(); SharedNodePointer assetServer = nodeList->soloNodeOfType(NodeType::AssetServer); - + if (assetServer) { auto packetList = NLPacketList::create(PacketType::AssetMappingOperation, QByteArray(), true, true); @@ -501,7 +504,7 @@ MessageID AssetClient::getAllAssetMappings(MappingOperationCallback callback) { MessageID AssetClient::deleteAssetMappings(const AssetPathList& paths, MappingOperationCallback callback) { auto nodeList = DependencyManager::get(); SharedNodePointer assetServer = nodeList->soloNodeOfType(NodeType::AssetServer); - + if (assetServer) { auto packetList = NLPacketList::create(PacketType::AssetMappingOperation, QByteArray(), true, true); @@ -532,7 +535,7 @@ MessageID AssetClient::setAssetMapping(const QString& path, const AssetHash& has auto nodeList = DependencyManager::get(); SharedNodePointer assetServer = nodeList->soloNodeOfType(NodeType::AssetServer); - + if (assetServer) { auto packetList = NLPacketList::create(PacketType::AssetMappingOperation, QByteArray(), true, true); @@ -644,7 +647,7 @@ MessageID AssetClient::uploadAsset(const QByteArray& data, UploadResultCallback auto nodeList = DependencyManager::get(); SharedNodePointer assetServer = nodeList->soloNodeOfType(NodeType::AssetServer); - + if (assetServer) { auto packetList = NLPacketList::create(PacketType::AssetUpload, QByteArray(), true, true); @@ -682,7 +685,7 @@ void AssetClient::handleAssetUploadReply(QSharedPointer message } else { auto hash = message->read(SHA256_HASH_LENGTH); hashString = hash.toHex(); - + qCDebug(asset_client) << "Successfully uploaded asset to asset-server - SHA256 hash is " << hashString; } diff --git a/libraries/networking/src/AssetClient.h b/libraries/networking/src/AssetClient.h index 2bc694f367..3f6602b76b 100644 --- a/libraries/networking/src/AssetClient.h +++ b/libraries/networking/src/AssetClient.h @@ -49,7 +49,7 @@ using ProgressCallback = std::function class AssetClient : public QObject, public Dependency { Q_OBJECT public: - AssetClient(const QString& cacheDir=""); + AssetClient(); Q_INVOKABLE GetMappingRequest* createGetMappingRequest(const AssetPath& path); Q_INVOKABLE GetAllMappingsRequest* createGetAllMappingsRequest(); diff --git a/libraries/networking/src/ResourceManager.cpp b/libraries/networking/src/ResourceManager.cpp index e9fe2f1ec1..3ee66f89c1 100644 --- a/libraries/networking/src/ResourceManager.cpp +++ b/libraries/networking/src/ResourceManager.cpp @@ -28,7 +28,7 @@ ResourceManager::ResourceManager() { _thread.setObjectName("Resource Manager Thread"); - auto assetClient = DependencyManager::set(_cacheDir); + auto assetClient = DependencyManager::set(); assetClient->moveToThread(&_thread); QObject::connect(&_thread, &QThread::started, assetClient.data(), &AssetClient::init); @@ -160,7 +160,3 @@ bool ResourceManager::resourceExists(const QUrl& url) { return false; } -void ResourceManager::setCacheDir(const QString& cacheDir) { - // TODO: check for existence? - _cacheDir = cacheDir; -} diff --git a/libraries/networking/src/ResourceManager.h b/libraries/networking/src/ResourceManager.h index 4e7cd3d92d..fdfd05736e 100644 --- a/libraries/networking/src/ResourceManager.h +++ b/libraries/networking/src/ResourceManager.h @@ -59,7 +59,6 @@ private: PrefixMap _prefixMap; QMutex _prefixMapLock; - QString _cacheDir; }; #endif diff --git a/libraries/shared/src/PathUtils.cpp b/libraries/shared/src/PathUtils.cpp index 1fe9e2f83d..0636411f51 100644 --- a/libraries/shared/src/PathUtils.cpp +++ b/libraries/shared/src/PathUtils.cpp @@ -19,6 +19,7 @@ #include "PathUtils.h" #include #include // std::once +#include "shared/GlobalAppProperties.h" const QString& PathUtils::resourcesPath() { #ifdef Q_OS_MAC @@ -34,12 +35,8 @@ QString PathUtils::getAppDataPath() { return QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/"; } -QString PathUtils::getAppLocalDataPath(const QString& overridePath /* = "" */) { - static QString overriddenPath = ""; - // set the overridden path if one was passed in - if (!overridePath.isEmpty()) { - overriddenPath = overridePath; - } +QString PathUtils::getAppLocalDataPath() { + QString overriddenPath = qApp->property(hifi::properties::APP_LOCAL_DATA_PATH).toString(); // return overridden path if set if (!overriddenPath.isEmpty()) { return overriddenPath; diff --git a/libraries/shared/src/PathUtils.h b/libraries/shared/src/PathUtils.h index 42dd09c8b0..14eb81dd9a 100644 --- a/libraries/shared/src/PathUtils.h +++ b/libraries/shared/src/PathUtils.h @@ -28,7 +28,7 @@ public: static const QString& resourcesPath(); static QString getAppDataPath(); - static QString getAppLocalDataPath(const QString& overridePath = ""); + static QString getAppLocalDataPath(); static QString getAppDataFilePath(const QString& filename); static QString getAppLocalDataFilePath(const QString& filename); diff --git a/libraries/shared/src/shared/GlobalAppProperties.cpp b/libraries/shared/src/shared/GlobalAppProperties.cpp index b0ba0bf83d..6c9f3f9601 100644 --- a/libraries/shared/src/shared/GlobalAppProperties.cpp +++ b/libraries/shared/src/shared/GlobalAppProperties.cpp @@ -17,6 +17,7 @@ namespace hifi { namespace properties { const char* TEST = "com.highfidelity.test"; const char* TRACING = "com.highfidelity.tracing"; const char* HMD = "com.highfidelity.hmd"; + const char* APP_LOCAL_DATA_PATH = "com.highfidelity.appLocalDataPath"; namespace gl { const char* BACKEND = "com.highfidelity.gl.backend"; diff --git a/libraries/shared/src/shared/GlobalAppProperties.h b/libraries/shared/src/shared/GlobalAppProperties.h index b1811586ba..174be61939 100644 --- a/libraries/shared/src/shared/GlobalAppProperties.h +++ b/libraries/shared/src/shared/GlobalAppProperties.h @@ -19,6 +19,7 @@ namespace hifi { namespace properties { extern const char* TEST; extern const char* TRACING; extern const char* HMD; + extern const char* APP_LOCAL_DATA_PATH; namespace gl { extern const char* BACKEND; From 9d2fe8da9c1a6ef4fdf7516a54b7f3b63f8ef469 Mon Sep 17 00:00:00 2001 From: utkarshgautamnyu Date: Wed, 5 Jul 2017 18:02:44 -0700 Subject: [PATCH 36/54] Update DomainServer.cpp --- domain-server/src/DomainServer.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 095613a473..94a77af4ab 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -162,8 +162,10 @@ DomainServer::DomainServer(int argc, char* argv[]) : _gatekeeper.preloadAllowedUserPublicKeys(); // so they can connect on first request + //send signal to DomainMetadata when descriptors changed _metadata = new DomainMetadata(this); - + connect(&_settingsManager, &DomainServerSettingsManager::settingsUpdated, + _metadata, &DomainMetadata::descriptorsChanged); qDebug() << "domain-server is running"; static const QString AC_SUBNET_WHITELIST_SETTING_PATH = "security.ac_subnet_whitelist"; From 936c21e8497b055feef74de6cbcd8620eda1c91c Mon Sep 17 00:00:00 2001 From: David Kelly Date: Thu, 6 Jul 2017 07:24:58 -0700 Subject: [PATCH 37/54] remove unnecessary cacheDir member --- interface/src/Application.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/interface/src/Application.h b/interface/src/Application.h index 28d95a280c..cf0ae91a0f 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -299,7 +299,6 @@ public: void setAvatarOverrideUrl(const QUrl& url, bool save); QUrl getAvatarOverrideUrl() { return _avatarOverrideUrl; } bool getSaveAvatarOverrideUrl() { return _saveAvatarOverrideUrl; } - void setCacheOverrideDir(const QString& dirName) { _cacheDir = dirName; } signals: void svoImportRequested(const QString& url); @@ -691,6 +690,5 @@ private: QUrl _avatarOverrideUrl; bool _saveAvatarOverrideUrl { false }; - QString _cacheDir; }; #endif // hifi_Application_h From 258c21838e48d149742b9521b713f0f2a2038fad Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 6 Jul 2017 17:32:40 +0100 Subject: [PATCH 38/54] finished calibration-ui updates --- .../qml/controls-uit/ImageMessageBox.qml | 38 +++++++- .../qml/hifi/tablet/ControllerSettings.qml | 24 +++-- .../qml/hifi/tablet/OpenVrConfiguration.qml | 89 ++++++++++++------- 3 files changed, 111 insertions(+), 40 deletions(-) diff --git a/interface/resources/qml/controls-uit/ImageMessageBox.qml b/interface/resources/qml/controls-uit/ImageMessageBox.qml index 492f520d2a..95c753aab4 100644 --- a/interface/resources/qml/controls-uit/ImageMessageBox.qml +++ b/interface/resources/qml/controls-uit/ImageMessageBox.qml @@ -18,15 +18,47 @@ Item { anchors.fill: parent property alias source: image.source property alias imageWidth: image.width - proeprty alias imageHeight: image.height + property alias imageHeight: image.height + Rectangle { - acnhors.fill: parent + anchors.fill: parent color: "black" - opacity: 0.5 + opacity: 0.3 } Image { id: image + anchors.centerIn: parent + + HiFiGlyphs { + id: closeGlyphButton + text: hifi.glyphs.close + size: 25 + + anchors { + top: parent.top + topMargin: 15 + right: parent.right + rightMargin: 15 + } + + MouseArea { + anchors.fill: parent + hoverEnabled: true + + onEntered: { + parent.text = hifi.glyphs.closeInverted; + } + + onExited: { + parent.text = hifi.glyphs.close; + } + + onClicked: { + imageBox.visible = false; + } + } + } } } diff --git a/interface/resources/qml/hifi/tablet/ControllerSettings.qml b/interface/resources/qml/hifi/tablet/ControllerSettings.qml index e1ba93a840..4814eaf01c 100644 --- a/interface/resources/qml/hifi/tablet/ControllerSettings.qml +++ b/interface/resources/qml/hifi/tablet/ControllerSettings.qml @@ -16,6 +16,7 @@ import "../../controls-uit" as HifiControls StackView { id: stack initialItem: inputConfiguration + property alias messageVisible: imageMessageBox.visible Rectangle { id: inputConfiguration anchors.fill: parent @@ -26,6 +27,15 @@ StackView { property var pluginSettings: null + HifiControls.ImageMessageBox { + id: imageMessageBox + anchors.fill: parent + z: 2000 + imageWidth: 442 + imageHeight: 670 + source: "../../../images/calibration-help.png" + } + Rectangle { width: inputConfiguration.width height: 1 @@ -167,7 +177,7 @@ StackView { loader.item.pluginName = box.currentText; } } - + if (loader.item.hasOwnProperty("displayInformation")) { loader.item.displayConfiguration(); } @@ -183,20 +193,20 @@ StackView { return InputConfiguration.activeInputPlugins(); } } - + function initialize() { changeSource(); } - + function changeSource() { loader.source = ""; var source = ""; if (box.currentText == "Vive") { source = InputConfiguration.configurationLayout("OpenVR"); - } else { + } else { source = InputConfiguration.configurationLayout(box.currentText); } - + loader.source = source; if (source === "") { box.label = "(not configurable)"; @@ -204,14 +214,14 @@ StackView { box.label = ""; } } - + Timer { id: timer repeat: false interval: 300 onTriggered: initialize() } - + Component.onCompleted: { timer.start(); } diff --git a/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml b/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml index 2fe8a69321..9db80df3cc 100644 --- a/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml +++ b/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml @@ -50,9 +50,12 @@ Rectangle { readonly property int apply: 1 readonly property int applyAndCalibrate: 2 readonly property int calibrate: 3 - + } - + + + + MouseArea { id: mouseArea @@ -64,6 +67,7 @@ Rectangle { mouse.accepted = false; } } + color: hifi.colors.baseGray RalewayBold { @@ -162,14 +166,14 @@ Rectangle { stepSize: 0.0254 decimals: 4 colorScheme: hifi.colorSchemes.dark - + onEditingFinished: { sendConfigurationSettings(); } } } - - + + RalewayBold { id: hands @@ -245,7 +249,7 @@ Rectangle { anchors.left: openVrConfiguration.left anchors.leftMargin: leftMargin + 10 spacing: 10 - + HifiControls.SpinBox { id: handYOffset decimals: 4 @@ -269,7 +273,7 @@ Rectangle { stepSize: 0.0254 decimals: 4 colorScheme: hifi.colorSchemes.dark - + onEditingFinished: { sendConfigurationSettings(); } @@ -302,12 +306,37 @@ Rectangle { verticalCenter: additional.verticalCenter } + Rectangle { + id: selected + color: hifi.colors.blueHighlight + + width: info.width + height: 1 + + anchors { + top: info.bottom + topMargin: 1 + left: info.left + right: info.right + } + + visible: false + } + MouseArea { anchors.fill: parent; + hoverEnabled: true - onEntered: info.color = hifi.colors.blueAccent - onExited: info.color = hifi.colors.blueHighlight - onClicked: console.log("text clicked"); + onEntered: { + selected.visible = true; + } + + onExited: { + selected.visible = false; + } + onClicked: { + stack.messageVisible = true; + } } } @@ -486,7 +515,7 @@ Rectangle { anchors.leftMargin: leftMargin radius: hifi.buttons.radius - + gradient: Gradient { GradientStop { position: 0.2 @@ -502,7 +531,7 @@ Rectangle { } } } - + GradientStop { position: 1.0 color: { @@ -518,10 +547,10 @@ Rectangle { } } } - - + + HiFiGlyphs { id: glyphButton color: enabled ? hifi.buttons.textColor[calibrationButton.color] @@ -535,7 +564,7 @@ Rectangle { bottomMargin: 1 } } - + RalewayBold { id: calibrationText font.capitalization: Font.AllUppercase @@ -550,7 +579,7 @@ Rectangle { topMargin: 7 } } - + MouseArea { anchors.fill: parent @@ -572,19 +601,19 @@ Rectangle { } } } - + onPressed: { calibrationButton.pressed = true; } - + onReleased: { calibrationButton.pressed = false; } - + onEntered: { calibrationButton.hovered = true; } - + onExited: { calibrationButton.hovered = false; } @@ -690,14 +719,14 @@ Rectangle { calibratingScreen = screen.createObject(); stack.push(calibratingScreen); } - + if (status["calibrated"]) { calibrationScreen.success(); if (status["UI"]) { logAction("mocap_ui_success", status); } - + } else if (!status["calibrated"]) { calibrationScreen.failure(); @@ -809,11 +838,11 @@ Rectangle { var handOverride = handSetting["override"]; var settingsChanged = false; - + if (lastConfiguration["bodyConfiguration"] !== bodySetting) { settingsChanged = true; } - + var lastHead = lastConfiguration["headConfiguration"]; if (lastHead["override"] !== headOverride) { settingsChanged = true; @@ -823,13 +852,13 @@ Rectangle { if (lastHand["override"] !== handOverride) { settingsChanged = true; } - + if (settingsChanged) { if ((!handOverride) && (!headOverride) && (bodySetting === "None")) { state = buttonState.apply; } else { state = buttonState.applyAndCalibrate; - } + } } else { if (state == buttonState.apply) { state = buttonState.disabled; @@ -837,7 +866,7 @@ Rectangle { state = buttonState.calibrate; } } - + lastConfiguration = settings; } @@ -854,7 +883,7 @@ Rectangle { state = buttonState.disabled; } else { state = buttonState.calibrate; - } + } } function updateCalibrationButton() { @@ -920,11 +949,11 @@ Rectangle { "Y": handYOffset.value, "Z": handZOffset.value } - + var settingsObject = { "bodyConfiguration": trackerConfiguration, "headConfiguration": headObject, - "handConfiguration": handObject + "handConfiguration": handObject } return settingsObject; From 6e1f9d275cc6a741a6eb54f9bdc14d1a491bfc47 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 6 Jul 2017 17:54:06 +0100 Subject: [PATCH 39/54] chnaged default head offset --- interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml b/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml index 9db80df3cc..b5698104d2 100644 --- a/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml +++ b/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml @@ -150,6 +150,7 @@ Rectangle { label: "Y: offset" minimumValue: -10 stepSize: 0.0254 + value: -0.05 colorScheme: hifi.colorSchemes.dark onEditingFinished: { @@ -165,6 +166,7 @@ Rectangle { minimumValue: -10 stepSize: 0.0254 decimals: 4 + value: -0.05 colorScheme: hifi.colorSchemes.dark onEditingFinished: { From 916f57772bc1767168127756960f81d9a5573003 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 6 Jul 2017 10:21:07 -0700 Subject: [PATCH 40/54] default the UAL off for all targets, enable manually for Interface --- assignment-client/src/AssignmentClientApp.cpp | 4 - domain-server/src/DomainServer.cpp | 4 - interface/src/Application.cpp | 108 ++++++++++-------- libraries/networking/src/UserActivityLogger.h | 3 +- tools/ac-client/src/ACClientApp.cpp | 4 - 5 files changed, 61 insertions(+), 62 deletions(-) diff --git a/assignment-client/src/AssignmentClientApp.cpp b/assignment-client/src/AssignmentClientApp.cpp index 91554d915b..ed8d0eb2d1 100644 --- a/assignment-client/src/AssignmentClientApp.cpp +++ b/assignment-client/src/AssignmentClientApp.cpp @@ -16,7 +16,6 @@ #include #include #include -#include #include "Assignment.h" #include "AssignmentClient.h" @@ -208,9 +207,6 @@ AssignmentClientApp::AssignmentClientApp(int argc, char* argv[]) : DependencyManager::registerInheritance(); - // the ACs should not send any user activity events so disable the logger ASAP - UserActivityLogger::getInstance().disable(true); - if (numForks || minForks || maxForks) { AssignmentClientMonitor* monitor = new AssignmentClientMonitor(numForks, minForks, maxForks, requestAssignmentType, assignmentPool, diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 545484d79d..504af97f80 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -42,7 +42,6 @@ #include #include #include -#include #include "DomainServerNodeData.h" #include "NodeConnectionData.h" @@ -76,9 +75,6 @@ DomainServer::DomainServer(int argc, char* argv[]) : { parseCommandLine(); - // the DS should not send any user activity events so disable the logger ASAP - UserActivityLogger::getInstance().disable(true); - DependencyManager::set(); DependencyManager::set(); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9052f082dc..85f9469933 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -950,58 +950,68 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo // Make sure we don't time out during slow operations at startup updateHeartbeat(); - - // sessionRunTime will be reset soon by loadSettings. Grab it now to get previous session value. - // The value will be 0 if the user blew away settings this session, which is both a feature and a bug. - static const QString TESTER = "HIFI_TESTER"; - auto gpuIdent = GPUIdent::getInstance(); - auto glContextData = getGLContextData(); - QJsonObject properties = { - { "version", applicationVersion() }, - { "tester", QProcessEnvironment::systemEnvironment().contains(TESTER) }, - { "previousSessionCrashed", _previousSessionCrashed }, - { "previousSessionRuntime", sessionRunTime.get() }, - { "cpu_architecture", QSysInfo::currentCpuArchitecture() }, - { "kernel_type", QSysInfo::kernelType() }, - { "kernel_version", QSysInfo::kernelVersion() }, - { "os_type", QSysInfo::productType() }, - { "os_version", QSysInfo::productVersion() }, - { "gpu_name", gpuIdent->getName() }, - { "gpu_driver", gpuIdent->getDriver() }, - { "gpu_memory", static_cast(gpuIdent->getMemory()) }, - { "gl_version_int", glVersionToInteger(glContextData.value("version").toString()) }, - { "gl_version", glContextData["version"] }, - { "gl_vender", glContextData["vendor"] }, - { "gl_sl_version", glContextData["sl_version"] }, - { "gl_renderer", glContextData["renderer"] }, - { "ideal_thread_count", QThread::idealThreadCount() } - }; - auto macVersion = QSysInfo::macVersion(); - if (macVersion != QSysInfo::MV_None) { - properties["os_osx_version"] = QSysInfo::macVersion(); - } - auto windowsVersion = QSysInfo::windowsVersion(); - if (windowsVersion != QSysInfo::WV_None) { - properties["os_win_version"] = QSysInfo::windowsVersion(); - } - - ProcessorInfo procInfo; - if (getProcessorInfo(procInfo)) { - properties["processor_core_count"] = procInfo.numProcessorCores; - properties["logical_processor_count"] = procInfo.numLogicalProcessors; - properties["processor_l1_cache_count"] = procInfo.numProcessorCachesL1; - properties["processor_l2_cache_count"] = procInfo.numProcessorCachesL2; - properties["processor_l3_cache_count"] = procInfo.numProcessorCachesL3; - } - - // add firstRun flag from settings to launch event Setting::Handle firstRun { Settings::firstRun, true }; - properties["first_run"] = firstRun.get(); - // add the user's machine ID to the launch event - properties["machine_fingerprint"] = uuidStringWithoutCurlyBraces(FingerprintUtils::getMachineFingerprint()); + // once the settings have been loaded, check if we need to flip the default for UserActivityLogger + auto& userActivityLogger = UserActivityLogger::getInstance(); + if (!userActivityLogger.isDisabledSettingSet()) { + // the user activity logger is opt-out for Interface + // but it's defaulted to disabled for other targets + // so we need to enable it here if it has never been disabled by the user + userActivityLogger.disable(false); + } - UserActivityLogger::getInstance().logAction("launch", properties); + if (userActivityLogger.isEnabled()) { + // sessionRunTime will be reset soon by loadSettings. Grab it now to get previous session value. + // The value will be 0 if the user blew away settings this session, which is both a feature and a bug. + static const QString TESTER = "HIFI_TESTER"; + auto gpuIdent = GPUIdent::getInstance(); + auto glContextData = getGLContextData(); + QJsonObject properties = { + { "version", applicationVersion() }, + { "tester", QProcessEnvironment::systemEnvironment().contains(TESTER) }, + { "previousSessionCrashed", _previousSessionCrashed }, + { "previousSessionRuntime", sessionRunTime.get() }, + { "cpu_architecture", QSysInfo::currentCpuArchitecture() }, + { "kernel_type", QSysInfo::kernelType() }, + { "kernel_version", QSysInfo::kernelVersion() }, + { "os_type", QSysInfo::productType() }, + { "os_version", QSysInfo::productVersion() }, + { "gpu_name", gpuIdent->getName() }, + { "gpu_driver", gpuIdent->getDriver() }, + { "gpu_memory", static_cast(gpuIdent->getMemory()) }, + { "gl_version_int", glVersionToInteger(glContextData.value("version").toString()) }, + { "gl_version", glContextData["version"] }, + { "gl_vender", glContextData["vendor"] }, + { "gl_sl_version", glContextData["sl_version"] }, + { "gl_renderer", glContextData["renderer"] }, + { "ideal_thread_count", QThread::idealThreadCount() } + }; + auto macVersion = QSysInfo::macVersion(); + if (macVersion != QSysInfo::MV_None) { + properties["os_osx_version"] = QSysInfo::macVersion(); + } + auto windowsVersion = QSysInfo::windowsVersion(); + if (windowsVersion != QSysInfo::WV_None) { + properties["os_win_version"] = QSysInfo::windowsVersion(); + } + + ProcessorInfo procInfo; + if (getProcessorInfo(procInfo)) { + properties["processor_core_count"] = procInfo.numProcessorCores; + properties["logical_processor_count"] = procInfo.numLogicalProcessors; + properties["processor_l1_cache_count"] = procInfo.numProcessorCachesL1; + properties["processor_l2_cache_count"] = procInfo.numProcessorCachesL2; + properties["processor_l3_cache_count"] = procInfo.numProcessorCachesL3; + } + + properties["first_run"] = firstRun.get(); + + // add the user's machine ID to the launch event + properties["machine_fingerprint"] = uuidStringWithoutCurlyBraces(FingerprintUtils::getMachineFingerprint()); + + userActivityLogger.logAction("launch", properties); + } // Tell our entity edit sender about our known jurisdictions _entityEditSender.setServerJurisdictions(&_entityServerJurisdictions); diff --git a/libraries/networking/src/UserActivityLogger.h b/libraries/networking/src/UserActivityLogger.h index 179e8e6e66..b44c60eba7 100644 --- a/libraries/networking/src/UserActivityLogger.h +++ b/libraries/networking/src/UserActivityLogger.h @@ -33,6 +33,7 @@ public: public slots: bool isEnabled() { return !_disabled.get(); } + bool isDisabledSettingSet() const { return _disabled.isSet(); } void disable(bool disable); void logAction(QString action, QJsonObject details = QJsonObject(), JSONCallbackParameters params = JSONCallbackParameters()); @@ -53,7 +54,7 @@ private slots: private: UserActivityLogger(); - Setting::Handle _disabled { "UserActivityLoggerDisabled", false }; + Setting::Handle _disabled { "UserActivityLoggerDisabled", true }; QElapsedTimer _timer; }; diff --git a/tools/ac-client/src/ACClientApp.cpp b/tools/ac-client/src/ACClientApp.cpp index 34b7d5b049..1a2e6e4049 100644 --- a/tools/ac-client/src/ACClientApp.cpp +++ b/tools/ac-client/src/ACClientApp.cpp @@ -18,7 +18,6 @@ #include #include #include -#include #include "ACClientApp.h" @@ -43,9 +42,6 @@ ACClientApp::ACClientApp(int argc, char* argv[]) : const QCommandLineOption listenPortOption("listenPort", "listen port", QString::number(INVALID_PORT)); parser.addOption(listenPortOption); - // the AC client should not send any user activity events so disable the logger ASAP - UserActivityLogger::getInstance().disable(true); - if (!parser.parse(QCoreApplication::arguments())) { qCritical() << parser.errorText() << endl; parser.showHelp(); From c3c9df0cd0dd521e37f99679b029647c437b53e5 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 6 Jul 2017 10:41:46 -0700 Subject: [PATCH 41/54] restore old camera state --- scripts/system/controllers/godView.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/scripts/system/controllers/godView.js b/scripts/system/controllers/godView.js index f4990b7921..4b406399fd 100644 --- a/scripts/system/controllers/godView.js +++ b/scripts/system/controllers/godView.js @@ -52,9 +52,6 @@ function keyPressEvent(event) { function mousePress(event) { if (godView) { var pickRay = Camera.computePickRay(event.x, event.y); - Vec3.print("pr.o:", pickRay.origin); - Vec3.print("pr.d:", pickRay.direction); - Vec3.print("c.p:", Camera.position); var pointingAt = Vec3.sum(pickRay.origin, Vec3.multiply(pickRay.direction,300)); var moveToPosition = { x: pointingAt.x, y: MyAvatar.position.y, z: pointingAt.z }; moveTo(moveToPosition); @@ -62,9 +59,11 @@ function mousePress(event) { } +var oldCameraMode = Camera.mode; + function startGodView() { if (!godView) { - Camera.mode = "first person"; + oldCameraMode = Camera.mode; MyAvatar.position = Vec3.sum(MyAvatar.position, {x:0, y: GOD_VIEW_HEIGHT, z: 0}); Camera.mode = "independent"; Camera.position = Vec3.sum(MyAvatar.position, {x:0, y: GOD_CAMERA_OFFSET, z: 0}); @@ -75,7 +74,7 @@ function startGodView() { function endGodView() { if (godView) { - Camera.mode = "first person"; + Camera.mode = oldCameraMode; MyAvatar.position = Vec3.sum(MyAvatar.position, {x:0, y: (-1 * GOD_VIEW_HEIGHT) + ABOVE_GROUND_DROP, z: 0}); godView = false; } From 8c15d1bab900e349a8d76670181af8e3cd95e326 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Wed, 5 Jul 2017 15:50:47 -0700 Subject: [PATCH 42/54] delete-trailing-whitespace --- plugins/openvr/src/ViveControllerManager.cpp | 24 ++++++++++---------- plugins/openvr/src/ViveControllerManager.h | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index b0e7297879..2b0a485a00 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -124,7 +124,7 @@ static glm::mat4 calculateResetMat() { float const UI_RADIUS = 1.0f; float const UI_HEIGHT = 1.6f; float const UI_Z_OFFSET = 0.5; - + float xSize, zSize; chaperone->GetPlayAreaSize(&xSize, &zSize); glm::vec3 uiPos(0.0f, UI_HEIGHT, UI_RADIUS - (0.5f * zSize) - UI_Z_OFFSET); @@ -251,7 +251,7 @@ void ViveControllerManager::pluginUpdate(float deltaTime, const controller::Inpu _resetMat = calculateResetMat(); _resetMatCalculated = true; } - + _system->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseStanding, 0, _nextSimPoseData.vrPoses, vr::k_unMaxTrackedDeviceCount); _nextSimPoseData.update(_resetMat); } else if (isDesktopMode()) { @@ -429,7 +429,7 @@ void ViveControllerManager::InputDevice::emitCalibrationStatus() { status["hand_pucks"] = (_handConfig == HandConfig::Pucks); status["puckCount"] = (int)_validTrackedObjects.size(); status["UI"] = _calibrate; - + emit inputConfiguration->calibrationStatus(status); } @@ -480,7 +480,7 @@ void ViveControllerManager::InputDevice::sendUserActivityData(QString activity) {"head_puck", (_headConfig == HeadConfig::Puck) ? true : false}, {"hand_pucks", (_handConfig == HandConfig::Pucks) ? true : false} }; - + UserActivityLogger::getInstance().logAction(activity, jsonData); } @@ -513,12 +513,12 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr glm::mat4 defaultToReferenceMat = glm::mat4(); if (_headConfig == HeadConfig::HMD) { defaultToReferenceMat = calculateDefaultToReferenceForHmd(inputCalibration); - } else if (_headConfig == HeadConfig::Puck) { + } else if (_headConfig == HeadConfig::Puck) { defaultToReferenceMat = calculateDefaultToReferenceForHeadPuck(inputCalibration); } - + _config = _preferedConfig; - + bool headConfigured = configureHead(defaultToReferenceMat, inputCalibration); bool handsConfigured = configureHands(defaultToReferenceMat, inputCalibration); bool bodyConfigured = configureBody(defaultToReferenceMat, inputCalibration); @@ -952,12 +952,12 @@ void ViveControllerManager::InputDevice::calibrateLeftHand(glm::mat4& defaultToR glm::mat4 newHandMat = glm::mat4(glm::vec4(xPrime, 0.0f), glm::vec4(yPrime, 0.0f), glm::vec4(zPrime, 0.0f), glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)); - + glm::vec3 translationOffset = glm::vec3(0.0f, _handPuckYOffset, _handPuckZOffset); glm::quat initialRotation = glmExtractRotation(handPoseAvatarMat); glm::quat finalRotation = glmExtractRotation(newHandMat); - + glm::quat rotationOffset = glm::inverse(initialRotation) * finalRotation; glm::mat4 offsetMat = createMatFromQuatAndPos(rotationOffset, translationOffset); @@ -982,13 +982,13 @@ void ViveControllerManager::InputDevice::calibrateRightHand(glm::mat4& defaultTo glm::vec3 yPrime = glm::normalize(glm::cross(zPrime, xPrime)); glm::mat4 newHandMat = glm::mat4(glm::vec4(xPrime, 0.0f), glm::vec4(yPrime, 0.0f), glm::vec4(zPrime, 0.0f), glm::vec4(0.0f, 0.0f, 0.0f, 1.0f)); - + glm::vec3 translationOffset = glm::vec3(0.0f, _handPuckYOffset, _handPuckZOffset); glm::quat initialRotation = glmExtractRotation(handPoseAvatarMat); glm::quat finalRotation = glmExtractRotation(newHandMat); - + glm::quat rotationOffset = glm::inverse(initialRotation) * finalRotation; glm::mat4 offsetMat = createMatFromQuatAndPos(rotationOffset, translationOffset); @@ -1005,7 +1005,7 @@ void ViveControllerManager::InputDevice::calibrateFeet(glm::mat4& defaultToRefer auto& secondFoot = _validTrackedObjects[SECOND_FOOT]; controller::Pose& firstFootPose = firstFoot.second; controller::Pose& secondFootPose = secondFoot.second; - + if (determineLimbOrdering(firstFootPose, secondFootPose, headXAxis, headPosition)) { calibrateFoot(defaultToReferenceMat, inputCalibration, firstFoot, true); calibrateFoot(defaultToReferenceMat, inputCalibration, secondFoot, false); diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index d94320dfb2..2c7aee5dad 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -152,7 +152,7 @@ private: HandController, Pucks }; - + Config _config { Config::None }; Config _preferedConfig { Config::None }; HeadConfig _headConfig { HeadConfig::HMD }; From dee9769be34eb4317083f06deca1350ada12d26c Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 6 Jul 2017 10:50:47 -0700 Subject: [PATCH 43/54] Can now use chest, hips, shoulder & feet pucks in desktop mode. * Fixed bug where head puck would sometimes not work properly when other vive trackers were enabled. * Fixed calibration to work in sensor space instead of avatar space, this was necessary because the sensor to world matrix is unreliable when in desktop mode. --- plugins/openvr/src/ViveControllerManager.cpp | 102 +++++++++---------- plugins/openvr/src/ViveControllerManager.h | 4 +- 2 files changed, 53 insertions(+), 53 deletions(-) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 2b0a485a00..a531dfad4c 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -466,7 +466,9 @@ void ViveControllerManager::InputDevice::handleTrackedObject(uint32_t deviceInde // transform into avatar frame glm::mat4 controllerToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat; _poseStateMap[poseIndex] = pose.transform(controllerToAvatar); - _validTrackedObjects.push_back(std::make_pair(poseIndex, _poseStateMap[poseIndex])); + + // but _validTrackedObjects remain in sensor frame + _validTrackedObjects.push_back(std::make_pair(poseIndex, pose)); } else { controller::Pose invalidPose; _poseStateMap[poseIndex] = invalidPose; @@ -514,6 +516,7 @@ void ViveControllerManager::InputDevice::calibrate(const controller::InputCalibr if (_headConfig == HeadConfig::HMD) { defaultToReferenceMat = calculateDefaultToReferenceForHmd(inputCalibration); } else if (_headConfig == HeadConfig::Puck) { + std::sort(_validTrackedObjects.begin(), _validTrackedObjects.end(), sortPucksYPosition); defaultToReferenceMat = calculateDefaultToReferenceForHeadPuck(inputCalibration); } @@ -708,63 +711,65 @@ void ViveControllerManager::InputDevice::handleHandController(float deltaTime, u } } } + +// defaultToReferenceMat is an offset from avatar space to sensor space. +// it aligns the default head in avatar space with the hmd in sensor space. +// +// * E_a is the the default center-eye transform in avatar space. +// * E_s is the the hmd center-eye transform in sensor space, with roll and pitch removed. +// * D is the defaultReferenceMat. +// +// E_s = D * E_a => +// D = E_s * inverse(E_a) +// glm::mat4 ViveControllerManager::InputDevice::calculateDefaultToReferenceForHmd(const controller::InputCalibrationData& inputCalibration) { - // convert the hmd head from sensor space to avatar space - glm::mat4 hmdSensorFlippedMat = inputCalibration.hmdSensorMat * Matrices::Y_180; - glm::mat4 sensorToAvatarMat = glm::inverse(inputCalibration.avatarMat) * inputCalibration.sensorToWorldMat; - glm::mat4 hmdAvatarMat = sensorToAvatarMat * hmdSensorFlippedMat; - // cancel the roll and pitch for the hmd head - glm::quat hmdRotation = cancelOutRollAndPitch(glmExtractRotation(hmdAvatarMat)); - glm::vec3 hmdTranslation = extractTranslation(hmdAvatarMat); - glm::mat4 currentHmd = createMatFromQuatAndPos(hmdRotation, hmdTranslation); + // the center-eye transform in avatar space. + glm::mat4 E_a = inputCalibration.defaultCenterEyeMat; - // calculate the offset from the centerOfEye to defaultHeadMat - glm::mat4 defaultHeadOffset = glm::inverse(inputCalibration.defaultCenterEyeMat) * inputCalibration.defaultHeadMat; + // the center-eye transform in sensor space. + glm::mat4 E_s = inputCalibration.hmdSensorMat * Matrices::Y_180; // the Y_180 is to convert hmd from -z forward to z forward. - glm::mat4 currentHead = currentHmd * defaultHeadOffset; + // cancel out roll and pitch on E_s + glm::quat rot = cancelOutRollAndPitch(glmExtractRotation(E_s)); + glm::vec3 trans = extractTranslation(E_s); + E_s = createMatFromQuatAndPos(rot, trans); - // calculate the defaultToRefrenceXform - glm::mat4 defaultToReferenceMat = currentHead * glm::inverse(inputCalibration.defaultHeadMat); - - return defaultToReferenceMat; + return E_s * glm::inverse(E_a); } +// defaultToReferenceMat is an offset from avatar space to sensor space. +// it aligns the default head in avatar space with the head-puck in sensor space. +// +// * E_a is the the default center-eye transform in avatar space. +// * E_s is the the head-puck center-eye transform in sensor space, with roll and pitch removed. +// * D is the defaultReferenceMat. +// +// E_s = D * E_a => +// D = E_s * inverse(E_a) +// glm::mat4 ViveControllerManager::InputDevice::calculateDefaultToReferenceForHeadPuck(const controller::InputCalibrationData& inputCalibration) { - glm::mat4 avatarToSensorMat = glm::inverse(inputCalibration.sensorToWorldMat) * inputCalibration.avatarMat; - glm::mat4 sensorToAvatarMat = glm::inverse(inputCalibration.avatarMat) * inputCalibration.sensorToWorldMat; + + // the center-eye transform in avatar space. + glm::mat4 E_a = inputCalibration.defaultCenterEyeMat; + + // calculate the center-eye transform in sensor space, via the head-puck size_t headPuckIndex = _validTrackedObjects.size() - 1; controller::Pose headPuckPose = _validTrackedObjects[headPuckIndex].second; - glm::mat4 headPuckAvatarMat = createMatFromQuatAndPos(headPuckPose.getRotation(), headPuckPose.getTranslation()) * Matrices::Y_180; - glm::vec3 headPuckTranslation = extractTranslation(headPuckAvatarMat); - glm::vec3 headPuckZAxis = cancelOutRollAndPitch(glmExtractRotation(headPuckAvatarMat)) * glm::vec3(0.0f, 0.0f, 1.0f); - glm::vec3 worldUp = glm::vec3(0.0f, 1.0f, 0.0f); - // check that the head puck z axis is not parrallel to the world up - const float EPSILON = 1.0e-4f; - glm::vec3 zAxis = glmExtractRotation(headPuckAvatarMat) * glm::vec3(0.0f, 0.0f, 1.0f); - if (fabsf(fabsf(glm::dot(glm::normalize(worldUp), glm::normalize(zAxis))) - 1.0f) < EPSILON) { - headPuckZAxis = glm::vec3(1.0f, 0.0f, 0.0f); - } + // AJT: TODO: handle case were forward is parallel with UNIT_Y. + glm::vec3 forward = headPuckPose.rotation * -Vectors::UNIT_Z; + glm::vec3 x = glm::normalize(glm::cross(Vectors::UNIT_Y, forward)); + glm::vec3 z = glm::normalize(glm::cross(x, Vectors::UNIT_Y)); + glm::mat3 centerEyeRotMat(x, Vectors::UNIT_Y, z); + glm::vec3 centerEyeTrans = headPuckPose.translation + centerEyeRotMat * glm::vec3(0.0f, _headPuckYOffset, _headPuckZOffset); - glm::vec3 yPrime = glm::vec3(0.0f, 1.0f, 0.0f); - glm::vec3 xPrime = glm::normalize(glm::cross(worldUp, headPuckZAxis)); - glm::vec3 zPrime = glm::normalize(glm::cross(xPrime, yPrime)); - glm::mat4 newHeadPuck = glm::mat4(glm::vec4(xPrime, 0.0f), glm::vec4(yPrime, 0.0f), - glm::vec4(zPrime, 0.0f), glm::vec4(headPuckTranslation, 1.0f)); + glm::mat4 E_s(glm::vec4(centerEyeRotMat[0], 0.0f), + glm::vec4(centerEyeRotMat[1], 0.0f), + glm::vec4(centerEyeRotMat[2], 0.0f), + glm::vec4(centerEyeTrans, 1.0f)); - glm::mat4 headPuckOffset = glm::mat4(glm::vec4(1.0f, 0.0f, 0.0f, 0.0f), glm::vec4(0.0f, 1.0f, 0.0f, 0.0f), - glm::vec4(0.0f, 0.0f, 1.0f, 0.0f), glm::vec4(0.0f, _headPuckYOffset, _headPuckZOffset, 1.0f)); - - glm::mat4 finalHeadPuck = newHeadPuck * headPuckOffset; - - glm::mat4 defaultHeadOffset = glm::inverse(inputCalibration.defaultCenterEyeMat) * inputCalibration.defaultHeadMat; - - glm::mat4 currentHead = finalHeadPuck * defaultHeadOffset; - - // calculate the defaultToRefrenceXform - glm::mat4 defaultToReferenceMat = currentHead * glm::inverse(inputCalibration.defaultHeadMat); - return defaultToReferenceMat; + return E_s * glm::inverse(E_a); } void ViveControllerManager::InputDevice::partitionTouchpad(int sButton, int xAxis, int yAxis, int centerPseudoButton, int xPseudoButton, int yPseudoButton) { @@ -1070,13 +1075,8 @@ void ViveControllerManager::InputDevice::calibrateShoulders(glm::mat4& defaultTo void ViveControllerManager::InputDevice::calibrateHead(glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration) { size_t headIndex = _validTrackedObjects.size() - 1; const PuckPosePair& head = _validTrackedObjects[headIndex]; - - // assume the person is wearing the head puck on his/her forehead - glm::mat4 defaultHeadOffset = glm::inverse(inputCalibration.defaultCenterEyeMat) * inputCalibration.defaultHeadMat; - controller::Pose newHead = head.second.postTransform(defaultHeadOffset); - _jointToPuckMap[controller::HEAD] = head.first; - _pucksOffset[head.first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultHeadMat, newHead); + _pucksOffset[head.first] = computeOffset(defaultToReferenceMat, inputCalibration.defaultHeadMat, head.second); } QString ViveControllerManager::InputDevice::configToString(Config config) { diff --git a/plugins/openvr/src/ViveControllerManager.h b/plugins/openvr/src/ViveControllerManager.h index 2c7aee5dad..a9bcc7e4e2 100644 --- a/plugins/openvr/src/ViveControllerManager.h +++ b/plugins/openvr/src/ViveControllerManager.h @@ -177,8 +177,8 @@ private: float _leftHapticDuration { 0.0f }; float _rightHapticStrength { 0.0f }; float _rightHapticDuration { 0.0f }; - float _headPuckYOffset { 0.0f }; - float _headPuckZOffset { 0.0f }; + float _headPuckYOffset { -0.05f }; + float _headPuckZOffset { -0.05f }; float _handPuckYOffset { 0.0f }; float _handPuckZOffset { 0.0f }; bool _triggersPressedHandled { false }; From 4e9b8c1ef94e7e1384f2fc0e697708f72d229855 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 6 Jul 2017 11:01:59 -0700 Subject: [PATCH 44/54] updated comments --- plugins/openvr/src/ViveControllerManager.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index a531dfad4c..e505051536 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -713,10 +713,10 @@ void ViveControllerManager::InputDevice::handleHandController(float deltaTime, u } // defaultToReferenceMat is an offset from avatar space to sensor space. -// it aligns the default head in avatar space with the hmd in sensor space. +// it aligns the default center-eye in avatar space with the hmd in sensor space. // -// * E_a is the the default center-eye transform in avatar space. -// * E_s is the the hmd center-eye transform in sensor space, with roll and pitch removed. +// * E_a is the the default center-of-the-eyes transform in avatar space. +// * E_s is the the hmd eye-center transform in sensor space, with roll and pitch removed. // * D is the defaultReferenceMat. // // E_s = D * E_a => @@ -739,7 +739,9 @@ glm::mat4 ViveControllerManager::InputDevice::calculateDefaultToReferenceForHmd( } // defaultToReferenceMat is an offset from avatar space to sensor space. -// it aligns the default head in avatar space with the head-puck in sensor space. +// it aligns the default center-of-the-eyes transform in avatar space with the head-puck in sensor space. +// The offset from the center-of-the-eyes to the head-puck can be configured via _headPuckYOffset and _headPuckZOffset, +// these values are exposed in the configuration UI. // // * E_a is the the default center-eye transform in avatar space. // * E_s is the the head-puck center-eye transform in sensor space, with roll and pitch removed. From eb486c8f470344f2239e4818bc8ea353929d2370 Mon Sep 17 00:00:00 2001 From: "Anthony J. Thibault" Date: Thu, 6 Jul 2017 11:03:03 -0700 Subject: [PATCH 45/54] comments --- plugins/openvr/src/ViveControllerManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index e505051536..07b3b2f73d 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -739,9 +739,9 @@ glm::mat4 ViveControllerManager::InputDevice::calculateDefaultToReferenceForHmd( } // defaultToReferenceMat is an offset from avatar space to sensor space. -// it aligns the default center-of-the-eyes transform in avatar space with the head-puck in sensor space. +// It aligns the default center-of-the-eyes transform in avatar space with the head-puck in sensor space. // The offset from the center-of-the-eyes to the head-puck can be configured via _headPuckYOffset and _headPuckZOffset, -// these values are exposed in the configuration UI. +// These values are exposed in the configuration UI. // // * E_a is the the default center-eye transform in avatar space. // * E_s is the the head-puck center-eye transform in sensor space, with roll and pitch removed. From 4e3dba176734e72fc1b45b38a9cc7c15afbbd0ad Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 6 Jul 2017 19:12:52 +0100 Subject: [PATCH 46/54] goto HMD keyboard fix --- interface/resources/qml/hifi/tablet/TabletAddressDialog.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml index 073f143dbe..1a8b33c974 100644 --- a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml +++ b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml @@ -227,7 +227,7 @@ StackView { MouseArea { anchors.fill: parent; onClicked: { - if (!addressLine.focus || !HMD.active) { + if (!addressLine.focus || HMD.active) { addressLine.focus = true; addressLine.forceActiveFocus(); addressBarDialog.keyboardEnabled = HMD.active; From de5802418f98fa72059cfb76d878969c44d6ee87 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 6 Jul 2017 19:27:48 +0100 Subject: [PATCH 47/54] fixed some keybaord logic --- interface/resources/qml/hifi/tablet/TabletAddressDialog.qml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml index 1a8b33c974..9828b3e068 100644 --- a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml +++ b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml @@ -227,9 +227,9 @@ StackView { MouseArea { anchors.fill: parent; onClicked: { - if (!addressLine.focus || HMD.active) { - addressLine.focus = true; - addressLine.forceActiveFocus(); + addressLine.focus = true; + addressLine.forceActiveFocus(); + if (HMD.active) { addressBarDialog.keyboardEnabled = HMD.active; } tabletRoot.playButtonClickSound(); From bdcdff3dbc34aadaffdc75605f95f31ffd4d8516 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 6 Jul 2017 12:01:08 -0700 Subject: [PATCH 48/54] force _isSet to be set before isSet() called --- libraries/shared/src/SettingHandle.h | 1 + 1 file changed, 1 insertion(+) diff --git a/libraries/shared/src/SettingHandle.h b/libraries/shared/src/SettingHandle.h index 258d1f8491..341a4cb101 100644 --- a/libraries/shared/src/SettingHandle.h +++ b/libraries/shared/src/SettingHandle.h @@ -107,6 +107,7 @@ namespace Setting { } bool isSet() const { + maybeInit(); return _isSet; } From 2d876377d58071255f4dc0e9fa4150f98da13e9a Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 6 Jul 2017 20:04:44 +0100 Subject: [PATCH 49/54] keyboard know disappears when you click of the address line --- .../qml/hifi/tablet/TabletAddressDialog.qml | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml index 9828b3e068..a02e79a5e2 100644 --- a/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml +++ b/interface/resources/qml/hifi/tablet/TabletAddressDialog.qml @@ -94,10 +94,20 @@ StackView { property bool keyboardEnabled: false property bool keyboardRaised: false property bool punctuationMode: false - + width: parent.width height: parent.height + MouseArea { + anchors.fill: parent + propagateComposedEvents: true + onPressed: { + parent.forceActiveFocus(); + addressBarDialog.keyboardEnabled = false; + mouse.accepted = false; + } + } + anchors { right: parent.right left: parent.left From a5c7324ec500bc044630684dffe1fc4abbded05e Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 6 Jul 2017 12:15:44 -0700 Subject: [PATCH 50/54] Ensure admins see PAL admin column --- scripts/system/pal.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/system/pal.js b/scripts/system/pal.js index 2c81622668..c6cf4af0ad 100644 --- a/scripts/system/pal.js +++ b/scripts/system/pal.js @@ -482,10 +482,10 @@ function populateNearbyUserList(selectData, oldAudioData) { isPresent: true, isReplicated: avatar.isReplicated }; + // Everyone needs to see admin status. Username and fingerprint returns default constructor output if the requesting user isn't an admin. + Users.requestUsernameFromID(id); if (id) { addAvatarNode(id); // No overlay for ourselves - // Everyone needs to see admin status. Username and fingerprint returns default constructor output if the requesting user isn't an admin. - Users.requestUsernameFromID(id); avatarsOfInterest[id] = true; } else { // Return our username from the Account API From 1fcb3b32d60e921776f824529e9b4bd1b3030887 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Thu, 6 Jul 2017 20:55:19 +0100 Subject: [PATCH 51/54] fixed letter cap --- interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml b/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml index d6d37e6dae..90d6ba7022 100644 --- a/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml +++ b/interface/resources/qml/hifi/tablet/OpenVrConfiguration.qml @@ -737,7 +737,7 @@ Rectangle { RalewayBold { id: viveDesktopText size: 10 - text: "Use vive devices in desktop mode" + text: "Use Vive devices in desktop mode" color: hifi.colors.white anchors { From 6d98d20b129d5f69f1257e8f103898b6cb506b28 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Thu, 6 Jul 2017 16:15:23 -0700 Subject: [PATCH 52/54] cleanup bad QEventLoop::exec() OAuth handling code --- domain-server/src/DomainServer.cpp | 92 +++++++++++++++++++++--------- domain-server/src/DomainServer.h | 7 +++ 2 files changed, 71 insertions(+), 28 deletions(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index 9303bed2b5..bf7a8e2f1e 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -1959,7 +1959,8 @@ bool DomainServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url return _settingsManager.handleAuthenticatedHTTPRequest(connection, url); } -const QString HIFI_SESSION_COOKIE_KEY = "DS_WEB_SESSION_UUID"; +static const QString HIFI_SESSION_COOKIE_KEY = "DS_WEB_SESSION_UUID"; +static const QString STATE_QUERY_KEY = "state"; bool DomainServer::handleHTTPSRequest(HTTPSConnection* connection, const QUrl &url, bool skipSubHandler) { qDebug() << "HTTPS request received at" << url.toString(); @@ -1970,10 +1971,9 @@ bool DomainServer::handleHTTPSRequest(HTTPSConnection* connection, const QUrl &u const QString CODE_QUERY_KEY = "code"; QString authorizationCode = codeURLQuery.queryItemValue(CODE_QUERY_KEY); - const QString STATE_QUERY_KEY = "state"; QUuid stateUUID = QUuid(codeURLQuery.queryItemValue(STATE_QUERY_KEY)); - if (!authorizationCode.isEmpty() && !stateUUID.isNull()) { + if (!authorizationCode.isEmpty() && !stateUUID.isNull() && _webAuthenticationStateSet.remove(stateUUID)) { // fire off a request with this code and state to get an access token for the user const QString OAUTH_TOKEN_REQUEST_PATH = "/oauth/token"; @@ -1991,47 +1991,83 @@ bool DomainServer::handleHTTPSRequest(HTTPSConnection* connection, const QUrl &u tokenRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); QNetworkReply* tokenReply = NetworkAccessManager::getInstance().post(tokenRequest, tokenPostBody.toLocal8Bit()); + connect(tokenReply, &QNetworkReply::finished, this, &DomainServer::tokenGrantFinished); - if (_webAuthenticationStateSet.remove(stateUUID)) { - // this is a web user who wants to auth to access web interface - // we hold the response back to them until we get their profile information - // and can decide if they are let in or not + // add this connection to our list of pending connections so that we can hold the response + _pendingOAuthConnections.insert(stateUUID, connection); - QEventLoop loop; - connect(tokenReply, &QNetworkReply::finished, &loop, &QEventLoop::quit); + // set the state UUID on the reply so that we can associate the response with the connection later + tokenReply->setProperty(STATE_QUERY_KEY.toLocal8Bit(), stateUUID); - // start the loop for the token request - loop.exec(); + return true; + } else { + connection->respond(HTTPConnection::StatusCode400); - QNetworkReply* profileReply = profileRequestGivenTokenReply(tokenReply); + return true; + } + } else { + return false; + } +} - // stop the loop once the profileReply is complete - connect(profileReply, &QNetworkReply::finished, &loop, &QEventLoop::quit); +HTTPSConnection* DomainServer::connectionFromReplyWithState(QNetworkReply* reply) { + // grab the UUID state property from the reply + QUuid stateUUID = reply->property(STATE_QUERY_KEY.toLocal8Bit()).toUuid(); - // restart the loop for the profile request - loop.exec(); + if (!stateUUID.isNull()) { + return _pendingOAuthConnections.take(stateUUID); + } else { + return nullptr; + } +} +void DomainServer::tokenGrantFinished() { + auto tokenReply = qobject_cast(sender()); + + if (tokenReply) { + if (tokenReply->error() == QNetworkReply::NoError) { + // now that we have a token for this profile, send off a profile request + QNetworkReply* profileReply = profileRequestGivenTokenReply(tokenReply); + + // forward along the state UUID that we kept with the token request + profileReply->setProperty(STATE_QUERY_KEY.toLocal8Bit(), tokenReply->property(STATE_QUERY_KEY.toLocal8Bit())); + + connect(profileReply, &QNetworkReply::finished, this, &DomainServer::profileRequestFinished); + } else { + // the token grant failed, send back a 500 (assuming the connection is still around) + auto connection = connectionFromReplyWithState(tokenReply); + + if (connection) { + connection->respond(HTTPConnection::StatusCode500); + } + } + + tokenReply->deleteLater(); + } +} + +void DomainServer::profileRequestFinished() { + + auto profileReply = qobject_cast(sender()); + + if (profileReply) { + auto connection = connectionFromReplyWithState(profileReply); + + if (connection) { + if (profileReply->error() == QNetworkReply::NoError) { // call helper method to get cookieHeaders Headers cookieHeaders = setupCookieHeadersFromProfileReply(profileReply); connection->respond(HTTPConnection::StatusCode302, QByteArray(), HTTPConnection::DefaultContentType, cookieHeaders); - delete tokenReply; - delete profileReply; - - // we've redirected the user back to our homepage - return true; - + } else { + // the profile request failed, send back a 500 (assuming the connection is still around) + connection->respond(HTTPConnection::StatusCode500); } } - // respond with a 200 code indicating that login is complete - connection->respond(HTTPConnection::StatusCode200); - - return true; - } else { - return false; + profileReply->deleteLater(); } } diff --git a/domain-server/src/DomainServer.h b/domain-server/src/DomainServer.h index 8851e3380b..4808297c89 100644 --- a/domain-server/src/DomainServer.h +++ b/domain-server/src/DomainServer.h @@ -111,6 +111,9 @@ private slots: void updateDownstreamNodes(); void updateUpstreamNodes(); + void tokenGrantFinished(); + void profileRequestFinished(); + signals: void iceServerChanged(); void userConnected(); @@ -178,6 +181,8 @@ private: void updateReplicationNodes(ReplicationServerDirection direction); + HTTPSConnection* connectionFromReplyWithState(QNetworkReply* reply); + SubnetList _acSubnetWhitelist; std::vector _replicatedUsernames; @@ -235,6 +240,8 @@ private: bool _sendICEServerAddressToMetaverseAPIInProgress { false }; bool _sendICEServerAddressToMetaverseAPIRedo { false }; + + QHash> _pendingOAuthConnections; }; From 4c1bf6af4716f8dfe6b6ea5cecf6865dcd9d1d3d Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 7 Jul 2017 11:38:25 +0200 Subject: [PATCH 53/54] REmoving comments --- libraries/render-utils/src/ZoneRenderer.cpp | 9 +++------ tests/gpu-test/src/TestWindow.cpp | 1 - tests/render-perf/src/main.cpp | 7 ------- 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/libraries/render-utils/src/ZoneRenderer.cpp b/libraries/render-utils/src/ZoneRenderer.cpp index 80be123f0f..8fa243c13b 100644 --- a/libraries/render-utils/src/ZoneRenderer.cpp +++ b/libraries/render-utils/src/ZoneRenderer.cpp @@ -136,14 +136,13 @@ void DebugZoneLighting::run(const render::RenderContextPointer& context, const I auto deferredTransform = inputs; - auto lightStage = context->_scene->getStage("LIGHT_STAGE"); + auto lightStage = context->_scene->getStage(LightStage::getName()); std::vector keyLightStack; if (lightStage && lightStage->_currentFrame._sunLights.size()) { for (auto index : lightStage->_currentFrame._sunLights) { keyLightStack.push_back(lightStage->getLight(index)); } } - // keyLightStack.push_back(lightStage->getLight(0)); std::vector ambientLightStack; if (lightStage && lightStage->_currentFrame._ambientLights.size()) { @@ -151,9 +150,8 @@ void DebugZoneLighting::run(const render::RenderContextPointer& context, const I ambientLightStack.push_back(lightStage->getLight(index)); } } - // ambientLightStack.push_back(lightStage->getLight(0)); - auto backgroundStage = context->_scene->getStage("BACKGROUND_STAGE"); + auto backgroundStage = context->_scene->getStage(BackgroundStage::getName()); std::vector skyboxStack; if (backgroundStage && backgroundStage->_currentFrame._backgrounds.size()) { for (auto index : backgroundStage->_currentFrame._backgrounds) { @@ -162,8 +160,7 @@ void DebugZoneLighting::run(const render::RenderContextPointer& context, const I skyboxStack.push_back(background->getSkybox()); } } - } - // skyboxStack.push_back(backgroundStage->getBackground(0)->getSkybox()); + } gpu::doInBatch(args->_context, [=](gpu::Batch& batch) { diff --git a/tests/gpu-test/src/TestWindow.cpp b/tests/gpu-test/src/TestWindow.cpp index 5b5102701a..39043805b8 100644 --- a/tests/gpu-test/src/TestWindow.cpp +++ b/tests/gpu-test/src/TestWindow.cpp @@ -77,7 +77,6 @@ void TestWindow::initGl() { #ifdef DEFERRED_LIGHTING auto deferredLightingEffect = DependencyManager::get(); deferredLightingEffect->init(); - // deferredLightingEffect->setGlobalLight(_light); initDeferredPipelines(*_shapePlumber); #endif } diff --git a/tests/render-perf/src/main.cpp b/tests/render-perf/src/main.cpp index 2b91a36b48..ce47a896aa 100644 --- a/tests/render-perf/src/main.cpp +++ b/tests/render-perf/src/main.cpp @@ -889,11 +889,6 @@ private: BackgroundRenderData::_item = _main3DScene->allocateID(); transaction.resetItem(BackgroundRenderData::_item, backgroundRenderPayload); } - // Setup the current Zone Entity lighting - { - auto stage = DependencyManager::get()->getSkyStage(); - // DependencyManager::get()->setGlobalLight(stage->getSunLight()); - } { PerformanceTimer perfTimer("SceneProcessTransaction"); @@ -914,8 +909,6 @@ private: PerformanceTimer perfTimer("draw"); // The pending changes collecting the changes here render::Transaction transaction; - // Setup the current Zone Entity lighting - // DependencyManager::get()->setGlobalLight(_sunSkyStage.getSunLight()); { PerformanceTimer perfTimer("SceneProcessTransaction"); _main3DScene->enqueueTransaction(transaction); From a8086764dae94e8195d939d69ed76a03e8d99d2f Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 7 Jul 2017 12:19:22 +0200 Subject: [PATCH 54/54] REmoving warnings for unused var --- libraries/render-utils/src/DeferredLightingEffect.cpp | 6 +++--- libraries/render-utils/src/DeferredLightingEffect.h | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 5f18916a92..7b1ea1768d 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -740,8 +740,8 @@ void DefaultLightingSetup::run(const RenderContextPointer& renderContext) { _defaultLight = lp; // Add the global light to the light stage (for later shadow rendering) - auto defaultLightID = lightStage->addLight(lp); - lightStage->addShadow(defaultLightID); + _defaultLightID = lightStage->addLight(lp); + lightStage->addShadow(_defaultLightID); } auto backgroundStage = renderContext->_scene->getStage(); @@ -754,7 +754,7 @@ void DefaultLightingSetup::run(const RenderContextPointer& renderContext) { _defaultBackground = background; // Add the global light to the light stage (for later shadow rendering) - auto defaultBackgroundID = backgroundStage->addBackground(_defaultBackground); + _defaultBackgroundID = backgroundStage->addBackground(_defaultBackground); } } } diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 7fc9600d18..a4d62ea407 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -180,7 +180,9 @@ public: protected: model::LightPointer _defaultLight; + LightStage::Index _defaultLightID{ LightStage::INVALID_INDEX }; model::SunSkyStagePointer _defaultBackground; + BackgroundStage::Index _defaultBackgroundID{ BackgroundStage::INVALID_INDEX }; model::SkyboxPointer _defaultSkybox { new ProceduralSkybox() }; gpu::TexturePointer _defaultSkyboxTexture; gpu::TexturePointer _defaultSkyboxAmbientTexture;