From 7e93747acf686494e02ff2be79ea42c10fdfd08d Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Sun, 31 Jul 2016 18:19:28 -0700 Subject: [PATCH] Working on reprojection --- .../resources/shaders/hmd_reproject.frag | 65 +---- .../resources/shaders/hmd_reproject.vert | 88 +++++- libraries/display-plugins/CMakeLists.txt | 1 + .../src/display-plugins/DisplayPlugin.cpp | 2 + .../display-plugins/OpenGLDisplayPlugin.cpp | 14 +- .../src/display-plugins/OpenGLDisplayPlugin.h | 9 +- .../hmd/DebugHmdDisplayPlugin.cpp | 76 +++++ .../hmd/DebugHmdDisplayPlugin.h | 33 +++ .../display-plugins/hmd/HmdDisplayPlugin.cpp | 260 +++++++++++++----- .../display-plugins/hmd/HmdDisplayPlugin.h | 28 +- .../display-plugins/src/hmd_hand_lasers.slf | 35 +++ .../display-plugins/src/hmd_hand_lasers.slg | 70 +++++ .../display-plugins/src/hmd_hand_lasers.slv | 13 + .../display-plugins/src/hmd_reproject.slf | 109 ++++++++ .../display-plugins/src/hmd_reproject.slv | 18 ++ libraries/display-plugins/src/hmd_ui_glow.slf | 75 +++++ libraries/display-plugins/src/hmd_ui_glow.slv | 32 +++ libraries/gpu-gl/src/gpu/gl/GLBackend.h | 2 +- libraries/gpu-gl/src/gpu/gl/GLTexture.h | 12 +- libraries/plugins/src/plugins/DisplayPlugin.h | 1 - libraries/shared/src/shared/NsightHelpers.cpp | 6 +- libraries/shared/src/shared/NsightHelpers.h | 5 + .../src/ui-plugins/PluginContainer.cpp | 7 - .../oculus/src/OculusDebugDisplayPlugin.cpp | 2 +- plugins/oculus/src/OculusDisplayPlugin.cpp | 3 +- plugins/openvr/CMakeLists.txt | 4 +- plugins/openvr/src/OpenVrDisplayPlugin.cpp | 121 ++++---- plugins/openvr/src/OpenVrHelpers.cpp | 4 +- plugins/openvr/src/OpenVrHelpers.h | 17 ++ plugins/openvr/src/ViveControllerManager.cpp | 16 +- 30 files changed, 868 insertions(+), 260 deletions(-) create mode 100644 libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.cpp create mode 100644 libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.h create mode 100644 libraries/display-plugins/src/hmd_hand_lasers.slf create mode 100644 libraries/display-plugins/src/hmd_hand_lasers.slg create mode 100644 libraries/display-plugins/src/hmd_hand_lasers.slv create mode 100644 libraries/display-plugins/src/hmd_reproject.slf create mode 100644 libraries/display-plugins/src/hmd_reproject.slv create mode 100644 libraries/display-plugins/src/hmd_ui_glow.slf create mode 100644 libraries/display-plugins/src/hmd_ui_glow.slv diff --git a/interface/resources/shaders/hmd_reproject.frag b/interface/resources/shaders/hmd_reproject.frag index adda0315a3..4704ded9cc 100644 --- a/interface/resources/shaders/hmd_reproject.frag +++ b/interface/resources/shaders/hmd_reproject.frag @@ -6,73 +6,12 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#version 410 core - uniform sampler2D sampler; -uniform mat3 reprojection = mat3(1); -uniform mat4 inverseProjections[2]; -uniform mat4 projections[2]; -in vec2 vTexCoord; -in vec3 vPosition; +in vec2 varTexCoord0; out vec4 FragColor; void main() { - vec2 uv = vTexCoord; - - mat4 eyeInverseProjection; - mat4 eyeProjection; - - float xoffset = 1.0; - vec2 uvmin = vec2(0.0); - vec2 uvmax = vec2(1.0); - // determine the correct projection and inverse projection to use. - if (vTexCoord.x < 0.5) { - uvmax.x = 0.5; - eyeInverseProjection = inverseProjections[0]; - eyeProjection = projections[0]; - } else { - xoffset = -1.0; - uvmin.x = 0.5; - uvmax.x = 1.0; - eyeInverseProjection = inverseProjections[1]; - eyeProjection = projections[1]; - } - - // Account for stereo in calculating the per-eye NDC coordinates - vec4 ndcSpace = vec4(vPosition, 1.0); - ndcSpace.x *= 2.0; - ndcSpace.x += xoffset; - - // Convert from NDC to eyespace - vec4 eyeSpace = eyeInverseProjection * ndcSpace; - eyeSpace /= eyeSpace.w; - - // Convert to a noramlized ray - vec3 ray = eyeSpace.xyz; - ray = normalize(ray); - - // Adjust the ray by the rotation - ray = reprojection * ray; - - // Project back on to the texture plane - ray *= eyeSpace.z / ray.z; - - // Update the eyespace vector - eyeSpace.xyz = ray; - - // Reproject back into NDC - ndcSpace = eyeProjection * eyeSpace; - ndcSpace /= ndcSpace.w; - ndcSpace.x -= xoffset; - ndcSpace.x /= 2.0; - - // Calculate the new UV coordinates - uv = (ndcSpace.xy / 2.0) + 0.5; - if (any(greaterThan(uv, uvmax)) || any(lessThan(uv, uvmin))) { - FragColor = vec4(0.0, 0.0, 0.0, 1.0); - } else { - FragColor = texture(sampler, uv); - } + FragColor = texture(sampler, varTexCoord0); } \ No newline at end of file diff --git a/interface/resources/shaders/hmd_reproject.vert b/interface/resources/shaders/hmd_reproject.vert index 923375613a..d5dd5b4d1a 100644 --- a/interface/resources/shaders/hmd_reproject.vert +++ b/interface/resources/shaders/hmd_reproject.vert @@ -6,15 +6,85 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#version 410 core -in vec3 Position; -in vec2 TexCoord; +precision highp float; -out vec3 vPosition; -out vec2 vTexCoord; +struct TransformCamera { + mat4 _view; + mat4 _viewInverse; + mat4 _projectionViewUntranslated; + mat4 _projection; + mat4 _projectionInverse; + vec4 _viewport; + vec4 _stereoInfo; +}; -void main() { - gl_Position = vec4(Position, 1); - vTexCoord = TexCoord; - vPosition = Position; +layout(std140) uniform transformCameraBuffer { + TransformCamera _camera; +}; + +TransformCamera getTransformCamera() { + return _camera; +} + +vec3 getEyeWorldPos() { + return _camera._viewInverse[3].xyz; +} + + +bool cam_isStereo() { + return _camera._stereoInfo.x > 0.0; +} + +float cam_getStereoSide() { + return _camera._stereoInfo.y; +} + + +struct Reprojection { + mat4 rotation; +}; + +layout(std140) uniform reprojectionBuffer { + Reprojection reprojection; +}; + +layout(location = 0) in vec4 inPosition; + +noperspective out vec2 varTexCoord0; + + +void main(void) { + // standard transform + TransformCamera cam = getTransformCamera(); + vec2 uv = inPosition.xy; + uv.x /= 2.0; + vec4 pos = inPosition; + pos *= 2.0; + pos -= 1.0; + if (cam_getStereoSide() > 0.0) { + uv.x += 0.5; + } + if (reprojection.rotation != mat4(1)) { + vec4 eyeSpace = _camera._projectionInverse * pos; + eyeSpace /= eyeSpace.w; + + // Convert to a noramlized ray + vec3 ray = eyeSpace.xyz; + ray = normalize(ray); + + // Adjust the ray by the rotation + ray = mat3(inverse(reprojection.rotation)) * ray; + + // Project back on to the texture plane + ray *= eyeSpace.z / ray.z; + eyeSpace.xyz = ray; + + // Move back into NDC space + eyeSpace = _camera._projection * eyeSpace; + eyeSpace /= eyeSpace.w; + eyeSpace.z = 0.0; + pos = eyeSpace; + } + gl_Position = pos; + varTexCoord0 = uv; } diff --git a/libraries/display-plugins/CMakeLists.txt b/libraries/display-plugins/CMakeLists.txt index fe08647074..d1ab0f28c6 100644 --- a/libraries/display-plugins/CMakeLists.txt +++ b/libraries/display-plugins/CMakeLists.txt @@ -1,4 +1,5 @@ set(TARGET_NAME display-plugins) +AUTOSCRIBE_SHADER_LIB(gpu display-plugins) setup_hifi_library(OpenGL) link_hifi_libraries(shared plugins ui-plugins gl gpu-gl ui) diff --git a/libraries/display-plugins/src/display-plugins/DisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/DisplayPlugin.cpp index 08368597d0..3e090dc7b3 100644 --- a/libraries/display-plugins/src/display-plugins/DisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/DisplayPlugin.cpp @@ -12,6 +12,7 @@ #include "NullDisplayPlugin.h" #include "stereo/SideBySideStereoDisplayPlugin.h" #include "stereo/InterleavedStereoDisplayPlugin.h" +#include "hmd/DebugHmdDisplayPlugin.h" #include "Basic2DWindowOpenGLDisplayPlugin.h" const QString& DisplayPlugin::MENU_PATH() { @@ -23,6 +24,7 @@ const QString& DisplayPlugin::MENU_PATH() { DisplayPluginList getDisplayPlugins() { DisplayPlugin* PLUGIN_POOL[] = { new Basic2DWindowOpenGLDisplayPlugin(), + new DebugHmdDisplayPlugin(), #ifdef DEBUG new NullDisplayPlugin(), #endif diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 8968b1e80b..7a6db7b92b 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -213,9 +214,6 @@ private: QGLContext* _context { nullptr }; }; -bool OpenGLDisplayPlugin::isRenderThread() const { - return QThread::currentThread() == DependencyManager::get()->thread(); -} OpenGLDisplayPlugin::OpenGLDisplayPlugin() { } @@ -253,6 +251,9 @@ bool OpenGLDisplayPlugin::activate() { presentThread->start(); } _presentThread = presentThread.data(); + if (!RENDER_THREAD) { + RENDER_THREAD = _presentThread; + } // Child classes may override this in order to do things like initialize // libraries, etc @@ -677,3 +678,10 @@ ivec4 OpenGLDisplayPlugin::eyeViewport(Eye eye) const { } return ivec4(vpPos, vpSize); } + +gpu::gl::GLBackend* OpenGLDisplayPlugin::getGLBackend() { + if (!_backend) { + return nullptr; + } + return dynamic_cast(_backend.get()); +} diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h index 5d8f55ebbd..367c64a635 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -21,6 +21,12 @@ #include #include +namespace gpu { + namespace gl { + class GLBackend; + } +} + class OpenGLDisplayPlugin : public DisplayPlugin { Q_OBJECT Q_PROPERTY(float overlayAlpha MEMBER _overlayAlpha) @@ -37,8 +43,6 @@ public: // between the main thread and the presentation thread bool activate() override final; void deactivate() override final; - bool isRenderThread() const override final; - bool eventFilter(QObject* receiver, QEvent* event) override; bool isDisplayVisible() const override { return true; } @@ -139,6 +143,7 @@ protected: f(); } + gpu::gl::GLBackend* getGLBackend(); private: // Any resource shared by the main thread and the presentation thread must // be serialized through this mutex diff --git a/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.cpp new file mode 100644 index 0000000000..2ec1507fdd --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.cpp @@ -0,0 +1,76 @@ +// +// Created by Bradley Austin Davis on 2016/07/31 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "DebugHmdDisplayPlugin.h" + +#include +#include +#include + +const QString DebugHmdDisplayPlugin::NAME("HMD Simulator"); + +static const QString DEBUG_FLAG("HIFI_DEBUG_HMD"); + +bool DebugHmdDisplayPlugin::isSupported() const { + // FIXME use the env variable + return true; +} + +void DebugHmdDisplayPlugin::resetSensors() { + _currentRenderFrameInfo.renderPose = glm::mat4(); // identity +} + +bool DebugHmdDisplayPlugin::beginFrameRender(uint32_t frameIndex) { + _currentRenderFrameInfo = FrameInfo(); + _currentRenderFrameInfo.sensorSampleTime = secTimestampNow(); + _currentRenderFrameInfo.predictedDisplayTime = _currentRenderFrameInfo.sensorSampleTime; + // FIXME simulate head movement + //_currentRenderFrameInfo.renderPose = ; + //_currentRenderFrameInfo.presentPose = _currentRenderFrameInfo.renderPose; + + withNonPresentThreadLock([&] { + _uiModelTransform = DependencyManager::get()->getModelTransform(); + _frameInfos[frameIndex] = _currentRenderFrameInfo; + }); + return Parent::beginFrameRender(frameIndex); +} + +// DLL based display plugins MUST initialize GLEW inside the DLL code. +void DebugHmdDisplayPlugin::customizeContext() { + glewExperimental = true; + GLenum err = glewInit(); + glGetError(); // clear the potential error from glewExperimental + Parent::customizeContext(); +} + +bool DebugHmdDisplayPlugin::internalActivate() { + _ipd = 0.0327499993f * 2.0f; + _eyeProjections[0][0] = vec4{ 0.759056330, 0.000000000, 0.000000000, 0.000000000 }; + _eyeProjections[0][1] = vec4{ 0.000000000, 0.682773232, 0.000000000, 0.000000000 }; + _eyeProjections[0][2] = vec4{ -0.0580431037, -0.00619550655, -1.00000489, -1.00000000 }; + _eyeProjections[0][3] = vec4{ 0.000000000, 0.000000000, -0.0800003856, 0.000000000 }; + _eyeProjections[1][0] = vec4{ 0.752847493, 0.000000000, 0.000000000, 0.000000000 }; + _eyeProjections[1][1] = vec4{ 0.000000000, 0.678060353, 0.000000000, 0.000000000 }; + _eyeProjections[1][2] = vec4{ 0.0578232110, -0.00669418881, -1.00000489, -1.000000000 }; + _eyeProjections[1][3] = vec4{ 0.000000000, 0.000000000, -0.0800003856, 0.000000000 }; + _eyeInverseProjections[0] = glm::inverse(_eyeProjections[0]); + _eyeInverseProjections[1] = glm::inverse(_eyeProjections[1]); + _eyeOffsets[0][3] = vec4{ -0.0327499993, 0.0, 0.0149999997, 1.0 }; + _eyeOffsets[0][3] = vec4{ 0.0327499993, 0.0, 0.0149999997, 1.0 }; + _renderTargetSize = { 3024, 1680 }; + _cullingProjection = _eyeProjections[0]; + // This must come after the initialization, so that the values calculated + // above are available during the customizeContext call (when not running + // in threaded present mode) + return Parent::internalActivate(); +} + +void DebugHmdDisplayPlugin::updatePresentPose() { +// if (usecTimestampNow() % 4000000 > 2000000) { + _currentPresentFrameInfo.presentPose = glm::mat4_cast(glm::angleAxis(0.5f, Vectors::UP)); +// } +} diff --git a/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.h new file mode 100644 index 0000000000..509e13eda7 --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/hmd/DebugHmdDisplayPlugin.h @@ -0,0 +1,33 @@ +// +// Created by Bradley Austin Davis on 2016/07/31 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#pragma once + +#include "HmdDisplayPlugin.h" + +class DebugHmdDisplayPlugin : public HmdDisplayPlugin { + using Parent = HmdDisplayPlugin; + +public: + const QString& getName() const override { return NAME; } + grouping getGrouping() const override { return DEVELOPER; } + + bool isSupported() const override; + void resetSensors() override final; + bool beginFrameRender(uint32_t frameIndex) override; + float getTargetFrameRate() const override { return 90; } + + +protected: + void updatePresentPose() override; + void hmdPresent() override {} + bool isHmdMounted() const override { return true; } + void customizeContext() override; + bool internalActivate() override; +private: + static const QString NAME; +}; diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp index b8b2638f6f..00b5a66960 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.cpp @@ -5,6 +5,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // + #include "HmdDisplayPlugin.h" #include @@ -25,13 +26,16 @@ #include #include +#include #include #include +#include "hmd_reproject_vert.h" +#include "hmd_reproject_frag.h" + #include "../Logging.h" #include "../CompositorHelper.h" - static const QString MONO_PREVIEW = "Mono Preview"; static const QString REPROJECTION = "Allow Reprojection"; static const QString FRAMERATE = DisplayPlugin::MENU_PATH() + ">Framerate"; @@ -41,6 +45,7 @@ static const int NUMBER_OF_HANDS = 2; static const glm::mat4 IDENTITY_MATRIX; //#define LIVE_SHADER_RELOAD 1 +extern glm::vec3 getPoint(float yaw, float pitch); static QString readFile(const QString& filename) { QFile file(filename); @@ -103,10 +108,36 @@ void HmdDisplayPlugin::internalDeactivate() { Parent::internalDeactivate(); } -extern glm::vec3 getPoint(float yaw, float pitch); +void HmdDisplayPlugin::customizeContext() { + Parent::customizeContext(); + // Only enable mirroring if we know vsync is disabled + // On Mac, this won't work due to how the contexts are handled, so don't try +#if !defined(Q_OS_MAC) + enableVsync(false); +#endif + _enablePreview = !isVsyncEnabled(); + _overlay.build(); +#if 0 + updateReprojectionProgram(); + updateLaserProgram(); + _laserGeometry = loadLaser(_laserProgram); +#endif -void flushBuffer(const gpu::BufferPointer& buffer) { - buffer->applyUpdate(buffer->getUpdate()); + _compositeFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create(gpu::Element::COLOR_SRGBA_32, _renderTargetSize.x, _renderTargetSize.y)); + _compositeTexture = _compositeFramebuffer->getRenderBuffer(0); +} + +void HmdDisplayPlugin::uncustomizeContext() { +#if 0 + _overlayProgram.reset(); + _sphereSection.reset(); + _compositeFramebuffer.reset(); + _previewProgram.reset(); + _reprojectionProgram.reset(); + _laserProgram.reset(); + _laserGeometry.reset(); +#endif + Parent::uncustomizeContext(); } void HmdDisplayPlugin::OverlayRender::build() { @@ -137,7 +168,7 @@ void HmdDisplayPlugin::OverlayRender::build() { vertices->append(sizeof(Vertex), (gpu::Byte*)&vertex); } } - flushBuffer(vertices); + vertices->flush(); // Compute number of indices needed static const int VERTEX_PER_TRANGLE = 3; @@ -164,7 +195,7 @@ void HmdDisplayPlugin::OverlayRender::build() { } } this->indices->append(indices); - flushBuffer(this->indices); + this->indices->flush(); format = std::make_shared(); // 1 for everyone format->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); format->setAttribute(gpu::Stream::TEXCOORD, gpu::Stream::TEXCOORD, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV)); @@ -206,13 +237,13 @@ void HmdDisplayPlugin::OverlayRender::updatePipeline() { pipeline = gpu::Pipeline::create(program, state); } - } +} -void HmdDisplayPlugin::OverlayRender::render() { +void HmdDisplayPlugin::OverlayRender::render(HmdDisplayPlugin& plugin) { for_each_eye([&](Eye eye){ uniforms.mvp = mvps[eye]; uniformBuffers[eye]->setSubData(0, uniforms); - flushBuffer(uniformBuffers[eye]); + uniformBuffers[eye]->flush(); }); gpu::Batch batch; batch.enableStereo(false); @@ -233,22 +264,6 @@ void HmdDisplayPlugin::OverlayRender::render() { plugin._backend->render(batch); } -void HmdDisplayPlugin::customizeContext() { - Parent::customizeContext(); - // Only enable mirroring if we know vsync is disabled - // On Mac, this won't work due to how the contexts are handled, so don't try -#if !defined(Q_OS_MAC) - enableVsync(false); -#endif - _enablePreview = !isVsyncEnabled(); - _overlay.build(); -#if 0 - updateReprojectionProgram(); - updateLaserProgram(); - _laserGeometry = loadLaser(_laserProgram); -#endif -} - #if 0 void HmdDisplayPlugin::updateReprojectionProgram() { static const QString vsFile = PathUtils::resourcesPath() + "/shaders/hmd_reproject.vert"; @@ -328,54 +343,145 @@ void HmdDisplayPlugin::updateLaserProgram() { #endif } -void HmdDisplayPlugin::uncustomizeContext() { -#if 0 - _overlayProgram.reset(); - _sphereSection.reset(); - _compositeFramebuffer.reset(); - _previewProgram.reset(); - _reprojectionProgram.reset(); - _laserProgram.reset(); - _laserGeometry.reset(); -#endif - Parent::uncustomizeContext(); -} - // By default assume we'll present with the same pose as the render void HmdDisplayPlugin::updatePresentPose() { _currentPresentFrameInfo.presentPose = _currentPresentFrameInfo.renderPose; } -void HmdDisplayPlugin::compositeScene() { - updatePresentPose(); +//static const std::string HMD_REPROJECT_FRAG = R"SHADER( +// +//in vec2 varTexCoord0; +// +//out vec4 outFragColor; +// +//uniform sampler2D sampler; +// +//void main() { +// vec2 uv = varTexCoord0; +// outFragColor = texture(sampler, uv); // vec4(varTexCoord0, 0.0, 1.0); +//} +// +//)SHADER"; +void HmdDisplayPlugin::SceneRenderer::build() { + static const QString vsFile = "C:/Users/bdavis/Git/hifi/interface/resources/shaders/hmd_reproject.vert"; + static const QString fsFile = "C:/Users/bdavis/Git/hifi/interface/resources/shaders/hmd_reproject.frag"; - if (!_enableReprojection || glm::mat3() == _currentPresentFrameInfo.presentReprojection) { - // No reprojection required - Parent::compositeScene(); - return; +#if 1 //LIVE_SHADER_RELOAD + static qint64 vsBuiltAge = 0; + static qint64 fsBuiltAge = 0; + QFileInfo vsInfo(vsFile); + QFileInfo fsInfo(fsFile); + auto vsAge = vsInfo.lastModified().toMSecsSinceEpoch(); + auto fsAge = fsInfo.lastModified().toMSecsSinceEpoch(); + if (!pipeline || vsAge > vsBuiltAge || fsAge > fsBuiltAge) { + vsBuiltAge = vsAge; + fsBuiltAge = fsAge; +#else + if (!pipeline) { +#endif + QString vsSource = readFile(vsFile); + QString fsSource = readFile(fsFile); + auto vs = gpu::Shader::createVertex(vsSource.toLocal8Bit().toStdString()); + auto ps = gpu::Shader::createPixel(fsSource.toLocal8Bit().toStdString()); + gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps); + gpu::gl::GLBackend::makeProgram(*program); + uniformsLocation = program->getBuffers().findLocation("reprojectionBuffer"); + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + state->setDepthTest(gpu::State::DepthTest(false)); + pipeline = gpu::Pipeline::create(program, state); } -#ifdef DEBUG_REPROJECTION_SHADER - _reprojectionProgram = getReprojectionProgram(); -#endif -#if 0 - useProgram(_reprojectionProgram); + if (!uniformBuffer) { + uniformBuffer = std::make_shared(sizeof(Uniforms), nullptr); + } - using namespace oglplus; - Texture::MinFilter(TextureTarget::_2D, TextureMinFilter::Linear); - Texture::MagFilter(TextureTarget::_2D, TextureMagFilter::Linear); - Uniform(*_reprojectionProgram, _reprojectionUniforms.reprojectionMatrix).Set(_currentPresentFrameInfo.presentReprojection); - //Uniform(*_reprojectionProgram, PROJECTION_MATRIX_LOCATION).Set(_eyeProjections); - //Uniform(*_reprojectionProgram, INVERSE_PROJECTION_MATRIX_LOCATION).Set(_eyeInverseProjections); - // FIXME what's the right oglplus mechanism to do this? It's not that ^^^ ... better yet, switch to a uniform buffer - glUniformMatrix4fv(_reprojectionUniforms.inverseProjectionMatrix, 2, GL_FALSE, &(_eyeInverseProjections[0][0][0])); - glUniformMatrix4fv(_reprojectionUniforms.projectionMatrix, 2, GL_FALSE, &(_eyeProjections[0][0][0])); - _plane->UseInProgram(*_reprojectionProgram); - _plane->Draw(); -#endif + if (!vertices) { + static const uint16_t stacks = 128; + static const uint16_t slices = 64; + static const vec3 increment = vec3(1) / vec3(slices, stacks, 1); + std::vector vertexBuffer; + vertexCount = stacks * slices * 3 * 2; + for (size_t x = 0; x < slices; ++x) { + for (size_t y = 0; y < stacks; ++y) { + vertexBuffer.push_back(vec3(x, y + 1, 0) * increment); + vertexBuffer.push_back(vec3(x, y, 0) * increment); + vertexBuffer.push_back(vec3(x + 1, y + 1, 0) * increment); + + vertexBuffer.push_back(vec3(x + 1, y + 1, 0) * increment); + vertexBuffer.push_back(vec3(x, y, 0) * increment); + vertexBuffer.push_back(vec3(x + 1, y, 0) * increment); + } + } + vertices = std::make_shared(); + vertices->setData(sizeof(vec3) * vertexBuffer.size(), (gpu::Byte*)vertexBuffer.data()); + vertices->flush(); + format = std::make_shared(); + format->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); + } +} + +void HmdDisplayPlugin::SceneRenderer::update(const glm::mat4& rotation) { + build(); + { + uniforms.rotation = mat4(); + float correctionMagnitude = glm::angle(glm::quat_cast(rotation)); + if (correctionMagnitude > 0.001f) { + uniforms.rotation = rotation; + } + static size_t i = 0; + if (0 == (++i % 10)) { + qDebug() << "Correction angle size " << correctionMagnitude; + } + } + uniformBuffer->setSubData(0, uniforms); + uniformBuffer->flush(); +} + +void HmdDisplayPlugin::SceneRenderer::render(gpu::Batch& batch) { + if (pipeline) { + batch.setPipeline(pipeline); + batch.setInputFormat(format); + batch.setInputBuffer(gpu::Stream::POSITION, + gpu::BufferView(vertices, 0, vertices->getSize(), sizeof(vec3), format->getAttributes().at(gpu::Stream::POSITION)._element)); + batch.draw(gpu::TRIANGLES, vertexCount); + } +} + + +void HmdDisplayPlugin::compositeScene() { + { + auto batchPose = glm::dmat3(glm::mat3(_currentFrame->pose)); + auto currentPose = glm::dmat3(glm::mat3(_currentPresentFrameInfo.presentPose)); + auto correction = glm::inverse(batchPose) * currentPose; + _sceneRenderer.update(glm::mat4(glm::dmat4(correction))); + } + + { + gpu::Batch batch; + batch.enableStereo(false); + batch.setViewportTransform(ivec4(uvec2(), _renderTargetSize)); + batch.setFramebuffer(_compositeFramebuffer); + batch.clearColorFramebuffer(gpu::Framebuffer::BUFFER_COLOR0, glm::vec4(1, 1, 0, 1)); + _backend->render(batch); + } + + { + gpu::Batch batch; + if (_sceneRenderer.uniformsLocation >= 0) { + batch.setUniformBuffer(_sceneRenderer.uniformsLocation, _sceneRenderer.uniformBuffer); + } + batch.setViewportTransform(ivec4(uvec2(), _renderTargetSize)); + batch.setViewTransform(Transform()); + batch.setProjectionTransform(mat4()); + batch.setFramebuffer(_compositeFramebuffer); + batch.setResourceTexture(0, _currentFrame->framebuffer->getRenderBuffer(0)); + _sceneRenderer.render(batch); + _backend->render(batch); + } } void HmdDisplayPlugin::compositeOverlay() { +#if 0 if (!_currentFrame) { return; } @@ -455,9 +561,11 @@ void HmdDisplayPlugin::compositeOverlay() { _overlay.uniforms.glowColors[1] = _presentHandLasers[1].color; } _overlay.render(); +#endif } void HmdDisplayPlugin::compositePointer() { +#if 0 auto& cursorManager = Cursor::Manager::instance(); const auto& cursorData = _cursorsData[cursorManager.getCursor()->getIcon()]; auto compositorHelper = DependencyManager::get(); @@ -469,7 +577,7 @@ void HmdDisplayPlugin::compositePointer() { batch.setFramebuffer(_currentFrame->framebuffer); batch.setPipeline(_cursorPipeline); batch.setResourceTexture(0, cursorData.texture); - batch.setViewTransform(Transform()); + batch.clearViewTransform(); for_each_eye([&](Eye eye) { auto eyePose = _currentPresentFrameInfo.presentPose * getEyeToHeadTransform(eye); auto reticleTransform = compositorHelper->getReticleTransform(eyePose, headPosition); @@ -479,15 +587,16 @@ void HmdDisplayPlugin::compositePointer() { batch.draw(gpu::TRIANGLE_STRIP, 4); }); _backend->render(batch); +#endif } void HmdDisplayPlugin::internalPresent() { - PROFILE_RANGE_EX(__FUNCTION__, 0xff00ff00, (uint64_t)presentCount()) // Composite together the scene, overlay and mouse cursor hmdPresent(); + /* // screen preview mirroring auto window = _container->getPrimaryWidget(); auto devicePixelRatio = window->devicePixelRatio(); @@ -513,20 +622,19 @@ void HmdDisplayPlugin::internalPresent() { } else if (targetViewportSize.y < windowSize.y) { targetViewportPosition.y = (windowSize.y - targetViewportSize.y) / 2; } - + */ if (_enablePreview) { - Parent::internalPresent(); - //gpu::Batch presentBatch; - //presentBatch.enableStereo(false); - //presentBatch.setViewTransform(Transform()); - //presentBatch.setFramebuffer(gpu::FramebufferPointer()); - //presentBatch.setViewportTransform(ivec4(targetViewportPosition, targetViewportSize)); - //presentBatch.setResourceTexture(0, _currentFrame->framebuffer->getRenderBuffer(0)); - //presentBatch.setPipeline(_presentPipeline); - //presentBatch.draw(gpu::TRIANGLE_STRIP, 4); - //_backend->render(presentBatch); - //swapBuffers(); + gpu::Batch presentBatch; + presentBatch.enableStereo(false); + presentBatch.setViewTransform(Transform()); + presentBatch.setFramebuffer(gpu::FramebufferPointer()); + presentBatch.setViewportTransform(ivec4(uvec2(0), getSurfacePixels())); + presentBatch.setResourceTexture(0, _compositeTexture); + presentBatch.setPipeline(_presentPipeline); + presentBatch.draw(gpu::TRIANGLE_STRIP, 4); + _backend->render(presentBatch); + swapBuffers(); } postPreview(); @@ -553,6 +661,8 @@ void HmdDisplayPlugin::updateFrameData() { } }); } + + updatePresentPose(); } glm::mat4 HmdDisplayPlugin::getHeadPose() const { diff --git a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h index aad1fa061e..a4bff0e369 100644 --- a/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/hmd/HmdDisplayPlugin.h @@ -23,7 +23,6 @@ class HmdDisplayPlugin : public OpenGLDisplayPlugin { using Parent = OpenGLDisplayPlugin; public: - HmdDisplayPlugin() : _overlay( *this ) {} bool isHmd() const override final { return true; } float getIPD() const override final { return _ipd; } glm::mat4 getEyeToHeadTransform(Eye eye) const override final { return _eyeOffsets[eye]; } @@ -67,9 +66,6 @@ protected: } }; - - - Transform _uiModelTransform; std::array _handLasers; std::array _handPoses; @@ -87,9 +83,7 @@ protected: float _ipd { 0.064f }; struct FrameInfo { - glm::mat4 rawRenderPose; glm::mat4 renderPose; - glm::mat4 rawPresentPose; glm::mat4 presentPose; double sensorSampleTime { 0 }; double predictedDisplayTime { 0 }; @@ -99,6 +93,8 @@ protected: QMap _frameInfos; FrameInfo _currentPresentFrameInfo; FrameInfo _currentRenderFrameInfo; + gpu::FramebufferPointer _compositeFramebuffer; + gpu::TexturePointer _compositeTexture; private: void updateLaserProgram(); @@ -113,10 +109,24 @@ private: glm::uvec2 _prevWindowSize { 0, 0 }; qreal _prevDevicePixelRatio { 0 }; + struct SceneRenderer { + int32_t uniformsLocation{ -1 }; + uint32_t vertexCount; + struct Uniforms { + mat4 rotation; + } uniforms; + + gpu::Stream::FormatPointer format; + gpu::BufferPointer vertices; + gpu::PipelinePointer pipeline; + gpu::BufferPointer uniformBuffer; + + void build(); + void update(const glm::mat4& rotation); + void render(gpu::Batch& batch); + } _sceneRenderer; struct OverlayRender { - OverlayRender(HmdDisplayPlugin& plugin) : plugin(plugin) {}; - HmdDisplayPlugin& plugin; gpu::Stream::FormatPointer format; gpu::BufferPointer vertices; gpu::BufferPointer indices; @@ -148,7 +158,7 @@ private: void build(); void updatePipeline(); - void render(); + void render(HmdDisplayPlugin& plugin); } _overlay; #if 0 ProgramPtr _previewProgram; diff --git a/libraries/display-plugins/src/hmd_hand_lasers.slf b/libraries/display-plugins/src/hmd_hand_lasers.slf new file mode 100644 index 0000000000..6fffb1c521 --- /dev/null +++ b/libraries/display-plugins/src/hmd_hand_lasers.slf @@ -0,0 +1,35 @@ +// +// 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 +// + +#version 410 core + +uniform vec4 color = vec4(1.0, 1.0, 1.0, 1.0); + +layout(location = 0) in vec3 inLineDistance; + +out vec4 FragColor; + +void main() { + vec2 d = inLineDistance.xy; + d.y = abs(d.y); + d.x = abs(d.x); + if (d.x > 1.0) { + d.x = (d.x - 1.0) / 0.02; + } else { + d.x = 0.0; + } + float alpha = 1.0 - length(d); + if (alpha <= 0.0) { + discard; + } + alpha = pow(alpha, 10.0); + if (alpha < 0.05) { + discard; + } + FragColor = vec4(color.rgb, alpha); +} diff --git a/libraries/display-plugins/src/hmd_hand_lasers.slg b/libraries/display-plugins/src/hmd_hand_lasers.slg new file mode 100644 index 0000000000..16b5dafadd --- /dev/null +++ b/libraries/display-plugins/src/hmd_hand_lasers.slg @@ -0,0 +1,70 @@ +// +// 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 +// +#version 410 core +#extension GL_EXT_geometry_shader4 : enable + +layout(location = 0) out vec3 outLineDistance; + +layout(lines) in; +layout(triangle_strip, max_vertices = 24) out; + +vec3[2] getOrthogonals(in vec3 n, float scale) { + float yDot = abs(dot(n, vec3(0, 1, 0))); + + vec3 result[2]; + if (yDot < 0.9) { + result[0] = normalize(cross(n, vec3(0, 1, 0))); + } else { + result[0] = normalize(cross(n, vec3(1, 0, 0))); + } + // The cross of result[0] and n is orthogonal to both, which are orthogonal to each other + result[1] = cross(result[0], n); + result[0] *= scale; + result[1] *= scale; + return result; +} + + +vec2 orthogonal(vec2 v) { + vec2 result = v.yx; + result.y *= -1.0; + return result; +} + +void main() { + vec2 endpoints[2]; + for (int i = 0; i < 2; ++i) { + endpoints[i] = gl_PositionIn[i].xy / gl_PositionIn[i].w; + } + vec2 lineNormal = normalize(endpoints[1] - endpoints[0]); + vec2 lineOrthogonal = orthogonal(lineNormal); + lineNormal *= 0.02; + lineOrthogonal *= 0.02; + + gl_Position = gl_PositionIn[0]; + gl_Position.xy -= lineOrthogonal; + outLineDistance = vec3(-1.02, -1, gl_Position.z); + EmitVertex(); + + gl_Position = gl_PositionIn[0]; + gl_Position.xy += lineOrthogonal; + outLineDistance = vec3(-1.02, 1, gl_Position.z); + EmitVertex(); + + gl_Position = gl_PositionIn[1]; + gl_Position.xy -= lineOrthogonal; + outLineDistance = vec3(1.02, -1, gl_Position.z); + EmitVertex(); + + gl_Position = gl_PositionIn[1]; + gl_Position.xy += lineOrthogonal; + outLineDistance = vec3(1.02, 1, gl_Position.z); + EmitVertex(); + + EndPrimitive(); +} diff --git a/libraries/display-plugins/src/hmd_hand_lasers.slv b/libraries/display-plugins/src/hmd_hand_lasers.slv new file mode 100644 index 0000000000..6edb964b66 --- /dev/null +++ b/libraries/display-plugins/src/hmd_hand_lasers.slv @@ -0,0 +1,13 @@ +// +// 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 +// + +in vec3 Position; + +void main() { + gl_Position = mvp * vec4(Position, 1); +} diff --git a/libraries/display-plugins/src/hmd_reproject.slf b/libraries/display-plugins/src/hmd_reproject.slf new file mode 100644 index 0000000000..1a1233fd34 --- /dev/null +++ b/libraries/display-plugins/src/hmd_reproject.slf @@ -0,0 +1,109 @@ +// +// 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 +// + +struct ReprojectionData { + mat4 projections[2]; + mat4 inverseProjections[2]; + mat4 rotation; +}; + +layout(std140) uniform reprojectionBuffer { + ReprojectionData reprojection; +}; + +in vec2 varTexCoord0; + +out vec4 outFragColor; + +uniform sampler2D sampler; + +vec4 toNdcSpaceFromUv(vec2 uv) { + vec4 result = vec4(uv, 0.0, 1.0); + result.xy *= 2.0; + result.xy -= 1.0; + return result; +} + +vec4 toNdcSpaceFromStereoUv(vec2 uv) { + if (uv.x >= 0.5) { + uv.x -= 0.5; + } + uv.x *= 2.0; + return toNdcSpaceFromUv(uv); +} + +vec2 toUvFromNdcSpace(vec4 ndc) { + ndc /= ndc.w; + vec2 result = ndc.xy; + result += 1.0; + result /= 2.0; + return result; +} + +void main() { + vec2 uv = varTexCoord0; + + mat4 eyeInverseProjection; + mat4 eyeProjection; + + vec2 uvmin = vec2(0.0); + vec2 uvmax = vec2(1.0); + + // determine the correct projection and inverse projection to use. + if (uv.x < 0.5) { + uvmax.x = 0.5; + eyeInverseProjection = reprojection.inverseProjections[0]; + eyeProjection = reprojection.projections[0]; + } else { + uvmin.x = 0.5; + uvmax.x = 1.0; + eyeInverseProjection = reprojection.inverseProjections[1]; + eyeProjection = reprojection.projections[1]; + } + + // Account for stereo in calculating the per-eye NDC coordinates + vec4 ndcSpace = toNdcSpaceFromStereoUv(varTexCoord0); + + // Convert from NDC to eyespace + vec4 eyeSpace = eyeInverseProjection * ndcSpace; + eyeSpace /= eyeSpace.w; + + // Convert to a noramlized ray + vec3 ray = eyeSpace.xyz; + ray = normalize(ray); + + // Adjust the ray by the rotation + vec4 ray4 = reprojection.rotation * vec4(ray, 1.0); + ray4 /= ray4.w; + ray = ray4.xyz; + + // Project back on to the texture plane + ray *= eyeSpace.z / ray.z; + + // Update the eyespace vector + eyeSpace.xyz = ray; + + // Reproject back into NDC + ndcSpace = eyeProjection * eyeSpace; + + // Calculate the new UV coordinates + if (uv.x >= 0.5) { + uv = toUvFromNdcSpace(ndcSpace); + uv.x += 1.0; + } else { + uv = toUvFromNdcSpace(ndcSpace); + } + uv.x /= 2.0; + + if (any(greaterThan(uv, uvmax)) || any(lessThan(uv, uvmin))) { + outFragColor = vec4(0.0, 0.0, 0.0, 1.0); + } else { + outFragColor = texture(sampler, uv); + } +} + diff --git a/libraries/display-plugins/src/hmd_reproject.slv b/libraries/display-plugins/src/hmd_reproject.slv new file mode 100644 index 0000000000..2487514d4d --- /dev/null +++ b/libraries/display-plugins/src/hmd_reproject.slv @@ -0,0 +1,18 @@ +// +// 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 +// + +<@include gpu/Inputs.slh@> + +layout(location = 0) out vec3 outPosition; +layout(location = 1) out vec2 outTexCoord; + +void main() { + outTexCoord = TexCoord; + outPosition = Position; + gl_Position = vec4(Position, 1); +} diff --git a/libraries/display-plugins/src/hmd_ui_glow.slf b/libraries/display-plugins/src/hmd_ui_glow.slf new file mode 100644 index 0000000000..9270842092 --- /dev/null +++ b/libraries/display-plugins/src/hmd_ui_glow.slf @@ -0,0 +1,75 @@ +// +// 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; +}; + +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; + +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 dist = min(dist1, dist2); + vec3 glowColor = glowColors[0].rgb; + if (dist2 < dist1) { + glowColor = glowColors[1].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/libraries/display-plugins/src/hmd_ui_glow.slv b/libraries/display-plugins/src/hmd_ui_glow.slv new file mode 100644 index 0000000000..54eb062590 --- /dev/null +++ b/libraries/display-plugins/src/hmd_ui_glow.slv @@ -0,0 +1,32 @@ +// +// 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 +// + +struct OverlayData { + mat4 mvp; + vec4 glowPoints; + vec4 glowColors[2]; + vec4 resolutionRadiusAlpha; +}; + +layout(std140) uniform overlayBuffer { + OverlayData overlay; +}; + +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/libraries/gpu-gl/src/gpu/gl/GLBackend.h b/libraries/gpu-gl/src/gpu/gl/GLBackend.h index 2f77425f1e..ecfe7ed0f6 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gl/src/gpu/gl/GLBackend.h @@ -161,6 +161,7 @@ public: virtual void do_setStateScissorRect(Batch& batch, size_t paramOffset) final; virtual GLuint getFramebufferID(const FramebufferPointer& framebuffer) = 0; + virtual GLuint getTextureID(const TexturePointer& texture, bool needTransfer = true) = 0; protected: @@ -169,7 +170,6 @@ protected: virtual GLuint getBufferID(const Buffer& buffer) = 0; virtual GLBuffer* syncGPUObject(const Buffer& buffer) = 0; - virtual GLuint getTextureID(const TexturePointer& texture, bool needTransfer = true) = 0; virtual GLTexture* syncGPUObject(const TexturePointer& texture, bool sync = true) = 0; virtual GLuint getQueryID(const QueryPointer& query) = 0; diff --git a/libraries/gpu-gl/src/gpu/gl/GLTexture.h b/libraries/gpu-gl/src/gpu/gl/GLTexture.h index df2d38e2f3..c0b06782ad 100644 --- a/libraries/gpu-gl/src/gpu/gl/GLTexture.h +++ b/libraries/gpu-gl/src/gpu/gl/GLTexture.h @@ -92,11 +92,13 @@ public: GLuint result = object->_id; // Don't return textures that are in transfer state - if ((object->getSyncState() != GLSyncState::Idle) || - // Don't return transferrable textures that have never completed transfer - (!object->_transferrable || 0 != object->_transferCount)) { - // Will be either 0 or the original texture being downsampled. - result = object->_downsampleSource._texture; + if (shouldSync) { + if ((object->getSyncState() != GLSyncState::Idle) || + // Don't return transferrable textures that have never completed transfer + (!object->_transferrable || 0 != object->_transferCount)) { + // Will be either 0 or the original texture being downsampled. + result = object->_downsampleSource._texture; + } } return result; diff --git a/libraries/plugins/src/plugins/DisplayPlugin.h b/libraries/plugins/src/plugins/DisplayPlugin.h index 004407c821..414860f2bd 100644 --- a/libraries/plugins/src/plugins/DisplayPlugin.h +++ b/libraries/plugins/src/plugins/DisplayPlugin.h @@ -128,7 +128,6 @@ public: Present = QEvent::User + 1 }; - virtual bool isRenderThread() const { return false; } virtual bool isHmd() const { return false; } virtual int getHmdScreen() const { return -1; } /// By default, all HMDs are stereo diff --git a/libraries/shared/src/shared/NsightHelpers.cpp b/libraries/shared/src/shared/NsightHelpers.cpp index 3292205c1f..ef31ef5f0f 100644 --- a/libraries/shared/src/shared/NsightHelpers.cpp +++ b/libraries/shared/src/shared/NsightHelpers.cpp @@ -14,7 +14,11 @@ #include #include -extern bool isRenderThread(); +QThread* RENDER_THREAD = nullptr; + +bool isRenderThread() { + return QThread::currentThread() == RENDER_THREAD; +} ProfileRange::ProfileRange(const char *name) { if (!isRenderThread()) { diff --git a/libraries/shared/src/shared/NsightHelpers.h b/libraries/shared/src/shared/NsightHelpers.h index c637c78162..e1ac444ed2 100644 --- a/libraries/shared/src/shared/NsightHelpers.h +++ b/libraries/shared/src/shared/NsightHelpers.h @@ -12,6 +12,11 @@ #ifdef _WIN32 #include +#include + +extern QThread* RENDER_THREAD; +extern bool isRenderThread(); + class ProfileRange { public: ProfileRange(const char *name); diff --git a/libraries/ui-plugins/src/ui-plugins/PluginContainer.cpp b/libraries/ui-plugins/src/ui-plugins/PluginContainer.cpp index 6ae4d07a25..6d54351743 100644 --- a/libraries/ui-plugins/src/ui-plugins/PluginContainer.cpp +++ b/libraries/ui-plugins/src/ui-plugins/PluginContainer.cpp @@ -161,10 +161,3 @@ void PluginContainer::setBoolSetting(const QString& settingName, bool value) { Setting::Handle settingValue(settingName, value); return settingValue.set(value); } - -bool isRenderThread() { - return QThread::currentThread() != qApp->thread(); - // FIXME causes a deadlock on switching display plugins - auto displayPlugin = PluginContainer::getInstance().getActiveDisplayPlugin(); - return displayPlugin && displayPlugin->isRenderThread(); -} \ No newline at end of file diff --git a/plugins/oculus/src/OculusDebugDisplayPlugin.cpp b/plugins/oculus/src/OculusDebugDisplayPlugin.cpp index 7653fba764..f1d22f3ceb 100644 --- a/plugins/oculus/src/OculusDebugDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusDebugDisplayPlugin.cpp @@ -11,7 +11,7 @@ const QString OculusDebugDisplayPlugin::NAME("Oculus Rift (Simulator)"); static const QString DEBUG_FLAG("HIFI_DEBUG_OCULUS"); -static bool enableDebugOculus = QProcessEnvironment::systemEnvironment().contains("HIFI_DEBUG_OCULUS"); +static bool enableDebugOculus = true || QProcessEnvironment::systemEnvironment().contains("HIFI_DEBUG_OCULUS"); bool OculusDebugDisplayPlugin::isSupported() const { if (!enableDebugOculus) { diff --git a/plugins/oculus/src/OculusDisplayPlugin.cpp b/plugins/oculus/src/OculusDisplayPlugin.cpp index 24553ba494..da8297d54f 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusDisplayPlugin.cpp @@ -110,8 +110,7 @@ void OculusDisplayPlugin::hmdPresent() { PROFILE_RANGE_EX(__FUNCTION__, 0xff00ff00, (uint64_t)_currentFrame->frameIndex) // Manually bind the texture to the FBO - auto& glBackend = dynamic_cast(*_backend); - auto fbo = glBackend.getFramebufferID(_outputFramebuffer); + auto fbo = getGLBackend()->getFramebufferID(_outputFramebuffer); { int curIndex; ovr_GetTextureSwapChainCurrentIndex(_session, _textureSwapChain, &curIndex); diff --git a/plugins/openvr/CMakeLists.txt b/plugins/openvr/CMakeLists.txt index 8b0230d850..79bfd91068 100644 --- a/plugins/openvr/CMakeLists.txt +++ b/plugins/openvr/CMakeLists.txt @@ -6,7 +6,6 @@ # See the accompanying file LICENSE or http:#www.apache.org/licenses/LICENSE-2.0.html # -if (FALSE) if (WIN32) # we're using static GLEW, so define GLEW_STATIC add_definitions(-DGLEW_STATIC) @@ -14,7 +13,7 @@ if (WIN32) setup_hifi_plugin(OpenGL Script Qml Widgets) link_hifi_libraries(shared gl networking controllers ui plugins display-plugins ui-plugins input-plugins script-engine - render-utils model gpu render model-networking fbx) + render-utils model gpu gpu-gl render model-networking fbx) include_hifi_library_headers(octree) @@ -23,4 +22,3 @@ if (WIN32) target_include_directories(${TARGET_NAME} PRIVATE ${OPENVR_INCLUDE_DIRS}) target_link_libraries(${TARGET_NAME} ${OPENVR_LIBRARIES}) endif() -endif() \ No newline at end of file diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index a532261014..4f653ff806 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -18,6 +18,9 @@ #include #include +#include +#include + #include #include #include @@ -32,16 +35,15 @@ const QString OpenVrDisplayPlugin::NAME("OpenVR (Vive)"); const QString StandingHMDSensorMode = "Standing HMD Sensor Mode"; // this probably shouldn't be hardcoded here static vr::IVRCompositor* _compositor { nullptr }; -vr::TrackedDevicePose_t _trackedDevicePose[vr::k_unMaxTrackedDeviceCount]; -mat4 _trackedDevicePoseMat4[vr::k_unMaxTrackedDeviceCount]; -vec3 _trackedDeviceLinearVelocities[vr::k_unMaxTrackedDeviceCount]; -vec3 _trackedDeviceAngularVelocities[vr::k_unMaxTrackedDeviceCount]; +PoseData _nextRenderPoseData; +PoseData _nextSimPoseData; static mat4 _sensorResetMat; static std::array VR_EYES { { vr::Eye_Left, vr::Eye_Right } }; bool _openVrDisplayActive { false }; + bool OpenVrDisplayPlugin::isSupported() const { return openVrSupported(); } @@ -82,7 +84,7 @@ bool OpenVrDisplayPlugin::internalActivate() { // left + right eyes _renderTargetSize.x *= 2; - withRenderThreadLock([&] { + withNonPresentThreadLock([&] { openvr_for_each_eye([&](vr::Hmd_Eye eye) { _eyeOffsets[eye] = toGlm(_system->GetEyeToHeadTransform(eye)); _eyeProjections[eye] = toGlm(_system->GetProjectionMatrix(eye, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, vr::API_OpenGL)); @@ -124,9 +126,6 @@ void OpenVrDisplayPlugin::internalDeactivate() { if (_system) { // Invalidate poses. It's fine if someone else sets these shared values, but we're about to stop updating them, and // we don't want ViveControllerManager to consider old values to be valid. - for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) { - _trackedDevicePose[i].bPoseIsValid = false; - } releaseOpenVrSystem(); _system = nullptr; } @@ -146,10 +145,11 @@ void OpenVrDisplayPlugin::customizeContext() { } void OpenVrDisplayPlugin::resetSensors() { - withRenderThreadLock([&] { - glm::mat4 m = toGlm(_trackedDevicePose[0].mDeviceToAbsoluteTracking); - _sensorResetMat = glm::inverse(cancelOutRollAndPitch(m)); + glm::mat4 m; + withNonPresentThreadLock([&] { + m = toGlm(_nextSimPoseData.vrPoses[0].mDeviceToAbsoluteTracking); }); + _sensorResetMat = glm::inverse(cancelOutRollAndPitch(m)); } static bool isBadPose(vr::HmdMatrix34_t* mat) { @@ -165,30 +165,21 @@ bool OpenVrDisplayPlugin::beginFrameRender(uint32_t frameIndex) { QMetaObject::invokeMethod(qApp, "quit"); return false; } - double displayFrequency = _system->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_DisplayFrequency_Float); - double frameDuration = 1.f / displayFrequency; - double vsyncToPhotons = _system->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_SecondsFromVsyncToPhotons_Float); - _currentRenderFrameInfo = FrameInfo(); -#if THREADED_PRESENT - // 3 frames of prediction + vsyncToPhotons = 44ms total - const double NUM_PREDICTION_FRAMES = 3.0f; - _currentRenderFrameInfo.predictedDisplayTime = NUM_PREDICTION_FRAMES * frameDuration + vsyncToPhotons; -#else - _currentRenderFrameInfo.predictedDisplayTime = frameDuration + vsyncToPhotons; -#endif - _system->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseStanding, _currentRenderFrameInfo.predictedDisplayTime, _trackedDevicePose, vr::k_unMaxTrackedDeviceCount); + withNonPresentThreadLock([&] { + _currentRenderFrameInfo.renderPose = _nextSimPoseData.poses[vr::k_unTrackedDeviceIndex_Hmd]; + }); // HACK: when interface is launched and steam vr is NOT running, openvr will return bad HMD poses for a few frames // To workaround this, filter out any hmd poses that are obviously bad, i.e. beneath the floor. - if (isBadPose(&_trackedDevicePose[vr::k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking)) { + if (isBadPose(&_nextSimPoseData.vrPoses[vr::k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking)) { qDebug() << "WARNING: ignoring bad hmd pose from openvr"; // use the last known good HMD pose - _trackedDevicePose[vr::k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking = _lastGoodHMDPose; + _nextSimPoseData.vrPoses[vr::k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking = _lastGoodHMDPose; } else { - _lastGoodHMDPose = _trackedDevicePose[vr::k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking; + _lastGoodHMDPose = _nextSimPoseData.vrPoses[vr::k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking; } vr::TrackedDeviceIndex_t handIndices[2] { vr::k_unTrackedDeviceIndexInvalid, vr::k_unTrackedDeviceIndexInvalid }; @@ -197,7 +188,7 @@ bool OpenVrDisplayPlugin::beginFrameRender(uint32_t frameIndex) { auto trackedCount = _system->GetSortedTrackedDeviceIndicesOfClass(vr::TrackedDeviceClass_Controller, controllerIndices, 2); // Find the left and right hand controllers, if they exist for (uint32_t i = 0; i < std::min(trackedCount, 2); ++i) { - if (_trackedDevicePose[i].bPoseIsValid) { + if (_nextSimPoseData.vrPoses[i].bPoseIsValid) { auto role = _system->GetControllerRoleForTrackedDeviceIndex(controllerIndices[i]); if (vr::TrackedControllerRole_LeftHand == role) { handIndices[0] = controllerIndices[i]; @@ -208,14 +199,7 @@ bool OpenVrDisplayPlugin::beginFrameRender(uint32_t frameIndex) { } } - // copy and process predictedTrackedDevicePoses - for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) { - _trackedDevicePoseMat4[i] = _sensorResetMat * toGlm(_trackedDevicePose[i].mDeviceToAbsoluteTracking); - _trackedDeviceLinearVelocities[i] = transformVectorFast(_sensorResetMat, toGlm(_trackedDevicePose[i].vVelocity)); - _trackedDeviceAngularVelocities[i] = transformVectorFast(_sensorResetMat, toGlm(_trackedDevicePose[i].vAngularVelocity)); - } - _currentRenderFrameInfo.rawRenderPose = toGlm(_trackedDevicePose[vr::k_unTrackedDeviceIndex_Hmd].mDeviceToAbsoluteTracking); - _currentRenderFrameInfo.renderPose = _trackedDevicePoseMat4[vr::k_unTrackedDeviceIndex_Hmd]; + _currentRenderFrameInfo.renderPose = _nextSimPoseData.poses[vr::k_unTrackedDeviceIndex_Hmd]; bool keyboardVisible = isOpenVrKeyboardShown(); @@ -226,16 +210,16 @@ bool OpenVrDisplayPlugin::beginFrameRender(uint32_t frameIndex) { continue; } auto deviceIndex = handIndices[i]; - const mat4& mat = _trackedDevicePoseMat4[deviceIndex]; - const vec3& linearVelocity = _trackedDeviceLinearVelocities[deviceIndex]; - const vec3& angularVelocity = _trackedDeviceAngularVelocities[deviceIndex]; + const mat4& mat = _nextSimPoseData.poses[deviceIndex]; + const vec3& linearVelocity = _nextSimPoseData.linearVelocities[deviceIndex]; + const vec3& angularVelocity = _nextSimPoseData.angularVelocities[deviceIndex]; auto correctedPose = openVrControllerPoseToHandPose(i == 0, mat, linearVelocity, angularVelocity); static const glm::quat HAND_TO_LASER_ROTATION = glm::rotation(Vectors::UNIT_Z, Vectors::UNIT_NEG_Y); handPoses[i] = glm::translate(glm::mat4(), correctedPose.translation) * glm::mat4_cast(correctedPose.rotation * HAND_TO_LASER_ROTATION); } } - withRenderThreadLock([&] { + withNonPresentThreadLock([&] { _uiModelTransform = DependencyManager::get()->getModelTransform(); // Make controller poses available to the presentation thread _handPoses = handPoses; @@ -245,24 +229,44 @@ bool OpenVrDisplayPlugin::beginFrameRender(uint32_t frameIndex) { } void OpenVrDisplayPlugin::hmdPresent() { - PROFILE_RANGE_EX(__FUNCTION__, 0xff00ff00, (uint64_t)_currentPresentFrameIndex) + PROFILE_RANGE_EX(__FUNCTION__, 0xff00ff00, (uint64_t)_currentFrame->frameIndex) // Flip y-axis since GL UV coords are backwards. static vr::VRTextureBounds_t leftBounds { 0, 0, 0.5f, 1 }; static vr::VRTextureBounds_t rightBounds { 0.5f, 0, 1, 1 }; + auto glTexId = getGLBackend()->getTextureID(_compositeTexture, false); + vr::Texture_t vrTexture{ (void*)glTexId, vr::API_OpenGL, vr::ColorSpace_Auto }; - vr::Texture_t texture { (void*)oglplus::GetName(_compositeFramebuffer->color), vr::API_OpenGL, vr::ColorSpace_Auto }; - - _compositor->Submit(vr::Eye_Left, &texture, &leftBounds); - _compositor->Submit(vr::Eye_Right, &texture, &rightBounds); + _compositor->Submit(vr::Eye_Left, &vrTexture, &leftBounds); + _compositor->Submit(vr::Eye_Right, &vrTexture, &rightBounds); } void OpenVrDisplayPlugin::postPreview() { - PROFILE_RANGE_EX(__FUNCTION__, 0xff00ff00, (uint64_t)_currentPresentFrameIndex) + // Clear + { + // We want to make sure the glFinish waits for the entire present to complete, not just the submission + // of the command. So, we do a clear here right here so the glFinish will wait fully for the swap. + glClearColor(0, 0, 0, 1); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glFlush(); + } - vr::TrackedDevicePose_t currentTrackedDevicePose[vr::k_unMaxTrackedDeviceCount]; - _compositor->WaitGetPoses(currentTrackedDevicePose, vr::k_unMaxTrackedDeviceCount, nullptr, 0); - _hmdActivityLevel = _system->GetTrackedDeviceActivityLevel(vr::k_unTrackedDeviceIndex_Hmd); + // Flush and wait for swap. + PROFILE_RANGE_EX(__FUNCTION__, 0xff00ff00, (uint64_t)_currentFrame->frameIndex) + PoseData nextRender; + nextRender.frameIndex = presentCount(); + vr::VRCompositor()->WaitGetPoses(nextRender.vrPoses, vr::k_unMaxTrackedDeviceCount, nullptr, 0); + + glm::mat4 resetMat; + withPresentThreadLock([&] { + resetMat = _sensorResetMat; + }); + nextRender.update(resetMat); + withPresentThreadLock([&] { + _nextSimPoseData = nextRender; + }); + _nextRenderPoseData = nextRender; + _hmdActivityLevel = vr::k_EDeviceActivityLevel_UserInteraction; // _system->GetTrackedDeviceActivityLevel(vr::k_unTrackedDeviceIndex_Hmd); } bool OpenVrDisplayPlugin::isHmdMounted() const { @@ -270,25 +274,8 @@ bool OpenVrDisplayPlugin::isHmdMounted() const { } void OpenVrDisplayPlugin::updatePresentPose() { - mat4 sensorResetMat; - withPresentThreadLock([&] { - sensorResetMat = _sensorResetMat; - }); - { - float fSecondsSinceLastVsync; - _system->GetTimeSinceLastVsync(&fSecondsSinceLastVsync, nullptr); - float fDisplayFrequency = _system->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_DisplayFrequency_Float); - float fFrameDuration = 1.f / fDisplayFrequency; - float fVsyncToPhotons = _system->GetFloatTrackedDeviceProperty(vr::k_unTrackedDeviceIndex_Hmd, vr::Prop_SecondsFromVsyncToPhotons_Float); - float fPredictedSecondsFromNow = fFrameDuration - fSecondsSinceLastVsync + fVsyncToPhotons; - vr::TrackedDevicePose_t pose; - _system->GetDeviceToAbsoluteTrackingPose(vr::TrackingUniverseStanding, fPredictedSecondsFromNow, &pose, 1); - _currentPresentFrameInfo.rawPresentPose = toGlm(pose.mDeviceToAbsoluteTracking); - } - _currentPresentFrameInfo.presentPose = sensorResetMat * _currentPresentFrameInfo.rawPresentPose; - mat3 renderRotation(_currentPresentFrameInfo.rawRenderPose); - mat3 presentRotation(_currentPresentFrameInfo.rawPresentPose); - _currentPresentFrameInfo.presentReprojection = glm::mat3(glm::inverse(renderRotation) * presentRotation); + _currentPresentFrameInfo.presentPose = _nextRenderPoseData.poses[vr::k_unTrackedDeviceIndex_Hmd]; + //_currentPresentFrameInfo.presentPose = _currentPresentFrameInfo.renderPose; } bool OpenVrDisplayPlugin::suppressKeyboard() { diff --git a/plugins/openvr/src/OpenVrHelpers.cpp b/plugins/openvr/src/OpenVrHelpers.cpp index ee61a07da6..20a43d98d4 100644 --- a/plugins/openvr/src/OpenVrHelpers.cpp +++ b/plugins/openvr/src/OpenVrHelpers.cpp @@ -118,7 +118,7 @@ static vr::IVROverlay* _overlay { nullptr }; static QObject* _keyboardFocusObject { nullptr }; static QString _existingText; static Qt::InputMethodHints _currentHints; -extern vr::TrackedDevicePose_t _trackedDevicePose[vr::k_unMaxTrackedDeviceCount]; +extern PoseData _nextSimPoseData; static bool _keyboardShown { false }; static bool _overlayRevealed { false }; static const uint32_t SHOW_KEYBOARD_DELAY_MS = 400; @@ -160,7 +160,7 @@ void showOpenVrKeyboard(bool show = true) { if (vr::VROverlayError_None == showKeyboardResult) { _keyboardShown = true; // Try to position the keyboard slightly below where the user is looking. - mat4 headPose = cancelOutRollAndPitch(toGlm(_trackedDevicePose[0].mDeviceToAbsoluteTracking)); + mat4 headPose = cancelOutRollAndPitch(toGlm(_nextSimPoseData.vrPoses[0].mDeviceToAbsoluteTracking)); mat4 keyboardTransform = glm::translate(headPose, vec3(0, -0.5, -1)); keyboardTransform = keyboardTransform * glm::rotate(mat4(), 3.14159f / 4.0f, vec3(-1, 0, 0)); auto keyboardTransformVr = toOpenVr(keyboardTransform); diff --git a/plugins/openvr/src/OpenVrHelpers.h b/plugins/openvr/src/OpenVrHelpers.h index 19c9cbfff5..368b14cb1a 100644 --- a/plugins/openvr/src/OpenVrHelpers.h +++ b/plugins/openvr/src/OpenVrHelpers.h @@ -59,4 +59,21 @@ inline vr::HmdMatrix34_t toOpenVr(const mat4& m) { return result; } +struct PoseData { + uint32_t frameIndex{ 0 }; + vr::TrackedDevicePose_t vrPoses[vr::k_unMaxTrackedDeviceCount]; + mat4 poses[vr::k_unMaxTrackedDeviceCount]; + vec3 linearVelocities[vr::k_unMaxTrackedDeviceCount]; + vec3 angularVelocities[vr::k_unMaxTrackedDeviceCount]; + + void update(const glm::mat4& resetMat) { + for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) { + poses[i] = resetMat * toGlm(vrPoses[i].mDeviceToAbsoluteTracking); + linearVelocities[i] = transformVectorFast(resetMat, toGlm(vrPoses[i].vVelocity)); + angularVelocities[i] = transformVectorFast(resetMat, toGlm(vrPoses[i].vAngularVelocity)); + } + } +}; + + controller::Pose openVrControllerPoseToHandPose(bool isLeftHand, const mat4& mat, const vec3& linearVelocity, const vec3& angularVelocity); diff --git a/plugins/openvr/src/ViveControllerManager.cpp b/plugins/openvr/src/ViveControllerManager.cpp index 930b3dd450..596f3ab288 100644 --- a/plugins/openvr/src/ViveControllerManager.cpp +++ b/plugins/openvr/src/ViveControllerManager.cpp @@ -29,10 +29,7 @@ #include "OpenVrHelpers.h" -extern vr::TrackedDevicePose_t _trackedDevicePose[vr::k_unMaxTrackedDeviceCount]; -extern mat4 _trackedDevicePoseMat4[vr::k_unMaxTrackedDeviceCount]; -extern vec3 _trackedDeviceLinearVelocities[vr::k_unMaxTrackedDeviceCount]; -extern vec3 _trackedDeviceAngularVelocities[vr::k_unMaxTrackedDeviceCount]; +extern PoseData _nextSimPoseData; vr::IVRSystem* acquireOpenVrSystem(); void releaseOpenVrSystem(); @@ -48,6 +45,7 @@ static const QString RENDER_CONTROLLERS = "Render Hand Controllers"; const QString ViveControllerManager::NAME = "OpenVR"; bool ViveControllerManager::isSupported() const { + return false; return openVrSupported(); } @@ -279,12 +277,12 @@ void ViveControllerManager::InputDevice::handleHandController(float deltaTime, u if (_system->IsTrackedDeviceConnected(deviceIndex) && _system->GetTrackedDeviceClass(deviceIndex) == vr::TrackedDeviceClass_Controller && - _trackedDevicePose[deviceIndex].bPoseIsValid) { + _nextSimPoseData.vrPoses[deviceIndex].bPoseIsValid) { // process pose - const mat4& mat = _trackedDevicePoseMat4[deviceIndex]; - const vec3 linearVelocity = _trackedDeviceLinearVelocities[deviceIndex]; - const vec3 angularVelocity = _trackedDeviceAngularVelocities[deviceIndex]; + const mat4& mat = _nextSimPoseData.poses[deviceIndex]; + const vec3 linearVelocity = _nextSimPoseData.linearVelocities[deviceIndex]; + const vec3 angularVelocity = _nextSimPoseData.angularVelocities[deviceIndex]; handlePoseEvent(deltaTime, inputCalibrationData, mat, linearVelocity, angularVelocity, isLeftHand); vr::VRControllerState_t controllerState = vr::VRControllerState_t(); @@ -428,7 +426,7 @@ void ViveControllerManager::InputDevice::hapticsHelper(float deltaTime, bool lef if (_system->IsTrackedDeviceConnected(deviceIndex) && _system->GetTrackedDeviceClass(deviceIndex) == vr::TrackedDeviceClass_Controller && - _trackedDevicePose[deviceIndex].bPoseIsValid) { + _nextSimPoseData.vrPoses[deviceIndex].bPoseIsValid) { float strength = leftHand ? _leftHapticStrength : _rightHapticStrength; float duration = leftHand ? _leftHapticDuration : _rightHapticDuration;