From 8d89ea75f5af6c867abb48c7fb71e37f5e40c691 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Wed, 28 Jun 2017 17:41:08 -0700 Subject: [PATCH 1/8] Initial commit --- interface/src/SecondaryCamera.cpp | 18 ++++++++++++++++-- interface/src/SecondaryCamera.h | 2 ++ scripts/system/spectatorCamera.js | 3 ++- 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/interface/src/SecondaryCamera.cpp b/interface/src/SecondaryCamera.cpp index 1fbb75cdad..3adae61aaa 100644 --- a/interface/src/SecondaryCamera.cpp +++ b/interface/src/SecondaryCamera.cpp @@ -12,6 +12,7 @@ #include "SecondaryCamera.h" #include #include +#include using RenderArgsPointer = std::shared_ptr; @@ -40,6 +41,7 @@ void SecondaryCameraRenderTaskConfig::resetSizeSpectatorCamera(int width, int he } class BeginSecondaryCameraFrame { // Changes renderContext for our framebuffer and view. + QUuid _attachedEntityId{}; glm::vec3 _position{}; glm::quat _orientation{}; float _vFoV{}; @@ -54,8 +56,20 @@ public: void configure(const Config& config) { if (config.enabled || config.alwaysEnabled) { - _position = config.position; - _orientation = config.orientation; + _attachedEntityId = config.attachedEntityId; + if (_attachedEntityId != QUuid()) { + auto entityScriptingInterface = DependencyManager::get(); + EntityPropertyFlags entityPropertyFlags; + entityPropertyFlags += PROP_POSITION; + entityPropertyFlags += PROP_ROTATION; + EntityItemProperties entityProperties = entityScriptingInterface->getEntityProperties(config.attachedEntityId, entityPropertyFlags); + + _position = entityProperties.getPosition(); + _orientation = entityProperties.getRotation(); + } else { + _position = config.position; + _orientation = config.orientation; + } _vFoV = config.vFoV; _nearClipPlaneDistance = config.nearClipPlaneDistance; _farClipPlaneDistance = config.farClipPlaneDistance; diff --git a/interface/src/SecondaryCamera.h b/interface/src/SecondaryCamera.h index 5ad19c9614..15e6f41ad2 100644 --- a/interface/src/SecondaryCamera.h +++ b/interface/src/SecondaryCamera.h @@ -30,12 +30,14 @@ public: class BeginSecondaryCameraFrameConfig : public render::Task::Config { // Exposes secondary camera parameters to JavaScript. Q_OBJECT + Q_PROPERTY(QUuid attachedEntityId MEMBER attachedEntityId NOTIFY dirty) // entity whose properties define camera position and orientation Q_PROPERTY(glm::vec3 position MEMBER position NOTIFY dirty) // of viewpoint to render from Q_PROPERTY(glm::quat orientation MEMBER orientation NOTIFY dirty) // of viewpoint to render from Q_PROPERTY(float vFoV MEMBER vFoV NOTIFY dirty) // Secondary camera's vertical field of view. In degrees. Q_PROPERTY(float nearClipPlaneDistance MEMBER nearClipPlaneDistance NOTIFY dirty) // Secondary camera's near clip plane distance. In meters. Q_PROPERTY(float farClipPlaneDistance MEMBER farClipPlaneDistance NOTIFY dirty) // Secondary camera's far clip plane distance. In meters. public: + QUuid attachedEntityId{}; glm::vec3 position{}; glm::quat orientation{}; float vFoV{ 45.0f }; diff --git a/scripts/system/spectatorCamera.js b/scripts/system/spectatorCamera.js index 5154322daa..5b6c826e88 100644 --- a/scripts/system/spectatorCamera.js +++ b/scripts/system/spectatorCamera.js @@ -93,7 +93,7 @@ beginSpectatorFrameRenderConfig.nearClipPlaneDistance = nearClipPlaneDistance; beginSpectatorFrameRenderConfig.farClipPlaneDistance = farClipPlaneDistance; cameraRotation = MyAvatar.orientation, cameraPosition = inFrontOf(1, Vec3.sum(MyAvatar.position, { x: 0, y: 0.3, z: 0 })); - cameraUpdateInterval = Script.setInterval(updateRenderFromCamera, 11); // Update every 11ms (90.9hz) + //cameraUpdateInterval = Script.setInterval(updateRenderFromCamera, 11); // Update every 11ms (90.9hz) camera = Entities.addEntity({ "angularDamping": 1, "damping": 1, @@ -112,6 +112,7 @@ "type": "Model", "userData": "{\"grabbableKey\":{\"grabbable\":true}}" }, true); + beginSpectatorFrameRenderConfig.attachedEntityId = camera; updateOverlay(); setDisplay(monitorShowsCameraView); } From 5ceb80b3e7b9bafebb70ea47a759d0e0b7e9b7f8 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 29 Jun 2017 09:58:37 -0700 Subject: [PATCH 2/8] It's working! --- interface/src/SecondaryCamera.cpp | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/interface/src/SecondaryCamera.cpp b/interface/src/SecondaryCamera.cpp index 3adae61aaa..178286f614 100644 --- a/interface/src/SecondaryCamera.cpp +++ b/interface/src/SecondaryCamera.cpp @@ -57,19 +57,8 @@ public: void configure(const Config& config) { if (config.enabled || config.alwaysEnabled) { _attachedEntityId = config.attachedEntityId; - if (_attachedEntityId != QUuid()) { - auto entityScriptingInterface = DependencyManager::get(); - EntityPropertyFlags entityPropertyFlags; - entityPropertyFlags += PROP_POSITION; - entityPropertyFlags += PROP_ROTATION; - EntityItemProperties entityProperties = entityScriptingInterface->getEntityProperties(config.attachedEntityId, entityPropertyFlags); - - _position = entityProperties.getPosition(); - _orientation = entityProperties.getRotation(); - } else { - _position = config.position; - _orientation = config.orientation; - } + _position = config.position; + _orientation = config.orientation; _vFoV = config.vFoV; _nearClipPlaneDistance = config.nearClipPlaneDistance; _farClipPlaneDistance = config.farClipPlaneDistance; @@ -97,8 +86,19 @@ public: }); auto srcViewFrustum = args->getViewFrustum(); - srcViewFrustum.setPosition(_position); - srcViewFrustum.setOrientation(_orientation); + if (_attachedEntityId != QUuid()) { + auto entityScriptingInterface = DependencyManager::get(); + EntityPropertyFlags entityPropertyFlags; + entityPropertyFlags += PROP_POSITION; + entityPropertyFlags += PROP_ROTATION; + EntityItemProperties entityProperties = entityScriptingInterface->getEntityProperties(_attachedEntityId, entityPropertyFlags); + + srcViewFrustum.setPosition(entityProperties.getPosition()); + srcViewFrustum.setOrientation(entityProperties.getRotation()); + } else { + srcViewFrustum.setPosition(_position); + srcViewFrustum.setOrientation(_orientation); + } srcViewFrustum.setProjection(glm::perspective(glm::radians(_vFoV), ((float)args->_viewport.z / (float)args->_viewport.w), _nearClipPlaneDistance, _farClipPlaneDistance)); // Without calculating the bound planes, the secondary camera will use the same culling frustum as the main camera, // which is not what we want here. From 57692d263d741335cb4540c98028daf0b0489678 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 29 Jun 2017 09:59:52 -0700 Subject: [PATCH 3/8] Remove dead code --- scripts/system/spectatorCamera.js | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/scripts/system/spectatorCamera.js b/scripts/system/spectatorCamera.js index 5b6c826e88..fdb187bd9c 100644 --- a/scripts/system/spectatorCamera.js +++ b/scripts/system/spectatorCamera.js @@ -71,8 +71,6 @@ // -viewFinderOverlayDim: The x, y, and z dimensions of the viewFinderOverlay. // -camera: The camera model which is grabbable. // -viewFinderOverlay: The preview of what the spectator camera is viewing, placed inside the glass pane. - // -cameraUpdateInterval: Used when setting Script.setInterval() - // -CAMERA_UPDATE_INTERVAL_MS: Defines the time between calls to updateRenderFromCamera() var vFoV = 45.0; var nearClipPlaneDistance = 0.1; var farClipPlaneDistance = 100.0; @@ -83,8 +81,6 @@ // draws textures, but should be looked into at some point. Also the z dimension shouldn't affect // the overlay since it is an Image3DOverlay so it is set to 0. var viewFinderOverlayDim = { x: glassPaneWidth, y: -glassPaneWidth, z: 0 }; - var cameraUpdateInterval; - var CAMERA_UPDATE_INTERVAL_MS = 11; // Result of (1000 (ms/s)) / (90 (hz)) rounded down function spectatorCameraOn() { // Sets the special texture size based on the window it is displayed in, which doesn't include the menu bar spectatorFrameRenderConfig.resetSizeSpectatorCamera(Window.innerWidth, Window.innerHeight); @@ -93,7 +89,6 @@ beginSpectatorFrameRenderConfig.nearClipPlaneDistance = nearClipPlaneDistance; beginSpectatorFrameRenderConfig.farClipPlaneDistance = farClipPlaneDistance; cameraRotation = MyAvatar.orientation, cameraPosition = inFrontOf(1, Vec3.sum(MyAvatar.position, { x: 0, y: 0.3, z: 0 })); - //cameraUpdateInterval = Script.setInterval(updateRenderFromCamera, 11); // Update every 11ms (90.9hz) camera = Entities.addEntity({ "angularDamping": 1, "damping": 1, @@ -124,10 +119,7 @@ // destroy the camera entity. function spectatorCameraOff() { spectatorFrameRenderConfig.enabled = beginSpectatorFrameRenderConfig.enabled = false; - if (cameraUpdateInterval) { - Script.clearInterval(cameraUpdateInterval); - cameraUpdateInterval = false; - } + beginSpectatorFrameRenderConfig.attachedEntityId = false; if (camera) { Entities.deleteEntity(camera); } @@ -225,8 +217,8 @@ } function setDisplay(showCameraView) { - // It would be fancy if (showCameraView && !cameraUpdateInterval) would show instructions, but that's out of scope for now. - var url = (showCameraView && cameraUpdateInterval) ? "resource://spectatorCameraFrame" : ""; + // It would be fancy if (showCameraView) would show instructions, but that's out of scope for now. + var url = showCameraView ? "resource://spectatorCameraFrame" : ""; Window.setDisplayTexture(url); } const MONITOR_SHOWS_CAMERA_VIEW_DEFAULT = false; From f765b4136dc7645238ebe8ea8b59f208effdf638 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Thu, 29 Jun 2017 13:25:37 -0700 Subject: [PATCH 4/8] Cleanup --- interface/src/SecondaryCamera.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/interface/src/SecondaryCamera.cpp b/interface/src/SecondaryCamera.cpp index 178286f614..3f8c26c2e3 100644 --- a/interface/src/SecondaryCamera.cpp +++ b/interface/src/SecondaryCamera.cpp @@ -47,11 +47,16 @@ class BeginSecondaryCameraFrame { // Changes renderContext for our framebuffer float _vFoV{}; float _nearClipPlaneDistance{}; float _farClipPlaneDistance{}; + EntityPropertyFlags _attachedEntityPropertyFlags; + QSharedPointer _entityScriptingInterface; public: using Config = BeginSecondaryCameraFrameConfig; using JobModel = render::Job::ModelO; BeginSecondaryCameraFrame() { _cachedArgsPointer = std::make_shared(_cachedArgs); + _entityScriptingInterface = DependencyManager::get(); + _attachedEntityPropertyFlags += PROP_POSITION; + _attachedEntityPropertyFlags += PROP_ROTATION; } void configure(const Config& config) { @@ -87,12 +92,7 @@ public: auto srcViewFrustum = args->getViewFrustum(); if (_attachedEntityId != QUuid()) { - auto entityScriptingInterface = DependencyManager::get(); - EntityPropertyFlags entityPropertyFlags; - entityPropertyFlags += PROP_POSITION; - entityPropertyFlags += PROP_ROTATION; - EntityItemProperties entityProperties = entityScriptingInterface->getEntityProperties(_attachedEntityId, entityPropertyFlags); - + EntityItemProperties entityProperties = _entityScriptingInterface->getEntityProperties(_attachedEntityId, _attachedEntityPropertyFlags); srcViewFrustum.setPosition(entityProperties.getPosition()); srcViewFrustum.setOrientation(entityProperties.getRotation()); } else { From f78903eead17a05e6e84dc3a6f38f5204cd29427 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 30 Jun 2017 11:31:48 -0700 Subject: [PATCH 5/8] Clarify setDisplayTexture cases, also fixing crash bug --- scripts/system/spectatorCamera.js | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/scripts/system/spectatorCamera.js b/scripts/system/spectatorCamera.js index 5154322daa..cd4b54730b 100644 --- a/scripts/system/spectatorCamera.js +++ b/scripts/system/spectatorCamera.js @@ -223,9 +223,19 @@ } } + // Function Name: setDisplay() + // + // Description: + // -There are two bool variables that determine what the "url" argument to "setDisplayTexture(url)" should be: + // Camera on/off switch, and the "Monitor Shows" on/off switch. + // This results in four possible cases for the argument. Those four cases are: + // 1. Camera is off; "Monitor Shows" is "HMD Preview": "url" is "" + // 2. Camera is off; "Monitor Shows" is "Camera View": "url" is "" + // 3. Camera is on; "Monitor Shows" is "HMD Preview": "url" is "" + // 4. Camera is on; "Monitor Shows" is "Camera View": "url" is "resource://spectatorCameraFrame" function setDisplay(showCameraView) { // It would be fancy if (showCameraView && !cameraUpdateInterval) would show instructions, but that's out of scope for now. - var url = (showCameraView && cameraUpdateInterval) ? "resource://spectatorCameraFrame" : ""; + var url = (camera && showCameraView && cameraUpdateInterval) ? "resource://spectatorCameraFrame" : ""; Window.setDisplayTexture(url); } const MONITOR_SHOWS_CAMERA_VIEW_DEFAULT = false; From 9bd80ec2bf938a95c7035e3912efde38b220bfdc Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 30 Jun 2017 14:07:00 -0700 Subject: [PATCH 6/8] Improve naming and API --- interface/src/Application.cpp | 2 +- interface/src/SecondaryCamera.cpp | 40 ++++++++++++---------- interface/src/SecondaryCamera.h | 10 +++--- scripts/system/spectatorCamera.js | 56 +++++++++++-------------------- 4 files changed, 49 insertions(+), 59 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 75bcee0703..7437f2dd03 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1946,7 +1946,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("SecondaryCameraFrame", cullFunctor); + _renderEngine->addJob("SecondaryCameraJob", cullFunctor); _renderEngine->addJob("RenderMainView", cullFunctor, isDeferred); _renderEngine->load(); _renderEngine->registerScene(_main3DScene); diff --git a/interface/src/SecondaryCamera.cpp b/interface/src/SecondaryCamera.cpp index 3f8c26c2e3..f5e7cca8f6 100644 --- a/interface/src/SecondaryCamera.cpp +++ b/interface/src/SecondaryCamera.cpp @@ -9,6 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "Application.h" #include "SecondaryCamera.h" #include #include @@ -28,19 +29,7 @@ void MainRenderTask::build(JobModel& task, const render::Varying& inputs, render } } -void SecondaryCameraRenderTaskConfig::resetSize(int width, int height) { // FIXME: Add an arg here for "destinationFramebuffer" - bool wasEnabled = isEnabled(); - setEnabled(false); - auto textureCache = DependencyManager::get(); - textureCache->resetSpectatorCameraFramebuffer(width, height); // FIXME: Call the correct reset function based on the "destinationFramebuffer" arg - setEnabled(wasEnabled); -} - -void SecondaryCameraRenderTaskConfig::resetSizeSpectatorCamera(int width, int height) { // Carefully adjust the framebuffer / texture. - resetSize(width, height); -} - -class BeginSecondaryCameraFrame { // Changes renderContext for our framebuffer and view. +class SecondaryCameraJob { // Changes renderContext for our framebuffer and view. QUuid _attachedEntityId{}; glm::vec3 _position{}; glm::quat _orientation{}; @@ -50,9 +39,9 @@ class BeginSecondaryCameraFrame { // Changes renderContext for our framebuffer EntityPropertyFlags _attachedEntityPropertyFlags; QSharedPointer _entityScriptingInterface; public: - using Config = BeginSecondaryCameraFrameConfig; - using JobModel = render::Job::ModelO; - BeginSecondaryCameraFrame() { + using Config = SecondaryCameraJobConfig; + using JobModel = render::Job::ModelO; + SecondaryCameraJob() { _cachedArgsPointer = std::make_shared(_cachedArgs); _entityScriptingInterface = DependencyManager::get(); _attachedEntityPropertyFlags += PROP_POSITION; @@ -113,6 +102,23 @@ protected: RenderArgsPointer _cachedArgsPointer; }; +void SecondaryCameraJobConfig::enableSecondaryCameraRenderConfigs(bool enabled) { + qApp->getRenderEngine()->getConfiguration()->getConfig()->setEnabled(enabled); + setEnabled(enabled); +} + +void SecondaryCameraJobConfig::resetSizeSpectatorCamera(int width, int height) { // Carefully adjust the framebuffer / texture. + qApp->getRenderEngine()->getConfiguration()->getConfig()->resetSize(width, height); +} + +void SecondaryCameraRenderTaskConfig::resetSize(int width, int height) { // FIXME: Add an arg here for "destinationFramebuffer" + bool wasEnabled = isEnabled(); + setEnabled(false); + auto textureCache = DependencyManager::get(); + textureCache->resetSpectatorCameraFramebuffer(width, height); // FIXME: Call the correct reset function based on the "destinationFramebuffer" arg + setEnabled(wasEnabled); +} + class EndSecondaryCameraFrame { // Restores renderContext. public: using JobModel = render::Job::ModelI; @@ -133,7 +139,7 @@ public: }; void SecondaryCameraRenderTask::build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor) { - const auto cachedArg = task.addJob("BeginSecondaryCamera"); + const auto cachedArg = task.addJob("SecondaryCamera"); const auto items = task.addJob("FetchCullSort", cullFunctor); assert(items.canCast()); task.addJob("RenderDeferredTask", items); diff --git a/interface/src/SecondaryCamera.h b/interface/src/SecondaryCamera.h index 15e6f41ad2..e06332f4e9 100644 --- a/interface/src/SecondaryCamera.h +++ b/interface/src/SecondaryCamera.h @@ -28,7 +28,7 @@ public: void build(JobModel& task, const render::Varying& inputs, render::Varying& outputs, render::CullFunctor cullFunctor, bool isDeferred = true); }; -class BeginSecondaryCameraFrameConfig : public render::Task::Config { // Exposes secondary camera parameters to JavaScript. +class SecondaryCameraJobConfig : public render::Task::Config { // Exposes secondary camera parameters to JavaScript. Q_OBJECT Q_PROPERTY(QUuid attachedEntityId MEMBER attachedEntityId NOTIFY dirty) // entity whose properties define camera position and orientation Q_PROPERTY(glm::vec3 position MEMBER position NOTIFY dirty) // of viewpoint to render from @@ -43,21 +43,21 @@ public: float vFoV{ 45.0f }; float nearClipPlaneDistance{ 0.1f }; float farClipPlaneDistance{ 100.0f }; - BeginSecondaryCameraFrameConfig() : render::Task::Config(false) {} + SecondaryCameraJobConfig() : render::Task::Config(false) {} signals: void dirty(); +public slots: + void enableSecondaryCameraRenderConfigs(bool enabled); + void resetSizeSpectatorCamera(int width, int height); }; class SecondaryCameraRenderTaskConfig : public render::Task::Config { Q_OBJECT public: SecondaryCameraRenderTaskConfig() : render::Task::Config(false) {} -private: void resetSize(int width, int height); signals: void dirty(); -public slots: - void resetSizeSpectatorCamera(int width, int height); }; class SecondaryCameraRenderTask { diff --git a/scripts/system/spectatorCamera.js b/scripts/system/spectatorCamera.js index fd09943212..00b774c483 100644 --- a/scripts/system/spectatorCamera.js +++ b/scripts/system/spectatorCamera.js @@ -28,33 +28,6 @@ Vec3.multiply(distance, Quat.getForward(orientation || MyAvatar.orientation))); } - // Function Name: updateRenderFromCamera() - // - // Description: - // -The update function for the spectator camera. Modifies the camera's position - // and orientation. - // - // Relevant Variables: - // -spectatorFrameRenderConfig: The render configuration of the spectator camera - // render job. It controls the rendered texture size of the spectator camera. - // -beginSpectatorFrameRenderConfig: The render configuration of the spectator camera - // render job. It controls the orientation and position of the secondary camera whose viewport is rendered to - // the texture. - // -viewFinderOverlay: The in-world overlay that displays the spectator camera's view. - // -camera: The in-world entity that corresponds to the spectator camera. - // -cameraIsDynamic: "false" for now while we figure out why dynamic, parented overlays - // drift with respect to their parent. - var spectatorFrameRenderConfig = Render.getConfig("SecondaryCameraFrame"); - var beginSpectatorFrameRenderConfig = Render.getConfig("BeginSecondaryCamera"); - var viewFinderOverlay = false; - var camera = false; - var cameraIsDynamic = false; - function updateRenderFromCamera() { - var cameraData = Entities.getEntityProperties(camera, ['position', 'rotation']); - beginSpectatorFrameRenderConfig.orientation = cameraData.rotation; - beginSpectatorFrameRenderConfig.position = cameraData.position; - } - // Function Name: spectatorCameraOn() // // Description: @@ -62,6 +35,13 @@ // spawn the camera entity. // // Relevant Variables: + // -spectatorCameraConfig: The render configuration of the spectator camera + // render job. It controls the orientation and position of the secondary camera whose viewport is rendered to + // the texture, as well as the rendered texture size. + // -viewFinderOverlay: The in-world overlay that displays the spectator camera's view. + // -camera: The in-world entity that corresponds to the spectator camera. + // -cameraIsDynamic: "false" for now while we figure out why dynamic, parented overlays + // drift with respect to their parent. // -vFoV: The vertical field of view of the spectator camera. // -nearClipPlaneDistance: The near clip plane distance of the spectator camera (aka "camera"). // -farClipPlaneDistance: The far clip plane distance of the spectator camera. @@ -71,6 +51,10 @@ // -viewFinderOverlayDim: The x, y, and z dimensions of the viewFinderOverlay. // -camera: The camera model which is grabbable. // -viewFinderOverlay: The preview of what the spectator camera is viewing, placed inside the glass pane. + var spectatorCameraConfig = Render.getConfig("SecondaryCamera"); + var viewFinderOverlay = false; + var camera = false; + var cameraIsDynamic = false; var vFoV = 45.0; var nearClipPlaneDistance = 0.1; var farClipPlaneDistance = 100.0; @@ -83,11 +67,11 @@ var viewFinderOverlayDim = { x: glassPaneWidth, y: -glassPaneWidth, z: 0 }; function spectatorCameraOn() { // Sets the special texture size based on the window it is displayed in, which doesn't include the menu bar - spectatorFrameRenderConfig.resetSizeSpectatorCamera(Window.innerWidth, Window.innerHeight); - spectatorFrameRenderConfig.enabled = beginSpectatorFrameRenderConfig.enabled = true; - beginSpectatorFrameRenderConfig.vFoV = vFoV; - beginSpectatorFrameRenderConfig.nearClipPlaneDistance = nearClipPlaneDistance; - beginSpectatorFrameRenderConfig.farClipPlaneDistance = farClipPlaneDistance; + spectatorCameraConfig.enableSecondaryCameraRenderConfigs(true); + spectatorCameraConfig.resetSizeSpectatorCamera(Window.innerWidth, Window.innerHeight); + spectatorCameraConfig.vFoV = vFoV; + spectatorCameraConfig.nearClipPlaneDistance = nearClipPlaneDistance; + spectatorCameraConfig.farClipPlaneDistance = farClipPlaneDistance; cameraRotation = MyAvatar.orientation, cameraPosition = inFrontOf(1, Vec3.sum(MyAvatar.position, { x: 0, y: 0.3, z: 0 })); camera = Entities.addEntity({ "angularDamping": 1, @@ -107,7 +91,7 @@ "type": "Model", "userData": "{\"grabbableKey\":{\"grabbable\":true}}" }, true); - beginSpectatorFrameRenderConfig.attachedEntityId = camera; + spectatorCameraConfig.attachedEntityId = camera; updateOverlay(); setDisplay(monitorShowsCameraView); } @@ -118,8 +102,8 @@ // -Call this function to shut down the spectator camera and // destroy the camera entity. function spectatorCameraOff() { - spectatorFrameRenderConfig.enabled = beginSpectatorFrameRenderConfig.enabled = false; - beginSpectatorFrameRenderConfig.attachedEntityId = false; + spectatorCameraConfig.attachedEntityId = false; + spectatorCameraConfig.enableSecondaryCameraRenderConfigs(false); if (camera) { Entities.deleteEntity(camera); } @@ -292,7 +276,7 @@ viewFinderOverlayDim = { x: glassPaneWidth, y: -glassPaneWidth, z: 0 }; } updateOverlay(); - spectatorFrameRenderConfig.resetSizeSpectatorCamera(geometryChanged.width, geometryChanged.height); + spectatorCameraConfig.resetSizeSpectatorCamera(geometryChanged.width, geometryChanged.height); setDisplay(monitorShowsCameraView); } From 36dfff78e203d6d35d60b0f86db8fbf515c2eb72 Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 30 Jun 2017 15:13:31 -0700 Subject: [PATCH 7/8] Emit qDebug() error when trying to change position or orientation while attachedEntityId is defined --- interface/src/SecondaryCamera.cpp | 20 +++++++++++++++++++- interface/src/SecondaryCamera.h | 8 ++++++-- scripts/system/spectatorCamera.js | 10 ++++++++-- 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/interface/src/SecondaryCamera.cpp b/interface/src/SecondaryCamera.cpp index f5e7cca8f6..730733ad13 100644 --- a/interface/src/SecondaryCamera.cpp +++ b/interface/src/SecondaryCamera.cpp @@ -80,7 +80,7 @@ public: }); auto srcViewFrustum = args->getViewFrustum(); - if (_attachedEntityId != QUuid()) { + if (!_attachedEntityId.isNull()) { EntityItemProperties entityProperties = _entityScriptingInterface->getEntityProperties(_attachedEntityId, _attachedEntityPropertyFlags); srcViewFrustum.setPosition(entityProperties.getPosition()); srcViewFrustum.setOrientation(entityProperties.getRotation()); @@ -102,6 +102,24 @@ protected: RenderArgsPointer _cachedArgsPointer; }; +void SecondaryCameraJobConfig::setPosition(glm::vec3 pos) { + if (attachedEntityId.isNull()) { + position = pos; + emit dirty(); + } else { + qDebug() << "ERROR: Cannot set position of SecondaryCamera while attachedEntityId is set."; + } +} + +void SecondaryCameraJobConfig::setOrientation(glm::quat orient) { + if (attachedEntityId.isNull()) { + orientation = orient; + emit dirty(); + } else { + qDebug() << "ERROR: Cannot set orientation of SecondaryCamera while attachedEntityId is set."; + } +} + void SecondaryCameraJobConfig::enableSecondaryCameraRenderConfigs(bool enabled) { qApp->getRenderEngine()->getConfiguration()->getConfig()->setEnabled(enabled); setEnabled(enabled); diff --git a/interface/src/SecondaryCamera.h b/interface/src/SecondaryCamera.h index e06332f4e9..ac82290211 100644 --- a/interface/src/SecondaryCamera.h +++ b/interface/src/SecondaryCamera.h @@ -31,8 +31,8 @@ public: class SecondaryCameraJobConfig : public render::Task::Config { // Exposes secondary camera parameters to JavaScript. Q_OBJECT Q_PROPERTY(QUuid attachedEntityId MEMBER attachedEntityId NOTIFY dirty) // entity whose properties define camera position and orientation - Q_PROPERTY(glm::vec3 position MEMBER position NOTIFY dirty) // of viewpoint to render from - Q_PROPERTY(glm::quat orientation MEMBER orientation NOTIFY dirty) // of viewpoint to render from + Q_PROPERTY(glm::vec3 position READ getPosition WRITE setPosition) // of viewpoint to render from + Q_PROPERTY(glm::quat orientation READ getOrientation WRITE setOrientation) // of viewpoint to render from Q_PROPERTY(float vFoV MEMBER vFoV NOTIFY dirty) // Secondary camera's vertical field of view. In degrees. Q_PROPERTY(float nearClipPlaneDistance MEMBER nearClipPlaneDistance NOTIFY dirty) // Secondary camera's near clip plane distance. In meters. Q_PROPERTY(float farClipPlaneDistance MEMBER farClipPlaneDistance NOTIFY dirty) // Secondary camera's far clip plane distance. In meters. @@ -47,6 +47,10 @@ public: signals: void dirty(); public slots: + glm::vec3 getPosition() { return position; } + void setPosition(glm::vec3 pos); + glm::quat getOrientation() { return orientation; } + void setOrientation(glm::quat orient); void enableSecondaryCameraRenderConfigs(bool enabled); void resetSizeSpectatorCamera(int width, int height); }; diff --git a/scripts/system/spectatorCamera.js b/scripts/system/spectatorCamera.js index 00b774c483..3c011cad99 100644 --- a/scripts/system/spectatorCamera.js +++ b/scripts/system/spectatorCamera.js @@ -36,8 +36,14 @@ // // Relevant Variables: // -spectatorCameraConfig: The render configuration of the spectator camera - // render job. It controls the orientation and position of the secondary camera whose viewport is rendered to - // the texture, as well as the rendered texture size. + // render job. It controls various attributes of the Secondary Camera, such as: + // -The entity ID to follow + // -Position + // -Orientation + // -Rendered texture size + // -Vertical field of view + // -Near clip plane distance + // -Far clip plane distance // -viewFinderOverlay: The in-world overlay that displays the spectator camera's view. // -camera: The in-world entity that corresponds to the spectator camera. // -cameraIsDynamic: "false" for now while we figure out why dynamic, parented overlays From 7851c8002fae08a44cb1c1f89f8b20cb8ee3b08a Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Fri, 30 Jun 2017 15:25:33 -0700 Subject: [PATCH 8/8] Remove unnecessary guard --- interface/src/SecondaryCamera.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/interface/src/SecondaryCamera.cpp b/interface/src/SecondaryCamera.cpp index 730733ad13..56b8b3ef85 100644 --- a/interface/src/SecondaryCamera.cpp +++ b/interface/src/SecondaryCamera.cpp @@ -49,14 +49,12 @@ public: } void configure(const Config& config) { - if (config.enabled || config.alwaysEnabled) { - _attachedEntityId = config.attachedEntityId; - _position = config.position; - _orientation = config.orientation; - _vFoV = config.vFoV; - _nearClipPlaneDistance = config.nearClipPlaneDistance; - _farClipPlaneDistance = config.farClipPlaneDistance; - } + _attachedEntityId = config.attachedEntityId; + _position = config.position; + _orientation = config.orientation; + _vFoV = config.vFoV; + _nearClipPlaneDistance = config.nearClipPlaneDistance; + _farClipPlaneDistance = config.farClipPlaneDistance; } void run(const render::RenderContextPointer& renderContext, RenderArgsPointer& cachedArgs) {