From 3c8b964cc9d10cd4e50c9672a0941118303dd497 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Mon, 24 Jul 2017 18:16:40 -0700 Subject: [PATCH] replace setHandLasers with drawHUDLayer overlay property --- interface/resources/shaders/hmd_ui.frag | 27 ++ .../shaders/{hmd_ui_glow.vert => hmd_ui.vert} | 9 +- interface/resources/shaders/hmd_ui_glow.frag | 86 ------- interface/src/Application.cpp | 16 +- .../src/scripting/HMDScriptingInterface.cpp | 60 ++--- .../src/scripting/HMDScriptingInterface.h | 12 +- interface/src/ui/overlays/Circle3DOverlay.cpp | 2 +- interface/src/ui/overlays/Cube3DOverlay.cpp | 2 +- interface/src/ui/overlays/Image3DOverlay.cpp | 2 +- interface/src/ui/overlays/Overlay.cpp | 7 + interface/src/ui/overlays/Overlay.h | 3 + interface/src/ui/overlays/Overlays.cpp | 45 +++- interface/src/ui/overlays/Overlays.h | 5 + interface/src/ui/overlays/Shape3DOverlay.cpp | 2 +- interface/src/ui/overlays/Sphere3DOverlay.cpp | 2 +- .../src/display-plugins/CompositorHelper.cpp | 5 +- .../src/display-plugins/CompositorHelper.h | 3 - .../display-plugins/OpenGLDisplayPlugin.cpp | 9 + .../hmd/DebugHmdDisplayPlugin.cpp | 9 - .../display-plugins/hmd/HmdDisplayPlugin.cpp | 230 +----------------- .../display-plugins/hmd/HmdDisplayPlugin.h | 40 --- libraries/gpu/src/gpu/Frame.h | 2 + libraries/plugins/src/plugins/DisplayPlugin.h | 18 -- .../oculus/src/OculusBaseDisplayPlugin.cpp | 2 - plugins/openvr/src/OpenVrDisplayPlugin.cpp | 3 - .../controllers/handControllerPointer.js | 169 ++++++++++--- 26 files changed, 275 insertions(+), 495 deletions(-) create mode 100644 interface/resources/shaders/hmd_ui.frag rename interface/resources/shaders/{hmd_ui_glow.vert => hmd_ui.vert} (76%) delete mode 100644 interface/resources/shaders/hmd_ui_glow.frag diff --git a/interface/resources/shaders/hmd_ui.frag b/interface/resources/shaders/hmd_ui.frag new file mode 100644 index 0000000000..af96169831 --- /dev/null +++ b/interface/resources/shaders/hmd_ui.frag @@ -0,0 +1,27 @@ +// +// Created by Bradley Austin Davis on 2016/07/11 +// Copyright 2013-2016 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 +// + +uniform sampler2D sampler; + +struct OverlayData { + mat4 mvp; + float alpha; +}; + +layout(std140) uniform overlayBuffer { + OverlayData overlay; +}; + +in vec2 vTexCoord; + +out vec4 FragColor; + +void main() { + FragColor = texture(sampler, vTexCoord); + FragColor.a *= overlay.alpha; +} \ No newline at end of file diff --git a/interface/resources/shaders/hmd_ui_glow.vert b/interface/resources/shaders/hmd_ui.vert similarity index 76% rename from interface/resources/shaders/hmd_ui_glow.vert rename to interface/resources/shaders/hmd_ui.vert index 71089d8608..41b9b3666f 100644 --- a/interface/resources/shaders/hmd_ui_glow.vert +++ b/interface/resources/shaders/hmd_ui.vert @@ -8,12 +8,7 @@ struct OverlayData { mat4 mvp; - vec4 glowPoints; - vec4 glowColors[2]; - vec4 resolutionRadiusAlpha; - - vec4 extraGlowColor; - vec2 extraGlowPoint; + float alpha; }; layout(std140) uniform overlayBuffer { @@ -25,11 +20,9 @@ mat4 mvp = overlay.mvp; layout(location = 0) in vec3 Position; layout(location = 3) in vec2 TexCoord; -out vec3 vPosition; out vec2 vTexCoord; void main() { gl_Position = mvp * vec4(Position, 1); vTexCoord = TexCoord; - vPosition = Position; } diff --git a/interface/resources/shaders/hmd_ui_glow.frag b/interface/resources/shaders/hmd_ui_glow.frag deleted file mode 100644 index 5dda76e89d..0000000000 --- a/interface/resources/shaders/hmd_ui_glow.frag +++ /dev/null @@ -1,86 +0,0 @@ -// -// Created by Bradley Austin Davis on 2016/07/11 -// Copyright 2013-2016 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 -// - -uniform sampler2D sampler; - -struct OverlayData { - mat4 mvp; - vec4 glowPoints; - vec4 glowColors[2]; - vec4 resolutionRadiusAlpha; - - vec4 extraGlowColor; - vec2 extraGlowPoint; -}; - -layout(std140) uniform overlayBuffer { - OverlayData overlay; -}; - -vec2 resolution = overlay.resolutionRadiusAlpha.xy; -float radius = overlay.resolutionRadiusAlpha.z; -float alpha = overlay.resolutionRadiusAlpha.w; -vec4 glowPoints = overlay.glowPoints; -vec4 glowColors[2] = overlay.glowColors; - -vec2 extraGlowPoint = overlay.extraGlowPoint; -vec4 extraGlowColor = overlay.extraGlowColor; - -in vec3 vPosition; -in vec2 vTexCoord; - -out vec4 FragColor; - -float easeInOutCubic(float f) { - const float d = 1.0; - const float b = 0.0; - const float c = 1.0; - float t = f; - if ((t /= d / 2.0) < 1.0) return c / 2.0 * t * t * t + b; - return c / 2.0 * ((t -= 2.0) * t * t + 2.0) + b; -} - -void main() { - FragColor = texture(sampler, vTexCoord); - - vec2 aspect = resolution; - aspect /= resolution.x; - - float glowIntensity = 0.0; - float dist1 = distance(vTexCoord * aspect, glowPoints.xy * aspect); - float dist2 = distance(vTexCoord * aspect, glowPoints.zw * aspect); - float dist3 = distance(vTexCoord * aspect, extraGlowPoint * aspect); - float distX = min(dist1, dist2); - float dist = min(distX, dist3); - vec3 glowColor = glowColors[0].rgb; - if (dist2 < dist1) { - glowColor = glowColors[1].rgb; - } - if (dist3 < dist2) { - glowColor = extraGlowColor.rgb; - } - - if (dist <= radius) { - glowIntensity = 1.0 - (dist / radius); - glowColor.rgb = pow(glowColor, vec3(1.0 - glowIntensity)); - glowIntensity = easeInOutCubic(glowIntensity); - glowIntensity = pow(glowIntensity, 0.5); - } - - if (alpha <= 0.0) { - if (glowIntensity <= 0.0) { - discard; - } - - FragColor = vec4(glowColor, glowIntensity); - return; - } - - FragColor.rgb = mix(FragColor.rgb, glowColor.rgb, glowIntensity); - FragColor.a *= alpha; -} \ No newline at end of file diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 69835caff0..7a42312f6c 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2378,6 +2378,7 @@ void Application::paintGL() { finalFramebuffer = framebufferCache->getFramebuffer(); } + mat4 eyeProjections[2]; { PROFILE_RANGE(render, "/mainRender"); PerformanceTimer perfTimer("mainRender"); @@ -2399,7 +2400,6 @@ void Application::paintGL() { _myCamera.setProjection(displayPlugin->getCullingProjection(_myCamera.getProjection())); renderArgs._context->enableStereo(true); mat4 eyeOffsets[2]; - mat4 eyeProjections[2]; auto baseProjection = renderArgs.getViewFrustum().getProjection(); auto hmdInterface = DependencyManager::get(); float IPDScale = hmdInterface->getIPDScale(); @@ -2430,6 +2430,19 @@ void Application::paintGL() { displaySide(&renderArgs, _myCamera); } + gpu::Batch postCompositeBatch; + { + PROFILE_RANGE(render, "/postComposite"); + PerformanceTimer perfTimer("postComposite"); + renderArgs._batch = &postCompositeBatch; + renderArgs._batch->setViewportTransform(ivec4(0, 0, finalFramebufferSize.width(), finalFramebufferSize.height())); + renderArgs._batch->setViewTransform(renderArgs.getViewFrustum().getView()); + for_each_eye([&](Eye eye) { + renderArgs._batch->setProjectionTransform(eyeProjections[eye]); + _overlays.render3DHUDOverlays(&renderArgs); + }); + } + auto frame = _gpuContext->endFrame(); frame->frameIndex = _frameCount; frame->framebuffer = finalFramebuffer; @@ -2437,6 +2450,7 @@ void Application::paintGL() { DependencyManager::get()->releaseFramebuffer(framebuffer); }; frame->overlay = _applicationOverlay.getOverlayTexture(); + frame->postCompositeBatch = postCompositeBatch; // deliver final scene rendering commands to the display plugin { PROFILE_RANGE(render, "/pluginOutput"); diff --git a/interface/src/scripting/HMDScriptingInterface.cpp b/interface/src/scripting/HMDScriptingInterface.cpp index 35f2e2aa86..af3c7c3d67 100644 --- a/interface/src/scripting/HMDScriptingInterface.cpp +++ b/interface/src/scripting/HMDScriptingInterface.cpp @@ -82,6 +82,22 @@ bool HMDScriptingInterface::shouldShowHandControllers() const { return _showHandControllersCount > 0; } +void HMDScriptingInterface::activateHMDHandMouse() { + QWriteLocker lock(&_hmdHandMouseLock); + auto offscreenUi = DependencyManager::get(); + offscreenUi->getDesktop()->setProperty("hmdHandMouseActive", true); + _hmdHandMouseCount++; +} + +void HMDScriptingInterface::deactivateHMDHandMouse() { + QWriteLocker lock(&_hmdHandMouseLock); + _hmdHandMouseCount = std::max(--_hmdHandMouseCount, 0); + if (_hmdHandMouseCount == 0) { + auto offscreenUi = DependencyManager::get(); + offscreenUi->getDesktop()->setProperty("hmdHandMouseActive", false); + } +} + void HMDScriptingInterface::closeTablet() { _showTablet = false; } @@ -153,50 +169,6 @@ QString HMDScriptingInterface::preferredAudioOutput() const { return qApp->getActiveDisplayPlugin()->getPreferredAudioOutDevice(); } -bool HMDScriptingInterface::setHandLasers(int hands, bool enabled, const glm::vec4& color, const glm::vec3& direction) { - if (QThread::currentThread() != thread()) { - bool result; - BLOCKING_INVOKE_METHOD(this, "setHandLasers", Q_RETURN_ARG(bool, result), - Q_ARG(int, hands), Q_ARG(bool, enabled), Q_ARG(glm::vec4, color), Q_ARG(glm::vec3, direction)); - return result; - } - - auto offscreenUi = DependencyManager::get(); - offscreenUi->getDesktop()->setProperty("hmdHandMouseActive", enabled); - return qApp->getActiveDisplayPlugin()->setHandLaser(hands, - enabled ? DisplayPlugin::HandLaserMode::Overlay : DisplayPlugin::HandLaserMode::None, - color, direction); -} - -bool HMDScriptingInterface::setExtraLaser(const glm::vec3& worldStart, bool enabled, const glm::vec4& color, const glm::vec3& direction) { - if (QThread::currentThread() != thread()) { - bool result; - BLOCKING_INVOKE_METHOD(this, "setExtraLaser", Q_RETURN_ARG(bool, result), - Q_ARG(glm::vec3, worldStart), Q_ARG(bool, enabled), Q_ARG(glm::vec4, color), Q_ARG(glm::vec3, direction)); - return result; - } - - auto offscreenUi = DependencyManager::get(); - offscreenUi->getDesktop()->setProperty("hmdHandMouseActive", enabled); - - auto myAvatar = DependencyManager::get()->getMyAvatar(); - auto sensorToWorld = myAvatar->getSensorToWorldMatrix(); - auto worldToSensor = glm::inverse(sensorToWorld); - auto sensorStart = ::transformPoint(worldToSensor, worldStart); - auto sensorDirection = ::transformVectorFast(worldToSensor, direction); - - return qApp->getActiveDisplayPlugin()->setExtraLaser(enabled ? DisplayPlugin::HandLaserMode::Overlay : DisplayPlugin::HandLaserMode::None, - color, sensorStart, sensorDirection); -} - -void HMDScriptingInterface::disableExtraLaser() { - setExtraLaser(vec3(0), false, vec4(0), vec3(0)); -} - -void HMDScriptingInterface::disableHandLasers(int hands) { - setHandLasers(hands, false, vec4(0), vec3(0)); -} - bool HMDScriptingInterface::suppressKeyboard() { return qApp->getActiveDisplayPlugin()->suppressKeyboard(); } diff --git a/interface/src/scripting/HMDScriptingInterface.h b/interface/src/scripting/HMDScriptingInterface.h index 3ed7db0232..2eefe6ea22 100644 --- a/interface/src/scripting/HMDScriptingInterface.h +++ b/interface/src/scripting/HMDScriptingInterface.h @@ -22,6 +22,7 @@ class QScriptEngine; #include #include +#include class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Dependency { Q_OBJECT @@ -51,12 +52,8 @@ public: Q_INVOKABLE void requestHideHandControllers(); Q_INVOKABLE bool shouldShowHandControllers() const; - Q_INVOKABLE bool setHandLasers(int hands, bool enabled, const glm::vec4& color, const glm::vec3& direction); - Q_INVOKABLE void disableHandLasers(int hands); - - Q_INVOKABLE bool setExtraLaser(const glm::vec3& worldStart, bool enabled, const glm::vec4& color, const glm::vec3& direction); - Q_INVOKABLE void disableExtraLaser(); - + Q_INVOKABLE void activateHMDHandMouse(); + Q_INVOKABLE void deactivateHMDHandMouse(); /// Suppress the activation of any on-screen keyboard so that a script operation will /// not be interrupted by a keyboard popup @@ -119,6 +116,9 @@ private: bool getHUDLookAtPosition3D(glm::vec3& result) const; glm::mat4 getWorldHMDMatrix() const; std::atomic _showHandControllersCount { 0 }; + + QReadWriteLock _hmdHandMouseLock; + int _hmdHandMouseCount; }; #endif // hifi_HMDScriptingInterface_h diff --git a/interface/src/ui/overlays/Circle3DOverlay.cpp b/interface/src/ui/overlays/Circle3DOverlay.cpp index 827417a912..52a3d7a929 100644 --- a/interface/src/ui/overlays/Circle3DOverlay.cpp +++ b/interface/src/ui/overlays/Circle3DOverlay.cpp @@ -267,7 +267,7 @@ const render::ShapeKey Circle3DOverlay::getShapeKey() { if (getAlpha() != 1.0f) { builder.withTranslucent(); } - if (!getIsSolid()) { + if (!getIsSolid() || shouldDrawHUDLayer()) { builder.withUnlit().withDepthBias(); } return builder.build(); diff --git a/interface/src/ui/overlays/Cube3DOverlay.cpp b/interface/src/ui/overlays/Cube3DOverlay.cpp index a353545245..31cbe5e822 100644 --- a/interface/src/ui/overlays/Cube3DOverlay.cpp +++ b/interface/src/ui/overlays/Cube3DOverlay.cpp @@ -120,7 +120,7 @@ const render::ShapeKey Cube3DOverlay::getShapeKey() { if (getAlpha() != 1.0f) { builder.withTranslucent(); } - if (!getIsSolid()) { + if (!getIsSolid() || shouldDrawHUDLayer()) { builder.withUnlit().withDepthBias(); } return builder.build(); diff --git a/interface/src/ui/overlays/Image3DOverlay.cpp b/interface/src/ui/overlays/Image3DOverlay.cpp index 7dfee2c491..82417db83a 100644 --- a/interface/src/ui/overlays/Image3DOverlay.cpp +++ b/interface/src/ui/overlays/Image3DOverlay.cpp @@ -123,7 +123,7 @@ void Image3DOverlay::render(RenderArgs* args) { const render::ShapeKey Image3DOverlay::getShapeKey() { auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias(); - if (_emissive) { + if (_emissive || shouldDrawHUDLayer()) { builder.withUnlit(); } if (getAlpha() != 1.0f) { diff --git a/interface/src/ui/overlays/Overlay.cpp b/interface/src/ui/overlays/Overlay.cpp index b650da3522..868cdf110b 100644 --- a/interface/src/ui/overlays/Overlay.cpp +++ b/interface/src/ui/overlays/Overlay.cpp @@ -29,6 +29,7 @@ Overlay::Overlay() : _alphaPulse(0.0f), _colorPulse(0.0f), _color(DEFAULT_OVERLAY_COLOR), + _drawHUDLayer(false), _visible(true), _anchor(NO_ANCHOR) { @@ -47,6 +48,7 @@ Overlay::Overlay(const Overlay* overlay) : _alphaPulse(overlay->_alphaPulse), _colorPulse(overlay->_colorPulse), _color(overlay->_color), + _drawHUDLayer(overlay->_drawHUDLayer), _visible(overlay->_visible), _anchor(overlay->_anchor) { @@ -86,6 +88,11 @@ void Overlay::setProperties(const QVariantMap& properties) { setColorPulse(properties["colorPulse"].toFloat()); } + if (properties["drawHUDLayer"].isValid()) { + bool drawHUDLayer = properties["drawHUDLayer"].toBool(); + setDrawHUDLayer(drawHUDLayer); + } + if (properties["visible"].isValid()) { bool visible = properties["visible"].toBool(); setVisible(visible); diff --git a/interface/src/ui/overlays/Overlay.h b/interface/src/ui/overlays/Overlay.h index 494c287676..0bb0d39d7a 100644 --- a/interface/src/ui/overlays/Overlay.h +++ b/interface/src/ui/overlays/Overlay.h @@ -58,6 +58,7 @@ public: virtual bool is3D() const = 0; bool isLoaded() { return _isLoaded; } bool getVisible() const { return _visible; } + bool shouldDrawHUDLayer() const { return _drawHUDLayer; } xColor getColor(); float getAlpha(); Anchor getAnchor() const { return _anchor; } @@ -72,6 +73,7 @@ public: // setters void setVisible(bool visible) { _visible = visible; } + void setDrawHUDLayer(bool drawHUDLayer) { _drawHUDLayer = drawHUDLayer; } void setColor(const xColor& color) { _color = color; } void setAlpha(float alpha) { _alpha = alpha; } void setAnchor(Anchor anchor) { _anchor = anchor; } @@ -114,6 +116,7 @@ protected: xColor _color; bool _visible; // should the overlay be drawn at all + bool _drawHUDLayer; // should the overlay be drawn on the HUD layer Anchor _anchor; unsigned int _stackOrder { 0 }; diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 72682fcb8c..067bfac0cb 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -37,20 +37,29 @@ #include "Web3DOverlay.h" #include +#include "render/ShapePipeline.h" + Q_LOGGING_CATEGORY(trace_render_overlays, "trace.render.overlays") +extern void initOverlay3DPipelines(render::ShapePlumber& plumber); + void Overlays::cleanupAllOverlays() { QMap overlaysHUD; + QMap overlays3DHUD; QMap overlaysWorld; { QMutexLocker locker(&_mutex); overlaysHUD.swap(_overlaysHUD); + overlays3DHUD.swap(_overlays3DHUD); overlaysWorld.swap(_overlaysWorld); } foreach(Overlay::Pointer overlay, overlaysHUD) { _overlaysToDelete.push_back(overlay); } + foreach(Overlay::Pointer overlay, overlays3DHUD) { + _overlaysToDelete.push_back(overlay); + } foreach(Overlay::Pointer overlay, overlaysWorld) { _overlaysToDelete.push_back(overlay); } @@ -64,6 +73,8 @@ void Overlays::init() { #if OVERLAY_PANELS _scriptEngine = new QScriptEngine(); #endif + _shapePlumber = std::make_shared(); + initOverlay3DPipelines(*_shapePlumber); } void Overlays::update(float deltatime) { @@ -72,6 +83,9 @@ void Overlays::update(float deltatime) { foreach(const auto& thisOverlay, _overlaysHUD) { thisOverlay->update(deltatime); } + foreach(const auto& thisOverlay, _overlays3DHUD) { + thisOverlay->update(deltatime); + } foreach(const auto& thisOverlay, _overlaysWorld) { thisOverlay->update(deltatime); } @@ -128,6 +142,23 @@ void Overlays::renderHUD(RenderArgs* renderArgs) { } } +void Overlays::render3DHUDOverlays(RenderArgs* renderArgs) { + PROFILE_RANGE(render_overlays, __FUNCTION__); + gpu::Batch& batch = *renderArgs->_batch; + + auto textureCache = DependencyManager::get(); + + QMutexLocker lock(&_mutex); + foreach(Overlay::Pointer thisOverlay, _overlays3DHUD) { + // Reset necessary batch pipeline settings between overlays + batch.setResourceTexture(0, textureCache->getWhiteTexture()); // FIXME - do we really need to do this?? + batch.setModelTransform(Transform()); + + renderArgs->_shapePipeline = _shapePlumber->pickPipeline(renderArgs, thisOverlay->getShapeKey()); + thisOverlay->render(renderArgs); + } +} + void Overlays::disable() { _enabled = false; } @@ -142,8 +173,9 @@ Overlay::Pointer Overlays::getOverlay(OverlayID id) const { QMutexLocker locker(&_mutex); if (_overlaysHUD.contains(id)) { return _overlaysHUD[id]; - } - if (_overlaysWorld.contains(id)) { + } else if (_overlays3DHUD.contains(id)) { + return _overlays3DHUD[id]; + } else if (_overlaysWorld.contains(id)) { return _overlaysWorld[id]; } return nullptr; @@ -200,7 +232,7 @@ OverlayID Overlays::addOverlay(const Overlay::Pointer& overlay) { OverlayID thisID = OverlayID(QUuid::createUuid()); overlay->setOverlayID(thisID); overlay->setStackOrder(_stackOrder++); - if (overlay->is3D()) { + if (overlay->is3D() && !overlay->shouldDrawHUDLayer()) { { QMutexLocker locker(&_mutex); _overlaysWorld[thisID] = overlay; @@ -210,6 +242,9 @@ OverlayID Overlays::addOverlay(const Overlay::Pointer& overlay) { render::Transaction transaction; overlay->addToScene(overlay, scene, transaction); scene->enqueueTransaction(transaction); + } else if (overlay->is3D() && overlay->shouldDrawHUDLayer()) { + QMutexLocker locker(&_mutex); + _overlays3DHUD[thisID] = overlay; } else { QMutexLocker locker(&_mutex); _overlaysHUD[thisID] = overlay; @@ -294,6 +329,8 @@ void Overlays::deleteOverlay(OverlayID id) { QMutexLocker locker(&_mutex); if (_overlaysHUD.contains(id)) { overlayToDelete = _overlaysHUD.take(id); + } else if (_overlays3DHUD.contains(id)) { + overlayToDelete = _overlays3DHUD.take(id); } else if (_overlaysWorld.contains(id)) { overlayToDelete = _overlaysWorld.take(id); } else { @@ -702,7 +739,7 @@ bool Overlays::isAddedOverlay(OverlayID id) { } QMutexLocker locker(&_mutex); - return _overlaysHUD.contains(id) || _overlaysWorld.contains(id); + return _overlaysHUD.contains(id) || _overlays3DHUD.contains(id) || _overlaysWorld.contains(id); } void Overlays::sendMousePressOnOverlay(OverlayID overlayID, const PointerEvent& event) { diff --git a/interface/src/ui/overlays/Overlays.h b/interface/src/ui/overlays/Overlays.h index 100f853a96..9efc003669 100644 --- a/interface/src/ui/overlays/Overlays.h +++ b/interface/src/ui/overlays/Overlays.h @@ -90,6 +90,7 @@ public: void init(); void update(float deltatime); void renderHUD(RenderArgs* renderArgs); + void render3DHUDOverlays(RenderArgs* renderArgs); void disable(); void enable(); @@ -325,7 +326,11 @@ private: mutable QMutex _mutex; QMap _overlaysHUD; + QMap _overlays3DHUD; QMap _overlaysWorld; + + render::ShapePlumberPointer _shapePlumber; + #if OVERLAY_PANELS QMap _panels; #endif diff --git a/interface/src/ui/overlays/Shape3DOverlay.cpp b/interface/src/ui/overlays/Shape3DOverlay.cpp index a6fcacc769..7126f7bde4 100644 --- a/interface/src/ui/overlays/Shape3DOverlay.cpp +++ b/interface/src/ui/overlays/Shape3DOverlay.cpp @@ -65,7 +65,7 @@ const render::ShapeKey Shape3DOverlay::getShapeKey() { if (getAlpha() != 1.0f) { builder.withTranslucent(); } - if (!getIsSolid()) { + if (!getIsSolid() || shouldDrawHUDLayer()) { builder.withUnlit().withDepthBias(); } return builder.build(); diff --git a/interface/src/ui/overlays/Sphere3DOverlay.cpp b/interface/src/ui/overlays/Sphere3DOverlay.cpp index 5bbf41eb94..ee3f9b9784 100644 --- a/interface/src/ui/overlays/Sphere3DOverlay.cpp +++ b/interface/src/ui/overlays/Sphere3DOverlay.cpp @@ -62,7 +62,7 @@ const render::ShapeKey Sphere3DOverlay::getShapeKey() { if (getAlpha() != 1.0f) { builder.withTranslucent(); } - if (!getIsSolid()) { + if (!getIsSolid() || shouldDrawHUDLayer()) { builder.withUnlit().withDepthBias(); } return builder.build(); diff --git a/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp b/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp index 29b8aee08b..4dc8d3378c 100644 --- a/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp +++ b/libraries/display-plugins/src/display-plugins/CompositorHelper.cpp @@ -349,10 +349,9 @@ bool CompositorHelper::calculateRayUICollisionPoint(const glm::vec3& position, c auto relativePosition = vec3(relativePosition4) / relativePosition4.w; auto relativeDirection = glm::inverse(glm::quat_cast(UITransform)) * direction; - float uiRadius = _hmdUIRadius; // * myAvatar->getUniformScale(); // FIXME - how do we want to handle avatar scale - + const float UI_RADIUS = 1.0f; // * myAvatar->getUniformScale(); // FIXME - how do we want to handle avatar scale float instersectionDistance; - if (raySphereIntersect(relativeDirection, relativePosition, uiRadius, &instersectionDistance)){ + if (raySphereIntersect(relativeDirection, relativePosition, UI_RADIUS, &instersectionDistance)){ result = position + glm::normalize(direction) * instersectionDistance; return true; } diff --git a/libraries/display-plugins/src/display-plugins/CompositorHelper.h b/libraries/display-plugins/src/display-plugins/CompositorHelper.h index 5be2d68cf9..e6a32dcfb9 100644 --- a/libraries/display-plugins/src/display-plugins/CompositorHelper.h +++ b/libraries/display-plugins/src/display-plugins/CompositorHelper.h @@ -111,8 +111,6 @@ public: void setDisplayPlugin(const DisplayPluginPointer& displayPlugin) { _currentDisplayPlugin = displayPlugin; } void setFrameInfo(uint32_t frame, const glm::mat4& camera) { _currentCamera = camera; } - float getHmdUiRadius() const { return _hmdUIRadius; } - signals: void allowMouseCaptureChanged(); void alphaChanged(); @@ -142,7 +140,6 @@ private: float _textureAspectRatio { VIRTUAL_UI_ASPECT_RATIO }; float _alpha { 1.0f }; - float _hmdUIRadius { 1.0f }; int _previousBorderWidth { -1 }; int _previousBorderHeight { -1 }; diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index e1259fc5fc..1c361ed1ca 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -641,6 +641,15 @@ void OpenGLDisplayPlugin::compositeLayers() { compositePointer(); } + { + PROFILE_RANGE_EX(render_detail, "compositeHUDOverlays", 0xff0077ff, (uint64_t)presentCount()) + render([&](gpu::Batch& batch) { + batch.enableStereo(false); + batch.setFramebuffer(_compositeFramebuffer); + }); + _gpuContext->executeBatch(_currentFrame->postCompositeBatch); + } + { PROFILE_RANGE_EX(render_detail, "compositeExtra", 0xff0077ff, (uint64_t)presentCount()) compositeExtra(); diff --git a/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.cpp index fd45398236..1e0e7e6c1f 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.cpp @@ -35,16 +35,7 @@ bool DebugHmdDisplayPlugin::beginFrameRender(uint32_t frameIndex) { //_currentRenderFrameInfo.presentPose = _currentRenderFrameInfo.renderPose; withNonPresentThreadLock([&] { - _uiModelTransform = DependencyManager::get()->getModelTransform(); _frameInfos[frameIndex] = _currentRenderFrameInfo; - - _handPoses[0] = glm::translate(mat4(), vec3(0.3f * cosf(secTimestampNow() * 3.0f), -0.3f * sinf(secTimestampNow() * 5.0f), 0.0f)); - _handLasers[0].color = vec4(1, 0, 0, 1); - _handLasers[0].mode = HandLaserMode::Overlay; - - _handPoses[1] = glm::translate(mat4(), vec3(0.3f * sinf(secTimestampNow() * 3.0f), -0.3f * cosf(secTimestampNow() * 5.0f), 0.0f)); - _handLasers[1].color = vec4(0, 1, 1, 1); - _handLasers[1].mode = HandLaserMode::Overlay; }); return Parent::beginFrameRender(frameIndex); } diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp index b183850e7f..fe109e7bc9 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp @@ -32,9 +32,6 @@ #include "../Logging.h" #include "../CompositorHelper.h" -#include <../render-utils/shaders/render-utils/glowLine_vert.h> -#include <../render-utils/shaders/render-utils/glowLine_frag.h> - static const QString MONO_PREVIEW = "Mono Preview"; static const QString DISABLE_PREVIEW = "Disable Preview"; @@ -123,26 +120,6 @@ static const int32_t LINE_DATA_SLOT = 1; void HmdDisplayPlugin::customizeContext() { Parent::customizeContext(); _overlayRenderer.build(); - - { - auto state = std::make_shared(); - auto VS = gpu::Shader::createVertex(std::string(glowLine_vert)); - auto PS = gpu::Shader::createPixel(std::string(glowLine_frag)); - auto program = gpu::Shader::createProgram(VS, PS); - state->setCullMode(gpu::State::CULL_NONE); - state->setDepthTest(true, false, gpu::LESS_EQUAL); - state->setBlendFunction(true, - gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, - gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); - - gpu::Shader::BindingSet bindings; - bindings.insert({ "lineData", LINE_DATA_SLOT });; - gpu::Shader::makeProgram(*program, bindings); - _glowLinePipeline = gpu::Pipeline::create(program, state); - _handLaserUniforms = std::array{ { std::make_shared(), std::make_shared() } }; - _extraLaserUniforms = std::make_shared(); - }; - } void HmdDisplayPlugin::uncustomizeContext() { @@ -157,10 +134,6 @@ void HmdDisplayPlugin::uncustomizeContext() { }); _overlayRenderer = OverlayRenderer(); _previewTexture.reset(); - _handLaserUniforms[0].reset(); - _handLaserUniforms[1].reset(); - _extraLaserUniforms.reset(); - _glowLinePipeline.reset(); Parent::uncustomizeContext(); } @@ -383,132 +356,13 @@ void HmdDisplayPlugin::updateFrameData() { getGLBackend()->setCameraCorrection(correction); } - withPresentThreadLock([&] { - _presentHandLasers = _handLasers; - _presentHandPoses = _handPoses; - _presentUiModelTransform = _uiModelTransform; - - _presentExtraLaser = _extraLaser; - _presentExtraLaserStart = _extraLaserStart; - }); - auto compositorHelper = DependencyManager::get(); glm::mat4 modelMat = compositorHelper->getModelTransform().getMatrix(); - static const float OUT_OF_BOUNDS = -1; - std::array handGlowPoints { { vec2(OUT_OF_BOUNDS), vec2(OUT_OF_BOUNDS) } }; - vec2 extraGlowPoint(OUT_OF_BOUNDS); - - float uiRadius = compositorHelper->getHmdUiRadius(); - - // compute the glow point interesections - for (size_t i = 0; i < NUMBER_OF_HANDS; ++i) { - if (_presentHandPoses[i] == IDENTITY_MATRIX) { - continue; - } - const auto& handLaser = _presentHandLasers[i]; - if (!handLaser.valid()) { - continue; - } - - const vec3& laserDirection = handLaser.direction; - mat4 model = _presentHandPoses[i]; - vec3 castStart = vec3(model[3]); - vec3 castDirection = glm::quat_cast(model) * laserDirection; - - // this offset needs to match GRAB_POINT_SPHERE_OFFSET in scripts/system/libraries/controllers.js:19 - static const vec3 GRAB_POINT_SPHERE_OFFSET(0.04f, 0.13f, 0.039f); // x = upward, y = forward, z = lateral - - // swizzle grab point so that (x = upward, y = lateral, z = forward) - vec3 grabPointOffset = glm::vec3(GRAB_POINT_SPHERE_OFFSET.x, GRAB_POINT_SPHERE_OFFSET.z, -GRAB_POINT_SPHERE_OFFSET.y); - if (i == 0) { - grabPointOffset.x *= -1.0f; // this changes between left and right hands - } - castStart += glm::quat_cast(model) * grabPointOffset; - - // Find the intersection of the laser with he UI and use it to scale the model matrix - float distance; - if (!glm::intersectRaySphere(castStart, castDirection, - _presentUiModelTransform.getTranslation(), uiRadius * uiRadius, distance)) { - continue; - } - - _presentHandLaserPoints[i].first = castStart; - _presentHandLaserPoints[i].second = _presentHandLaserPoints[i].first + (castDirection * distance); - - vec3 intersectionPosition = castStart + (castDirection * distance) - _presentUiModelTransform.getTranslation(); - intersectionPosition = glm::inverse(_presentUiModelTransform.getRotation()) * intersectionPosition; - - // Take the interesection normal and convert it to a texture coordinate - vec2 yawPitch; - { - vec2 xdir = glm::normalize(vec2(intersectionPosition.x, -intersectionPosition.z)); - yawPitch.x = glm::atan(xdir.x, xdir.y); - yawPitch.y = (acosf(intersectionPosition.y) * -1.0f) + (float)M_PI_2; - } - vec2 halfFov = CompositorHelper::VIRTUAL_UI_TARGET_FOV / 2.0f; - - // Are we out of range - if (glm::any(glm::greaterThan(glm::abs(yawPitch), halfFov))) { - continue; - } - - yawPitch /= CompositorHelper::VIRTUAL_UI_TARGET_FOV; - yawPitch += 0.5f; - handGlowPoints[i] = yawPitch; - } - - // compute the glow point interesections - if (_presentExtraLaser.valid()) { - const vec3& laserDirection = _presentExtraLaser.direction; - vec3 castStart = _presentExtraLaserStart; - vec3 castDirection = laserDirection; - - // Find the intersection of the laser with he UI and use it to scale the model matrix - float distance; - if (glm::intersectRaySphere(castStart, castDirection, - _presentUiModelTransform.getTranslation(), uiRadius * uiRadius, distance)) { - - - _presentExtraLaserPoints.first = castStart; - _presentExtraLaserPoints.second = _presentExtraLaserPoints.first + (castDirection * distance); - - vec3 intersectionPosition = castStart + (castDirection * distance) - _presentUiModelTransform.getTranslation(); - intersectionPosition = glm::inverse(_presentUiModelTransform.getRotation()) * intersectionPosition; - - // Take the interesection normal and convert it to a texture coordinate - vec2 yawPitch; - { - vec2 xdir = glm::normalize(vec2(intersectionPosition.x, -intersectionPosition.z)); - yawPitch.x = glm::atan(xdir.x, xdir.y); - yawPitch.y = (acosf(intersectionPosition.y) * -1.0f) + (float)M_PI_2; - } - vec2 halfFov = CompositorHelper::VIRTUAL_UI_TARGET_FOV / 2.0f; - - // Are we out of range - if (!glm::any(glm::greaterThan(glm::abs(yawPitch), halfFov))) { - yawPitch /= CompositorHelper::VIRTUAL_UI_TARGET_FOV; - yawPitch += 0.5f; - extraGlowPoint = yawPitch; - } - } - } - for_each_eye([&](Eye eye) { auto modelView = glm::inverse(_currentPresentFrameInfo.presentPose * getEyeToHeadTransform(eye)) * modelMat; _overlayRenderer.mvps[eye] = _eyeProjections[eye] * modelView; }); - - // Setup the uniforms - { - auto& uniforms = _overlayRenderer.uniforms; - uniforms.alpha = _compositeOverlayAlpha; - uniforms.glowPoints = vec4(handGlowPoints[0], handGlowPoints[1]); - uniforms.glowColors[0] = _presentHandLasers[0].color; - uniforms.glowColors[1] = _presentHandLasers[1].color; - uniforms.extraGlowPoint = extraGlowPoint; - uniforms.extraGlowColor = _presentExtraLaser.color; - } } void HmdDisplayPlugin::OverlayRenderer::build() { @@ -573,8 +427,8 @@ void HmdDisplayPlugin::OverlayRenderer::build() { } void HmdDisplayPlugin::OverlayRenderer::updatePipeline() { - static const QString vsFile = PathUtils::resourcesPath() + "/shaders/hmd_ui_glow.vert"; - static const QString fsFile = PathUtils::resourcesPath() + "/shaders/hmd_ui_glow.frag"; + static const QString vsFile = PathUtils::resourcesPath() + "/shaders/hmd_ui.vert"; + static const QString fsFile = PathUtils::resourcesPath() + "/shaders/hmd_ui.frag"; #if LIVE_SHADER_RELOAD static qint64 vsBuiltAge = 0; @@ -598,7 +452,7 @@ void HmdDisplayPlugin::OverlayRenderer::updatePipeline() { this->uniformsLocation = program->getUniformBuffers().findLocation("overlayBuffer"); gpu::StatePointer state = gpu::StatePointer(new gpu::State()); - state->setDepthTest(gpu::State::DepthTest(false)); + state->setDepthTest(gpu::State::DepthTest(true)); state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); @@ -665,84 +519,6 @@ void HmdDisplayPlugin::compositeOverlay() { _overlayRenderer.render(*this); } -bool HmdDisplayPlugin::setHandLaser(uint32_t hands, HandLaserMode mode, const vec4& color, const vec3& direction) { - HandLaserInfo info; - info.mode = mode; - info.color = color; - info.direction = direction; - withNonPresentThreadLock([&] { - if (hands & Hand::LeftHand) { - _handLasers[0] = info; - } - if (hands & Hand::RightHand) { - _handLasers[1] = info; - } - }); - // FIXME defer to a child class plugin to determine if hand lasers are actually - // available based on the presence or absence of hand controllers - return true; -} - -bool HmdDisplayPlugin::setExtraLaser(HandLaserMode mode, const vec4& color, const glm::vec3& sensorSpaceStart, const vec3& sensorSpaceDirection) { - HandLaserInfo info; - info.mode = mode; - info.color = color; - info.direction = sensorSpaceDirection; - withNonPresentThreadLock([&] { - _extraLaser = info; - _extraLaserStart = sensorSpaceStart; - }); - - // FIXME defer to a child class plugin to determine if hand lasers are actually - // available based on the presence or absence of hand controllers - return true; -} - - -void HmdDisplayPlugin::compositeExtra() { - // If neither hand laser is activated, exit - if (!_presentHandLasers[0].valid() && !_presentHandLasers[1].valid() && !_presentExtraLaser.valid()) { - return; - } - - if (_presentHandPoses[0] == IDENTITY_MATRIX && _presentHandPoses[1] == IDENTITY_MATRIX && !_presentExtraLaser.valid()) { - return; - } - - render([&](gpu::Batch& batch) { - batch.setFramebuffer(_compositeFramebuffer); - batch.setModelTransform(Transform()); - batch.setViewportTransform(ivec4(uvec2(0), _renderTargetSize)); - batch.setViewTransform(_currentPresentFrameInfo.presentPose, false); - // Compile the shaders - batch.setPipeline(_glowLinePipeline); - - - bilateral::for_each_side([&](bilateral::Side side){ - auto index = bilateral::index(side); - if (_presentHandPoses[index] == IDENTITY_MATRIX) { - return; - } - const auto& laser = _presentHandLasers[index]; - if (laser.valid()) { - const auto& points = _presentHandLaserPoints[index]; - _handLaserUniforms[index]->resize(sizeof(HandLaserData)); - _handLaserUniforms[index]->setSubData(0, HandLaserData { vec4(points.first, 1.0f), vec4(points.second, 1.0f), _handLasers[index].color }); - batch.setUniformBuffer(LINE_DATA_SLOT, _handLaserUniforms[index]); - batch.draw(gpu::TRIANGLE_STRIP, 4, 0); - } - }); - - if (_presentExtraLaser.valid()) { - const auto& points = _presentExtraLaserPoints; - _extraLaserUniforms->resize(sizeof(HandLaserData)); - _extraLaserUniforms->setSubData(0, HandLaserData { vec4(points.first, 1.0f), vec4(points.second, 1.0f), _presentExtraLaser.color }); - batch.setUniformBuffer(LINE_DATA_SLOT, _extraLaserUniforms); - batch.draw(gpu::TRIANGLE_STRIP, 4, 0); - } - }); -} - HmdDisplayPlugin::~HmdDisplayPlugin() { } diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h index 055328ee21..0827d04922 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h @@ -37,9 +37,6 @@ public: virtual glm::mat4 getHeadPose() const override; - bool setHandLaser(uint32_t hands, HandLaserMode mode, const vec4& color, const vec3& direction) override; - bool setExtraLaser(HandLaserMode mode, const vec4& color, const glm::vec3& sensorSpaceStart, const vec3& sensorSpaceDirection) override; - bool wantVsync() const override { return false; } @@ -63,33 +60,6 @@ protected: void customizeContext() override; void uncustomizeContext() override; void updateFrameData() override; - void compositeExtra() override; - - struct HandLaserInfo { - HandLaserMode mode { HandLaserMode::None }; - vec4 color { 1.0f }; - vec3 direction { 0, 0, -1 }; - - // Is this hand laser info suitable for drawing? - bool valid() const { - return (mode != HandLaserMode::None && color.a > 0.0f && direction != vec3()); - } - }; - - Transform _uiModelTransform; - std::array _handLasers; - std::array _handPoses; - - Transform _presentUiModelTransform; - std::array _presentHandLasers; - std::array _presentHandPoses; - std::array, 2> _presentHandLaserPoints; - - HandLaserInfo _extraLaser; - HandLaserInfo _presentExtraLaser; - vec3 _extraLaserStart; - vec3 _presentExtraLaserStart; - std::pair _presentExtraLaserPoints; std::array _eyeOffsets; std::array _eyeProjections; @@ -120,9 +90,6 @@ private: bool _disablePreviewItemAdded { false }; bool _monoPreview { true }; bool _clearPreviewFlag { false }; - std::array _handLaserUniforms; - gpu::BufferPointer _extraLaserUniforms; - gpu::PipelinePointer _glowLinePipeline; gpu::TexturePointer _previewTexture; glm::vec2 _lastWindowSize; @@ -140,14 +107,7 @@ private: struct Uniforms { mat4 mvp; - vec4 glowPoints { -1 }; - vec4 glowColors[2]; - vec2 resolution { CompositorHelper::VIRTUAL_SCREEN_SIZE }; - float radius { 0.005f }; float alpha { 1.0f }; - - vec4 extraGlowColor; - vec2 extraGlowPoint { -1 }; } uniforms; struct Vertex { diff --git a/libraries/gpu/src/gpu/Frame.h b/libraries/gpu/src/gpu/Frame.h index 3c6fed9393..bfebe85753 100644 --- a/libraries/gpu/src/gpu/Frame.h +++ b/libraries/gpu/src/gpu/Frame.h @@ -32,6 +32,8 @@ namespace gpu { Mat4 pose; /// The collection of batches which make up the frame Batches batches; + /// Single batch containing overlays to be drawn in the composite framebuffer + Batch postCompositeBatch; /// The main thread updates to buffers that are applicable for this frame. BufferUpdates bufferUpdates; /// The destination framebuffer in which the results will be placed diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index 481a2609fc..398e586ef1 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -107,24 +107,6 @@ public: RightHand = 0x02, }; - enum class HandLaserMode { - None, // Render no hand lasers - Overlay, // Render hand lasers only if they intersect with the UI layer, and stop at the UI layer - }; - - virtual bool setHandLaser( - uint32_t hands, // Bits from the Hand enum - HandLaserMode mode, // Mode in which to render - const vec4& color = vec4(1), // The color of the rendered laser - const vec3& direction = vec3(0, 0, -1) // The direction in which to render the hand lasers - ) { - return false; - } - - virtual bool setExtraLaser(HandLaserMode mode, const vec4& color, const glm::vec3& sensorSpaceStart, const vec3& sensorSpaceDirection) { - return false; - } - virtual bool suppressKeyboard() { return false; } virtual void unsuppressKeyboard() {}; virtual bool isKeyboardVisible() { return false; } diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp index 93f4787f0f..426c162628 100644 --- a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp @@ -51,8 +51,6 @@ bool OculusBaseDisplayPlugin::beginFrameRender(uint32_t frameIndex) { }); withNonPresentThreadLock([&] { - _uiModelTransform = DependencyManager::get()->getModelTransform(); - _handPoses = handPoses; _frameInfos[frameIndex] = _currentRenderFrameInfo; }); return Parent::beginFrameRender(frameIndex); diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index 7a73c91c7d..394125a734 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -594,9 +594,6 @@ bool OpenVrDisplayPlugin::beginFrameRender(uint32_t frameIndex) { } withNonPresentThreadLock([&] { - _uiModelTransform = DependencyManager::get()->getModelTransform(); - // Make controller poses available to the presentation thread - _handPoses = handPoses; _frameInfos[frameIndex] = _currentRenderFrameInfo; }); return Parent::beginFrameRender(frameIndex); diff --git a/scripts/system/controllers/handControllerPointer.js b/scripts/system/controllers/handControllerPointer.js index eb94428100..f169204206 100644 --- a/scripts/system/controllers/handControllerPointer.js +++ b/scripts/system/controllers/handControllerPointer.js @@ -150,15 +150,92 @@ var setReticlePosition = function (point2d) { Reticle.setPosition(point2d); }; -// Generalizations of utilities that work with system and overlay elements. -function findRayIntersection(pickRay) { - // Check 3D overlays and entities. Argument is an object with origin and direction. - var result = Overlays.findRayIntersection(pickRay); - if (!result.intersects) { - result = Entities.findRayIntersection(pickRay, true); - } - return result; +// VISUAL AID ----------- +// Same properties as handControllerGrab search sphere +var LASER_ALPHA = 0.5; +var LASER_SEARCH_COLOR = {red: 10, green: 10, blue: 255}; +var LASER_TRIGGER_COLOR = {red: 250, green: 10, blue: 10}; +var END_DIAMETER = 0.05; +var systemLaserOn = false; + +var triggerPath = { + type: "line3d", + color: LASER_SEARCH_COLOR, + ignoreRayIntersection: true, + visible: true, + alpha: LASER_ALPHA, + solid: true, + glow: 1.0, + drawHUDLayer: true } +var triggerEnd = { + type: "sphere", + dimensions: {x: END_DIAMETER, y: END_DIAMETER, z: END_DIAMETER}, + color: LASER_SEARCH_COLOR, + ignoreRayIntersection: true, + visible: true, + alpha: LASER_ALPHA, + solid: true, + drawHUDLayer: true +} + +var searchPath = { + type: "line3d", + color: LASER_TRIGGER_COLOR, + ignoreRayIntersection: true, + visible: true, + alpha: LASER_ALPHA, + solid: true, + glow: 1.0, + drawHUDLayer: true +} +var searchEnd = { + type: "sphere", + dimensions: {x: END_DIAMETER, y: END_DIAMETER, z: END_DIAMETER}, + color: LASER_TRIGGER_COLOR, + ignoreRayIntersection: true, + visible: true, + alpha: LASER_ALPHA, + solid: true, + drawHUDLayer: true +} + +var hudRayStates = [{name: "trigger", path: triggerPath, end: triggerEnd}, + {name: "search", path: searchPath, end: searchEnd}]; +// this offset needs to match the one in libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp:378 +var GRAB_POINT_SPHERE_OFFSET_RIGHT = { x: 0.04, y: 0.13, z: 0.039 }; +var GRAB_POINT_SPHERE_OFFSET_LEFT = { x: -0.04, y: 0.13, z: 0.039 }; +var hudRayRight = LaserPointers.createLaserPointer({ + joint: "_CAMERA_RELATIVE_CONTROLLER_RIGHTHAND", + filter: RayPick.PICK_HUD, + posOffset: GRAB_POINT_SPHERE_OFFSET_RIGHT, + renderStates: hudRayStates, + enabled: true +}); +var hudRayLeft = LaserPointers.createLaserPointer({ + joint: "_CAMERA_RELATIVE_CONTROLLER_LEFTHAND", + filter: RayPick.PICK_HUD, + posOffset: GRAB_POINT_SPHERE_OFFSET_LEFT, + renderStates: hudRayStates, + enabled: true +}); + +// NOTE: keep this offset in sync with scripts/system/librarires/controllers.js:57 +var VERTICAL_HEAD_LASER_OFFSET = 0.1; +var hudRayHead = LaserPointers.createLaserPointer({ + joint: "Avatar", + filter: RayPick.PICK_HUD, + posOffset: {x: 0, y: VERTICAL_HEAD_LASER_OFFSET, z: 0}, + renderStates: hudRayStates, + enabled: true +}); + +var mouseRayPick = RayPick.createRayPick({ + joint: "Mouse", + filter: RayPick.PICK_ENTITIES | RayPick.PICK_OVERLAYS, + enabled: true +}); + function isPointingAtOverlay(optionalHudPosition2d) { return Reticle.pointingAtSystemOverlay || Overlays.getOverlayAtPoint(optionalHudPosition2d || Reticle.position); } @@ -166,10 +243,21 @@ function isPointingAtOverlay(optionalHudPosition2d) { // Generalized HUD utilities, with or without HMD: // This "var" is for documentation. Do not change the value! var PLANAR_PERPENDICULAR_HUD_DISTANCE = 1; -function calculateRayUICollisionPoint(position, direction) { +function calculateRayUICollisionPoint(position, direction, isHands) { // Answer the 3D intersection of the HUD by the given ray, or falsey if no intersection. if (HMD.active) { - return HMD.calculateRayUICollisionPoint(position, direction); + var laserPointer; + if (isHands) { + laserPointer = activeHand == Controller.Standard.RightHand ? hudRayRight : hudRayLeft; + } else { + laserPointer = hudRayHead; + } + var result = LaserPointers.getPrevRayPickResult(laserPointer); + if (result.type != RayPick.INTERSECTED_NONE) { + return result.intersection; + } else { + return null; + } } // interect HUD plane, 1m in front of camera, using formula: // scale = hudNormal dot (hudPoint - position) / hudNormal dot direction @@ -215,7 +303,7 @@ function activeHudPoint2dGamePad() { var headPosition = MyAvatar.getHeadPosition(); var headDirection = Quat.getUp(Quat.multiply(MyAvatar.headOrientation, Quat.angleAxis(-90, { x: 1, y: 0, z: 0 }))); - var hudPoint3d = calculateRayUICollisionPoint(headPosition, headDirection); + var hudPoint3d = calculateRayUICollisionPoint(headPosition, headDirection, false); if (!hudPoint3d) { if (Menu.isOptionChecked("Overlays")) { // With our hud resetting strategy, hudPoint3d should be valid here @@ -241,7 +329,7 @@ function activeHudPoint2d(activeHand) { // if controller is valid, update reticl var controllerPosition = controllerPose.position; var controllerDirection = Quat.getUp(controllerPose.rotation); - var hudPoint3d = calculateRayUICollisionPoint(controllerPosition, controllerDirection); + var hudPoint3d = calculateRayUICollisionPoint(controllerPosition, controllerDirection, true); if (!hudPoint3d) { if (Menu.isOptionChecked("Overlays")) { // With our hud resetting strategy, hudPoint3d should be valid here print('Controller is parallel to HUD'); // so let us know that our assumptions are wrong. @@ -355,7 +443,7 @@ function onMouseMove() { if (isPointingAtOverlay()) { Reticle.depth = hudReticleDistance(); } else { - var result = findRayIntersection(Camera.computePickRay(Reticle.position.x, Reticle.position.y)); + var result = RayPick.getPrevRayPickResult(mouseRayPick); Reticle.depth = result.intersects ? result.distance : APPARENT_MAXIMUM_DEPTH; } } @@ -473,14 +561,6 @@ clickMapping.from(rightTrigger.partial).to(makeToggleAction(Controller.Standard. clickMapping.from(leftTrigger.partial).to(makeToggleAction(Controller.Standard.LeftHand)); clickMapping.enable(); -// VISUAL AID ----------- -// Same properties as handControllerGrab search sphere -var LASER_ALPHA = 0.5; -var LASER_SEARCH_COLOR_XYZW = {x: 10 / 255, y: 10 / 255, z: 255 / 255, w: LASER_ALPHA}; -var LASER_TRIGGER_COLOR_XYZW = {x: 250 / 255, y: 10 / 255, z: 10 / 255, w: LASER_ALPHA}; -var SYSTEM_LASER_DIRECTION = {x: 0, y: 0, z: -1}; -var systemLaserOn = false; - var HIFI_POINTER_DISABLE_MESSAGE_CHANNEL = "Hifi-Pointer-Disable"; var isPointerEnabled = true; @@ -488,23 +568,34 @@ function clearSystemLaser() { if (!systemLaserOn) { return; } - HMD.disableHandLasers(BOTH_HUD_LASERS); - HMD.disableExtraLaser(); + HMD.deactivateHMDHandMouse(); + LaserPointers.setRenderState(hudRayRight, ""); + LaserPointers.setRenderState(hudRayLeft, ""); + LaserPointers.setRenderState(hudRayHead, ""); systemLaserOn = false; weMovedReticle = true; } function setColoredLaser() { // answer trigger state if lasers supported, else falsey. - var color = (activeTrigger.state === 'full') ? LASER_TRIGGER_COLOR_XYZW : LASER_SEARCH_COLOR_XYZW; + var mode = (activeTrigger.state === 'full') ? 'trigger' : 'search'; - if (!HMD.isHandControllerAvailable()) { - // NOTE: keep this offset in sync with scripts/system/librarires/controllers.js:57 - var VERTICAL_HEAD_LASER_OFFSET = 0.1; - var position = Vec3.sum(HMD.position, Vec3.multiplyQbyV(HMD.orientation, {x: 0, y: VERTICAL_HEAD_LASER_OFFSET, z: 0})); - var orientation = Quat.multiply(HMD.orientation, Quat.angleAxis(-90, { x: 1, y: 0, z: 0 })); - return HMD.setExtraLaser(position, true, color, Quat.getUp(orientation)); + if (!systemLaserOn) { + HMD.activateHMDHandMouse(); } - return HMD.setHandLasers(activeHudLaser, true, color, SYSTEM_LASER_DIRECTION) && activeTrigger.state; + var pose = Controller.getPoseValue(activeHand); + if (!pose.valid) { + LaserPointers.setRenderState(hudRayRight, ""); + LaserPointers.setRenderState(hudRayLeft, ""); + LaserPointers.setRenderState(hudRayHead, mode); + return true; + } + + var right = activeHand == Controller.Standard.RightHand; + LaserPointers.setRenderState(hudRayRight, right ? mode : ""); + LaserPointers.setRenderState(hudRayLeft, right ? "" : mode); + LaserPointers.setRenderState(hudRayHead, ""); + + return activeTrigger.state; } // MAIN OPERATIONS ----------- @@ -551,11 +642,13 @@ function update() { if (HMD.active) { Reticle.depth = hudReticleDistance(); - if (!HMD.isHandControllerAvailable()) { - var color = (activeTrigger.state === 'full') ? LASER_TRIGGER_COLOR_XYZW : LASER_SEARCH_COLOR_XYZW; - var position = MyAvatar.getHeadPosition(); - var direction = Quat.getUp(Quat.multiply(MyAvatar.headOrientation, Quat.angleAxis(-90, { x: 1, y: 0, z: 0 }))); - HMD.setExtraLaser(position, true, color, direction); + var pose = Controller.getPoseValue(activeHand); + if (!pose.valid) { + var mode = (activeTrigger.state === 'full') ? 'trigger' : 'search'; + if (!systemLaserOn) { + HMD.activateHMDHandMouse(); + } + LaserPointers.setRenderState(hudRayHead, mode); } } @@ -604,6 +697,10 @@ Script.scriptEnding.connect(function () { Script.clearInterval(settingsChecker); Script.update.disconnect(update); OffscreenFlags.navigationFocusDisabled = false; + LaserPointers.removeLaserPointer(hudRayRight); + LaserPointers.removeLaserPointer(hudRayLeft); + LaserPointers.removeLaserPointer(hudRayHead); + HMD.deactivateHMDHandMouse(); }); }()); // END LOCAL_SCOPE