From 15d214f335f334b2707daddf38829c3b2008832c Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 12 Jun 2015 17:29:05 -0700 Subject: [PATCH] Initial pass at OpenVR --- cmake/externals/openvr/CMakeLists.txt | 3 + interface/src/Application.cpp | 55 ++---- interface/src/DisplayPlugins.cpp | 5 +- interface/src/devices/TV3DManager.cpp | 158 ----------------- interface/src/devices/TV3DManager.h | 62 ------- interface/src/ui/ApplicationOverlay.cpp | 14 +- interface/src/ui/ApplicationOverlay.h | 2 - .../src/ui/overlays/LocalModelsOverlay.cpp | 2 + .../Basic2DWindowOpenGLDisplayPlugin.cpp | 2 +- .../Basic2DWindowOpenGLDisplayPlugin.h | 2 +- .../src/display-plugins/NullDisplayPlugin.cpp | 6 +- .../src/display-plugins/NullDisplayPlugin.h | 34 ++-- .../WidgetOpenGLDisplayPlugin.h | 2 +- .../oculus/OculusWin32DisplayPlugin.cpp | 4 +- .../oculus/OculusWin32DisplayPlugin.h | 4 +- .../openvr/OpenVrDisplayPlugin.cpp | 165 ++++++++++++++++++ .../openvr/OpenVrDisplayPlugin.h | 41 +++++ .../display-plugins/openvr/OpenVrHelpers.h | 14 ++ .../stereo/InterleavedStereoDisplayPlugin.cpp | 2 +- .../stereo/InterleavedStereoDisplayPlugin.h | 2 +- .../stereo/SideBySideStereoDisplayPlugin.cpp | 2 +- .../stereo/SideBySideStereoDisplayPlugin.h | 2 +- libraries/plugins/src/plugins/Plugin.h | 2 +- 23 files changed, 280 insertions(+), 305 deletions(-) create mode 100644 libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.cpp create mode 100644 libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h create mode 100644 libraries/display-plugins/src/display-plugins/openvr/OpenVrHelpers.h diff --git a/cmake/externals/openvr/CMakeLists.txt b/cmake/externals/openvr/CMakeLists.txt index 826c3dbb13..413618c842 100644 --- a/cmake/externals/openvr/CMakeLists.txt +++ b/cmake/externals/openvr/CMakeLists.txt @@ -23,16 +23,19 @@ if (WIN32) # FIXME need to account for different architectures set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/lib/win32/openvr_api.lib CACHE TYPE INTERNAL) + add_paths_to_fixup_libs(${SOURCE_DIR}/bin/win32) elseif(APPLE) # FIXME need to account for different architectures set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/lib/osx32/libopenvr_api.dylib CACHE TYPE INTERNAL) + add_paths_to_fixup_libs(${SOURCE_DIR}/bin/osx32) elseif(NOT ANDROID) # FIXME need to account for different architectures set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/lib/linux32/libopenvr_api.so CACHE TYPE INTERNAL) + add_paths_to_fixup_libs(${SOURCE_DIR}/bin/linux32) endif() diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 28a8d3cb58..5df5a5a308 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -865,7 +865,7 @@ void Application::paintGL() { auto displayPlugin = getActiveDisplayPlugin(); displayPlugin->preRender(); - _glWidget->makeCurrent(); + _offscreenContext->makeCurrent(); auto lodManager = DependencyManager::get(); gpu::Context context(new gpu::GLBackend()); @@ -875,7 +875,6 @@ void Application::paintGL() { PerformanceTimer perfTimer("paintGL"); - _offscreenContext->makeCurrent(); PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings)); bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::paintGL()"); @@ -938,7 +937,7 @@ void Application::paintGL() { } renderArgs._renderMode = RenderArgs::DEFAULT_RENDER_MODE; - DependencyManager::get()->prepare(); + DependencyManager::get()->prepare(&renderArgs); // Primary rendering pass auto primaryFbo = DependencyManager::get()->getPrimaryFramebuffer(); auto finalFbo = primaryFbo; @@ -963,13 +962,13 @@ void Application::paintGL() { eyeCamera.setTransform(displayPlugin->getModelview(eye, _myCamera.getTransform())); eyeCamera.setProjection(displayPlugin->getProjection(eye, _myCamera.getProjection())); - displaySide(eyeCamera); + displaySide(&renderArgs, eyeCamera); if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) { glm::vec2 mpos = getActiveDisplayPlugin()->getUiMousePosition(); - _rearMirrorTools->render(true, QPoint(mpos.x, mpos.y)); + _rearMirrorTools->render(&renderArgs, true, QPoint(mpos.x, mpos.y)); } else if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { - renderRearViewMirror(_mirrorViewRect); + renderRearViewMirror(&renderArgs, _mirrorViewRect); } }, [&] { r.moveLeft(r.width()); @@ -977,15 +976,15 @@ void Application::paintGL() { glDisable(GL_SCISSOR_TEST); } else { glViewport(0, 0, size.width(), size.height()); - displaySide(_myCamera); + displaySide(&renderArgs, _myCamera); if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) { glm::vec2 mpos = getActiveDisplayPlugin()->getUiMousePosition(); - _rearMirrorTools->render(true, QPoint(mpos.x, mpos.y)); + _rearMirrorTools->render(&renderArgs, true, QPoint(mpos.x, mpos.y)); } else if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { - renderRearViewMirror(_mirrorViewRect); + renderRearViewMirror(&renderArgs, _mirrorViewRect); } } - finalFbo = DependencyManager::get()->render(); + finalFbo = DependencyManager::get()->render(&renderArgs); } glPopMatrix(); @@ -3030,7 +3029,8 @@ void Application::updateShadowMap(RenderArgs* renderArgs) { glMatrixMode(GL_MODELVIEW); } - glViewport(0, 0, _glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); + + glViewport(0, 0, getDeviceSize().width(), getDeviceSize().height()); activeRenderingThread = nullptr; } @@ -3271,7 +3271,7 @@ namespace render { PerformanceTimer perfTimer("atmosphere"); PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide() ... atmosphere..."); - background->_environment->renderAtmospheres(*(args->_viewFrustum)); + background->_environment->renderAtmospheres(args->_viewFrustum->getPosition()); } } @@ -3291,7 +3291,7 @@ namespace render { } -void Application::displaySide(RenderArgs* renderArgs, const Camera& theCamera, bool selfAvatarOnly) { +void Application::displaySide(RenderArgs* renderArgs, const Camera& theCamera, bool selfAvatarOnly, bool billboard) { activeRenderingThread = QThread::currentThread(); PROFILE_RANGE(__FUNCTION__); PerformanceTimer perfTimer("display"); @@ -3555,32 +3555,6 @@ bool Application::getCascadeShadowsEnabled() { return Menu::getInstance()->isOptionChecked(MenuOption::CascadedShadows); } -glm::vec2 Application::getScaledScreenPoint(glm::vec2 projectedPoint) { - float horizontalScale = _glWidget->getDeviceWidth() / 2.0f; - float verticalScale = _glWidget->getDeviceHeight() / 2.0f; - - // -1,-1 is 0,windowHeight - // 1,1 is windowWidth,0 - - // -1,1 1,1 - // +-----------------------+ - // | | | - // | | | - // | -1,0 | | - // |-----------+-----------| - // | 0,0 | - // | | | - // | | | - // | | | - // +-----------------------+ - // -1,-1 1,-1 - - glm::vec2 screenPoint((projectedPoint.x + 1.0) * horizontalScale, - ((projectedPoint.y + 1.0) * -verticalScale) + _glWidget->getDeviceHeight()); - - return screenPoint; -} - void Application::renderRearViewMirror(RenderArgs* renderArgs, const QRect& region, bool billboard) { // Grab current viewport to reset it at the end int viewport[4]; @@ -3643,7 +3617,7 @@ void Application::renderRearViewMirror(RenderArgs* renderArgs, const QRect& regi glPopMatrix(); if (!billboard) { - _rearMirrorTools->render(renderArgs, false, _glWidget->mapFromGlobal(QCursor::pos())); + _rearMirrorTools->render(renderArgs, false, getActiveDisplayPlugin()->getWindow()->mapFromGlobal(QCursor::pos())); } // reset Viewport and projection matrix glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); @@ -4829,7 +4803,6 @@ void Application::updateDisplayMode() { auto offscreenUi = DependencyManager::get(); offscreenUi->setMouseTranslator(getActiveDisplayPlugin()->getMouseTranslator()); - updateCursorVisibility(); } Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin"); } diff --git a/interface/src/DisplayPlugins.cpp b/interface/src/DisplayPlugins.cpp index 3a4b9fb654..a9602a9517 100644 --- a/interface/src/DisplayPlugins.cpp +++ b/interface/src/DisplayPlugins.cpp @@ -21,6 +21,8 @@ #else #endif +#include + static void addDisplayPluginToMenu(DisplayPluginPointer displayPlugin, bool active = false) { auto menu = Menu::getInstance(); @@ -56,7 +58,8 @@ const DisplayPluginList& getDisplayPlugins() { #endif new SideBySideStereoDisplayPlugin(), new InterleavedStereoDisplayPlugin(), - new OculusWin32DisplayPlugin(), +// new OculusWin32DisplayPlugin(), + new OpenVrDisplayPlugin(), nullptr }; for (int i = 0; PLUGIN_POOL[i]; ++i) { diff --git a/interface/src/devices/TV3DManager.cpp b/interface/src/devices/TV3DManager.cpp index a1e58fa8dc..e69de29bb2 100644 --- a/interface/src/devices/TV3DManager.cpp +++ b/interface/src/devices/TV3DManager.cpp @@ -1,158 +0,0 @@ -// -// TV3DManager.cpp -// interface/src/devices -// -// Created by Brad Hefta-Gaub on 12/24/13. -// Copyright 2013 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 "InterfaceConfig.h" - -#include - -#include -#include "gpu/GLBackend.h" -#include "Application.h" - -#include "TV3DManager.h" -#include "Menu.h" - -int TV3DManager::_screenWidth = 1; -int TV3DManager::_screenHeight = 1; -double TV3DManager::_aspect = 1.0; -eyeFrustum TV3DManager::_leftEye; -eyeFrustum TV3DManager::_rightEye; -eyeFrustum* TV3DManager::_activeEye = NULL; - - -bool TV3DManager::isConnected() { - return Menu::getInstance()->isOptionChecked(MenuOption::Enable3DTVMode); -} - -void TV3DManager::connect() { - auto deviceSize = qApp->getDeviceSize(); - configureCamera(*(qApp->getCamera()), deviceSize.width(), deviceSize.height()); -} - - -// The basic strategy of this stereoscopic rendering is explained here: -// http://www.orthostereo.com/geometryopengl.html -void TV3DManager::setFrustum(const Camera& whichCamera) { - const double DTR = 0.0174532925; // degree to radians - const double IOD = 0.05; //intraocular distance - double fovy = DEFAULT_FIELD_OF_VIEW_DEGREES; // field of view in y-axis - double nearZ = DEFAULT_NEAR_CLIP; // near clipping plane - double screenZ = 0.25f; // screen projection plane - - double top = nearZ * tan(DTR * fovy / 2.0); //sets top of frustum based on fovy and near clipping plane - double right = _aspect * top; // sets right of frustum based on aspect ratio - double frustumshift = (IOD / 2) * nearZ / screenZ; - - _leftEye.top = top; - _leftEye.bottom = -top; - _leftEye.left = -right + frustumshift; - _leftEye.right = right + frustumshift; - _leftEye.modelTranslation = IOD / 2; - - _rightEye.top = top; - _rightEye.bottom = -top; - _rightEye.left = -right - frustumshift; - _rightEye.right = right - frustumshift; - _rightEye.modelTranslation = -IOD / 2; -} - -void TV3DManager::configureCamera(Camera& whichCamera_, int screenWidth, int screenHeight) { - const Camera& whichCamera = whichCamera_; - - if (screenHeight == 0) { - screenHeight = 1; // prevent divide by 0 - } - _screenWidth = screenWidth; - _screenHeight = screenHeight; - _aspect= (double)_screenWidth / (double)_screenHeight; - setFrustum(whichCamera); - - glViewport (0, 0, _screenWidth, _screenHeight); // sets drawing viewport - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); -} - -void TV3DManager::display(RenderArgs* renderArgs, Camera& whichCamera) { - double nearZ = DEFAULT_NEAR_CLIP; // near clipping plane - double farZ = DEFAULT_FAR_CLIP; // far clipping plane - - // left eye portal - int portalX = 0; - int portalY = 0; - QSize deviceSize = qApp->getDeviceSize() * - qApp->getRenderResolutionScale(); - int portalW = deviceSize.width() / 2; - int portalH = deviceSize.height(); - - - DependencyManager::get()->prepare(renderArgs); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - Camera eyeCamera; - eyeCamera.setRotation(whichCamera.getRotation()); - eyeCamera.setPosition(whichCamera.getPosition()); - - glEnable(GL_SCISSOR_TEST); - glPushMatrix(); - forEachEye([&](eyeFrustum& eye){ - _activeEye = &eye; - glViewport(portalX, portalY, portalW, portalH); - glScissor(portalX, portalY, portalW, portalH); - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); // reset projection matrix - glFrustum(eye.left, eye.right, eye.bottom, eye.top, nearZ, farZ); // set left view frustum - GLfloat p[4][4]; - // Really? - glGetFloatv(GL_PROJECTION_MATRIX, &(p[0][0])); - float cotangent = p[1][1]; - GLfloat fov = atan(1.0f / cotangent); - glTranslatef(eye.modelTranslation, 0.0, 0.0); // translate to cancel parallax - - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - renderArgs->_renderSide = RenderArgs::MONO; - qApp->displaySide(renderArgs, eyeCamera, false); - qApp->getApplicationOverlay().displayOverlayTextureStereo(whichCamera, _aspect, fov); - _activeEye = NULL; - }, [&]{ - // render right side view - portalX = deviceSize.width() / 2; - }); - glPopMatrix(); - glDisable(GL_SCISSOR_TEST); - - auto finalFbo = DependencyManager::get()->render(renderArgs); - auto fboSize = finalFbo->getSize(); - // Get the ACTUAL device size for the BLIT - deviceSize = qApp->getDeviceSize(); - - glBindFramebuffer(GL_READ_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(finalFbo)); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - glBlitFramebuffer(0, 0, fboSize.x, fboSize.y, - 0, 0, deviceSize.width(), deviceSize.height(), - GL_COLOR_BUFFER_BIT, GL_NEAREST); - glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); - - // reset the viewport to how we started - glViewport(0, 0, deviceSize.width(), deviceSize.height()); -} - -void TV3DManager::overrideOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& nearVal, - float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) { - if (_activeEye) { - left = _activeEye->left; - right = _activeEye->right; - bottom = _activeEye->bottom; - top = _activeEye->top; - } -} diff --git a/interface/src/devices/TV3DManager.h b/interface/src/devices/TV3DManager.h index 1a63161b1e..e69de29bb2 100644 --- a/interface/src/devices/TV3DManager.h +++ b/interface/src/devices/TV3DManager.h @@ -1,62 +0,0 @@ -// -// TV3DManager.h -// interface/src/devices -// -// Created by Brad Hefta-Gaub on 12/24/2013. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_TV3DManager_h -#define hifi_TV3DManager_h -#include - -#include - -class Camera; - -struct eyeFrustum { - double left; - double right; - double bottom; - double top; - float modelTranslation; -}; - - -/// Handles interaction with 3D TVs -class TV3DManager { -public: - static void connect(); - static bool isConnected(); - static void configureCamera(Camera& camera, int screenWidth, int screenHeight); - static void display(RenderArgs* renderArgs, Camera& whichCamera); - static void overrideOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& nearVal, - float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane); -private: - static void setFrustum(const Camera& whichCamera); - static int _screenWidth; - static int _screenHeight; - static double _aspect; - static eyeFrustum _leftEye; - static eyeFrustum _rightEye; - static eyeFrustum* _activeEye; - - // The first function is the code executed for each eye - // while the second is code to be executed between the two eyes. - // The use case here is to modify the output viewport coordinates - // for the new eye. - // FIXME: we'd like to have a default empty lambda for the second parameter, - // but gcc 4.8.1 complains about it due to a bug. See - // http://stackoverflow.com/questions/25490662/lambda-as-default-parameter-to-a-member-function-template - template - static void forEachEye(F f, FF ff) { - f(_leftEye); - ff(); - f(_rightEye); - } -}; - -#endif // hifi_TV3DManager_h diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 80ff3bc8df..f2bd6e0035 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -621,9 +621,6 @@ bool ApplicationOverlay::calculateRayUICollisionPoint(const glm::vec3& position, //Renders optional pointers void ApplicationOverlay::renderPointers() { //lazily load crosshair texture - if (_crosshairTexture == 0) { - _crosshairTexture = TextureCache::getImageTexture(PathUtils::resourcesPath() + "images/sixense-reticle.png"); - } glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); @@ -791,16 +788,16 @@ void ApplicationOverlay::renderControllerPointers() { } void ApplicationOverlay::renderPointersOculus() { - +#if 0 glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glEnable(GL_TEXTURE_2D); - - glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_crosshairTexture)); glDisable(GL_DEPTH_TEST); + glEnable(GL_TEXTURE_2D); + bindCursorTexture(); + glMatrixMode(GL_MODELVIEW); - + //Controller Pointers MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); for (int i = 0; i < (int)myAvatar->getHand()->getNumPalms(); i++) { @@ -825,6 +822,7 @@ void ApplicationOverlay::renderPointersOculus() { glEnable(GL_DEPTH_TEST); glDisable(GL_TEXTURE_2D); glDisable(GL_BLEND); +#endif } //Renders a small magnification of the currently bound texture at the coordinates diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index 9681f52b0e..9b2dbd345d 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -81,8 +81,6 @@ private: void renderDomainConnectionStatusBorder(); void bindCursorTexture(gpu::Batch& batch, uint8_t cursorId = 0); - TexturedHemisphere _overlays; - float _textureFov; float _textureAspectRatio; diff --git a/interface/src/ui/overlays/LocalModelsOverlay.cpp b/interface/src/ui/overlays/LocalModelsOverlay.cpp index e5c8e6076d..076f8c14a7 100644 --- a/interface/src/ui/overlays/LocalModelsOverlay.cpp +++ b/interface/src/ui/overlays/LocalModelsOverlay.cpp @@ -45,10 +45,12 @@ void LocalModelsOverlay::render(RenderArgs* args) { glPushMatrix(); { Application* app = Application::getInstance(); +#if 0 glm::vec3 oldTranslation = app->getViewMatrixTranslation(); app->setViewMatrixTranslation(oldTranslation + _position); _entityTreeRenderer->render(args); Application::getInstance()->setViewMatrixTranslation(oldTranslation); +#endif } glPopMatrix(); } } diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp index 2cb0343107..ef8c5ed39f 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp @@ -9,6 +9,6 @@ const QString Basic2DWindowOpenGLDisplayPlugin::NAME("2D Display"); -const QString & Basic2DWindowOpenGLDisplayPlugin::getName() { +const QString & Basic2DWindowOpenGLDisplayPlugin::getName() const { return NAME; } diff --git a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h index 364b7652c6..63027d2bd9 100644 --- a/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h @@ -13,7 +13,7 @@ class Basic2DWindowOpenGLDisplayPlugin : public MainWindowOpenGLDisplayPlugin { Q_OBJECT public: - virtual const QString & getName() override; + virtual const QString & getName() const override; private: static const QString NAME; diff --git a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp index 3de57b051b..7c0c446af3 100644 --- a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp @@ -11,7 +11,7 @@ const QString NullDisplayPlugin::NAME("NullDisplayPlugin"); -const QString & NullDisplayPlugin::getName() { +const QString & NullDisplayPlugin::getName() const { return NAME; } @@ -27,10 +27,6 @@ bool NullDisplayPlugin::hasFocus() const { return false; } -glm::ivec2 NullDisplayPlugin::getRelativeMousePosition() const { - return glm::ivec2(); -} - glm::ivec2 NullDisplayPlugin::getTrueMousePosition() const { return glm::ivec2(); } diff --git a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h index a80ec6567b..bf32083658 100644 --- a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h @@ -11,24 +11,26 @@ class NullDisplayPlugin : public DisplayPlugin { public: - static const QString NAME; virtual ~NullDisplayPlugin() final {} - virtual const QString & getName(); + virtual const QString & getName() const override; - void activate(PluginContainer * container); - void deactivate(); + void activate(PluginContainer * container) override; + void deactivate() override; - virtual QSize getDeviceSize() const; - virtual glm::ivec2 getCanvasSize() const; - virtual bool hasFocus() const; - virtual glm::ivec2 getRelativeMousePosition() const; - virtual glm::ivec2 getTrueMousePosition() const; - virtual PickRay computePickRay(const glm::vec2 & pos) const; - virtual bool isMouseOnScreen() const; - virtual QWindow* getWindow() const; - virtual void preRender(); - virtual void preDisplay(); - virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize); - virtual void finishFrame(); + virtual QSize getDeviceSize() const override; + virtual glm::ivec2 getCanvasSize() const override; + virtual bool hasFocus() const override; +// virtual glm::ivec2 getRelativeMousePosition() const override; + virtual glm::ivec2 getTrueMousePosition() const override; + virtual PickRay computePickRay(const glm::vec2 & pos) const override; + virtual bool isMouseOnScreen() const override; + virtual QWindow* getWindow() const override; + virtual void preRender() override; + virtual void preDisplay() override; + virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize) override; + virtual void finishFrame() override; + +private: + static const QString NAME; }; diff --git a/libraries/display-plugins/src/display-plugins/WidgetOpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/WidgetOpenGLDisplayPlugin.h index 94242cf042..3416aec3ad 100644 --- a/libraries/display-plugins/src/display-plugins/WidgetOpenGLDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/WidgetOpenGLDisplayPlugin.h @@ -18,7 +18,7 @@ public: WidgetOpenGLDisplayPlugin(); - virtual const QString & getName() override; + virtual const QString & getName() const override; virtual glm::ivec2 getTrueMousePosition() const override; virtual QSize getDeviceSize() const override; virtual glm::ivec2 getCanvasSize() const override; diff --git a/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.cpp index 4c7c6a076a..03ca1f100e 100644 --- a/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.cpp @@ -146,11 +146,11 @@ private: const QString OculusWin32DisplayPlugin::NAME("Oculus Rift"); -const QString & OculusWin32DisplayPlugin::getName() { +const QString & OculusWin32DisplayPlugin::getName() const { return NAME; } -bool OculusWin32DisplayPlugin::isSupported() { +bool OculusWin32DisplayPlugin::isSupported() const { if (!OVR_SUCCESS(ovr_Initialize(nullptr))) { return false; } diff --git a/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.h b/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.h index 8352b0c63a..2d892fdb67 100644 --- a/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.h @@ -20,8 +20,8 @@ using MirrorFboPtr = QSharedPointer; class OculusWin32DisplayPlugin : public OculusBaseDisplayPlugin { public: - virtual bool isSupported(); - virtual const QString & getName(); + virtual bool isSupported() const override; + virtual const QString & getName() const override; virtual void activate(PluginContainer * container) override; virtual void deactivate() override; diff --git a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.cpp new file mode 100644 index 0000000000..1e71753a6e --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.cpp @@ -0,0 +1,165 @@ +// +// Created by Bradley Austin Davis on 2015/05/12 +// 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 "OpenVrDisplayPlugin.h" + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "OpenVrHelpers.h" +#include "../OglplusHelpers.h" + + +const QString OpenVrDisplayPlugin::NAME("OpenVR (Vive)"); + +const QString & OpenVrDisplayPlugin::getName() const { + return NAME; +} + +static vr::IVRSystem *_hmd{ nullptr }; +static vr::IVRCompositor* _compositor{ nullptr }; +static vr::TrackedDevicePose_t _trackedDevicePose[vr::k_unMaxTrackedDeviceCount]; +static mat4 _trackedDevicePoseMat4[vr::k_unMaxTrackedDeviceCount]; +static uvec2 _windowSize; +static ivec2 _windowPosition; +static uvec2 _renderTargetSize; + +struct PerEyeData { + uvec2 _viewportOrigin; + uvec2 _viewportSize; + mat4 _projectionMatrix; + mat4 _eyeOffset; + mat4 _pose; +}; + +static PerEyeData _eyesData[2]; + + +template +void openvr_for_each_eye(F f) { + f(vr::Hmd_Eye::Eye_Left); + f(vr::Hmd_Eye::Eye_Right); +} + +mat4 toGlm(const vr::HmdMatrix44_t& m) { + return glm::transpose(glm::make_mat4(&m.m[0][0])); +} + +mat4 toGlm(const vr::HmdMatrix34_t& m) { + mat4 result = mat4( + m.m[0][0], m.m[1][0], m.m[2][0], 0.0, + m.m[0][1], m.m[1][1], m.m[2][1], 0.0, + m.m[0][2], m.m[1][2], m.m[2][2], 0.0, + m.m[0][3], m.m[1][3], m.m[2][3], 1.0f); + return result; +} + +bool OpenVrDisplayPlugin::isSupported() const { + return vr::VR_IsHmdPresent(); +} + +void OpenVrDisplayPlugin::activate(PluginContainer * container) { + vr::HmdError eError = vr::HmdError_None; + _hmd = vr::VR_Init(&eError); + Q_ASSERT(eError == vr::HmdError_None); + Q_ASSERT(_hmd); + + _hmd->GetWindowBounds(&_windowPosition.x, &_windowPosition.y, &_windowSize.x, &_windowSize.y); + _hmd->GetRecommendedRenderTargetSize(&_renderTargetSize.x, &_renderTargetSize.y); + openvr_for_each_eye([&](vr::Hmd_Eye eye) { + PerEyeData& eyeData = _eyesData[eye]; + _hmd->GetEyeOutputViewport(eye, + &eyeData._viewportOrigin.x, &eyeData._viewportOrigin.y, + &eyeData._viewportSize.x, &eyeData._viewportSize.y); + eyeData._projectionMatrix = toGlm(_hmd->GetProjectionMatrix(eye, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, vr::API_OpenGL)); + eyeData._eyeOffset = toGlm(_hmd->GetEyeToHeadTransform(eye)); + }); + + + _compositor = (vr::IVRCompositor*)vr::VR_GetGenericInterface(vr::IVRCompositor_Version, &eError); + Q_ASSERT(eError == vr::HmdError_None); + Q_ASSERT(_compositor); + + _compositor->SetGraphicsDevice(vr::Compositor_DeviceType_OpenGL, NULL); + + uint32_t unSize = _compositor->GetLastError(NULL, 0); + if (unSize > 1) { + char* buffer = new char[unSize]; + _compositor->GetLastError(buffer, unSize); + printf("Compositor - %s\n", buffer); + delete[] buffer; + } + Q_ASSERT(unSize <= 1); + MainWindowOpenGLDisplayPlugin::activate(container); +} + +void OpenVrDisplayPlugin::deactivate() { + vr::VR_Shutdown(); + _hmd = nullptr; + _compositor = nullptr; +} + +QSize OpenVrDisplayPlugin::getRecommendedFramebufferSize() const { + return QSize(_renderTargetSize.x, _renderTargetSize.y); +} + +mat4 OpenVrDisplayPlugin::getProjection(Eye eye, const mat4& baseProjection) const { + return _eyesData[eye]._projectionMatrix; +} + +glm::mat4 OpenVrDisplayPlugin::getModelview(Eye eye, const mat4& baseModelview) const { + return baseModelview * _eyesData[eye]._pose; +} + +void OpenVrDisplayPlugin::preRender() { +} + +void OpenVrDisplayPlugin::resetSensors() { + _hmd->ResetSeatedZeroPose(); +} + +glm::mat4 OpenVrDisplayPlugin::getEyePose(Eye eye) const { + return _eyesData[eye]._pose; +} + +glm::mat4 OpenVrDisplayPlugin::getHeadPose() const { + return _trackedDevicePoseMat4[0]; +} + +void OpenVrDisplayPlugin::customizeContext(PluginContainer * container) { + MainWindowOpenGLDisplayPlugin::customizeContext(container); +} + +void OpenVrDisplayPlugin::display(GLuint finalTexture, const glm::uvec2& sceneSize) { + // Flip y-axis since GL UV coords are backwards. + static vr::Compositor_TextureBounds leftBounds{ 0, 1, 0.5f, 0 }; + static vr::Compositor_TextureBounds rightBounds{ 0.5f, 1, 1, 0 }; + _compositor->Submit(vr::Eye_Left, (void*)finalTexture, &leftBounds); + _compositor->Submit(vr::Eye_Right, (void*)finalTexture, &rightBounds); + glFinish(); +} + +void OpenVrDisplayPlugin::finishFrame() { +// swapBuffers(); + doneCurrent(); + _compositor->WaitGetPoses(_trackedDevicePose, vr::k_unMaxTrackedDeviceCount); + _trackedDevicePoseMat4[0] = toGlm(_trackedDevicePose[0].mDeviceToAbsoluteTracking); + openvr_for_each_eye([&](vr::Hmd_Eye eye) { + _eyesData[eye]._pose = _trackedDevicePoseMat4[0]; + }); +}; + diff --git a/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h new file mode 100644 index 0000000000..48a7b24279 --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/openvr/OpenVrDisplayPlugin.h @@ -0,0 +1,41 @@ +// +// Created by Bradley Austin Davis on 2015/06/12 +// 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 "../MainWindowOpenGLDisplayPlugin.h" + +class OpenVrDisplayPlugin : public MainWindowOpenGLDisplayPlugin { +public: + virtual bool isSupported() const override; + virtual const QString & getName() const override; + + virtual void activate(PluginContainer * container) override; + virtual void deactivate() override; + + // Stereo specific methods + virtual bool isHmd() const override { return true; } + virtual glm::mat4 getProjection(Eye eye, const glm::mat4& baseProjection) const override; + virtual glm::mat4 getModelview(Eye eye, const glm::mat4& baseModelview) const override; + + virtual void preRender() override; + virtual QSize getRecommendedFramebufferSize() const override; + virtual void resetSensors() override; + + virtual glm::ivec2 getCanvasSize() const override { return ivec2(1920, 1080); } + virtual glm::mat4 getEyePose(Eye eye) const override; + virtual glm::mat4 getHeadPose() const override; + +protected: + virtual void display(GLuint finalTexture, const glm::uvec2& sceneSize) override; + virtual void customizeContext(PluginContainer * container) override; + // Do not perform swap in finish + virtual void finishFrame() override; + +private: + static const QString NAME; +}; diff --git a/libraries/display-plugins/src/display-plugins/openvr/OpenVrHelpers.h b/libraries/display-plugins/src/display-plugins/openvr/OpenVrHelpers.h new file mode 100644 index 0000000000..e62950f5c4 --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/openvr/OpenVrHelpers.h @@ -0,0 +1,14 @@ +// +// Created by Bradley Austin Davis on 2015/06/12 +// 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 +#include +#include +#include + diff --git a/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.cpp index b4e74ef7ba..65ef1837ed 100644 --- a/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.cpp @@ -19,7 +19,7 @@ const QString InterleavedStereoDisplayPlugin::NAME("Interleaved Stereo Display"); -const QString & InterleavedStereoDisplayPlugin::getName() { +const QString & InterleavedStereoDisplayPlugin::getName() const { return NAME; } diff --git a/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.h index 240c09c6b7..fae145d9b8 100644 --- a/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.h @@ -13,7 +13,7 @@ class InterleavedStereoDisplayPlugin : public StereoDisplayPlugin { Q_OBJECT public: InterleavedStereoDisplayPlugin(); - virtual const QString & getName() override; + virtual const QString & getName() const override; // initialize OpenGL context settings needed by the plugin virtual void customizeContext(PluginContainer * container) override; diff --git a/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.cpp index bc38558822..e348143250 100644 --- a/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.cpp @@ -19,7 +19,7 @@ const QString SideBySideStereoDisplayPlugin::NAME("SBS Stereo Display"); -const QString & SideBySideStereoDisplayPlugin::getName() { +const QString & SideBySideStereoDisplayPlugin::getName() const { return NAME; } diff --git a/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.h index e052b7f1a1..ead9ea7dc4 100644 --- a/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.h @@ -13,7 +13,7 @@ class SideBySideStereoDisplayPlugin : public StereoDisplayPlugin { Q_OBJECT public: SideBySideStereoDisplayPlugin(); - virtual const QString & getName() override; + virtual const QString & getName() const override; private: static const QString NAME; }; diff --git a/libraries/plugins/src/plugins/Plugin.h b/libraries/plugins/src/plugins/Plugin.h index 6f55cb2b1d..051d426ff1 100644 --- a/libraries/plugins/src/plugins/Plugin.h +++ b/libraries/plugins/src/plugins/Plugin.h @@ -7,7 +7,7 @@ class PluginContainer; class Plugin : public QObject { public: - virtual const QString& getName() = 0; + virtual const QString& getName() const = 0; virtual bool isSupported() const; /// Called when plugin is initially loaded, typically at application start