mirror of
https://github.com/overte-org/overte.git
synced 2025-08-10 22:40:27 +02:00
replace setHandLasers with drawHUDLayer overlay property
This commit is contained in:
parent
ee02a0bff4
commit
3c8b964cc9
26 changed files with 275 additions and 495 deletions
27
interface/resources/shaders/hmd_ui.frag
Normal file
27
interface/resources/shaders/hmd_ui.frag
Normal file
|
@ -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;
|
||||||
|
}
|
|
@ -8,12 +8,7 @@
|
||||||
|
|
||||||
struct OverlayData {
|
struct OverlayData {
|
||||||
mat4 mvp;
|
mat4 mvp;
|
||||||
vec4 glowPoints;
|
float alpha;
|
||||||
vec4 glowColors[2];
|
|
||||||
vec4 resolutionRadiusAlpha;
|
|
||||||
|
|
||||||
vec4 extraGlowColor;
|
|
||||||
vec2 extraGlowPoint;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
layout(std140) uniform overlayBuffer {
|
layout(std140) uniform overlayBuffer {
|
||||||
|
@ -25,11 +20,9 @@ mat4 mvp = overlay.mvp;
|
||||||
layout(location = 0) in vec3 Position;
|
layout(location = 0) in vec3 Position;
|
||||||
layout(location = 3) in vec2 TexCoord;
|
layout(location = 3) in vec2 TexCoord;
|
||||||
|
|
||||||
out vec3 vPosition;
|
|
||||||
out vec2 vTexCoord;
|
out vec2 vTexCoord;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
gl_Position = mvp * vec4(Position, 1);
|
gl_Position = mvp * vec4(Position, 1);
|
||||||
vTexCoord = TexCoord;
|
vTexCoord = TexCoord;
|
||||||
vPosition = Position;
|
|
||||||
}
|
}
|
|
@ -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;
|
|
||||||
}
|
|
|
@ -2378,6 +2378,7 @@ void Application::paintGL() {
|
||||||
finalFramebuffer = framebufferCache->getFramebuffer();
|
finalFramebuffer = framebufferCache->getFramebuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mat4 eyeProjections[2];
|
||||||
{
|
{
|
||||||
PROFILE_RANGE(render, "/mainRender");
|
PROFILE_RANGE(render, "/mainRender");
|
||||||
PerformanceTimer perfTimer("mainRender");
|
PerformanceTimer perfTimer("mainRender");
|
||||||
|
@ -2399,7 +2400,6 @@ void Application::paintGL() {
|
||||||
_myCamera.setProjection(displayPlugin->getCullingProjection(_myCamera.getProjection()));
|
_myCamera.setProjection(displayPlugin->getCullingProjection(_myCamera.getProjection()));
|
||||||
renderArgs._context->enableStereo(true);
|
renderArgs._context->enableStereo(true);
|
||||||
mat4 eyeOffsets[2];
|
mat4 eyeOffsets[2];
|
||||||
mat4 eyeProjections[2];
|
|
||||||
auto baseProjection = renderArgs.getViewFrustum().getProjection();
|
auto baseProjection = renderArgs.getViewFrustum().getProjection();
|
||||||
auto hmdInterface = DependencyManager::get<HMDScriptingInterface>();
|
auto hmdInterface = DependencyManager::get<HMDScriptingInterface>();
|
||||||
float IPDScale = hmdInterface->getIPDScale();
|
float IPDScale = hmdInterface->getIPDScale();
|
||||||
|
@ -2430,6 +2430,19 @@ void Application::paintGL() {
|
||||||
displaySide(&renderArgs, _myCamera);
|
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();
|
auto frame = _gpuContext->endFrame();
|
||||||
frame->frameIndex = _frameCount;
|
frame->frameIndex = _frameCount;
|
||||||
frame->framebuffer = finalFramebuffer;
|
frame->framebuffer = finalFramebuffer;
|
||||||
|
@ -2437,6 +2450,7 @@ void Application::paintGL() {
|
||||||
DependencyManager::get<FramebufferCache>()->releaseFramebuffer(framebuffer);
|
DependencyManager::get<FramebufferCache>()->releaseFramebuffer(framebuffer);
|
||||||
};
|
};
|
||||||
frame->overlay = _applicationOverlay.getOverlayTexture();
|
frame->overlay = _applicationOverlay.getOverlayTexture();
|
||||||
|
frame->postCompositeBatch = postCompositeBatch;
|
||||||
// deliver final scene rendering commands to the display plugin
|
// deliver final scene rendering commands to the display plugin
|
||||||
{
|
{
|
||||||
PROFILE_RANGE(render, "/pluginOutput");
|
PROFILE_RANGE(render, "/pluginOutput");
|
||||||
|
|
|
@ -82,6 +82,22 @@ bool HMDScriptingInterface::shouldShowHandControllers() const {
|
||||||
return _showHandControllersCount > 0;
|
return _showHandControllersCount > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HMDScriptingInterface::activateHMDHandMouse() {
|
||||||
|
QWriteLocker lock(&_hmdHandMouseLock);
|
||||||
|
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||||
|
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>();
|
||||||
|
offscreenUi->getDesktop()->setProperty("hmdHandMouseActive", false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void HMDScriptingInterface::closeTablet() {
|
void HMDScriptingInterface::closeTablet() {
|
||||||
_showTablet = false;
|
_showTablet = false;
|
||||||
}
|
}
|
||||||
|
@ -153,50 +169,6 @@ QString HMDScriptingInterface::preferredAudioOutput() const {
|
||||||
return qApp->getActiveDisplayPlugin()->getPreferredAudioOutDevice();
|
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>();
|
|
||||||
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>();
|
|
||||||
offscreenUi->getDesktop()->setProperty("hmdHandMouseActive", enabled);
|
|
||||||
|
|
||||||
auto myAvatar = DependencyManager::get<AvatarManager>()->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() {
|
bool HMDScriptingInterface::suppressKeyboard() {
|
||||||
return qApp->getActiveDisplayPlugin()->suppressKeyboard();
|
return qApp->getActiveDisplayPlugin()->suppressKeyboard();
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,7 @@ class QScriptEngine;
|
||||||
#include <DependencyManager.h>
|
#include <DependencyManager.h>
|
||||||
#include <display-plugins/AbstractHMDScriptingInterface.h>
|
#include <display-plugins/AbstractHMDScriptingInterface.h>
|
||||||
|
|
||||||
|
#include <QReadWriteLock>
|
||||||
|
|
||||||
class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Dependency {
|
class HMDScriptingInterface : public AbstractHMDScriptingInterface, public Dependency {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -51,12 +52,8 @@ public:
|
||||||
Q_INVOKABLE void requestHideHandControllers();
|
Q_INVOKABLE void requestHideHandControllers();
|
||||||
Q_INVOKABLE bool shouldShowHandControllers() const;
|
Q_INVOKABLE bool shouldShowHandControllers() const;
|
||||||
|
|
||||||
Q_INVOKABLE bool setHandLasers(int hands, bool enabled, const glm::vec4& color, const glm::vec3& direction);
|
Q_INVOKABLE void activateHMDHandMouse();
|
||||||
Q_INVOKABLE void disableHandLasers(int hands);
|
Q_INVOKABLE void deactivateHMDHandMouse();
|
||||||
|
|
||||||
Q_INVOKABLE bool setExtraLaser(const glm::vec3& worldStart, bool enabled, const glm::vec4& color, const glm::vec3& direction);
|
|
||||||
Q_INVOKABLE void disableExtraLaser();
|
|
||||||
|
|
||||||
|
|
||||||
/// Suppress the activation of any on-screen keyboard so that a script operation will
|
/// Suppress the activation of any on-screen keyboard so that a script operation will
|
||||||
/// not be interrupted by a keyboard popup
|
/// not be interrupted by a keyboard popup
|
||||||
|
@ -119,6 +116,9 @@ private:
|
||||||
bool getHUDLookAtPosition3D(glm::vec3& result) const;
|
bool getHUDLookAtPosition3D(glm::vec3& result) const;
|
||||||
glm::mat4 getWorldHMDMatrix() const;
|
glm::mat4 getWorldHMDMatrix() const;
|
||||||
std::atomic<int> _showHandControllersCount { 0 };
|
std::atomic<int> _showHandControllersCount { 0 };
|
||||||
|
|
||||||
|
QReadWriteLock _hmdHandMouseLock;
|
||||||
|
int _hmdHandMouseCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_HMDScriptingInterface_h
|
#endif // hifi_HMDScriptingInterface_h
|
||||||
|
|
|
@ -267,7 +267,7 @@ const render::ShapeKey Circle3DOverlay::getShapeKey() {
|
||||||
if (getAlpha() != 1.0f) {
|
if (getAlpha() != 1.0f) {
|
||||||
builder.withTranslucent();
|
builder.withTranslucent();
|
||||||
}
|
}
|
||||||
if (!getIsSolid()) {
|
if (!getIsSolid() || shouldDrawHUDLayer()) {
|
||||||
builder.withUnlit().withDepthBias();
|
builder.withUnlit().withDepthBias();
|
||||||
}
|
}
|
||||||
return builder.build();
|
return builder.build();
|
||||||
|
|
|
@ -120,7 +120,7 @@ const render::ShapeKey Cube3DOverlay::getShapeKey() {
|
||||||
if (getAlpha() != 1.0f) {
|
if (getAlpha() != 1.0f) {
|
||||||
builder.withTranslucent();
|
builder.withTranslucent();
|
||||||
}
|
}
|
||||||
if (!getIsSolid()) {
|
if (!getIsSolid() || shouldDrawHUDLayer()) {
|
||||||
builder.withUnlit().withDepthBias();
|
builder.withUnlit().withDepthBias();
|
||||||
}
|
}
|
||||||
return builder.build();
|
return builder.build();
|
||||||
|
|
|
@ -123,7 +123,7 @@ void Image3DOverlay::render(RenderArgs* args) {
|
||||||
|
|
||||||
const render::ShapeKey Image3DOverlay::getShapeKey() {
|
const render::ShapeKey Image3DOverlay::getShapeKey() {
|
||||||
auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias();
|
auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias();
|
||||||
if (_emissive) {
|
if (_emissive || shouldDrawHUDLayer()) {
|
||||||
builder.withUnlit();
|
builder.withUnlit();
|
||||||
}
|
}
|
||||||
if (getAlpha() != 1.0f) {
|
if (getAlpha() != 1.0f) {
|
||||||
|
|
|
@ -29,6 +29,7 @@ Overlay::Overlay() :
|
||||||
_alphaPulse(0.0f),
|
_alphaPulse(0.0f),
|
||||||
_colorPulse(0.0f),
|
_colorPulse(0.0f),
|
||||||
_color(DEFAULT_OVERLAY_COLOR),
|
_color(DEFAULT_OVERLAY_COLOR),
|
||||||
|
_drawHUDLayer(false),
|
||||||
_visible(true),
|
_visible(true),
|
||||||
_anchor(NO_ANCHOR)
|
_anchor(NO_ANCHOR)
|
||||||
{
|
{
|
||||||
|
@ -47,6 +48,7 @@ Overlay::Overlay(const Overlay* overlay) :
|
||||||
_alphaPulse(overlay->_alphaPulse),
|
_alphaPulse(overlay->_alphaPulse),
|
||||||
_colorPulse(overlay->_colorPulse),
|
_colorPulse(overlay->_colorPulse),
|
||||||
_color(overlay->_color),
|
_color(overlay->_color),
|
||||||
|
_drawHUDLayer(overlay->_drawHUDLayer),
|
||||||
_visible(overlay->_visible),
|
_visible(overlay->_visible),
|
||||||
_anchor(overlay->_anchor)
|
_anchor(overlay->_anchor)
|
||||||
{
|
{
|
||||||
|
@ -86,6 +88,11 @@ void Overlay::setProperties(const QVariantMap& properties) {
|
||||||
setColorPulse(properties["colorPulse"].toFloat());
|
setColorPulse(properties["colorPulse"].toFloat());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (properties["drawHUDLayer"].isValid()) {
|
||||||
|
bool drawHUDLayer = properties["drawHUDLayer"].toBool();
|
||||||
|
setDrawHUDLayer(drawHUDLayer);
|
||||||
|
}
|
||||||
|
|
||||||
if (properties["visible"].isValid()) {
|
if (properties["visible"].isValid()) {
|
||||||
bool visible = properties["visible"].toBool();
|
bool visible = properties["visible"].toBool();
|
||||||
setVisible(visible);
|
setVisible(visible);
|
||||||
|
|
|
@ -58,6 +58,7 @@ public:
|
||||||
virtual bool is3D() const = 0;
|
virtual bool is3D() const = 0;
|
||||||
bool isLoaded() { return _isLoaded; }
|
bool isLoaded() { return _isLoaded; }
|
||||||
bool getVisible() const { return _visible; }
|
bool getVisible() const { return _visible; }
|
||||||
|
bool shouldDrawHUDLayer() const { return _drawHUDLayer; }
|
||||||
xColor getColor();
|
xColor getColor();
|
||||||
float getAlpha();
|
float getAlpha();
|
||||||
Anchor getAnchor() const { return _anchor; }
|
Anchor getAnchor() const { return _anchor; }
|
||||||
|
@ -72,6 +73,7 @@ public:
|
||||||
|
|
||||||
// setters
|
// setters
|
||||||
void setVisible(bool visible) { _visible = visible; }
|
void setVisible(bool visible) { _visible = visible; }
|
||||||
|
void setDrawHUDLayer(bool drawHUDLayer) { _drawHUDLayer = drawHUDLayer; }
|
||||||
void setColor(const xColor& color) { _color = color; }
|
void setColor(const xColor& color) { _color = color; }
|
||||||
void setAlpha(float alpha) { _alpha = alpha; }
|
void setAlpha(float alpha) { _alpha = alpha; }
|
||||||
void setAnchor(Anchor anchor) { _anchor = anchor; }
|
void setAnchor(Anchor anchor) { _anchor = anchor; }
|
||||||
|
@ -114,6 +116,7 @@ protected:
|
||||||
|
|
||||||
xColor _color;
|
xColor _color;
|
||||||
bool _visible; // should the overlay be drawn at all
|
bool _visible; // should the overlay be drawn at all
|
||||||
|
bool _drawHUDLayer; // should the overlay be drawn on the HUD layer
|
||||||
Anchor _anchor;
|
Anchor _anchor;
|
||||||
|
|
||||||
unsigned int _stackOrder { 0 };
|
unsigned int _stackOrder { 0 };
|
||||||
|
|
|
@ -37,20 +37,29 @@
|
||||||
#include "Web3DOverlay.h"
|
#include "Web3DOverlay.h"
|
||||||
#include <QtQuick/QQuickWindow>
|
#include <QtQuick/QQuickWindow>
|
||||||
|
|
||||||
|
#include "render/ShapePipeline.h"
|
||||||
|
|
||||||
Q_LOGGING_CATEGORY(trace_render_overlays, "trace.render.overlays")
|
Q_LOGGING_CATEGORY(trace_render_overlays, "trace.render.overlays")
|
||||||
|
|
||||||
|
extern void initOverlay3DPipelines(render::ShapePlumber& plumber);
|
||||||
|
|
||||||
void Overlays::cleanupAllOverlays() {
|
void Overlays::cleanupAllOverlays() {
|
||||||
QMap<OverlayID, Overlay::Pointer> overlaysHUD;
|
QMap<OverlayID, Overlay::Pointer> overlaysHUD;
|
||||||
|
QMap<OverlayID, Overlay::Pointer> overlays3DHUD;
|
||||||
QMap<OverlayID, Overlay::Pointer> overlaysWorld;
|
QMap<OverlayID, Overlay::Pointer> overlaysWorld;
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&_mutex);
|
QMutexLocker locker(&_mutex);
|
||||||
overlaysHUD.swap(_overlaysHUD);
|
overlaysHUD.swap(_overlaysHUD);
|
||||||
|
overlays3DHUD.swap(_overlays3DHUD);
|
||||||
overlaysWorld.swap(_overlaysWorld);
|
overlaysWorld.swap(_overlaysWorld);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach(Overlay::Pointer overlay, overlaysHUD) {
|
foreach(Overlay::Pointer overlay, overlaysHUD) {
|
||||||
_overlaysToDelete.push_back(overlay);
|
_overlaysToDelete.push_back(overlay);
|
||||||
}
|
}
|
||||||
|
foreach(Overlay::Pointer overlay, overlays3DHUD) {
|
||||||
|
_overlaysToDelete.push_back(overlay);
|
||||||
|
}
|
||||||
foreach(Overlay::Pointer overlay, overlaysWorld) {
|
foreach(Overlay::Pointer overlay, overlaysWorld) {
|
||||||
_overlaysToDelete.push_back(overlay);
|
_overlaysToDelete.push_back(overlay);
|
||||||
}
|
}
|
||||||
|
@ -64,6 +73,8 @@ void Overlays::init() {
|
||||||
#if OVERLAY_PANELS
|
#if OVERLAY_PANELS
|
||||||
_scriptEngine = new QScriptEngine();
|
_scriptEngine = new QScriptEngine();
|
||||||
#endif
|
#endif
|
||||||
|
_shapePlumber = std::make_shared<render::ShapePlumber>();
|
||||||
|
initOverlay3DPipelines(*_shapePlumber);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Overlays::update(float deltatime) {
|
void Overlays::update(float deltatime) {
|
||||||
|
@ -72,6 +83,9 @@ void Overlays::update(float deltatime) {
|
||||||
foreach(const auto& thisOverlay, _overlaysHUD) {
|
foreach(const auto& thisOverlay, _overlaysHUD) {
|
||||||
thisOverlay->update(deltatime);
|
thisOverlay->update(deltatime);
|
||||||
}
|
}
|
||||||
|
foreach(const auto& thisOverlay, _overlays3DHUD) {
|
||||||
|
thisOverlay->update(deltatime);
|
||||||
|
}
|
||||||
foreach(const auto& thisOverlay, _overlaysWorld) {
|
foreach(const auto& thisOverlay, _overlaysWorld) {
|
||||||
thisOverlay->update(deltatime);
|
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<TextureCache>();
|
||||||
|
|
||||||
|
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() {
|
void Overlays::disable() {
|
||||||
_enabled = false;
|
_enabled = false;
|
||||||
}
|
}
|
||||||
|
@ -142,8 +173,9 @@ Overlay::Pointer Overlays::getOverlay(OverlayID id) const {
|
||||||
QMutexLocker locker(&_mutex);
|
QMutexLocker locker(&_mutex);
|
||||||
if (_overlaysHUD.contains(id)) {
|
if (_overlaysHUD.contains(id)) {
|
||||||
return _overlaysHUD[id];
|
return _overlaysHUD[id];
|
||||||
}
|
} else if (_overlays3DHUD.contains(id)) {
|
||||||
if (_overlaysWorld.contains(id)) {
|
return _overlays3DHUD[id];
|
||||||
|
} else if (_overlaysWorld.contains(id)) {
|
||||||
return _overlaysWorld[id];
|
return _overlaysWorld[id];
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -200,7 +232,7 @@ OverlayID Overlays::addOverlay(const Overlay::Pointer& overlay) {
|
||||||
OverlayID thisID = OverlayID(QUuid::createUuid());
|
OverlayID thisID = OverlayID(QUuid::createUuid());
|
||||||
overlay->setOverlayID(thisID);
|
overlay->setOverlayID(thisID);
|
||||||
overlay->setStackOrder(_stackOrder++);
|
overlay->setStackOrder(_stackOrder++);
|
||||||
if (overlay->is3D()) {
|
if (overlay->is3D() && !overlay->shouldDrawHUDLayer()) {
|
||||||
{
|
{
|
||||||
QMutexLocker locker(&_mutex);
|
QMutexLocker locker(&_mutex);
|
||||||
_overlaysWorld[thisID] = overlay;
|
_overlaysWorld[thisID] = overlay;
|
||||||
|
@ -210,6 +242,9 @@ OverlayID Overlays::addOverlay(const Overlay::Pointer& overlay) {
|
||||||
render::Transaction transaction;
|
render::Transaction transaction;
|
||||||
overlay->addToScene(overlay, scene, transaction);
|
overlay->addToScene(overlay, scene, transaction);
|
||||||
scene->enqueueTransaction(transaction);
|
scene->enqueueTransaction(transaction);
|
||||||
|
} else if (overlay->is3D() && overlay->shouldDrawHUDLayer()) {
|
||||||
|
QMutexLocker locker(&_mutex);
|
||||||
|
_overlays3DHUD[thisID] = overlay;
|
||||||
} else {
|
} else {
|
||||||
QMutexLocker locker(&_mutex);
|
QMutexLocker locker(&_mutex);
|
||||||
_overlaysHUD[thisID] = overlay;
|
_overlaysHUD[thisID] = overlay;
|
||||||
|
@ -294,6 +329,8 @@ void Overlays::deleteOverlay(OverlayID id) {
|
||||||
QMutexLocker locker(&_mutex);
|
QMutexLocker locker(&_mutex);
|
||||||
if (_overlaysHUD.contains(id)) {
|
if (_overlaysHUD.contains(id)) {
|
||||||
overlayToDelete = _overlaysHUD.take(id);
|
overlayToDelete = _overlaysHUD.take(id);
|
||||||
|
} else if (_overlays3DHUD.contains(id)) {
|
||||||
|
overlayToDelete = _overlays3DHUD.take(id);
|
||||||
} else if (_overlaysWorld.contains(id)) {
|
} else if (_overlaysWorld.contains(id)) {
|
||||||
overlayToDelete = _overlaysWorld.take(id);
|
overlayToDelete = _overlaysWorld.take(id);
|
||||||
} else {
|
} else {
|
||||||
|
@ -702,7 +739,7 @@ bool Overlays::isAddedOverlay(OverlayID id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
QMutexLocker locker(&_mutex);
|
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) {
|
void Overlays::sendMousePressOnOverlay(OverlayID overlayID, const PointerEvent& event) {
|
||||||
|
|
|
@ -90,6 +90,7 @@ public:
|
||||||
void init();
|
void init();
|
||||||
void update(float deltatime);
|
void update(float deltatime);
|
||||||
void renderHUD(RenderArgs* renderArgs);
|
void renderHUD(RenderArgs* renderArgs);
|
||||||
|
void render3DHUDOverlays(RenderArgs* renderArgs);
|
||||||
void disable();
|
void disable();
|
||||||
void enable();
|
void enable();
|
||||||
|
|
||||||
|
@ -325,7 +326,11 @@ private:
|
||||||
|
|
||||||
mutable QMutex _mutex;
|
mutable QMutex _mutex;
|
||||||
QMap<OverlayID, Overlay::Pointer> _overlaysHUD;
|
QMap<OverlayID, Overlay::Pointer> _overlaysHUD;
|
||||||
|
QMap<OverlayID, Overlay::Pointer> _overlays3DHUD;
|
||||||
QMap<OverlayID, Overlay::Pointer> _overlaysWorld;
|
QMap<OverlayID, Overlay::Pointer> _overlaysWorld;
|
||||||
|
|
||||||
|
render::ShapePlumberPointer _shapePlumber;
|
||||||
|
|
||||||
#if OVERLAY_PANELS
|
#if OVERLAY_PANELS
|
||||||
QMap<OverlayID, OverlayPanel::Pointer> _panels;
|
QMap<OverlayID, OverlayPanel::Pointer> _panels;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -65,7 +65,7 @@ const render::ShapeKey Shape3DOverlay::getShapeKey() {
|
||||||
if (getAlpha() != 1.0f) {
|
if (getAlpha() != 1.0f) {
|
||||||
builder.withTranslucent();
|
builder.withTranslucent();
|
||||||
}
|
}
|
||||||
if (!getIsSolid()) {
|
if (!getIsSolid() || shouldDrawHUDLayer()) {
|
||||||
builder.withUnlit().withDepthBias();
|
builder.withUnlit().withDepthBias();
|
||||||
}
|
}
|
||||||
return builder.build();
|
return builder.build();
|
||||||
|
|
|
@ -62,7 +62,7 @@ const render::ShapeKey Sphere3DOverlay::getShapeKey() {
|
||||||
if (getAlpha() != 1.0f) {
|
if (getAlpha() != 1.0f) {
|
||||||
builder.withTranslucent();
|
builder.withTranslucent();
|
||||||
}
|
}
|
||||||
if (!getIsSolid()) {
|
if (!getIsSolid() || shouldDrawHUDLayer()) {
|
||||||
builder.withUnlit().withDepthBias();
|
builder.withUnlit().withDepthBias();
|
||||||
}
|
}
|
||||||
return builder.build();
|
return builder.build();
|
||||||
|
|
|
@ -349,10 +349,9 @@ bool CompositorHelper::calculateRayUICollisionPoint(const glm::vec3& position, c
|
||||||
auto relativePosition = vec3(relativePosition4) / relativePosition4.w;
|
auto relativePosition = vec3(relativePosition4) / relativePosition4.w;
|
||||||
auto relativeDirection = glm::inverse(glm::quat_cast(UITransform)) * direction;
|
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;
|
float instersectionDistance;
|
||||||
if (raySphereIntersect(relativeDirection, relativePosition, uiRadius, &instersectionDistance)){
|
if (raySphereIntersect(relativeDirection, relativePosition, UI_RADIUS, &instersectionDistance)){
|
||||||
result = position + glm::normalize(direction) * instersectionDistance;
|
result = position + glm::normalize(direction) * instersectionDistance;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -111,8 +111,6 @@ public:
|
||||||
void setDisplayPlugin(const DisplayPluginPointer& displayPlugin) { _currentDisplayPlugin = displayPlugin; }
|
void setDisplayPlugin(const DisplayPluginPointer& displayPlugin) { _currentDisplayPlugin = displayPlugin; }
|
||||||
void setFrameInfo(uint32_t frame, const glm::mat4& camera) { _currentCamera = camera; }
|
void setFrameInfo(uint32_t frame, const glm::mat4& camera) { _currentCamera = camera; }
|
||||||
|
|
||||||
float getHmdUiRadius() const { return _hmdUIRadius; }
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void allowMouseCaptureChanged();
|
void allowMouseCaptureChanged();
|
||||||
void alphaChanged();
|
void alphaChanged();
|
||||||
|
@ -142,7 +140,6 @@ private:
|
||||||
float _textureAspectRatio { VIRTUAL_UI_ASPECT_RATIO };
|
float _textureAspectRatio { VIRTUAL_UI_ASPECT_RATIO };
|
||||||
|
|
||||||
float _alpha { 1.0f };
|
float _alpha { 1.0f };
|
||||||
float _hmdUIRadius { 1.0f };
|
|
||||||
|
|
||||||
int _previousBorderWidth { -1 };
|
int _previousBorderWidth { -1 };
|
||||||
int _previousBorderHeight { -1 };
|
int _previousBorderHeight { -1 };
|
||||||
|
|
|
@ -641,6 +641,15 @@ void OpenGLDisplayPlugin::compositeLayers() {
|
||||||
compositePointer();
|
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())
|
PROFILE_RANGE_EX(render_detail, "compositeExtra", 0xff0077ff, (uint64_t)presentCount())
|
||||||
compositeExtra();
|
compositeExtra();
|
||||||
|
|
|
@ -35,16 +35,7 @@ bool DebugHmdDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||||
//_currentRenderFrameInfo.presentPose = _currentRenderFrameInfo.renderPose;
|
//_currentRenderFrameInfo.presentPose = _currentRenderFrameInfo.renderPose;
|
||||||
|
|
||||||
withNonPresentThreadLock([&] {
|
withNonPresentThreadLock([&] {
|
||||||
_uiModelTransform = DependencyManager::get<CompositorHelper>()->getModelTransform();
|
|
||||||
_frameInfos[frameIndex] = _currentRenderFrameInfo;
|
_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);
|
return Parent::beginFrameRender(frameIndex);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,9 +32,6 @@
|
||||||
|
|
||||||
#include "../Logging.h"
|
#include "../Logging.h"
|
||||||
#include "../CompositorHelper.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 MONO_PREVIEW = "Mono Preview";
|
||||||
static const QString DISABLE_PREVIEW = "Disable Preview";
|
static const QString DISABLE_PREVIEW = "Disable Preview";
|
||||||
|
@ -123,26 +120,6 @@ static const int32_t LINE_DATA_SLOT = 1;
|
||||||
void HmdDisplayPlugin::customizeContext() {
|
void HmdDisplayPlugin::customizeContext() {
|
||||||
Parent::customizeContext();
|
Parent::customizeContext();
|
||||||
_overlayRenderer.build();
|
_overlayRenderer.build();
|
||||||
|
|
||||||
{
|
|
||||||
auto state = std::make_shared<gpu::State>();
|
|
||||||
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<gpu::BufferPointer, 2>{ { std::make_shared<gpu::Buffer>(), std::make_shared<gpu::Buffer>() } };
|
|
||||||
_extraLaserUniforms = std::make_shared<gpu::Buffer>();
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HmdDisplayPlugin::uncustomizeContext() {
|
void HmdDisplayPlugin::uncustomizeContext() {
|
||||||
|
@ -157,10 +134,6 @@ void HmdDisplayPlugin::uncustomizeContext() {
|
||||||
});
|
});
|
||||||
_overlayRenderer = OverlayRenderer();
|
_overlayRenderer = OverlayRenderer();
|
||||||
_previewTexture.reset();
|
_previewTexture.reset();
|
||||||
_handLaserUniforms[0].reset();
|
|
||||||
_handLaserUniforms[1].reset();
|
|
||||||
_extraLaserUniforms.reset();
|
|
||||||
_glowLinePipeline.reset();
|
|
||||||
Parent::uncustomizeContext();
|
Parent::uncustomizeContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,132 +356,13 @@ void HmdDisplayPlugin::updateFrameData() {
|
||||||
getGLBackend()->setCameraCorrection(correction);
|
getGLBackend()->setCameraCorrection(correction);
|
||||||
}
|
}
|
||||||
|
|
||||||
withPresentThreadLock([&] {
|
|
||||||
_presentHandLasers = _handLasers;
|
|
||||||
_presentHandPoses = _handPoses;
|
|
||||||
_presentUiModelTransform = _uiModelTransform;
|
|
||||||
|
|
||||||
_presentExtraLaser = _extraLaser;
|
|
||||||
_presentExtraLaserStart = _extraLaserStart;
|
|
||||||
});
|
|
||||||
|
|
||||||
auto compositorHelper = DependencyManager::get<CompositorHelper>();
|
auto compositorHelper = DependencyManager::get<CompositorHelper>();
|
||||||
glm::mat4 modelMat = compositorHelper->getModelTransform().getMatrix();
|
glm::mat4 modelMat = compositorHelper->getModelTransform().getMatrix();
|
||||||
static const float OUT_OF_BOUNDS = -1;
|
|
||||||
std::array<vec2, NUMBER_OF_HANDS> 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) {
|
for_each_eye([&](Eye eye) {
|
||||||
auto modelView = glm::inverse(_currentPresentFrameInfo.presentPose * getEyeToHeadTransform(eye)) * modelMat;
|
auto modelView = glm::inverse(_currentPresentFrameInfo.presentPose * getEyeToHeadTransform(eye)) * modelMat;
|
||||||
_overlayRenderer.mvps[eye] = _eyeProjections[eye] * modelView;
|
_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() {
|
void HmdDisplayPlugin::OverlayRenderer::build() {
|
||||||
|
@ -573,8 +427,8 @@ void HmdDisplayPlugin::OverlayRenderer::build() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HmdDisplayPlugin::OverlayRenderer::updatePipeline() {
|
void HmdDisplayPlugin::OverlayRenderer::updatePipeline() {
|
||||||
static const QString vsFile = PathUtils::resourcesPath() + "/shaders/hmd_ui_glow.vert";
|
static const QString vsFile = PathUtils::resourcesPath() + "/shaders/hmd_ui.vert";
|
||||||
static const QString fsFile = PathUtils::resourcesPath() + "/shaders/hmd_ui_glow.frag";
|
static const QString fsFile = PathUtils::resourcesPath() + "/shaders/hmd_ui.frag";
|
||||||
|
|
||||||
#if LIVE_SHADER_RELOAD
|
#if LIVE_SHADER_RELOAD
|
||||||
static qint64 vsBuiltAge = 0;
|
static qint64 vsBuiltAge = 0;
|
||||||
|
@ -598,7 +452,7 @@ void HmdDisplayPlugin::OverlayRenderer::updatePipeline() {
|
||||||
this->uniformsLocation = program->getUniformBuffers().findLocation("overlayBuffer");
|
this->uniformsLocation = program->getUniformBuffers().findLocation("overlayBuffer");
|
||||||
|
|
||||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||||
state->setDepthTest(gpu::State::DepthTest(false));
|
state->setDepthTest(gpu::State::DepthTest(true));
|
||||||
state->setBlendFunction(true,
|
state->setBlendFunction(true,
|
||||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
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::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||||
|
@ -665,84 +519,6 @@ void HmdDisplayPlugin::compositeOverlay() {
|
||||||
_overlayRenderer.render(*this);
|
_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() {
|
HmdDisplayPlugin::~HmdDisplayPlugin() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,9 +37,6 @@ public:
|
||||||
|
|
||||||
virtual glm::mat4 getHeadPose() const override;
|
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 {
|
bool wantVsync() const override {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -63,33 +60,6 @@ protected:
|
||||||
void customizeContext() override;
|
void customizeContext() override;
|
||||||
void uncustomizeContext() override;
|
void uncustomizeContext() override;
|
||||||
void updateFrameData() 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<HandLaserInfo, 2> _handLasers;
|
|
||||||
std::array<mat4, 2> _handPoses;
|
|
||||||
|
|
||||||
Transform _presentUiModelTransform;
|
|
||||||
std::array<HandLaserInfo, 2> _presentHandLasers;
|
|
||||||
std::array<mat4, 2> _presentHandPoses;
|
|
||||||
std::array<std::pair<vec3, vec3>, 2> _presentHandLaserPoints;
|
|
||||||
|
|
||||||
HandLaserInfo _extraLaser;
|
|
||||||
HandLaserInfo _presentExtraLaser;
|
|
||||||
vec3 _extraLaserStart;
|
|
||||||
vec3 _presentExtraLaserStart;
|
|
||||||
std::pair<vec3, vec3> _presentExtraLaserPoints;
|
|
||||||
|
|
||||||
std::array<mat4, 2> _eyeOffsets;
|
std::array<mat4, 2> _eyeOffsets;
|
||||||
std::array<mat4, 2> _eyeProjections;
|
std::array<mat4, 2> _eyeProjections;
|
||||||
|
@ -120,9 +90,6 @@ private:
|
||||||
bool _disablePreviewItemAdded { false };
|
bool _disablePreviewItemAdded { false };
|
||||||
bool _monoPreview { true };
|
bool _monoPreview { true };
|
||||||
bool _clearPreviewFlag { false };
|
bool _clearPreviewFlag { false };
|
||||||
std::array<gpu::BufferPointer, 2> _handLaserUniforms;
|
|
||||||
gpu::BufferPointer _extraLaserUniforms;
|
|
||||||
gpu::PipelinePointer _glowLinePipeline;
|
|
||||||
gpu::TexturePointer _previewTexture;
|
gpu::TexturePointer _previewTexture;
|
||||||
glm::vec2 _lastWindowSize;
|
glm::vec2 _lastWindowSize;
|
||||||
|
|
||||||
|
@ -140,14 +107,7 @@ private:
|
||||||
|
|
||||||
struct Uniforms {
|
struct Uniforms {
|
||||||
mat4 mvp;
|
mat4 mvp;
|
||||||
vec4 glowPoints { -1 };
|
|
||||||
vec4 glowColors[2];
|
|
||||||
vec2 resolution { CompositorHelper::VIRTUAL_SCREEN_SIZE };
|
|
||||||
float radius { 0.005f };
|
|
||||||
float alpha { 1.0f };
|
float alpha { 1.0f };
|
||||||
|
|
||||||
vec4 extraGlowColor;
|
|
||||||
vec2 extraGlowPoint { -1 };
|
|
||||||
} uniforms;
|
} uniforms;
|
||||||
|
|
||||||
struct Vertex {
|
struct Vertex {
|
||||||
|
|
|
@ -32,6 +32,8 @@ namespace gpu {
|
||||||
Mat4 pose;
|
Mat4 pose;
|
||||||
/// The collection of batches which make up the frame
|
/// The collection of batches which make up the frame
|
||||||
Batches batches;
|
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.
|
/// The main thread updates to buffers that are applicable for this frame.
|
||||||
BufferUpdates bufferUpdates;
|
BufferUpdates bufferUpdates;
|
||||||
/// The destination framebuffer in which the results will be placed
|
/// The destination framebuffer in which the results will be placed
|
||||||
|
|
|
@ -107,24 +107,6 @@ public:
|
||||||
RightHand = 0x02,
|
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 bool suppressKeyboard() { return false; }
|
||||||
virtual void unsuppressKeyboard() {};
|
virtual void unsuppressKeyboard() {};
|
||||||
virtual bool isKeyboardVisible() { return false; }
|
virtual bool isKeyboardVisible() { return false; }
|
||||||
|
|
|
@ -51,8 +51,6 @@ bool OculusBaseDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||||
});
|
});
|
||||||
|
|
||||||
withNonPresentThreadLock([&] {
|
withNonPresentThreadLock([&] {
|
||||||
_uiModelTransform = DependencyManager::get<CompositorHelper>()->getModelTransform();
|
|
||||||
_handPoses = handPoses;
|
|
||||||
_frameInfos[frameIndex] = _currentRenderFrameInfo;
|
_frameInfos[frameIndex] = _currentRenderFrameInfo;
|
||||||
});
|
});
|
||||||
return Parent::beginFrameRender(frameIndex);
|
return Parent::beginFrameRender(frameIndex);
|
||||||
|
|
|
@ -594,9 +594,6 @@ bool OpenVrDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||||
}
|
}
|
||||||
|
|
||||||
withNonPresentThreadLock([&] {
|
withNonPresentThreadLock([&] {
|
||||||
_uiModelTransform = DependencyManager::get<CompositorHelper>()->getModelTransform();
|
|
||||||
// Make controller poses available to the presentation thread
|
|
||||||
_handPoses = handPoses;
|
|
||||||
_frameInfos[frameIndex] = _currentRenderFrameInfo;
|
_frameInfos[frameIndex] = _currentRenderFrameInfo;
|
||||||
});
|
});
|
||||||
return Parent::beginFrameRender(frameIndex);
|
return Parent::beginFrameRender(frameIndex);
|
||||||
|
|
|
@ -150,15 +150,92 @@ var setReticlePosition = function (point2d) {
|
||||||
Reticle.setPosition(point2d);
|
Reticle.setPosition(point2d);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Generalizations of utilities that work with system and overlay elements.
|
// VISUAL AID -----------
|
||||||
function findRayIntersection(pickRay) {
|
// Same properties as handControllerGrab search sphere
|
||||||
// Check 3D overlays and entities. Argument is an object with origin and direction.
|
var LASER_ALPHA = 0.5;
|
||||||
var result = Overlays.findRayIntersection(pickRay);
|
var LASER_SEARCH_COLOR = {red: 10, green: 10, blue: 255};
|
||||||
if (!result.intersects) {
|
var LASER_TRIGGER_COLOR = {red: 250, green: 10, blue: 10};
|
||||||
result = Entities.findRayIntersection(pickRay, true);
|
var END_DIAMETER = 0.05;
|
||||||
}
|
var systemLaserOn = false;
|
||||||
return result;
|
|
||||||
|
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) {
|
function isPointingAtOverlay(optionalHudPosition2d) {
|
||||||
return Reticle.pointingAtSystemOverlay || Overlays.getOverlayAtPoint(optionalHudPosition2d || Reticle.position);
|
return Reticle.pointingAtSystemOverlay || Overlays.getOverlayAtPoint(optionalHudPosition2d || Reticle.position);
|
||||||
}
|
}
|
||||||
|
@ -166,10 +243,21 @@ function isPointingAtOverlay(optionalHudPosition2d) {
|
||||||
// Generalized HUD utilities, with or without HMD:
|
// Generalized HUD utilities, with or without HMD:
|
||||||
// This "var" is for documentation. Do not change the value!
|
// This "var" is for documentation. Do not change the value!
|
||||||
var PLANAR_PERPENDICULAR_HUD_DISTANCE = 1;
|
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.
|
// Answer the 3D intersection of the HUD by the given ray, or falsey if no intersection.
|
||||||
if (HMD.active) {
|
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:
|
// interect HUD plane, 1m in front of camera, using formula:
|
||||||
// scale = hudNormal dot (hudPoint - position) / hudNormal dot direction
|
// scale = hudNormal dot (hudPoint - position) / hudNormal dot direction
|
||||||
|
@ -215,7 +303,7 @@ function activeHudPoint2dGamePad() {
|
||||||
var headPosition = MyAvatar.getHeadPosition();
|
var headPosition = MyAvatar.getHeadPosition();
|
||||||
var headDirection = Quat.getUp(Quat.multiply(MyAvatar.headOrientation, Quat.angleAxis(-90, { x: 1, y: 0, z: 0 })));
|
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 (!hudPoint3d) {
|
||||||
if (Menu.isOptionChecked("Overlays")) { // With our hud resetting strategy, hudPoint3d should be valid here
|
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 controllerPosition = controllerPose.position;
|
||||||
var controllerDirection = Quat.getUp(controllerPose.rotation);
|
var controllerDirection = Quat.getUp(controllerPose.rotation);
|
||||||
|
|
||||||
var hudPoint3d = calculateRayUICollisionPoint(controllerPosition, controllerDirection);
|
var hudPoint3d = calculateRayUICollisionPoint(controllerPosition, controllerDirection, true);
|
||||||
if (!hudPoint3d) {
|
if (!hudPoint3d) {
|
||||||
if (Menu.isOptionChecked("Overlays")) { // With our hud resetting strategy, hudPoint3d should be valid here
|
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.
|
print('Controller is parallel to HUD'); // so let us know that our assumptions are wrong.
|
||||||
|
@ -355,7 +443,7 @@ function onMouseMove() {
|
||||||
if (isPointingAtOverlay()) {
|
if (isPointingAtOverlay()) {
|
||||||
Reticle.depth = hudReticleDistance();
|
Reticle.depth = hudReticleDistance();
|
||||||
} else {
|
} 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;
|
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.from(leftTrigger.partial).to(makeToggleAction(Controller.Standard.LeftHand));
|
||||||
clickMapping.enable();
|
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 HIFI_POINTER_DISABLE_MESSAGE_CHANNEL = "Hifi-Pointer-Disable";
|
||||||
var isPointerEnabled = true;
|
var isPointerEnabled = true;
|
||||||
|
|
||||||
|
@ -488,23 +568,34 @@ function clearSystemLaser() {
|
||||||
if (!systemLaserOn) {
|
if (!systemLaserOn) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
HMD.disableHandLasers(BOTH_HUD_LASERS);
|
HMD.deactivateHMDHandMouse();
|
||||||
HMD.disableExtraLaser();
|
LaserPointers.setRenderState(hudRayRight, "");
|
||||||
|
LaserPointers.setRenderState(hudRayLeft, "");
|
||||||
|
LaserPointers.setRenderState(hudRayHead, "");
|
||||||
systemLaserOn = false;
|
systemLaserOn = false;
|
||||||
weMovedReticle = true;
|
weMovedReticle = true;
|
||||||
}
|
}
|
||||||
function setColoredLaser() { // answer trigger state if lasers supported, else falsey.
|
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()) {
|
if (!systemLaserOn) {
|
||||||
// NOTE: keep this offset in sync with scripts/system/librarires/controllers.js:57
|
HMD.activateHMDHandMouse();
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 -----------
|
// MAIN OPERATIONS -----------
|
||||||
|
@ -551,11 +642,13 @@ function update() {
|
||||||
if (HMD.active) {
|
if (HMD.active) {
|
||||||
Reticle.depth = hudReticleDistance();
|
Reticle.depth = hudReticleDistance();
|
||||||
|
|
||||||
if (!HMD.isHandControllerAvailable()) {
|
var pose = Controller.getPoseValue(activeHand);
|
||||||
var color = (activeTrigger.state === 'full') ? LASER_TRIGGER_COLOR_XYZW : LASER_SEARCH_COLOR_XYZW;
|
if (!pose.valid) {
|
||||||
var position = MyAvatar.getHeadPosition();
|
var mode = (activeTrigger.state === 'full') ? 'trigger' : 'search';
|
||||||
var direction = Quat.getUp(Quat.multiply(MyAvatar.headOrientation, Quat.angleAxis(-90, { x: 1, y: 0, z: 0 })));
|
if (!systemLaserOn) {
|
||||||
HMD.setExtraLaser(position, true, color, direction);
|
HMD.activateHMDHandMouse();
|
||||||
|
}
|
||||||
|
LaserPointers.setRenderState(hudRayHead, mode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -604,6 +697,10 @@ Script.scriptEnding.connect(function () {
|
||||||
Script.clearInterval(settingsChecker);
|
Script.clearInterval(settingsChecker);
|
||||||
Script.update.disconnect(update);
|
Script.update.disconnect(update);
|
||||||
OffscreenFlags.navigationFocusDisabled = false;
|
OffscreenFlags.navigationFocusDisabled = false;
|
||||||
|
LaserPointers.removeLaserPointer(hudRayRight);
|
||||||
|
LaserPointers.removeLaserPointer(hudRayLeft);
|
||||||
|
LaserPointers.removeLaserPointer(hudRayHead);
|
||||||
|
HMD.deactivateHMDHandMouse();
|
||||||
});
|
});
|
||||||
|
|
||||||
}()); // END LOCAL_SCOPE
|
}()); // END LOCAL_SCOPE
|
||||||
|
|
Loading…
Reference in a new issue