From 9f0d41038789f546fa188d5aa2c7ecea1808ac73 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Sun, 12 Apr 2015 22:07:41 -0700 Subject: [PATCH 001/552] Working on decoupling rendering --- interface/CMakeLists.txt | 20 +- interface/src/Application.cpp | 361 +++++++----- interface/src/Application.h | 34 +- interface/src/Camera.cpp | 49 +- interface/src/Camera.h | 18 - interface/src/GLCanvas.cpp | 12 +- interface/src/audio/AudioToolBox.cpp | 13 +- interface/src/audio/AudioToolBox.h | 7 +- interface/src/avatar/Head.cpp | 3 + interface/src/avatar/MyAvatar.cpp | 15 +- interface/src/devices/OculusManager.cpp | 3 +- interface/src/devices/TV3DManager.cpp | 23 +- interface/src/devices/TV3DManager.h | 3 +- interface/src/main.cpp | 5 +- interface/src/plugins/Plugin.cpp | 1 + interface/src/plugins/Plugin.h | 20 + interface/src/plugins/PluginManager.cpp | 1 + interface/src/plugins/PluginManager.h | 12 + .../src/plugins/render/HmdRenderPlugin.cpp | 11 + .../src/plugins/render/HmdRenderPlugin.h | 15 + .../src/plugins/render/LegacyRenderPlugin.cpp | 87 +++ .../src/plugins/render/LegacyRenderPlugin.h | 36 ++ .../src/plugins/render/NullRenderPlugin.cpp | 44 ++ .../src/plugins/render/NullRenderPlugin.h | 29 + .../plugins/render/OculusBaseRenderPlugin.cpp | 10 + .../plugins/render/OculusBaseRenderPlugin.h | 77 +++ .../render/OculusDirectD3DRenderPlugin.cpp | 10 + .../render/OculusDirectD3DRenderPlugin.h | 12 + .../render/OculusDirectRenderPlugin.cpp | 10 + .../plugins/render/OculusDirectRenderPlugin.h | 12 + .../render/OculusExtendedRenderPlugin.cpp | 10 + .../render/OculusExtendedRenderPlugin.h | 12 + interface/src/plugins/render/RenderPlugin.cpp | 16 + interface/src/plugins/render/RenderPlugin.h | 63 +++ .../src/plugins/render/SimpleRenderPlugin.cpp | 13 + .../src/plugins/render/SimpleRenderPlugin.h | 56 ++ .../src/plugins/render/StereoRenderPlugin.cpp | 10 + .../src/plugins/render/StereoRenderPlugin.h | 17 + .../src/plugins/render/Tv3dRenderPlugin.cpp | 11 + .../src/plugins/render/Tv3dRenderPlugin.h | 13 + .../src/plugins/render/WindowRenderPlugin.cpp | 514 ++++++++++++++++++ .../src/plugins/render/WindowRenderPlugin.h | 40 ++ .../ControllerScriptingInterface.cpp | 3 +- .../scripting/WindowScriptingInterface.cpp | 2 +- interface/src/ui/ApplicationOverlay.cpp | 87 +-- interface/src/ui/ApplicationOverlay.h | 14 +- interface/src/ui/DialogsManager.cpp | 12 +- interface/src/ui/DialogsManager.h | 7 +- interface/src/ui/HMDToolsDialog.cpp | 3 +- interface/src/ui/HMDToolsDialog.h | 3 +- interface/src/ui/NodeBounds.cpp | 3 +- interface/src/ui/PreferencesDialog.cpp | 13 +- interface/src/ui/RearMirrorTools.cpp | 21 +- interface/src/ui/RearMirrorTools.h | 15 +- interface/src/ui/Snapshot.cpp | 3 + interface/src/ui/Stats.cpp | 21 +- interface/src/ui/overlays/Overlays.cpp | 5 +- .../src/AbstractViewStateInterface.h | 2 +- libraries/render-utils/src/GlowEffect.cpp | 53 +- libraries/render-utils/src/GlowEffect.h | 5 +- .../render-utils/src/OffscreenGlContext.cpp | 43 ++ .../render-utils/src/OffscreenGlContext.h | 33 ++ libraries/render-utils/src/TextureCache.cpp | 33 +- libraries/render-utils/src/TextureCache.h | 6 - 64 files changed, 1703 insertions(+), 412 deletions(-) create mode 100644 interface/src/plugins/Plugin.cpp create mode 100644 interface/src/plugins/Plugin.h create mode 100644 interface/src/plugins/PluginManager.cpp create mode 100644 interface/src/plugins/PluginManager.h create mode 100644 interface/src/plugins/render/HmdRenderPlugin.cpp create mode 100644 interface/src/plugins/render/HmdRenderPlugin.h create mode 100644 interface/src/plugins/render/LegacyRenderPlugin.cpp create mode 100644 interface/src/plugins/render/LegacyRenderPlugin.h create mode 100644 interface/src/plugins/render/NullRenderPlugin.cpp create mode 100644 interface/src/plugins/render/NullRenderPlugin.h create mode 100644 interface/src/plugins/render/OculusBaseRenderPlugin.cpp create mode 100644 interface/src/plugins/render/OculusBaseRenderPlugin.h create mode 100644 interface/src/plugins/render/OculusDirectD3DRenderPlugin.cpp create mode 100644 interface/src/plugins/render/OculusDirectD3DRenderPlugin.h create mode 100644 interface/src/plugins/render/OculusDirectRenderPlugin.cpp create mode 100644 interface/src/plugins/render/OculusDirectRenderPlugin.h create mode 100644 interface/src/plugins/render/OculusExtendedRenderPlugin.cpp create mode 100644 interface/src/plugins/render/OculusExtendedRenderPlugin.h create mode 100644 interface/src/plugins/render/RenderPlugin.cpp create mode 100644 interface/src/plugins/render/RenderPlugin.h create mode 100644 interface/src/plugins/render/SimpleRenderPlugin.cpp create mode 100644 interface/src/plugins/render/SimpleRenderPlugin.h create mode 100644 interface/src/plugins/render/StereoRenderPlugin.cpp create mode 100644 interface/src/plugins/render/StereoRenderPlugin.h create mode 100644 interface/src/plugins/render/Tv3dRenderPlugin.cpp create mode 100644 interface/src/plugins/render/Tv3dRenderPlugin.h create mode 100644 interface/src/plugins/render/WindowRenderPlugin.cpp create mode 100644 interface/src/plugins/render/WindowRenderPlugin.h create mode 100644 libraries/render-utils/src/OffscreenGlContext.cpp create mode 100644 libraries/render-utils/src/OffscreenGlContext.h diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index f4f390607b..85a4b3ccee 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -36,8 +36,22 @@ endif () configure_file(InterfaceConfig.h.in "${PROJECT_BINARY_DIR}/includes/InterfaceConfig.h") configure_file(InterfaceVersion.h.in "${PROJECT_BINARY_DIR}/includes/InterfaceVersion.h") + +macro(GroupSources curdir) + file(GLOB children RELATIVE ${PROJECT_SOURCE_DIR}/${curdir} ${PROJECT_SOURCE_DIR}/${curdir}/*) + foreach(child ${children}) + if(IS_DIRECTORY ${PROJECT_SOURCE_DIR}/${curdir}/${child}) + GroupSources(${curdir}/${child}) + else() + string(REPLACE "/" "\\" groupname ${curdir}) + source_group(${groupname} FILES ${PROJECT_SOURCE_DIR}/${curdir}/${child}) + endif() + endforeach() +endmacro() + # grab the implementation and header files from src dirs file(GLOB_RECURSE INTERFACE_SRCS "src/*.cpp" "src/*.h") +GroupSources("src") # Add SpeechRecognizer if on Windows or OS X, otherwise remove if (WIN32) @@ -54,10 +68,14 @@ else () list(REMOVE_ITEM INTERFACE_SRCS ${SPEECHRECOGNIZER_CPP}) endif () -find_package(Qt5 COMPONENTS Gui Multimedia Network OpenGL Script Svg WebKitWidgets) +find_package(Qt5 COMPONENTS Gui Multimedia Network OpenGL Qml Quick Script Svg WebKitWidgets) # grab the ui files in resources/ui file (GLOB_RECURSE QT_UI_FILES ui/*.ui) +source_group("UI Files" FILES ${QT_UI_FILES}) + + + # have qt5 wrap them and generate the appropriate header files qt5_wrap_ui(QT_UI_HEADERS "${QT_UI_FILES}") diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 82447257fb..6abdc744d7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -267,6 +267,7 @@ bool setupEssentials(int& argc, char** argv) { Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : QApplication(argc, argv), _dependencyManagerIsSetup(setupEssentials(argc, argv)), + _offscreenContext(new OffscreenGlContext()), _window(new MainWindow(desktop())), _toolWindow(NULL), _friendsWindow(NULL), @@ -476,18 +477,14 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : ResourceCache::setRequestLimit(3); - _window->setCentralWidget(_glWidget); - + _window->setCentralWidget(new QWidget()); _window->restoreGeometry(); - _window->setVisible(true); - _glWidget->setFocusPolicy(Qt::StrongFocus); - _glWidget->setFocus(); - - // enable mouse tracking; otherwise, we only get drag events - _glWidget->setMouseTracking(true); +#if 0 _fullscreenMenuWidget->setParent(_glWidget); +#endif + _menuBarHeight = Menu::getInstance()->height(); if (Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen)) { setFullscreen(true); // Initialize menu bar show/hide @@ -497,6 +494,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _toolWindow->setWindowFlags(_toolWindow->windowFlags() | Qt::WindowStaysOnTopHint); _toolWindow->setWindowTitle("Tools"); + _offscreenContext->create(); + _offscreenContext->makeCurrent(); + initializeGL(); // initialization continues in initializeGL when OpenGL context is ready // Tell our entity edit sender about our known jurisdictions @@ -629,9 +629,8 @@ Application::~Application() { _myAvatar = NULL; ModelEntityItem::cleanupLoadedAnimations(); - - // stop the glWidget frame timer so it doesn't call paintGL - _glWidget->stopFrameTimer(); + + getActiveRenderPlugin()->deactivate(); DependencyManager::destroy(); DependencyManager::destroy(); @@ -732,19 +731,14 @@ void Application::paintGL() { bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::paintGL()"); - // Set the desired FBO texture size. If it hasn't changed, this does nothing. - // Otherwise, it must rebuild the FBOs - if (OculusManager::isConnected()) { - DependencyManager::get()->setFrameBufferSize(OculusManager::getRenderTargetSize()); - } else { - QSize fbSize = _glWidget->getDeviceSize() * getRenderResolutionScale(); - DependencyManager::get()->setFrameBufferSize(fbSize); - } + _offscreenContext->makeCurrent(); + QSize fbSize = getActiveRenderPlugin()->getRecommendedFramebufferSize() * getRenderResolutionScale(); + DependencyManager::get()->setFrameBufferSize(fbSize); glEnable(GL_LINE_SMOOTH); if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) { - if (!OculusManager::isConnected()) { + if (!getActiveRenderPlugin()->isHmd()) { // If there isn't an HMD, match exactly to avatar's head _myCamera.setPosition(_myAvatar->getHead()->getEyePosition()); _myCamera.setRotation(_myAvatar->getHead()->getCameraOrientation()); @@ -753,17 +747,15 @@ void Application::paintGL() { _myCamera.setPosition(_myAvatar->getDefaultEyePosition()); _myCamera.setRotation(_myAvatar->getWorldAlignedOrientation()); } - } else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) { static const float THIRD_PERSON_CAMERA_DISTANCE = 1.5f; _myCamera.setPosition(_myAvatar->getDefaultEyePosition() + _myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, 1.0f) * THIRD_PERSON_CAMERA_DISTANCE * _myAvatar->getScale()); - if (OculusManager::isConnected()) { + if (getActiveRenderPlugin()->isHmd()) { _myCamera.setRotation(_myAvatar->getWorldAlignedOrientation()); } else { _myCamera.setRotation(_myAvatar->getHead()->getOrientation()); } - } else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { _myCamera.setRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f))); _myCamera.setPosition(_myAvatar->getDefaultEyePosition() + @@ -772,30 +764,17 @@ void Application::paintGL() { glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror); } - // Update camera position - if (!OculusManager::isConnected()) { - _myCamera.update(1.0f / _fps); - } - if (getShadowsEnabled()) { updateShadowMap(); } - if (OculusManager::isConnected()) { - //When in mirror mode, use camera rotation. Otherwise, use body rotation - if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { - OculusManager::display(_myCamera.getRotation(), _myCamera.getPosition(), _myCamera); - } else { - OculusManager::display(_myAvatar->getWorldAlignedOrientation(), _myAvatar->getDefaultEyePosition(), _myCamera); - } - _myCamera.update(1.0f / _fps); + DependencyManager::get()->prepare(); - } else if (TV3DManager::isConnected()) { - - TV3DManager::display(_myCamera); - - } else { - DependencyManager::get()->prepare(); + // Primary rendering pass + auto primaryFbo = DependencyManager::get()->getPrimaryFramebufferObject(); + primaryFbo->bind(); + { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Viewport is assigned to the size of the framebuffer QSize size = DependencyManager::get()->getPrimaryFramebufferObject()->size(); @@ -809,20 +788,32 @@ void Application::paintGL() { if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) { _rearMirrorTools->render(true); - } else if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { - renderRearViewMirror(_mirrorViewRect); - } - - DependencyManager::get()->render(); - - { - PerformanceTimer perfTimer("renderOverlay"); - _applicationOverlay.renderOverlay(true); - _applicationOverlay.displayOverlayTexture(); + renderRearViewMirror(_mirrorViewRect); } } + primaryFbo->release(); + + QOpenGLFramebufferObject * finalFbo = DependencyManager::get()->render(); + // This might not be needed *right now*. We want to ensure that the FBO rendering + // has completed before we start trying to read from it in another context. However + // once we have multi-threaded rendering, this will almost certainly be critical, + // but may be better handled with a fence object + glFinish(); +#if 0 + { + PerformanceTimer perfTimer("renderOverlay"); + _applicationOverlay.renderOverlay(); + _applicationOverlay.displayOverlayTexture(); + } +#endif + + _offscreenContext->doneCurrent(); + Q_ASSERT(!QOpenGLContext::currentContext()); + getActiveRenderPlugin()->render(finalFbo->texture()); + Q_ASSERT(!QOpenGLContext::currentContext()); + _offscreenContext->makeCurrent(); _frameCount++; } @@ -845,14 +836,23 @@ void Application::showEditEntitiesHelp() { } void Application::resetCamerasOnResizeGL(Camera& camera, int width, int height) { +#if 0 if (OculusManager::isConnected()) { OculusManager::configureCamera(camera, width, height); } else if (TV3DManager::isConnected()) { TV3DManager::configureCamera(camera, width, height); } else { +#endif camera.setAspectRatio((float)width / height); camera.setFieldOfView(_fieldOfView.get()); +#if 0 } +#endif +} + +void Application::resizeEvent(QResizeEvent * event) { + const QSize & newSize = event->size(); + resizeGL(newSize.width(), newSize.height()); } void Application::resizeGL(int width, int height) { @@ -911,6 +911,43 @@ bool Application::importSVOFromURL(const QString& urlString) { } bool Application::event(QEvent* event) { + switch (event->type()) { + case QEvent::MouseMove: + mouseMoveEvent((QMouseEvent*)event); + return true; + + case QEvent::MouseButtonPress: + mousePressEvent((QMouseEvent*)event); + return true; + + case QEvent::MouseButtonRelease: + mouseReleaseEvent((QMouseEvent*)event); + return true; + + case QEvent::KeyPress: + keyPressEvent((QKeyEvent*)event); + return true; + + case QEvent::KeyRelease: + keyReleaseEvent((QKeyEvent*)event); + return true; + + case QEvent::FocusIn: + //focusInEvent((QFocusEvent*)event); + //return true; + break; + + case QEvent::FocusOut: + focusOutEvent((QFocusEvent*)event); + return true; + + case QEvent::Resize: + resizeEvent((QResizeEvent *)event); + return true; + + default: + break; + } // handle custom URL if (event->type() == QEvent::FileOpen) { @@ -1102,9 +1139,11 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_J: if (isShifted) { _viewFrustum.setFocalLength(_viewFrustum.getFocalLength() - 0.1f); +#if 0 if (TV3DManager::isConnected()) { TV3DManager::configureCamera(_myCamera, _glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); } +#endif } else { _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(-0.001, 0, 0)); } @@ -1114,10 +1153,11 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_M: if (isShifted) { _viewFrustum.setFocalLength(_viewFrustum.getFocalLength() + 0.1f); +#if 0 if (TV3DManager::isConnected()) { TV3DManager::configureCamera(_myCamera, _glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); } - +#endif } else { _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0.001, 0, 0)); } @@ -1168,17 +1208,14 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_Space: { if (!event->isAutoRepeat()) { // this starts an HFActionEvent - HFActionEvent startActionEvent(HFActionEvent::startType(), - _myCamera.computePickRay(getTrueMouseX(), - getTrueMouseY())); + HFActionEvent startActionEvent(HFActionEvent::startType(), computePickRay()); sendEvent(this, &startActionEvent); } break; } case Qt::Key_Escape: { - OculusManager::abandonCalibration(); - + getActiveRenderPlugin()->abandonCalibration(); if (!event->isAutoRepeat()) { // this starts the HFCancelEvent HFBackEvent startBackEvent(HFBackEvent::startType()); @@ -1266,9 +1303,7 @@ void Application::keyReleaseEvent(QKeyEvent* event) { case Qt::Key_Space: { if (!event->isAutoRepeat()) { // this ends the HFActionEvent - HFActionEvent endActionEvent(HFActionEvent::endType(), - _myCamera.computePickRay(getTrueMouseX(), - getTrueMouseY())); + HFActionEvent endActionEvent(HFActionEvent::endType(), computePickRay()); sendEvent(this, &endActionEvent); } break; @@ -1362,7 +1397,7 @@ void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { // nobody handled this - make it an action event on the _window object HFActionEvent actionEvent(HFActionEvent::startType(), - _myCamera.computePickRay(event->x(), event->y())); + computePickRay(event->x(), event->y())); sendEvent(this, &actionEvent); } else if (event->button() == Qt::RightButton) { @@ -1397,7 +1432,7 @@ void Application::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) { // fire an action end event HFActionEvent actionEvent(HFActionEvent::endType(), - _myCamera.computePickRay(event->x(), event->y())); + computePickRay(event->x(), event->y())); sendEvent(this, &actionEvent); } } @@ -1569,11 +1604,13 @@ void Application::idle() { const float BIGGEST_DELTA_TIME_SECS = 0.25f; update(glm::clamp((float)timeSinceLastUpdate / 1000.0f, 0.0f, BIGGEST_DELTA_TIME_SECS)); } + { PerformanceTimer perfTimer("updateGL"); PerformanceWarning warn(showWarnings, "Application::idle()... updateGL()"); - _glWidget->updateGL(); + getActiveRenderPlugin()->idle(); } + { PerformanceTimer perfTimer("rest"); PerformanceWarning warn(showWarnings, "Application::idle()... rest of it"); @@ -1653,11 +1690,15 @@ void Application::setFullscreen(bool fullscreen) { } } + void Application::setEnable3DTVMode(bool enable3DTVMode) { +#if 0 resizeGL(_glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); +#endif } void Application::setEnableVRMode(bool enableVRMode) { +#if 0 if (Menu::getInstance()->isOptionChecked(MenuOption::EnableVRMode) != enableVRMode) { Menu::getInstance()->getActionForOption(MenuOption::EnableVRMode)->setChecked(enableVRMode); } @@ -1682,6 +1723,7 @@ void Application::setEnableVRMode(bool enableVRMode) { resizeGL(_glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); updateCursorVisibility(); +#endif } void Application::setLowVelocityFilter(bool lowVelocityFilter) { @@ -1689,44 +1731,36 @@ void Application::setLowVelocityFilter(bool lowVelocityFilter) { } bool Application::mouseOnScreen() const { - if (OculusManager::isConnected()) { - return getMouseX() >= 0 && getMouseX() <= _glWidget->getDeviceWidth() && - getMouseY() >= 0 && getMouseY() <= _glWidget->getDeviceHeight(); - } - return true; + return getActiveRenderPlugin()->isMouseOnScreen(); } int Application::getMouseX() const { - if (OculusManager::isConnected()) { - glm::vec2 pos = _applicationOverlay.screenToOverlay(glm::vec2(getTrueMouseX(), getTrueMouseY())); - return pos.x; - } - return getTrueMouseX(); + return getActiveRenderPlugin()->getUiMousePosition().x; } int Application::getMouseY() const { - if (OculusManager::isConnected()) { - glm::vec2 pos = _applicationOverlay.screenToOverlay(glm::vec2(getTrueMouseX(), getTrueMouseY())); - return pos.y; - } - return getTrueMouseY(); + return getActiveRenderPlugin()->getUiMousePosition().x; } int Application::getMouseDragStartedX() const { +#if 0 if (OculusManager::isConnected()) { glm::vec2 pos = _applicationOverlay.screenToOverlay(glm::vec2(getTrueMouseDragStartedX(), getTrueMouseDragStartedY())); return pos.x; } +#endif return getTrueMouseDragStartedX(); } int Application::getMouseDragStartedY() const { +#if 0 if (OculusManager::isConnected()) { glm::vec2 pos = _applicationOverlay.screenToOverlay(glm::vec2(getTrueMouseDragStartedX(), getTrueMouseDragStartedY())); return pos.y; } +#endif return getTrueMouseDragStartedY(); } @@ -1878,6 +1912,7 @@ void Application::init() { _mirrorCamera.setMode(CAMERA_MODE_MIRROR); +#if 0 OculusManager::connect(); if (OculusManager::isConnected()) { QMetaObject::invokeMethod(Menu::getInstance()->getActionForOption(MenuOption::Fullscreen), @@ -1891,6 +1926,7 @@ void Application::init() { "trigger", Qt::QueuedConnection); } +#endif _timerStart.start(); _lastTimeUpdated.start(); @@ -1955,19 +1991,20 @@ void Application::init() { _entityClipboardRenderer.setViewFrustum(getViewFrustum()); _entityClipboardRenderer.setTree(&_entityClipboard); - _rearMirrorTools = new RearMirrorTools(_glWidget, _mirrorViewRect); + _rearMirrorTools = new RearMirrorTools(_mirrorViewRect); connect(_rearMirrorTools, SIGNAL(closeView()), SLOT(closeMirrorView())); connect(_rearMirrorTools, SIGNAL(restoreView()), SLOT(restoreMirrorView())); connect(_rearMirrorTools, SIGNAL(shrinkView()), SLOT(shrinkMirrorView())); connect(_rearMirrorTools, SIGNAL(resetView()), SLOT(resetSensors())); +#if 0 // make sure our texture cache knows about window size changes DependencyManager::get()->associateWithWidget(_glWidget); +#endif // initialize the GlowEffect with our widget - DependencyManager::get()->init(_glWidget, - Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)); + DependencyManager::get()->init(Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)); } void Application::closeMirrorView() { @@ -2018,7 +2055,7 @@ void Application::updateMouseRay() { // make sure the frustum is up-to-date loadViewFrustum(_myCamera, _viewFrustum); - PickRay pickRay = _myCamera.computePickRay(getTrueMouseX(), getTrueMouseY()); + PickRay pickRay = computePickRay(); _mouseRayOrigin = pickRay.origin; _mouseRayDirection = pickRay.direction; @@ -2043,6 +2080,7 @@ void Application::updateMyAvatarLookAtPosition() { bool isLookingAtSomeone = false; glm::vec3 lookAtSpot; if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { +#if 0 // When I am in mirror mode, just look right at the camera (myself) if (!OculusManager::isConnected()) { lookAtSpot = _myCamera.getPosition(); @@ -2053,7 +2091,7 @@ void Application::updateMyAvatarLookAtPosition() { lookAtSpot = OculusManager::getRightEyePosition(); } } - +#endif } else { AvatarSharedPointer lookingAt = _myAvatar->getLookAtTargetAvatar().toStrongRef(); if (lookingAt && _myAvatar != lookingAt.data()) { @@ -2138,6 +2176,7 @@ void Application::updateCamera(float deltaTime) { bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::updateCamera()"); +#if 0 if (!OculusManager::isConnected() && !TV3DManager::isConnected() && Menu::getInstance()->isOptionChecked(MenuOption::OffAxisProjection)) { FaceTracker* tracker = getActiveFaceTracker(); @@ -2149,6 +2188,8 @@ void Application::updateCamera(float deltaTime) { updateProjectionMatrix(); } } +#endif + } void Application::updateDialogs(float deltaTime) { @@ -2239,13 +2280,13 @@ void Application::update(float deltaTime) { PerformanceTimer perfTimer("overlays"); _overlays.update(deltaTime); } - +#if 0 { PerformanceTimer perfTimer("myAvatar"); updateMyAvatarLookAtPosition(); DependencyManager::get()->updateMyAvatar(deltaTime); // Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes } - +#endif { PerformanceTimer perfTimer("emitSimulating"); // let external parties know we're updating @@ -2561,16 +2602,12 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node } bool Application::isHMDMode() const { - if (OculusManager::isConnected()) { - return true; - } else { - return false; - } + return getActiveRenderPlugin()->isHmd(); } QRect Application::getDesirableApplicationGeometry() { QRect applicationGeometry = getWindow()->geometry(); - +#if 0 // If our parent window is on the HMD, then don't use its geometry, instead use // the "main screen" geometry. HMDToolsDialog* hmdTools = DependencyManager::get()->getHMDToolsDialog(); @@ -2588,6 +2625,7 @@ QRect Application::getDesirableApplicationGeometry() { applicationGeometry = betterScreen->geometry(); } } +#endif return applicationGeometry; } @@ -2786,8 +2824,6 @@ void Application::updateShadowMap() { } fbo->release(); - - glViewport(0, 0, _glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); activeRenderingThread = nullptr; } @@ -2826,10 +2862,6 @@ int Application::getBoundaryLevelAdjust() const { return DependencyManager::get()->getBoundaryLevelAdjust(); } -PickRay Application::computePickRay(float x, float y) { - return getCamera()->computePickRay(x, y); -} - QImage Application::renderAvatarBillboard() { DependencyManager::get()->getPrimaryFramebufferObject()->bind(); @@ -2837,9 +2869,11 @@ QImage Application::renderAvatarBillboard() { Glower glower; const int BILLBOARD_SIZE = 64; +#if 0 renderRearViewMirror(QRect(0, _glWidget->getDeviceHeight() - BILLBOARD_SIZE, BILLBOARD_SIZE, BILLBOARD_SIZE), true); +#endif QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32); glReadPixels(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE, GL_BGRA, GL_UNSIGNED_BYTE, image.bits()); @@ -3130,12 +3164,13 @@ void Application::computeOffAxisFrustum(float& left, float& right, float& bottom // allow 3DTV/Oculus to override parameters from camera _displayViewFrustum.computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); +#if 0 if (OculusManager::isConnected()) { OculusManager::overrideOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); - } else if (TV3DManager::isConnected()) { TV3DManager::overrideOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); } +#endif } bool Application::getShadowsEnabled() { @@ -3148,32 +3183,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(const QRect& region, bool billboard) { // Grab current viewport to reset it at the end int viewport[4]; @@ -3214,7 +3223,6 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) { _mirrorCamera.setAspectRatio((float)region.width() / region.height()); _mirrorCamera.setRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI, 0.0f))); - _mirrorCamera.update(1.0f/_fps); // set the bounds of rear mirror view if (billboard) { @@ -3254,15 +3262,19 @@ void Application::resetSensors() { DependencyManager::get()->reset(); DependencyManager::get()->reset(); + getActiveRenderPlugin()->resetSensors(); +#if 0 OculusManager::reset(); +#endif //_leapmotion.reset(); +#if 0 QScreen* currentScreen = _window->windowHandle()->screen(); QWindow* mainWindow = _window->windowHandle(); QPoint windowCenter = mainWindow->geometry().center(); _glWidget->cursor().setPos(currentScreen, windowCenter); - +#endif _myAvatar->reset(); QMetaObject::invokeMethod(DependencyManager::get().data(), "reset", Qt::QueuedConnection); @@ -4021,7 +4033,7 @@ void Application::setPreviousScriptLocation(const QString& previousScriptLocatio void Application::loadDialog() { - QString fileNameString = QFileDialog::getOpenFileName(_glWidget, + QString fileNameString = QFileDialog::getOpenFileName(desktop(), tr("Open Script"), getPreviousScriptLocation(), tr("JavaScript Files (*.js)")); @@ -4062,7 +4074,7 @@ void Application::setScriptsLocation(const QString& scriptsLocation) { void Application::toggleLogDialog() { if (! _logDialog) { - _logDialog = new LogDialog(_glWidget, getLogger()); + _logDialog = new LogDialog(desktop(), getLogger()); } if (_logDialog->isVisible()) { @@ -4119,7 +4131,7 @@ void Application::parseVersionXml() { } if (!shouldSkipVersion(latestVersion) && applicationVersion() != latestVersion) { - new UpdateDialog(_glWidget, releaseNotes, latestVersion, downloadUrl); + new UpdateDialog(desktop(), releaseNotes, latestVersion, downloadUrl); } sender->deleteLater(); } @@ -4152,7 +4164,7 @@ void Application::takeSnapshot() { } if (!_snapshotShareDialog) { - _snapshotShareDialog = new SnapshotShareDialog(fileName, _glWidget); + _snapshotShareDialog = new SnapshotShareDialog(fileName, desktop()); } _snapshotShareDialog->show(); } @@ -4330,3 +4342,90 @@ void Application::friendsWindowClosed() { delete _friendsWindow; _friendsWindow = NULL; } + + +PickRay Application::computePickRay() const { + return computePickRay(getTrueMouseX(), getTrueMouseY()); +} + +PickRay Application::computeViewPickRay(float xRatio, float yRatio) const { + PickRay result; +#if 0 + if (OculusManager::isConnected()) { + Application::getInstance()->getApplicationOverlay().computeOculusPickRay(xRatio, yRatio, result.origin, result.direction); + } else { +#endif + Application::getInstance()->getViewFrustum()->computePickRay(xRatio, yRatio, result.origin, result.direction); +#if 0 + } +#endif + return result; +} + +PickRay Application::computePickRay(float x, float y) const { + glm::vec2 canvasSize = getCanvasSize(); + x /= canvasSize.x; + y /= canvasSize.y; + return computeViewPickRay(x, y); +} + +glm::ivec2 Application::getCanvasSize() const { + return getActiveRenderPlugin()->getCanvasSize(); +} + +QSize Application::getDeviceSize() const { + return getActiveRenderPlugin()->getRecommendedFramebufferSize(); // _glWidget->getDeviceSize(); +} + +void Application::resizeGL() { + auto size = getCanvasSize(); + return resizeGL(size.x, size.y); +} + +bool Application::hasFocus() const { + return getActiveRenderPlugin()->hasFocus(); +} + +glm::vec2 Application::getViewportDimensions() const { + return toGlm(getDeviceSize()); +} + +int Application::getTrueMouseX() const { + return getActiveRenderPlugin()->getTrueMousePosition().x; +} + +int Application::getTrueMouseY() const { + return getActiveRenderPlugin()->getTrueMousePosition().y; +} + +bool Application::isThrottleRendering() const { + return getActiveRenderPlugin()->isThrottled(); +} + +#include "plugins/render/NullRenderPlugin.h" +#include "plugins/render/WindowRenderPlugin.h" +#include "plugins/render/LegacyRenderPlugin.h" + +static RenderPlugin * renderPlugin = nullptr; + +RenderPlugin * Application::getActiveRenderPlugin() { + if (nullptr == renderPlugin) { + //renderPlugin = new WindowRenderPlugin(); + renderPlugin = new LegacyRenderPlugin(); + renderPlugin->init(); + renderPlugin->activate(); + connect(renderPlugin, &RenderPlugin::requestRender, this, [&] { + this->paintGL(); + }); + connect(renderPlugin, &RenderPlugin::recommendedFramebufferSizeChanged, this, [&](const QSize & size) { + DependencyManager::get()->setFrameBufferSize(size * getRenderResolutionScale()); + this->resizeGL(size.width(), size.height()); + }); + _offscreenContext->makeCurrent(); + } + return renderPlugin; +} + +const RenderPlugin * Application::getActiveRenderPlugin() const { + return ((Application*)this)->getActiveRenderPlugin(); +} diff --git a/interface/src/Application.h b/interface/src/Application.h index cf047f02d4..40db775f60 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -36,6 +36,8 @@ #include #include #include +#include + #include "AudioClient.h" #include "Bookmarks.h" @@ -70,6 +72,7 @@ #include "octree/OctreeFade.h" #include "octree/OctreePacketProcessor.h" #include "UndoStackScriptingInterface.h" +#include "plugins/render/RenderPlugin.h" class QGLWidget; @@ -154,6 +157,8 @@ public: void paintGL(); void resizeGL(int width, int height); + void resizeEvent(QResizeEvent * size); + void keyPressEvent(QKeyEvent* event); void keyReleaseEvent(QKeyEvent* event); @@ -174,8 +179,14 @@ public: bool event(QEvent* event); bool eventFilter(QObject* object, QEvent* event); - GLCanvas* getGLWidget() { return _glWidget; } - bool isThrottleRendering() const { return _glWidget->isThrottleRendering(); } + glm::ivec2 getCanvasSize() const; + QSize getDeviceSize() const; + bool hasFocus() const; + PickRay computePickRay() const; + PickRay computeViewPickRay(float xRatio, float yRatio) const; + void resizeGL(); + + bool isThrottleRendering() const; Camera* getCamera() { return &_myCamera; } // Represents the current view frustum of the avatar. @@ -201,8 +212,8 @@ public: bool mouseOnScreen() const; int getMouseX() const; int getMouseY() const; - int getTrueMouseX() const { return _glWidget->mapFromGlobal(QCursor::pos()).x(); } - int getTrueMouseY() const { return _glWidget->mapFromGlobal(QCursor::pos()).y(); } + int getTrueMouseX() const; + int getTrueMouseY() const; int getMouseDragStartedX() const; int getMouseDragStartedY() const; int getTrueMouseDragStartedX() const { return _mouseDragStartedX; } @@ -271,15 +282,17 @@ public: virtual QThread* getMainThread() { return thread(); } virtual float getSizeScale() const; virtual int getBoundaryLevelAdjust() const; - virtual PickRay computePickRay(float x, float y); + virtual PickRay computePickRay(float x, float y) const; virtual const glm::vec3& getAvatarPosition() const { return _myAvatar->getPosition(); } + RenderPlugin * getActiveRenderPlugin(); + const RenderPlugin * getActiveRenderPlugin() const; NodeBounds& getNodeBoundsDisplay() { return _nodeBoundsDisplay; } FileLogger* getLogger() { return _logger; } - glm::vec2 getViewportDimensions() const { return glm::vec2(_glWidget->getDeviceWidth(), - _glWidget->getDeviceHeight()); } + glm::vec2 getViewportDimensions() const; + NodeToJurisdictionMap& getEntityServerJurisdictions() { return _entityServerJurisdictions; } void skipVersion(QString latestVersion); @@ -411,8 +424,6 @@ private slots: void setEnableVRMode(bool enableVRMode); void cameraMenuChanged(); - glm::vec2 getScaledScreenPoint(glm::vec2 projectedPoint); - void closeMirrorView(); void restoreMirrorView(); void shrinkMirrorView(); @@ -471,6 +482,9 @@ private: int sendNackPackets(); bool _dependencyManagerIsSetup; + + OffscreenGlContext* _offscreenContext{ new OffscreenGlContext() }; + MainWindow* _window; ToolWindow* _toolWindow; @@ -611,7 +625,7 @@ private: QThread _settingsThread; QTimer _settingsTimer; - GLCanvas* _glWidget = new GLCanvas(); // our GLCanvas has a couple extra features + void checkSkeleton(); diff --git a/interface/src/Camera.cpp b/interface/src/Camera.cpp index e334fd7c65..40ce59ffdb 100644 --- a/interface/src/Camera.cpp +++ b/interface/src/Camera.cpp @@ -55,42 +55,24 @@ Camera::Camera() : _farClip(DEFAULT_FAR_CLIP), // default _hmdPosition(), _hmdRotation(), - _scale(1.0f), - _isKeepLookingAt(false), - _lookingAt(0.0f, 0.0f, 0.0f) + _scale(1.0f) { } -void Camera::update(float deltaTime) { - if (_isKeepLookingAt) { - lookAt(_lookingAt); - } - return; -} - void Camera::setPosition(const glm::vec3& position) { _position = position; } void Camera::setRotation(const glm::quat& rotation) { _rotation = rotation; - if (_isKeepLookingAt) { - lookAt(_lookingAt); - } } void Camera::setHmdPosition(const glm::vec3& hmdPosition) { _hmdPosition = hmdPosition; - if (_isKeepLookingAt) { - lookAt(_lookingAt); - } } void Camera::setHmdRotation(const glm::quat& hmdRotation) { _hmdRotation = hmdRotation; - if (_isKeepLookingAt) { - lookAt(_lookingAt); - } } float Camera::getFarClip() const { @@ -121,21 +103,6 @@ void Camera::setFarClip(float f) { _farClip = f; } -PickRay Camera::computePickRay(float x, float y) { - auto glCanvas = Application::getInstance()->getGLWidget(); - return computeViewPickRay(x / glCanvas->width(), y / glCanvas->height()); -} - -PickRay Camera::computeViewPickRay(float xRatio, float yRatio) { - PickRay result; - if (OculusManager::isConnected()) { - Application::getInstance()->getApplicationOverlay().computeOculusPickRay(xRatio, yRatio, result.origin, result.direction); - } else { - Application::getInstance()->getViewFrustum()->computePickRay(xRatio, yRatio, result.origin, result.direction); - } - return result; -} - void Camera::setModeString(const QString& mode) { CameraMode targetMode = stringToMode(mode); @@ -164,17 +131,3 @@ void Camera::setModeString(const QString& mode) { QString Camera::getModeString() const { return modeToString(_mode); } - -void Camera::lookAt(const glm::vec3& lookAt) { - glm::vec3 up = IDENTITY_UP; - glm::mat4 lookAtMatrix = glm::lookAt(_position, lookAt, up); - glm::quat rotation = glm::quat_cast(lookAtMatrix); - rotation.w = -rotation.w; // Rosedale approved - _rotation = rotation; -} - -void Camera::keepLookingAt(const glm::vec3& point) { - lookAt(point); - _isKeepLookingAt = true; - _lookingAt = point; -} diff --git a/interface/src/Camera.h b/interface/src/Camera.h index 7c6951b920..216ddcae61 100644 --- a/interface/src/Camera.h +++ b/interface/src/Camera.h @@ -41,8 +41,6 @@ public: void initialize(); // instantly put the camera at the ideal position and rotation. - void update( float deltaTime ); - void setRotation(const glm::quat& rotation); void setHmdPosition(const glm::vec3& hmdPosition); void setHmdRotation(const glm::quat& hmdRotation); @@ -77,20 +75,6 @@ public slots: void setOrientation(const glm::quat& orientation) { setRotation(orientation); } glm::quat getOrientation() const { return getRotation(); } - - PickRay computePickRay(float x, float y); - PickRay computeViewPickRay(float xRatio, float yRatio); - - // These only work on independent cameras - /// one time change to what the camera is looking at - void lookAt(const glm::vec3& value); - - /// fix what the camera is looking at, and keep the camera looking at this even if position changes - void keepLookingAt(const glm::vec3& value); - - /// stops the keep looking at feature, doesn't change what's being looked at, but will stop camera from - /// continuing to update it's orientation to keep looking at the item - void stopLooking() { _isKeepLookingAt = false; } signals: void modeUpdated(const QString& newMode); @@ -108,8 +92,6 @@ private: glm::vec3 _hmdPosition; glm::quat _hmdRotation; float _scale; - bool _isKeepLookingAt; - glm::vec3 _lookingAt; }; #endif // hifi_Camera_h diff --git a/interface/src/GLCanvas.cpp b/interface/src/GLCanvas.cpp index 12a10681ce..a8b3a29a98 100644 --- a/interface/src/GLCanvas.cpp +++ b/interface/src/GLCanvas.cpp @@ -60,21 +60,27 @@ void GLCanvas::initializeGL() { void GLCanvas::paintGL() { if (!_throttleRendering && !Application::getInstance()->getWindow()->isMinimized()) { +#if 0 //Need accurate frame timing for the oculus rift if (OculusManager::isConnected()) { OculusManager::beginFrameTiming(); } - +#endif Application::getInstance()->paintGL(); +#if 0 if (!OculusManager::isConnected()) { +#endif + swapBuffers(); +#if 0 } else { if (OculusManager::allowSwap()) { swapBuffers(); } OculusManager::endFrameTiming(); } +#endif } } @@ -134,17 +140,21 @@ void GLCanvas::activeChanged(Qt::ApplicationState state) { void GLCanvas::throttleRender() { _frameTimer.start(_idleRenderInterval); if (!Application::getInstance()->getWindow()->isMinimized()) { +#if 0 //Need accurate frame timing for the oculus rift if (OculusManager::isConnected()) { OculusManager::beginFrameTiming(); } +#endif Application::getInstance()->paintGL(); swapBuffers(); +#if 0 if (OculusManager::isConnected()) { OculusManager::endFrameTiming(); } +#endif } } diff --git a/interface/src/audio/AudioToolBox.cpp b/interface/src/audio/AudioToolBox.cpp index 330e7bc194..5d1b12b5a7 100644 --- a/interface/src/audio/AudioToolBox.cpp +++ b/interface/src/audio/AudioToolBox.cpp @@ -38,15 +38,14 @@ bool AudioToolBox::mousePressEvent(int x, int y) { void AudioToolBox::render(int x, int y, bool boxed) { glEnable(GL_TEXTURE_2D); - auto glCanvas = Application::getInstance()->getGLWidget(); if (_micTextureId == 0) { - _micTextureId = glCanvas->bindTexture(QImage(PathUtils::resourcesPath() + "images/mic.svg")); + _micTextureId = new QOpenGLTexture(QImage(PathUtils::resourcesPath() + "images/mic.svg")); } if (_muteTextureId == 0) { - _muteTextureId = glCanvas->bindTexture(QImage(PathUtils::resourcesPath() + "images/mic-mute.svg")); + _muteTextureId = new QOpenGLTexture(QImage(PathUtils::resourcesPath() + "images/mic-mute.svg")); } if (_boxTextureId == 0) { - _boxTextureId = glCanvas->bindTexture(QImage(PathUtils::resourcesPath() + "images/audio-box.svg")); + _boxTextureId = new QOpenGLTexture(QImage(PathUtils::resourcesPath() + "images/audio-box.svg")); } auto audioIO = DependencyManager::get(); @@ -60,7 +59,7 @@ void AudioToolBox::render(int x, int y, bool boxed) { QRect boxBounds = QRect(x - BOX_LEFT_PADDING, y - BOX_TOP_PADDING, BOX_WIDTH, BOX_HEIGHT); - glBindTexture(GL_TEXTURE_2D, _boxTextureId); + _boxTextureId->bind(); glm::vec4 quadColor; @@ -81,10 +80,10 @@ void AudioToolBox::render(int x, int y, bool boxed) { _iconBounds = QRect(x, y, MUTE_ICON_SIZE, MUTE_ICON_SIZE); if (!audioIO->isMuted()) { - glBindTexture(GL_TEXTURE_2D, _micTextureId); + _micTextureId->bind(); iconColor = 1.0f; } else { - glBindTexture(GL_TEXTURE_2D, _muteTextureId); + _muteTextureId->bind(); // Make muted icon pulsate static const float PULSE_MIN = 0.4f; diff --git a/interface/src/audio/AudioToolBox.h b/interface/src/audio/AudioToolBox.h index 526de89b9c..8ace687b9b 100644 --- a/interface/src/audio/AudioToolBox.h +++ b/interface/src/audio/AudioToolBox.h @@ -14,6 +14,7 @@ #include #include +#include class AudioToolBox : public Dependency { SINGLETON_DEPENDENCY @@ -24,9 +25,9 @@ public: protected: AudioToolBox(); private: - GLuint _micTextureId = 0; - GLuint _muteTextureId = 0; - GLuint _boxTextureId = 0; + QOpenGLTexture* _micTextureId = 0; + QOpenGLTexture* _muteTextureId = 0; + QOpenGLTexture* _boxTextureId = 0; int _boxQuadID = GeometryCache::UNKNOWN_ID; QRect _iconBounds; qint64 _iconPulseTimeReference = 0; diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index b90b693139..af5455653a 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -289,9 +289,12 @@ glm::quat Head::getCameraOrientation() const { // to change the driving direction while in Oculus mode. It is used to support driving toward where you're // head is looking. Note that in oculus mode, your actual camera view and where your head is looking is not // always the same. +#if 0 if (OculusManager::isConnected()) { return getOrientation(); } +#endif + Avatar* owningAvatar = static_cast(_owningAvatar); return owningAvatar->getWorldAlignedOrientation() * glm::quat(glm::radians(glm::vec3(_basePitch, 0.0f, 0.0f))); } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 6b70577754..48f6a9a75f 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -230,6 +230,7 @@ void MyAvatar::simulate(float deltaTime) { void MyAvatar::updateFromTrackers(float deltaTime) { glm::vec3 estimatedPosition, estimatedRotation; +#if 0 if (isPlaying() && !OculusManager::isConnected()) { return; } @@ -301,6 +302,7 @@ void MyAvatar::updateFromTrackers(float deltaTime) { -MAX_LEAN, MAX_LEAN)); head->setLeanForward(glm::clamp(glm::degrees(atanf(relativePosition.z * _leanScale / TORSO_LENGTH)), -MAX_LEAN, MAX_LEAN)); +#endif } @@ -829,11 +831,15 @@ void MyAvatar::updateLookAtTargetAvatar() { howManyLookingAtMe++; // Have that avatar look directly at my camera // Philip TODO: correct to look at left/right eye +#if 0 if (OculusManager::isConnected()) { avatar->getHead()->setCorrectedLookAtPosition(OculusManager::getLeftEyePosition()); } else { +#endif avatar->getHead()->setCorrectedLookAtPosition(Application::getInstance()->getViewFrustum()->getPosition()); +#if 0 } +#endif } else { avatar->getHead()->clearCorrectedLookAtPosition(); } @@ -1017,6 +1023,7 @@ void MyAvatar::renderBody(ViewFrustum* renderFrustum, RenderArgs::RenderMode ren renderFrustum->setNearClip(DEFAULT_NEAR_CLIP); } else { float clipDistance = _skeletonModel.getHeadClipDistance(); +#if 0 if (OculusManager::isConnected()) { // If avatar is horizontally in front of camera, increase clip distance by the amount it is in front. glm::vec3 cameraToAvatar = _position - cameraPos; @@ -1027,6 +1034,7 @@ void MyAvatar::renderBody(ViewFrustum* renderFrustum, RenderArgs::RenderMode ren clipDistance += headOffset; } } +#endif renderFrustum->setNearClip(clipDistance); } } @@ -1061,11 +1069,13 @@ void MyAvatar::updateOrientation(float deltaTime) { // Gather rotation information from keyboard const float TIME_BETWEEN_HMD_TURNS = 0.5f; const float HMD_TURN_DEGREES = 22.5f; +#if 0 if (!OculusManager::isConnected()) { // Smoothly rotate body with arrow keys if not in HMD _bodyYawDelta -= _driveKeys[ROT_RIGHT] * YAW_SPEED * deltaTime; _bodyYawDelta += _driveKeys[ROT_LEFT] * YAW_SPEED * deltaTime; } else { +#endif // Jump turns if in HMD if (_driveKeys[ROT_RIGHT] || _driveKeys[ROT_LEFT]) { if (_turningKeyPressTime == 0.0f) { @@ -1079,7 +1089,9 @@ void MyAvatar::updateOrientation(float deltaTime) { } else { _turningKeyPressTime = 0.0f; } +#if 0 } +#endif getHead()->setBasePitch(getHead()->getBasePitch() + (_driveKeys[ROT_UP] - _driveKeys[ROT_DOWN]) * PITCH_SPEED * deltaTime); // update body orientation by movement inputs @@ -1095,6 +1107,7 @@ void MyAvatar::updateOrientation(float deltaTime) { float MINIMUM_ROTATION_RATE = 2.0f; if (fabs(_bodyYawDelta) < MINIMUM_ROTATION_RATE) { _bodyYawDelta = 0.0f; } +#if 0 if (OculusManager::isConnected()) { // these angles will be in radians float yaw, pitch, roll; @@ -1117,7 +1130,7 @@ void MyAvatar::updateOrientation(float deltaTime) { } } - +#endif } glm::vec3 MyAvatar::applyKeyboardMotor(float deltaTime, const glm::vec3& localVelocity, bool isHovering) { diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index d56ece12fb..22ac44c5d4 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -9,7 +9,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // - +#if 0 #include "InterfaceConfig.h" #include "OculusManager.h" @@ -860,3 +860,4 @@ int OculusManager::getHMDScreen() { return hmdScreenIndex; } +#endif \ No newline at end of file diff --git a/interface/src/devices/TV3DManager.cpp b/interface/src/devices/TV3DManager.cpp index f082c6de47..e64a547dc1 100644 --- a/interface/src/devices/TV3DManager.cpp +++ b/interface/src/devices/TV3DManager.cpp @@ -35,18 +35,15 @@ bool TV3DManager::isConnected() { } void TV3DManager::connect() { - auto glCanvas = Application::getInstance()->getGLWidget(); - int width = glCanvas->getDeviceWidth(); - int height = glCanvas->getDeviceHeight(); + auto deviceSize = qApp->getDeviceSize(); Camera& camera = *Application::getInstance()->getCamera(); - - configureCamera(camera, width, height); + configureCamera(camera, deviceSize.width(), deviceSize.height()); } // The basic strategy of this stereoscopic rendering is explained here: // http://www.orthostereo.com/geometryopengl.html -void TV3DManager::setFrustum(Camera& whichCamera) { +void TV3DManager::setFrustum(const Camera& whichCamera) { const double DTR = 0.0174532925; // degree to radians const double IOD = 0.05; //intraocular distance double fovy = whichCamera.getFieldOfView(); // field of view in y-axis @@ -70,7 +67,9 @@ void TV3DManager::setFrustum(Camera& whichCamera) { _rightEye.modelTranslation = -IOD / 2; } -void TV3DManager::configureCamera(Camera& whichCamera, int screenWidth, int screenHeight) { +void TV3DManager::configureCamera(Camera& whichCamera_, int screenWidth, int screenHeight) { + const Camera& whichCamera = whichCamera_; + if (screenHeight == 0) { screenHeight = 1; // prevent divide by 0 } @@ -93,8 +92,7 @@ void TV3DManager::display(Camera& whichCamera) { // left eye portal int portalX = 0; int portalY = 0; - auto glCanvas = Application::getInstance()->getGLWidget(); - QSize deviceSize = glCanvas->getDeviceSize() * + QSize deviceSize = qApp->getDeviceSize() * Application::getInstance()->getRenderResolutionScale(); int portalW = deviceSize.width() / 2; int portalH = deviceSize.height(); @@ -103,7 +101,7 @@ void TV3DManager::display(Camera& whichCamera) { // We only need to render the overlays to a texture once, then we just render the texture as a quad // PrioVR will only work if renderOverlay is called, calibration is connected to Application::renderingOverlay() - applicationOverlay.renderOverlay(true); + applicationOverlay.renderOverlay(); DependencyManager::get()->prepare(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -134,7 +132,9 @@ void TV3DManager::display(Camera& whichCamera) { eyeCamera.setEyeOffsetPosition(glm::vec3(-_activeEye->modelTranslation,0,0)); Application::getInstance()->displaySide(eyeCamera, false, RenderArgs::MONO); +#if 0 applicationOverlay.displayOverlayTexture3DTV(whichCamera, _aspect, fov); +#endif _activeEye = NULL; } glPopMatrix(); @@ -162,8 +162,9 @@ void TV3DManager::display(Camera& whichCamera) { glLoadIdentity(); eyeCamera.setEyeOffsetPosition(glm::vec3(-_activeEye->modelTranslation,0,0)); Application::getInstance()->displaySide(eyeCamera, false, RenderArgs::MONO); - +#if 0 applicationOverlay.displayOverlayTexture3DTV(whichCamera, _aspect, fov); +#endif _activeEye = NULL; } glPopMatrix(); diff --git a/interface/src/devices/TV3DManager.h b/interface/src/devices/TV3DManager.h index 2b2b9e0aa1..e68f1fc14e 100644 --- a/interface/src/devices/TV3DManager.h +++ b/interface/src/devices/TV3DManager.h @@ -11,7 +11,6 @@ #ifndef hifi_TV3DManager_h #define hifi_TV3DManager_h - #include #include @@ -37,7 +36,7 @@ public: 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(Camera& whichCamera); + static void setFrustum(const Camera& whichCamera); static int _screenWidth; static int _screenHeight; static double _aspect; diff --git a/interface/src/main.cpp b/interface/src/main.cpp index b4486ceb2b..cf4f00fc5a 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -94,11 +94,14 @@ int main(int argc, const char* argv[]) { usecTimestampNowForceClockSkew(clockSkew); qCDebug(interfaceapp, "clockSkewOption=%s clockSkew=%d", clockSkewOption, clockSkew); } + +#if 0 // Oculus initialization MUST PRECEDE OpenGL context creation. // The nature of the Application constructor means this has to be either here, // or in the main window ctor, before GL startup. OculusManager::init(); - +#endif + int exitCode; { QSettings::setDefaultFormat(QSettings::IniFormat); diff --git a/interface/src/plugins/Plugin.cpp b/interface/src/plugins/Plugin.cpp new file mode 100644 index 0000000000..d882c538b4 --- /dev/null +++ b/interface/src/plugins/Plugin.cpp @@ -0,0 +1 @@ +#include "Plugin.h" diff --git a/interface/src/plugins/Plugin.h b/interface/src/plugins/Plugin.h new file mode 100644 index 0000000000..9145139808 --- /dev/null +++ b/interface/src/plugins/Plugin.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include + +class Plugin : public QObject { +private: + bool _active{ false }; +public: + virtual const QString & getName() = 0; + virtual bool isSupported() { return true; } + + virtual void init() {} + virtual void deinit() {} + + virtual void activate() {} + virtual void deactivate() {} + + virtual void idle() {} +}; diff --git a/interface/src/plugins/PluginManager.cpp b/interface/src/plugins/PluginManager.cpp new file mode 100644 index 0000000000..7f631abd64 --- /dev/null +++ b/interface/src/plugins/PluginManager.cpp @@ -0,0 +1 @@ +#include "PluginManager.h" diff --git a/interface/src/plugins/PluginManager.h b/interface/src/plugins/PluginManager.h new file mode 100644 index 0000000000..96cb777235 --- /dev/null +++ b/interface/src/plugins/PluginManager.h @@ -0,0 +1,12 @@ +#pragma once + +#include "plugins/Plugin.h" +#include "plugins/render/RenderPlugin.h" +#include +#include + +class PluginManager : public QObject { +public: + static PluginManager * getInstance(); + const QList> getRenderPlugins(); +}; diff --git a/interface/src/plugins/render/HmdRenderPlugin.cpp b/interface/src/plugins/render/HmdRenderPlugin.cpp new file mode 100644 index 0000000000..eb2efcc8a8 --- /dev/null +++ b/interface/src/plugins/render/HmdRenderPlugin.cpp @@ -0,0 +1,11 @@ +// +// HmdRenderPlugin.cpp +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "HmdRenderPlugin.h" diff --git a/interface/src/plugins/render/HmdRenderPlugin.h b/interface/src/plugins/render/HmdRenderPlugin.h new file mode 100644 index 0000000000..aa158a1f52 --- /dev/null +++ b/interface/src/plugins/render/HmdRenderPlugin.h @@ -0,0 +1,15 @@ +// +// HmdRenderPlugin.h +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "StereoRenderPlugin.h" + +class HmdRenderPlugin : public StereoRenderPlugin { + virtual bool isHmd() const final { return true; } +}; diff --git a/interface/src/plugins/render/LegacyRenderPlugin.cpp b/interface/src/plugins/render/LegacyRenderPlugin.cpp new file mode 100644 index 0000000000..6d46c6d3f5 --- /dev/null +++ b/interface/src/plugins/render/LegacyRenderPlugin.cpp @@ -0,0 +1,87 @@ +// +// LegacyRenderPlugin.cpp +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "Application.h" +#include "LegacyRenderPlugin.h" +#include "MainWindow.h" +#include + +const QString LegacyRenderPlugin::NAME("LegacyRenderPlugin"); + +const QString & LegacyRenderPlugin::getName() { + return NAME; +} + +static QWidget * oldWidget = nullptr; + +void LegacyRenderPlugin::activate() { + _window = new GLCanvas(); + QGLFormat format(QGL::NoDepthBuffer | QGL::NoStencilBuffer); + _window->setContext(new QGLContext(format), + QGLContext::fromOpenGLContext(QOpenGLContext::currentContext())); + _window->makeCurrent(); + oldWidget = qApp->getWindow()->centralWidget(); + qApp->getWindow()->setCentralWidget(_window); + _window->doneCurrent(); + _window->setFocusPolicy(Qt::StrongFocus); + _window->setFocus(); + _window->setMouseTracking(true); +} + +void LegacyRenderPlugin::deactivate() { + qApp->getWindow()->setCentralWidget(oldWidget); + // stop the glWidget frame timer so it doesn't call paintGL + _window->stopFrameTimer(); + _window->doneCurrent(); + _window->deleteLater(); + _window = nullptr; +} + +QSize LegacyRenderPlugin::getRecommendedFramebufferSize() const { + return _window->getDeviceSize(); +} + +void LegacyRenderPlugin::makeCurrent() { + _window->makeCurrent(); + QSize windowSize = _window->size(); + glViewport(0, 0, windowSize.width(), windowSize.height()); +} + +void LegacyRenderPlugin::doneCurrent() { + _window->doneCurrent(); +} + +void LegacyRenderPlugin::swapBuffers() { + _window->swapBuffers(); + glFinish(); +} + +void LegacyRenderPlugin::idle() { + _window->updateGL(); +} + +glm::ivec2 LegacyRenderPlugin::getCanvasSize() const { + return toGlm(_window->size()); +} + +bool LegacyRenderPlugin::hasFocus() const { + return _window->hasFocus(); +} + +PickRay LegacyRenderPlugin::computePickRay(const glm::vec2 & pos) const { + return PickRay(); +} + +bool isMouseOnScreen() { + return false; +} + +bool LegacyRenderPlugin::isThrottled() { + return _window->isThrottleRendering(); +} \ No newline at end of file diff --git a/interface/src/plugins/render/LegacyRenderPlugin.h b/interface/src/plugins/render/LegacyRenderPlugin.h new file mode 100644 index 0000000000..68161f6c7d --- /dev/null +++ b/interface/src/plugins/render/LegacyRenderPlugin.h @@ -0,0 +1,36 @@ +// +// LegacyRenderPlugin.h +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "SimpleRenderPlugin.h" +#include "GLCanvas.h" + +class LegacyRenderPlugin : public SimpleRenderPlugin { + Q_OBJECT +public: + static const QString NAME; + virtual const QString & getName(); + + virtual void activate(); + virtual void deactivate(); + + virtual QSize getRecommendedFramebufferSize() const; + virtual glm::ivec2 getCanvasSize() const; + virtual bool hasFocus() const; + virtual PickRay computePickRay(const glm::vec2 & pos) const; + virtual bool isMouseOnScreen() const { return true; } + virtual bool isThrottled(); + +protected: + virtual void makeCurrent(); + virtual void doneCurrent(); + virtual void swapBuffers(); + virtual void idle(); +}; diff --git a/interface/src/plugins/render/NullRenderPlugin.cpp b/interface/src/plugins/render/NullRenderPlugin.cpp new file mode 100644 index 0000000000..f2221a5767 --- /dev/null +++ b/interface/src/plugins/render/NullRenderPlugin.cpp @@ -0,0 +1,44 @@ +// +// NullRenderPlugin.cpp +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "NullRenderPlugin.h" + +const QString NullRenderPlugin::NAME("NullRenderPlugin"); + +const QString & NullRenderPlugin::getName() { + return NAME; +} + +QSize NullRenderPlugin::getRecommendedFramebufferSize() const { + return QSize(100, 100); +} + +glm::ivec2 NullRenderPlugin::getCanvasSize() const { + return glm::ivec2(100, 100); +} + +bool NullRenderPlugin::hasFocus() const { + return false; +} + +glm::ivec2 NullRenderPlugin::getRelativeMousePosition() const { + return glm::ivec2(); +} + +glm::ivec2 NullRenderPlugin::getTrueMousePosition() const { + return glm::ivec2(); +} + +PickRay NullRenderPlugin::computePickRay(const glm::vec2 & pos) const { + return PickRay(); +} + +bool NullRenderPlugin::isMouseOnScreen() { + return false; +} diff --git a/interface/src/plugins/render/NullRenderPlugin.h b/interface/src/plugins/render/NullRenderPlugin.h new file mode 100644 index 0000000000..dfe0e5a0bf --- /dev/null +++ b/interface/src/plugins/render/NullRenderPlugin.h @@ -0,0 +1,29 @@ +// +// NullRenderPlugin.h +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "RenderPlugin.h" + +class NullRenderPlugin : public RenderPlugin { +public: + static const QString NAME; + + virtual ~NullRenderPlugin() final {} + virtual const QString & getName(); + + virtual QSize getRecommendedFramebufferSize() 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(); + +}; diff --git a/interface/src/plugins/render/OculusBaseRenderPlugin.cpp b/interface/src/plugins/render/OculusBaseRenderPlugin.cpp new file mode 100644 index 0000000000..1bdab2d65a --- /dev/null +++ b/interface/src/plugins/render/OculusBaseRenderPlugin.cpp @@ -0,0 +1,10 @@ +// +// OculusBaseRenderPlugin.cpp +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "OculusBaseRenderPlugin.h" diff --git a/interface/src/plugins/render/OculusBaseRenderPlugin.h b/interface/src/plugins/render/OculusBaseRenderPlugin.h new file mode 100644 index 0000000000..beefc45077 --- /dev/null +++ b/interface/src/plugins/render/OculusBaseRenderPlugin.h @@ -0,0 +1,77 @@ +// +// OculusBaseRenderPlugin.h +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "HmdRenderPlugin.h" + +class OculusRenderPluginBase : public HmdRenderPlugin { + +}; + +#if 0 +// Set the desired FBO texture size. If it hasn't changed, this does nothing. +// Otherwise, it must rebuild the FBOs +if (OculusManager::isConnected()) { + DependencyManager::get()->setFrameBufferSize(OculusManager::getRenderTargetSize()); +} else { + + + + +#endif + +#if 0 + // Update camera position + if (!OculusManager::isConnected()) { + _myCamera.update(1.0f / _fps); + } +#endif + +#if 0 + if (OculusManager::isConnected()) { + //When in mirror mode, use camera rotation. Otherwise, use body rotation + if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { + OculusManager::display(_myCamera.getRotation(), _myCamera.getPosition(), _myCamera); + } else { + OculusManager::display(_myAvatar->getWorldAlignedOrientation(), _myAvatar->getDefaultEyePosition(), _myCamera); + } + _myCamera.update(1.0f / _fps); + + } else if (TV3DManager::isConnected()) { + + TV3DManager::display(_myCamera); + + } else { +#endif + +#if 0 + OculusManager::abandonCalibration(); +#endif + +#if 0 + if (OculusManager::isConnected()) { + return getMouseX() >= 0 && getMouseX() <= _glWidget->getDeviceWidth() && + getMouseY() >= 0 && getMouseY() <= _glWidget->getDeviceHeight(); + } +#endif + +#if 0 + if (OculusManager::isConnected()) { + glm::vec2 pos = _applicationOverlay.screenToOverlay(glm::vec2(getTrueMouseX(), getTrueMouseY())); + return pos.x; + } +#endif +#if 0 + if (OculusManager::isConnected()) { + glm::vec2 pos = _applicationOverlay.screenToOverlay(glm::vec2(getTrueMouseX(), getTrueMouseY())); + return pos.y; + } +#endif + diff --git a/interface/src/plugins/render/OculusDirectD3DRenderPlugin.cpp b/interface/src/plugins/render/OculusDirectD3DRenderPlugin.cpp new file mode 100644 index 0000000000..fab4fd104f --- /dev/null +++ b/interface/src/plugins/render/OculusDirectD3DRenderPlugin.cpp @@ -0,0 +1,10 @@ +// +// OculusDirectD3DRenderPlugin.cpp +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "OculusDirectD3DRenderPlugin.h" diff --git a/interface/src/plugins/render/OculusDirectD3DRenderPlugin.h b/interface/src/plugins/render/OculusDirectD3DRenderPlugin.h new file mode 100644 index 0000000000..3874481e69 --- /dev/null +++ b/interface/src/plugins/render/OculusDirectD3DRenderPlugin.h @@ -0,0 +1,12 @@ +// +// OculusDirectD3DRenderPlugin.h +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "OculusBaseRenderPlugin.h" diff --git a/interface/src/plugins/render/OculusDirectRenderPlugin.cpp b/interface/src/plugins/render/OculusDirectRenderPlugin.cpp new file mode 100644 index 0000000000..cd96ff0fad --- /dev/null +++ b/interface/src/plugins/render/OculusDirectRenderPlugin.cpp @@ -0,0 +1,10 @@ +// +// OculusDirectRenderPlugin.cpp +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "OculusDirectRenderPlugin.h" diff --git a/interface/src/plugins/render/OculusDirectRenderPlugin.h b/interface/src/plugins/render/OculusDirectRenderPlugin.h new file mode 100644 index 0000000000..afa72cb92e --- /dev/null +++ b/interface/src/plugins/render/OculusDirectRenderPlugin.h @@ -0,0 +1,12 @@ +// +// OculusDirectRenderPlugin.h +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "OculusBaseRenderPlugin.h" diff --git a/interface/src/plugins/render/OculusExtendedRenderPlugin.cpp b/interface/src/plugins/render/OculusExtendedRenderPlugin.cpp new file mode 100644 index 0000000000..5ed0c5cacf --- /dev/null +++ b/interface/src/plugins/render/OculusExtendedRenderPlugin.cpp @@ -0,0 +1,10 @@ +// +// OculusExtendedRenderPlugin.cpp +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "OculusExtendedRenderPlugin.h" diff --git a/interface/src/plugins/render/OculusExtendedRenderPlugin.h b/interface/src/plugins/render/OculusExtendedRenderPlugin.h new file mode 100644 index 0000000000..a9e9a51f0c --- /dev/null +++ b/interface/src/plugins/render/OculusExtendedRenderPlugin.h @@ -0,0 +1,12 @@ +// +// OculusExtendedRenderPlugin.h +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "OculusBaseRenderPlugin.h" diff --git a/interface/src/plugins/render/RenderPlugin.cpp b/interface/src/plugins/render/RenderPlugin.cpp new file mode 100644 index 0000000000..11052aca11 --- /dev/null +++ b/interface/src/plugins/render/RenderPlugin.cpp @@ -0,0 +1,16 @@ +// +// RenderPlugin.cpp +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "RenderPlugin.h" + +bool RenderPlugin::isMouseOnScreen() const { + glm::ivec2 mousePosition = getTrueMousePosition(); + return (glm::all(glm::greaterThanEqual(mousePosition, glm::ivec2(0))) && + glm::all(glm::lessThanEqual(mousePosition, glm::ivec2(getCanvasSize())))); +} \ No newline at end of file diff --git a/interface/src/plugins/render/RenderPlugin.h b/interface/src/plugins/render/RenderPlugin.h new file mode 100644 index 0000000000..d63e8421d0 --- /dev/null +++ b/interface/src/plugins/render/RenderPlugin.h @@ -0,0 +1,63 @@ +// +// RenderPlugin.h +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "plugins/Plugin.h" + +#include + +#include +#include +#include + +class RenderPlugin : public Plugin { + Q_OBJECT +public: + virtual bool isHmd() const { return false; } + virtual bool isStereo() const { return false; } + virtual bool isThrottled() const { return false; } + + // Rendering support + virtual void preRender() {}; + virtual void render(int finalSceneTexture) {}; + virtual void postRender() {}; + + // Pointer support + virtual bool hasFocus() const = 0; + virtual QSize getRecommendedFramebufferSize() const = 0; + virtual glm::ivec2 getCanvasSize() const = 0; + virtual glm::ivec2 getUiMousePosition() const = 0; + virtual glm::ivec2 getTrueMousePosition() const = 0; + virtual PickRay computePickRay(const glm::vec2 & pos) const = 0; + virtual bool isMouseOnScreen() const; + + // HMD specific methods + // TODO move these into another class + virtual glm::mat4 headPose() const { + static const glm::mat4 pose; return pose; + } + virtual glm::quat headOrientation() const { + static const glm::quat orientation; return orientation; + } + virtual glm::vec3 headTranslation() const { + static const glm::vec3 tranlsation; return tranlsation; + } + virtual void abandonCalibration() {} + virtual void resetSensors() {} + +signals: + void recommendedFramebufferSizeChanged(const QSize & size); + void requestRender(); + +protected: + virtual void makeCurrent() {} + virtual void doneCurrent() {} + virtual void swapBuffers() {} +}; diff --git a/interface/src/plugins/render/SimpleRenderPlugin.cpp b/interface/src/plugins/render/SimpleRenderPlugin.cpp new file mode 100644 index 0000000000..40c80f48d6 --- /dev/null +++ b/interface/src/plugins/render/SimpleRenderPlugin.cpp @@ -0,0 +1,13 @@ +// +// SimpleRenderPlugin.cpp +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "SimpleRenderPlugin.h" +#include +#include + diff --git a/interface/src/plugins/render/SimpleRenderPlugin.h b/interface/src/plugins/render/SimpleRenderPlugin.h new file mode 100644 index 0000000000..8a8ee7edd4 --- /dev/null +++ b/interface/src/plugins/render/SimpleRenderPlugin.h @@ -0,0 +1,56 @@ +// +// SimpleRenderPlugin.h +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "RenderPlugin.h" +#include +#include +#include + +template +class SimpleRenderPlugin : public RenderPlugin { +public: + virtual void render(int finalSceneTexture) { + makeCurrent(); + + glDisable(GL_LIGHTING); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, finalSceneTexture); + renderFullscreenQuad(); + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_TEXTURE_2D); + + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + glEnable(GL_LIGHTING); + + swapBuffers(); + doneCurrent(); + } + + virtual glm::ivec2 getUiMousePosition() const { + return getTrueMousePosition(); + } + + virtual glm::ivec2 getTrueMousePosition() const { + return toGlm(_window->mapFromGlobal(QCursor::pos())); + } + +protected: + T * _window; +}; diff --git a/interface/src/plugins/render/StereoRenderPlugin.cpp b/interface/src/plugins/render/StereoRenderPlugin.cpp new file mode 100644 index 0000000000..705133dcc4 --- /dev/null +++ b/interface/src/plugins/render/StereoRenderPlugin.cpp @@ -0,0 +1,10 @@ +// +// StereoRenderPlugin.cpp +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "StereoRenderPlugin.h" diff --git a/interface/src/plugins/render/StereoRenderPlugin.h b/interface/src/plugins/render/StereoRenderPlugin.h new file mode 100644 index 0000000000..69504e2ccf --- /dev/null +++ b/interface/src/plugins/render/StereoRenderPlugin.h @@ -0,0 +1,17 @@ +// +// StereoRenderPlugin.h +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "RenderPlugin.h" + +class StereoRenderPlugin : public RenderPlugin { + virtual bool isStereo() const final { return true; } +}; + diff --git a/interface/src/plugins/render/Tv3dRenderPlugin.cpp b/interface/src/plugins/render/Tv3dRenderPlugin.cpp new file mode 100644 index 0000000000..cf9481aeb2 --- /dev/null +++ b/interface/src/plugins/render/Tv3dRenderPlugin.cpp @@ -0,0 +1,11 @@ +// +// Tv3dRenderPlugin.cpp +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "Tv3dRenderPlugin.h" diff --git a/interface/src/plugins/render/Tv3dRenderPlugin.h b/interface/src/plugins/render/Tv3dRenderPlugin.h new file mode 100644 index 0000000000..728d55becb --- /dev/null +++ b/interface/src/plugins/render/Tv3dRenderPlugin.h @@ -0,0 +1,13 @@ +// +// Tv3dRenderPlugin.h +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "StereoRenderPlugin.h" diff --git a/interface/src/plugins/render/WindowRenderPlugin.cpp b/interface/src/plugins/render/WindowRenderPlugin.cpp new file mode 100644 index 0000000000..78a0849bba --- /dev/null +++ b/interface/src/plugins/render/WindowRenderPlugin.cpp @@ -0,0 +1,514 @@ +// +// WindowRenderPlugin.cpp +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "WindowRenderPlugin.h" +#include "RenderUtil.h" + +#include + +WindowRenderPlugin::WindowRenderPlugin() { + connect(&_timer, &QTimer::timeout, this, [&] { + emit requestRender(); + }); +} + +const QString WindowRenderPlugin::NAME("WindowRenderPlugin"); + +const QString & WindowRenderPlugin::getName() { + return NAME; +} + +void WindowRenderPlugin::activate() { + Q_ASSERT(nullptr == _window); + + _context = new QOpenGLContext; + + _window = new QWindow; + _window->setSurfaceType(QSurface::OpenGLSurface); + _window->installEventFilter(this); + glMatrixMode(0); + { + QSurfaceFormat format; + format.setDepthBufferSize(0); + format.setStencilBufferSize(0); + format.setVersion(4, 1); + // Ugh.... + format.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile); + _window->setFormat(format); + _context->setFormat(format); + } + + _context->setShareContext(QOpenGLContext::currentContext()); + _context->create(); + + _window->show(); + + _timer.start(8); +} + +void WindowRenderPlugin::deactivate() { + _timer.stop(); + _context->doneCurrent(); + _context->deleteLater(); + _context = nullptr; + _window->hide(); + _window->destroy(); + _window = nullptr; +} + +bool WindowRenderPlugin::eventFilter(QObject* object, QEvent* event) { + switch (event->type()) { + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::KeyPress: + case QEvent::KeyRelease: + case QEvent::FocusIn: + case QEvent::FocusOut: + case QEvent::Resize: + case QEvent::MouseMove: + QCoreApplication::sendEvent(QCoreApplication::instance(), event); + break; + default: + break; + } + return false; +} + +QSize WindowRenderPlugin::getRecommendedFramebufferSize() const { + return _window->size(); +} + +void WindowRenderPlugin::makeCurrent() { + _context->makeCurrent(_window); + QSize windowSize = _window->size(); + glViewport(0, 0, windowSize.width(), windowSize.height()); +} + +void WindowRenderPlugin::doneCurrent() { + _context->doneCurrent(); +} + +void WindowRenderPlugin::swapBuffers() { + _context->swapBuffers(_window); +} + + +#if 0 + +// +// MainWindow.h +// interface +// +// Created by Mohammed Nafees on 04/06/2014. +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// +// 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__MainWindow__ +#define __hifi__MainWindow__ + +#include +#include + +#include + +#define MSECS_PER_FRAME_WHEN_THROTTLED 66 + +class MainWindow : public QWindow { +public: + explicit MainWindow(QWindow* parent = NULL); + + // Some helpers for compatiblity with QMainWindow + void activateWindow() { + requestActivate(); + } + + bool isMinimized() const { + return windowState() == Qt::WindowMinimized; + } + + void stopFrameTimer(); + + bool isThrottleRendering() const; + + int getDeviceWidth() const; + int getDeviceHeight() const; + QSize getDeviceSize() const { return QSize(getDeviceWidth(), getDeviceHeight()); } + + /* + + + + private slots: + void activeChanged(Qt::ApplicationState state); + void throttleRender(); + bool eventFilter(QObject*, QEvent* event); + */ + public slots: + void restoreGeometry(); + void saveGeometry(); + +signals: + void windowGeometryChanged(QRect geometry); + void windowShown(bool shown); + +protected: + virtual void moveEvent(QMoveEvent* event); + virtual void resizeEvent(QResizeEvent* event); + virtual void showEvent(QShowEvent* event); + virtual void hideEvent(QHideEvent* event); + virtual void changeEvent(QEvent* event); + virtual void windowStateChanged(Qt::WindowState windowState); + virtual void activeChanged(); + + virtual void initializeGL(); + virtual void paintGL(); + virtual void resizeGL(int width, int height); + +private: + Setting::Handle _windowGeometry; + Setting::Handle _windowState; + Qt::WindowState _lastState{ Qt::WindowNoState }; + QOpenGLContext * _context{ nullptr }; + QTimer _frameTimer; + bool _throttleRendering{ false }; + int _idleRenderInterval{ MSECS_PER_FRAME_WHEN_THROTTLED }; +}; + +#endif /* defined(__hifi__MainWindow__) */ + + + + +// +// MainWindow.cpp +// interface +// +// Created by Mohammed Nafees on 04/06/2014. +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Application.h" + +#include "MainWindow.h" +#include "Menu.h" +#include "Util.h" + +#include + + +MainWindow::MainWindow(QWindow * parent) : +QWindow(parent), +_windowGeometry("WindowGeometry"), +_windowState("WindowState", 0) { + setSurfaceType(QSurface::OpenGLSurface); + + QSurfaceFormat format; + // Qt Quick may need a depth and stencil buffer. Always make sure these are available. + format.setDepthBufferSize(16); + format.setStencilBufferSize(8); + format.setVersion(4, 1); + // Ugh.... + format.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile); + setFormat(format); + + _context = new QOpenGLContext; + _context->setFormat(format); + _context->create(); + + show(); +} + +void MainWindow::restoreGeometry() { + QRect geometry = _windowGeometry.get(qApp->desktop()->availableGeometry()); + setGeometry(geometry); + + // Restore to maximized or full screen after restoring to windowed so that going windowed goes to good position and sizes. + int state = _windowState.get(Qt::WindowNoState) & ~Qt::WindowActive; + if (state != Qt::WindowNoState) { + setWindowState((Qt::WindowState)state); + } +} + +void MainWindow::saveGeometry() { + // Did not use geometry() on purpose, + // see http://doc.qt.io/qt-5/qsettings.html#restoring-the-state-of-a-gui-application + _windowState.set((int)windowState()); + + // Save position and size only if windowed so that have good values for windowed after starting maximized or full screen. + if (windowState() == Qt::WindowNoState) { + _windowGeometry.set(geometry()); + } +} + +void MainWindow::moveEvent(QMoveEvent* event) { + emit windowGeometryChanged(QRect(event->pos(), size())); + QWindow::moveEvent(event); +} + +void MainWindow::resizeEvent(QResizeEvent* event) { + emit windowGeometryChanged(QRect(QPoint(x(), y()), event->size())); + QWindow::resizeEvent(event); +} + +void MainWindow::showEvent(QShowEvent* event) { + if (event->spontaneous()) { + emit windowShown(true); + } + QWindow::showEvent(event); +} + +void MainWindow::hideEvent(QHideEvent* event) { + if (event->spontaneous()) { + emit windowShown(false); + } + QWindow::hideEvent(event); +} + +void MainWindow::windowStateChanged(Qt::WindowState windowState) { + // If we're changing from minimized to non-minimized or vice versas, emit + // a windowShown signal (i.e. don't emit the signal if we're going from + // fullscreen to nostate + if ((_lastState == Qt::WindowMinimized) ^ (windowState == Qt::WindowMinimized)) { + emit windowShown(windowState != Qt::WindowMinimized); + } + + bool fullscreen = windowState == Qt::WindowFullScreen; + if (fullscreen != Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen)) { + Menu::getInstance()->setIsOptionChecked(MenuOption::Fullscreen, fullscreen); + } + + _lastState = windowState; + QWindow::windowStateChanged(windowState); +} + +void MainWindow::activeChanged() { + if (isActive()) { + emit windowShown(true); + } else { + emit windowShown(false); + } + QWindow::activeChanged(); +} + +void MainWindow::stopFrameTimer() { + _frameTimer.stop(); +} + +bool MainWindow::isThrottleRendering() const { + return _throttleRendering || isMinimized(); +} + + +int MainWindow::getDeviceWidth() const { + return width() * devicePixelRatio(); +} + +int MainWindow::getDeviceHeight() const { + return height() * devicePixelRatio(); +} + + + +void MainWindow::initializeGL() { + Application::getInstance()->initializeGL(); + // setAttribute(Qt::WA_AcceptTouchEvents); + // setAcceptDrops(true); + connect(Application::getInstance(), SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SLOT(activeChanged(Qt::ApplicationState))); + connect(&_frameTimer, SIGNAL(timeout()), this, SLOT(throttleRender())); +} + +void GLCanvas::resizeGL(int width, int height) { + Application::getInstance()->resizeGL(width, height); +} + +void GLCanvas::paintGL() { + if (!_throttleRendering && !Application::getInstance()->getWindow()->isMinimized()) { + //Need accurate frame timing for the oculus rift + if (OculusManager::isConnected()) { + OculusManager::beginFrameTiming(); + } + + Application::getInstance()->paintGL(); + + if (!OculusManager::isConnected()) { + swapBuffers(); + } else { + if (OculusManager::allowSwap()) { + swapBuffers(); + } + OculusManager::endFrameTiming(); + } + } +} + + + +/* + +GLCanvas::GLCanvas() : QGLWidget(QGL::NoDepthBuffer | QGL::NoStencilBuffer), +#ifdef Q_OS_LINUX +// Cause GLCanvas::eventFilter to be called. +// It wouldn't hurt to do this on Mac and PC too; but apparently it's only needed on linux. +qApp->installEventFilter(this); +#endif +} + +void GLCanvas::keyPressEvent(QKeyEvent* event) { +Application::getInstance()->keyPressEvent(event); +} + +void GLCanvas::keyReleaseEvent(QKeyEvent* event) { +Application::getInstance()->keyReleaseEvent(event); +} + +void GLCanvas::focusOutEvent(QFocusEvent* event) { +Application::getInstance()->focusOutEvent(event); +} + +void GLCanvas::mouseMoveEvent(QMouseEvent* event) { +Application::getInstance()->mouseMoveEvent(event); +} + +void GLCanvas::mousePressEvent(QMouseEvent* event) { +Application::getInstance()->mousePressEvent(event); +} + +void GLCanvas::mouseReleaseEvent(QMouseEvent* event) { +Application::getInstance()->mouseReleaseEvent(event); +} + +void GLCanvas::activeChanged(Qt::ApplicationState state) { +switch (state) { +case Qt::ApplicationActive: +// If we're active, stop the frame timer and the throttle. +_frameTimer.stop(); +_throttleRendering = false; +break; + +case Qt::ApplicationSuspended: +case Qt::ApplicationHidden: +// If we're hidden or are about to suspend, don't render anything. +_throttleRendering = false; +_frameTimer.stop(); +break; + +default: +// Otherwise, throttle. +if (!_throttleRendering && !Application::getInstance()->isAboutToQuit()) { +_frameTimer.start(_idleRenderInterval); +_throttleRendering = true; +} +break; +} +} + +void GLCanvas::throttleRender() { +_frameTimer.start(_idleRenderInterval); +if (!Application::getInstance()->getWindow()->isMinimized()) { +//Need accurate frame timing for the oculus rift +if (OculusManager::isConnected()) { +OculusManager::beginFrameTiming(); +} + +Application::getInstance()->paintGL(); +swapBuffers(); + +if (OculusManager::isConnected()) { +OculusManager::endFrameTiming(); +} +} +} + +int updateTime = 0; +bool GLCanvas::event(QEvent* event) { +switch (event->type()) { +case QEvent::TouchBegin: +Application::getInstance()->touchBeginEvent(static_cast(event)); +event->accept(); +return true; +case QEvent::TouchEnd: +Application::getInstance()->touchEndEvent(static_cast(event)); +return true; +case QEvent::TouchUpdate: +Application::getInstance()->touchUpdateEvent(static_cast(event)); +return true; +default: +break; +} +return QGLWidget::event(event); +} + +void GLCanvas::wheelEvent(QWheelEvent* event) { +Application::getInstance()->wheelEvent(event); +} + +void GLCanvas::dragEnterEvent(QDragEnterEvent* event) { +const QMimeData* mimeData = event->mimeData(); +foreach(QUrl url, mimeData->urls()) { +auto urlString = url.toString(); +if (Application::getInstance()->canAcceptURL(urlString)) { +event->acceptProposedAction(); +break; +} +} +} + +void GLCanvas::dropEvent(QDropEvent* event) { +Application::getInstance()->dropEvent(event); +} + +// Pressing Alt (and Meta) key alone activates the menubar because its style inherits the +// SHMenuBarAltKeyNavigation from QWindowsStyle. This makes it impossible for a scripts to +// receive keyPress events for the Alt (and Meta) key in a reliable manner. +// +// This filter catches events before QMenuBar can steal the keyboard focus. +// The idea was borrowed from +// http://www.archivum.info/qt-interest@trolltech.com/2006-09/00053/Re-(Qt4)-Alt-key-focus-QMenuBar-(solved).html + +bool GLCanvas::eventFilter(QObject*, QEvent* event) { +switch (event->type()) { +case QEvent::KeyPress: +case QEvent::KeyRelease: +case QEvent::ShortcutOverride: +{ +QKeyEvent* keyEvent = static_cast(event); +if (keyEvent->key() == Qt::Key_Alt || keyEvent->key() == Qt::Key_Meta) { +if (event->type() == QEvent::KeyPress) { +keyPressEvent(keyEvent); +} else if (event->type() == QEvent::KeyRelease) { +keyReleaseEvent(keyEvent); +} else { +QGLWidget::event(event); +} +return true; +} +} +default: +break; +} +return false; +} + +*/ +#endif diff --git a/interface/src/plugins/render/WindowRenderPlugin.h b/interface/src/plugins/render/WindowRenderPlugin.h new file mode 100644 index 0000000000..ec485e4d6e --- /dev/null +++ b/interface/src/plugins/render/WindowRenderPlugin.h @@ -0,0 +1,40 @@ +// +// WindowRenderPlugin.h +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "SimpleRenderPlugin.h" + +#include +#include +#include + +class WindowRenderPlugin : public SimpleRenderPlugin { + Q_OBJECT +public: + static const QString NAME; + + WindowRenderPlugin(); + + virtual const QString & getName(); + + virtual void activate(); + virtual void deactivate(); + virtual bool eventFilter(QObject* object, QEvent* event); + virtual QSize getRecommendedFramebufferSize() const; + +protected: + virtual void makeCurrent(); + virtual void doneCurrent(); + virtual void swapBuffers(); + +private: + QTimer _timer; + QOpenGLContext * _context{ nullptr }; +}; diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index 7d6012c880..5f12d73b37 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -286,8 +286,7 @@ void ControllerScriptingInterface::releaseJoystick(int joystickIndex) { } glm::vec2 ControllerScriptingInterface::getViewportDimensions() const { - auto glCanvas = Application::getInstance()->getGLWidget(); - return glm::vec2(glCanvas->width(), glCanvas->height()); + return Application::getInstance()->getCanvasSize(); } AbstractInputController* ControllerScriptingInterface::createInputController(const QString& deviceName, const QString& tracker) { diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index 6ed3e48274..5e1ac7c436 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -41,7 +41,7 @@ WebWindowClass* WindowScriptingInterface::doCreateWebWindow(const QString& title } QScriptValue WindowScriptingInterface::hasFocus() { - return Application::getInstance()->getGLWidget()->hasFocus(); + return Application::getInstance()->hasFocus(); } void WindowScriptingInterface::setFocus() { diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index f08df229cc..1964d67fab 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -12,6 +12,7 @@ #include "InterfaceConfig.h" #include +#include #include #include @@ -167,13 +168,13 @@ ApplicationOverlay::~ApplicationOverlay() { } // Renders the overlays either to a texture or to the screen -void ApplicationOverlay::renderOverlay(bool renderToTexture) { +void ApplicationOverlay::renderOverlay() { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()"); Overlays& overlays = qApp->getOverlays(); - auto glCanvas = Application::getInstance()->getGLWidget(); _textureFov = glm::radians(_oculusUIAngularSize); - _textureAspectRatio = (float)glCanvas->getDeviceWidth() / (float)glCanvas->getDeviceHeight(); + glm::vec2 canvasSize = Application::getInstance()->getCanvasSize(); + _textureAspectRatio = canvasSize.x / canvasSize.y;; //Handle fading and deactivation/activation of UI @@ -183,17 +184,15 @@ void ApplicationOverlay::renderOverlay(bool renderToTexture) { glDisable(GL_LIGHTING); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - if (renderToTexture) { - _overlays.buildFramebufferObject(); - _overlays.bind(); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - } + _overlays.buildFramebufferObject(); + _overlays.bind(); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glPushMatrix(); { const float NEAR_CLIP = -10000; const float FAR_CLIP = 10000; glLoadIdentity(); - glOrtho(0, glCanvas->width(), glCanvas->height(), 0, NEAR_CLIP, FAR_CLIP); + glOrtho(0, canvasSize.x, canvasSize.y, 0, NEAR_CLIP, FAR_CLIP); glMatrixMode(GL_MODELVIEW); @@ -217,10 +216,7 @@ void ApplicationOverlay::renderOverlay(bool renderToTexture) { glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); - - if (renderToTexture) { - _overlays.release(); - } + _overlays.release(); } // Draws the FBO texture for the screen @@ -228,7 +224,6 @@ void ApplicationOverlay::displayOverlayTexture() { if (_alpha == 0.0f) { return; } - auto glCanvas = Application::getInstance()->getGLWidget(); glEnable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0); @@ -237,15 +232,15 @@ void ApplicationOverlay::displayOverlayTexture() { glMatrixMode(GL_PROJECTION); glPushMatrix(); { glLoadIdentity(); - glOrtho(0, glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight(), 0, -1.0, 1.0); + glOrtho(0, 1, 1, 0, -1.0, 1.0); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glEnable(GL_BLEND); - glm::vec2 topLeft(0.0f, 0.0f); - glm::vec2 bottomRight(glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); - glm::vec2 texCoordTopLeft(0.0f, 1.0f); - glm::vec2 texCoordBottomRight(1.0f, 0.0f); + static const glm::vec2 topLeft(0); + static const glm::vec2 bottomRight(1); + static const glm::vec2 texCoordTopLeft(0.0f, 1.0f); + static const glm::vec2 texCoordBottomRight(1.0f, 0.0f); DependencyManager::get()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, glm::vec4(1.0f, 1.0f, 1.0f, _alpha)); @@ -255,6 +250,7 @@ void ApplicationOverlay::displayOverlayTexture() { glDisable(GL_TEXTURE_2D); } +#if 0 // Draws the FBO texture for Oculus rift. void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) { if (_alpha == 0.0f) { @@ -440,10 +436,10 @@ void ApplicationOverlay::computeOculusPickRay(float x, float y, glm::vec3& origi origin = myAvatar->getEyePosition(); direction = cursorPos - origin; } +#endif //Caculate the click location using one of the sixense controllers. Scale is not applied QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const { - auto glCanvas = Application::getInstance()->getGLWidget(); MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); glm::vec3 tip = myAvatar->getLaserPointerTipPosition(palm); @@ -454,8 +450,9 @@ QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const { glm::vec3 tipPos = invOrientation * (tip - eyePos); QPoint rv; - +#if 0 if (OculusManager::isConnected()) { + auto glCanvas = Application::getInstance()->getGLWidget(); float t; //We back the ray up by dir to ensure that it will not start inside the UI. @@ -483,6 +480,7 @@ QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const { rv.setY(INT_MAX); } } else { +#endif glm::dmat4 projection; qApp->getProjectionMatrix(&projection); @@ -492,9 +490,12 @@ QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const { ndcSpacePos = glm::vec3(clipSpacePos) / clipSpacePos.w; } - rv.setX(((ndcSpacePos.x + 1.0) / 2.0) * glCanvas->width()); - rv.setY((1.0 - ((ndcSpacePos.y + 1.0) / 2.0)) * glCanvas->height()); + glm::ivec2 canvasSize = Application::getInstance()->getCanvasSize(); + rv.setX(((ndcSpacePos.x + 1.0) / 2.0) * canvasSize.x); + rv.setY((1.0 - ((ndcSpacePos.y + 1.0) / 2.0)) * canvasSize.y); +#if 0 } +#endif return rv; } @@ -518,18 +519,19 @@ bool ApplicationOverlay::calculateRayUICollisionPoint(const glm::vec3& position, //Renders optional pointers void ApplicationOverlay::renderPointers() { - auto glCanvas = Application::getInstance()->getGLWidget(); //lazily load crosshair texture if (_crosshairTexture == 0) { - _crosshairTexture = glCanvas->bindTexture(QImage(PathUtils::resourcesPath() + "images/sixense-reticle.png")); + _crosshairTexture = new QOpenGLTexture(QImage(PathUtils::resourcesPath() + "images/sixense-reticle.png")); } glEnable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, _crosshairTexture); - + _crosshairTexture->bind(); +#if 0 + if (OculusManager::isConnected() && !qApp->getLastMouseMoveWasSimulated() && !qApp->isMouseHidden()) { + auto glCanvas = Application::getInstance()->getGLWidget(); //If we are in oculus, render reticle later if (_lastMouseMove == 0) { _lastMouseMove = usecTimestampNow(); @@ -564,7 +566,9 @@ void ApplicationOverlay::renderPointers() { _magActive[MOUSE] = _magnifier; _reticleActive[LEFT_CONTROLLER] = false; _reticleActive[RIGHT_CONTROLLER] = false; - } else if (qApp->getLastMouseMoveWasSimulated() && Menu::getInstance()->isOptionChecked(MenuOption::SixenseMouseInput)) { + } else +#endif + if (qApp->getLastMouseMoveWasSimulated() && Menu::getInstance()->isOptionChecked(MenuOption::SixenseMouseInput)) { _lastMouseMove = 0; //only render controller pointer if we aren't already rendering a mouse pointer _reticleActive[MOUSE] = false; @@ -576,6 +580,7 @@ void ApplicationOverlay::renderPointers() { } void ApplicationOverlay::renderControllerPointers() { +#if 0 auto glCanvas = Application::getInstance()->getGLWidget(); MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); @@ -683,10 +688,12 @@ void ApplicationOverlay::renderControllerPointers() { glm::vec4(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], 1.0f)); } +#endif + } void ApplicationOverlay::renderPointersOculus(const glm::vec3& eyePos) { - glBindTexture(GL_TEXTURE_2D, _crosshairTexture); + _crosshairTexture->bind(); glDisable(GL_DEPTH_TEST); glMatrixMode(GL_MODELVIEW); @@ -723,10 +730,10 @@ void ApplicationOverlay::renderMagnifier(glm::vec2 magPos, float sizeMult, bool if (!_magnifier) { return; } - auto glCanvas = Application::getInstance()->getGLWidget(); + auto canvasSize = Application::getInstance()->getCanvasSize(); - const int widgetWidth = glCanvas->width(); - const int widgetHeight = glCanvas->height(); + const int widgetWidth = canvasSize.x; + const int widgetHeight = canvasSize.y; const float halfWidth = (MAGNIFY_WIDTH / _textureAspectRatio) * sizeMult / 2.0f; const float halfHeight = MAGNIFY_HEIGHT * sizeMult / 2.0f; @@ -788,6 +795,7 @@ void ApplicationOverlay::renderMagnifier(glm::vec2 magPos, float sizeMult, bool } void ApplicationOverlay::renderAudioMeter() { +#if 0 auto glCanvas = Application::getInstance()->getGLWidget(); auto audio = DependencyManager::get(); @@ -900,9 +908,11 @@ void ApplicationOverlay::renderAudioMeter() { audioLevel, AUDIO_METER_HEIGHT, quadColor, _audioBlueQuad); } +#endif } void ApplicationOverlay::renderStatsAndLogs() { +#if 0 Application* application = Application::getInstance(); QSharedPointer bandwidthRecorder = DependencyManager::get(); @@ -938,9 +948,11 @@ void ApplicationOverlay::renderStatsAndLogs() { 0.30f, 0.0f, 0, frameTimer.toUtf8().constData(), WHITE_TEXT); } nodeBoundsDisplay.drawOverlay(); +#endif } void ApplicationOverlay::renderDomainConnectionStatusBorder() { +#if 0 auto nodeList = DependencyManager::get(); if (nodeList && !nodeList->getDomainHandler().isConnected()) { @@ -969,6 +981,7 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder() { geometryCache->renderVertices(gpu::LINE_STRIP, _domainStatusBorder); } +#endif } ApplicationOverlay::TexturedHemisphere::TexturedHemisphere() : @@ -1088,7 +1101,7 @@ void ApplicationOverlay::TexturedHemisphere::cleanupVBO() { } void ApplicationOverlay::TexturedHemisphere::buildFramebufferObject() { - QSize size = Application::getInstance()->getGLWidget()->getDeviceSize(); + QSize size = Application::getInstance()->getDeviceSize(); if (_framebufferObject != NULL && size == _framebufferObject->size()) { // Already build return; @@ -1159,7 +1172,7 @@ glm::vec3 ApplicationOverlay::sphericalToDirection(glm::vec2 sphericalPos) const } glm::vec2 ApplicationOverlay::screenToSpherical(glm::vec2 screenPos) const { - QSize screenSize = Application::getInstance()->getGLWidget()->getDeviceSize(); + QSize screenSize = Application::getInstance()->getDeviceSize(); float yaw = -(screenPos.x / screenSize.width() - 0.5f) * MOUSE_YAW_RANGE; float pitch = (screenPos.y / screenSize.height() - 0.5f) * MOUSE_PITCH_RANGE; @@ -1167,7 +1180,7 @@ glm::vec2 ApplicationOverlay::screenToSpherical(glm::vec2 screenPos) const { } glm::vec2 ApplicationOverlay::sphericalToScreen(glm::vec2 sphericalPos) const { - QSize screenSize = Application::getInstance()->getGLWidget()->getDeviceSize(); + QSize screenSize = Application::getInstance()->getDeviceSize(); float x = (-sphericalPos.x / MOUSE_YAW_RANGE + 0.5f) * screenSize.width(); float y = (sphericalPos.y / MOUSE_PITCH_RANGE + 0.5f) * screenSize.height(); @@ -1175,7 +1188,7 @@ glm::vec2 ApplicationOverlay::sphericalToScreen(glm::vec2 sphericalPos) const { } glm::vec2 ApplicationOverlay::sphericalToOverlay(glm::vec2 sphericalPos) const { - QSize screenSize = Application::getInstance()->getGLWidget()->getDeviceSize(); + QSize screenSize = Application::getInstance()->getDeviceSize(); float x = (-sphericalPos.x / (_textureFov * _textureAspectRatio) + 0.5f) * screenSize.width(); float y = (sphericalPos.y / _textureFov + 0.5f) * screenSize.height(); @@ -1183,7 +1196,7 @@ glm::vec2 ApplicationOverlay::sphericalToOverlay(glm::vec2 sphericalPos) const { } glm::vec2 ApplicationOverlay::overlayToSpherical(glm::vec2 overlayPos) const { - QSize screenSize = Application::getInstance()->getGLWidget()->getDeviceSize(); + QSize screenSize = Application::getInstance()->getDeviceSize(); float yaw = -(overlayPos.x / screenSize.width() - 0.5f) * _textureFov * _textureAspectRatio; float pitch = (overlayPos.y / screenSize.height() - 0.5f) * _textureFov; diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index cc424d0c8f..c2cab296de 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -15,6 +15,7 @@ class Camera; class Overlays; class QOpenGLFramebufferObject; +class QOpenGLTexture; const float MAGNIFY_WIDTH = 220.0f; const float MAGNIFY_HEIGHT = 100.0f; @@ -28,21 +29,26 @@ public: ApplicationOverlay(); ~ApplicationOverlay(); - void renderOverlay(bool renderToTexture = false); + void renderOverlay(); + void displayOverlayTexture(); +#if 0 void displayOverlayTextureOculus(Camera& whichCamera); void displayOverlayTexture3DTV(Camera& whichCamera, float aspectRatio, float fov); - void computeOculusPickRay(float x, float y, glm::vec3& origin, glm::vec3& direction) const; +#endif + QPoint getPalmClickLocation(const PalmData *palm) const; bool calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction, glm::vec3& result) const; bool hasMagnifier() const { return _magnifier; } void toggleMagnifier() { _magnifier = !_magnifier; } +#if 0 float getOculusUIAngularSize() const { return _oculusUIAngularSize; } void setOculusUIAngularSize(float oculusUIAngularSize) { _oculusUIAngularSize = oculusUIAngularSize; } - +#endif + // Converter from one frame of reference to another. // Frame of reference: // Direction: Ray that represents the spherical values @@ -121,7 +127,7 @@ private: float _oculusUIRadius; float _trailingAudioLoudness; - GLuint _crosshairTexture; + QOpenGLTexture * _crosshairTexture; int _reticleQuad; int _magnifierQuad; diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp index 701ceb0189..971f75b4ea 100644 --- a/interface/src/ui/DialogsManager.cpp +++ b/interface/src/ui/DialogsManager.cpp @@ -56,10 +56,11 @@ void DialogsManager::showLoginDialog() { void DialogsManager::octreeStatsDetails() { if (!_octreeStatsDialog) { _octreeStatsDialog = new OctreeStatsDialog(qApp->getWindow(), qApp->getOcteeSceneStats()); - +#if 0 if (_hmdToolsDialog) { _hmdToolsDialog->watchWindow(_octreeStatsDialog->windowHandle()); } +#endif connect(_octreeStatsDialog, SIGNAL(closed()), _octreeStatsDialog, SLOT(deleteLater())); _octreeStatsDialog->show(); } @@ -107,11 +108,12 @@ void DialogsManager::bandwidthDetails() { if (! _bandwidthDialog) { _bandwidthDialog = new BandwidthDialog(qApp->getWindow()); connect(_bandwidthDialog, SIGNAL(closed()), _bandwidthDialog, SLOT(deleteLater())); - +#if 0 if (_hmdToolsDialog) { _hmdToolsDialog->watchWindow(_bandwidthDialog->windowHandle()); } - +#endif + _bandwidthDialog->show(); } _bandwidthDialog->raise(); @@ -133,6 +135,7 @@ void DialogsManager::toggleToolWindow() { } void DialogsManager::hmdTools(bool showTools) { +#if 0 if (showTools) { if (!_hmdToolsDialog) { maybeCreateDialog(_hmdToolsDialog); @@ -144,11 +147,14 @@ void DialogsManager::hmdTools(bool showTools) { hmdToolsClosed(); } qApp->getWindow()->activateWindow(); +#endif } void DialogsManager::hmdToolsClosed() { +#if 0 Menu::getInstance()->getActionForOption(MenuOption::HMDTools)->setChecked(false); _hmdToolsDialog->hide(); +#endif } void DialogsManager::showScriptEditor() { diff --git a/interface/src/ui/DialogsManager.h b/interface/src/ui/DialogsManager.h index 897215cbff..8f4bbb3b08 100644 --- a/interface/src/ui/DialogsManager.h +++ b/interface/src/ui/DialogsManager.h @@ -40,7 +40,7 @@ class DialogsManager : public QObject, public Dependency { public: QPointer getBandwidthDialog() const { return _bandwidthDialog; } - QPointer getHMDToolsDialog() const { return _hmdToolsDialog; } +// QPointer getHMDToolsDialog() const { return _hmdToolsDialog; } QPointer getLodToolsDialog() const { return _lodToolsDialog; } QPointer getOctreeStatsDialog() const { return _octreeStatsDialog; } @@ -75,9 +75,12 @@ private: member = new T(parent); Q_CHECK_PTR(member); +#if 0 if (_hmdToolsDialog && member->windowHandle()) { _hmdToolsDialog->watchWindow(member->windowHandle()); } +#endif + } } @@ -88,7 +91,7 @@ private: QPointer _cachesSizeDialog; QPointer _diskCacheEditor; QPointer _ircInfoBox; - QPointer _hmdToolsDialog; +// QPointer _hmdToolsDialog; QPointer _lodToolsDialog; QPointer _loginDialog; QPointer _octreeStatsDialog; diff --git a/interface/src/ui/HMDToolsDialog.cpp b/interface/src/ui/HMDToolsDialog.cpp index 4a899a641e..dfe45866e1 100644 --- a/interface/src/ui/HMDToolsDialog.cpp +++ b/interface/src/ui/HMDToolsDialog.cpp @@ -8,6 +8,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#if 0 #include #include @@ -340,4 +341,4 @@ void HMDWindowWatcher::windowScreenChanged(QScreen* screen) { } } - +#endif diff --git a/interface/src/ui/HMDToolsDialog.h b/interface/src/ui/HMDToolsDialog.h index 10dc1c5c80..86bfc7bf1a 100644 --- a/interface/src/ui/HMDToolsDialog.h +++ b/interface/src/ui/HMDToolsDialog.h @@ -11,7 +11,7 @@ #ifndef hifi_HMDToolsDialog_h #define hifi_HMDToolsDialog_h - +#if 0 #include class HMDWindowWatcher; @@ -84,5 +84,6 @@ private: QRect _previousRect; QScreen* _previousScreen; }; +#endif #endif // hifi_HMDToolsDialog_h diff --git a/interface/src/ui/NodeBounds.cpp b/interface/src/ui/NodeBounds.cpp index f0f4d432db..c56b5d32c6 100644 --- a/interface/src/ui/NodeBounds.cpp +++ b/interface/src/ui/NodeBounds.cpp @@ -39,8 +39,7 @@ void NodeBounds::draw() { // Compute ray to find selected nodes later on. We can't use the pre-computed ray in Application because it centers // itself after the cursor disappears. Application* application = Application::getInstance(); - PickRay pickRay = application->getCamera()->computePickRay(application->getTrueMouseX(), - application->getTrueMouseY()); + PickRay pickRay = application->computePickRay(); // Variables to keep track of the selected node and properties to draw the cube later if needed Node* selectedNode = NULL; diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index bd32fc7c34..5d6adbad4d 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -192,9 +192,9 @@ void PreferencesDialog::loadPreferences() { ui.avatarScaleSpin->setValue(myAvatar->getScale()); ui.maxOctreePPSSpin->setValue(qApp->getOctreeQuery().getMaxOctreePacketsPerSecond()); - +#if 0 ui.oculusUIAngularSizeSpin->setValue(qApp->getApplicationOverlay().getOculusUIAngularSize()); - +#endif SixenseManager& sixense = SixenseManager::getInstance(); ui.sixenseReticleMoveSpeedSpin->setValue(sixense.getReticleMoveSpeed()); ui.invertSixenseButtonsCheckBox->setChecked(sixense.getInvertButtons()); @@ -266,8 +266,7 @@ void PreferencesDialog::savePreferences() { myAvatar->setLeanScale(ui.leanScaleSpin->value()); myAvatar->setClampedTargetScale(ui.avatarScaleSpin->value()); - auto glCanvas = Application::getInstance()->getGLWidget(); - Application::getInstance()->resizeGL(glCanvas->width(), glCanvas->height()); + Application::getInstance()->resizeGL(); DependencyManager::get()->getMyAvatar()->setRealWorldFieldOfView(ui.realWorldFieldOfViewSpin->value()); @@ -280,9 +279,9 @@ void PreferencesDialog::savePreferences() { faceshift->setHostname(ui.faceshiftHostnameEdit->text()); qApp->getOctreeQuery().setMaxOctreePacketsPerSecond(ui.maxOctreePPSSpin->value()); - +#if 0 qApp->getApplicationOverlay().setOculusUIAngularSize(ui.oculusUIAngularSizeSpin->value()); - +#endif SixenseManager& sixense = SixenseManager::getInstance(); sixense.setReticleMoveSpeed(ui.sixenseReticleMoveSpeedSpin->value()); sixense.setInvertButtons(ui.invertSixenseButtonsCheckBox->isChecked()); @@ -305,7 +304,7 @@ void PreferencesDialog::savePreferences() { audio->setOutputStarveDetectionThreshold(ui.outputStarveDetectionThresholdSpinner->value()); audio->setOutputStarveDetectionPeriod(ui.outputStarveDetectionPeriodSpinner->value()); - Application::getInstance()->resizeGL(glCanvas->width(), glCanvas->height()); + Application::getInstance()->resizeGL(); // LOD items auto lodManager = DependencyManager::get(); diff --git a/interface/src/ui/RearMirrorTools.cpp b/interface/src/ui/RearMirrorTools.cpp index a215d20148..830ceea507 100644 --- a/interface/src/ui/RearMirrorTools.cpp +++ b/interface/src/ui/RearMirrorTools.cpp @@ -28,16 +28,15 @@ const char ZOOM_LEVEL_SETTINGS[] = "ZoomLevel"; Setting::Handle RearMirrorTools::rearViewZoomLevel(QStringList() << SETTINGS_GROUP_NAME << ZOOM_LEVEL_SETTINGS, ZoomLevel::HEAD); -RearMirrorTools::RearMirrorTools(QGLWidget* parent, QRect& bounds) : - _parent(parent), +RearMirrorTools::RearMirrorTools(QRect& bounds) : _bounds(bounds), _windowed(false), _fullScreen(false) { - _closeTextureId = _parent->bindTexture(QImage(PathUtils::resourcesPath() + "images/close.svg")); + _closeTextureId = new QOpenGLTexture(QImage(PathUtils::resourcesPath() + "images/close.svg")); - _zoomHeadTextureId = _parent->bindTexture(QImage(PathUtils::resourcesPath() + "images/plus.svg")); - _zoomBodyTextureId = _parent->bindTexture(QImage(PathUtils::resourcesPath() + "images/minus.svg")); + _zoomHeadTextureId = new QOpenGLTexture(QImage(PathUtils::resourcesPath() + "images/plus.svg")); + _zoomBodyTextureId = new QOpenGLTexture(QImage(PathUtils::resourcesPath() + "images/minus.svg")); _shrinkIconRect = QRect(ICON_PADDING, ICON_PADDING, ICON_SIZE, ICON_SIZE); _closeIconRect = QRect(_bounds.left() + ICON_PADDING, _bounds.top() + ICON_PADDING, ICON_SIZE, ICON_SIZE); @@ -47,6 +46,7 @@ RearMirrorTools::RearMirrorTools(QGLWidget* parent, QRect& bounds) : } void RearMirrorTools::render(bool fullScreen) { +#if 0 if (fullScreen) { _fullScreen = true; displayIcon(_parent->geometry(), _shrinkIconRect, _closeTextureId); @@ -62,6 +62,7 @@ void RearMirrorTools::render(bool fullScreen) { displayIcon(_bounds, _bodyZoomIconRect, _zoomBodyTextureId, zoomLevel == BODY); } } +#endif } bool RearMirrorTools::mousePressEvent(int x, int y) { @@ -99,7 +100,7 @@ bool RearMirrorTools::mousePressEvent(int x, int y) { return false; } -void RearMirrorTools::displayIcon(QRect bounds, QRect iconBounds, GLuint textureId, bool selected) { +void RearMirrorTools::displayIcon(QRect bounds, QRect iconBounds, QOpenGLTexture * texture, bool selected) { glMatrixMode(GL_PROJECTION); glPushMatrix(); @@ -116,13 +117,13 @@ void RearMirrorTools::displayIcon(QRect bounds, QRect iconBounds, GLuint texture } else { quadColor = glm::vec4(1, 1, 1, 1); } - - glBindTexture(GL_TEXTURE_2D, textureId); + + texture->bind(); glm::vec2 topLeft(iconBounds.left(), iconBounds.top()); glm::vec2 bottomRight(iconBounds.right(), iconBounds.bottom()); - glm::vec2 texCoordTopLeft(0.0f, 1.0f); - glm::vec2 texCoordBottomRight(1.0f, 0.0f); + static const glm::vec2 texCoordTopLeft(0.0f, 1.0f); + static const glm::vec2 texCoordBottomRight(1.0f, 0.0f); DependencyManager::get()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, quadColor); diff --git a/interface/src/ui/RearMirrorTools.h b/interface/src/ui/RearMirrorTools.h index 8a76134627..d38afdbdfb 100644 --- a/interface/src/ui/RearMirrorTools.h +++ b/interface/src/ui/RearMirrorTools.h @@ -14,8 +14,7 @@ #include "InterfaceConfig.h" -#include - +#include #include enum ZoomLevel { @@ -26,7 +25,7 @@ enum ZoomLevel { class RearMirrorTools : public QObject { Q_OBJECT public: - RearMirrorTools(QGLWidget* parent, QRect& bounds); + RearMirrorTools(QRect& bounds); void render(bool fullScreen); bool mousePressEvent(int x, int y); @@ -39,12 +38,10 @@ signals: void restoreView(); private: - QGLWidget* _parent; QRect _bounds; - GLuint _closeTextureId; - GLuint _resetTextureId; - GLuint _zoomBodyTextureId; - GLuint _zoomHeadTextureId; + QOpenGLTexture * _closeTextureId; + QOpenGLTexture * _zoomBodyTextureId; + QOpenGLTexture *_zoomHeadTextureId; QRect _closeIconRect; QRect _resetIconRect; @@ -55,7 +52,7 @@ private: bool _windowed; bool _fullScreen; - void displayIcon(QRect bounds, QRect iconBounds, GLuint textureId, bool selected = false); + void displayIcon(QRect bounds, QRect iconBounds, QOpenGLTexture * textureId, bool selected = false); }; #endif // hifi_RearMirrorTools_h diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index 5a3109ff64..350d4c8d90 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -94,6 +94,7 @@ QTemporaryFile* Snapshot::saveTempSnapshot() { } QFile* Snapshot::savedFileForSnapshot(bool isTemporary) { +#if 0 auto glCanvas = Application::getInstance()->getGLWidget(); QImage shot = glCanvas->grabFrameBuffer(); @@ -157,6 +158,8 @@ QFile* Snapshot::savedFileForSnapshot(bool isTemporary) { return imageTempFile; } +#endif + return nullptr; } diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index ec225dde72..f94e268d2d 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -57,8 +57,8 @@ Stats::Stats(): _octreeStatsWidth(STATS_OCTREE_MIN_WIDTH), _lastHorizontalOffset(0) { - auto glCanvas = Application::getInstance()->getGLWidget(); - resetWidth(glCanvas->width(), 0); + auto canvasSize = Application::getInstance()->getCanvasSize(); + resetWidth(canvasSize.x, 0); } void Stats::toggleExpanded() { @@ -68,7 +68,8 @@ void Stats::toggleExpanded() { // called on mouse click release // check for clicks over stats in order to expand or contract them void Stats::checkClick(int mouseX, int mouseY, int mouseDragStartedX, int mouseDragStartedY, int horizontalOffset) { - auto glCanvas = Application::getInstance()->getGLWidget(); +// auto glCanvas = Application::getInstance()->getGLWidget(); + auto canvasSize = Application::getInstance()->getCanvasSize(); if (0 != glm::compMax(glm::abs(glm::ivec2(mouseX - mouseDragStartedX, mouseY - mouseDragStartedY)))) { // not worried about dragging on stats @@ -115,7 +116,7 @@ void Stats::checkClick(int mouseX, int mouseY, int mouseDragStartedX, int mouseD // top-right stats click lines = _expanded ? 11 : 3; statsHeight = lines * STATS_PELS_PER_LINE + 10; - statsWidth = glCanvas->width() - statsX; + statsWidth = canvasSize.x - statsX; if (mouseX > statsX && mouseX < statsX + statsWidth && mouseY > statsY && mouseY < statsY + statsHeight) { toggleExpanded(); return; @@ -123,8 +124,8 @@ void Stats::checkClick(int mouseX, int mouseY, int mouseDragStartedX, int mouseD } void Stats::resetWidth(int width, int horizontalOffset) { - auto glCanvas = Application::getInstance()->getGLWidget(); - int extraSpace = glCanvas->width() - horizontalOffset -2 + auto canvasSize = Application::getInstance()->getCanvasSize(); + int extraSpace = canvasSize.x - horizontalOffset - 2 - STATS_GENERAL_MIN_WIDTH - (Menu::getInstance()->isOptionChecked(MenuOption::TestPing) ? STATS_PING_MIN_WIDTH -1 : 0) - STATS_GEO_MIN_WIDTH @@ -148,7 +149,7 @@ void Stats::resetWidth(int width, int horizontalOffset) { _pingStatsWidth += (int) extraSpace / panels; } _geoStatsWidth += (int) extraSpace / panels; - _octreeStatsWidth += glCanvas->width() - + _octreeStatsWidth += canvasSize.x - (_generalStatsWidth + _pingStatsWidth + _geoStatsWidth + 3); } } @@ -197,7 +198,7 @@ void Stats::display( int outKbitsPerSecond, int voxelPacketsToProcess) { - auto glCanvas = Application::getInstance()->getGLWidget(); + auto canvasSize = Application::getInstance()->getCanvasSize(); unsigned int backgroundColor = 0x33333399; int verticalOffset = 0, lines = 0; @@ -211,7 +212,7 @@ void Stats::display( QSharedPointer bandwidthRecorder = DependencyManager::get(); if (_lastHorizontalOffset != horizontalOffset) { - resetWidth(glCanvas->width(), horizontalOffset); + resetWidth(canvasSize.x, horizontalOffset); _lastHorizontalOffset = horizontalOffset; } @@ -461,7 +462,7 @@ void Stats::display( lines = _expanded ? 10 : 2; - drawBackground(backgroundColor, horizontalOffset, 0, glCanvas->width() - horizontalOffset, + drawBackground(backgroundColor, horizontalOffset, 0, canvasSize.x - horizontalOffset, (lines + 1) * STATS_PELS_PER_LINE); horizontalOffset += 5; diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 158deb00ff..ba7726877a 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -291,10 +291,13 @@ void Overlays::deleteOverlay(unsigned int id) { unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) { glm::vec2 pointCopy = point; + +#if 0 if (OculusManager::isConnected()) { pointCopy = Application::getInstance()->getApplicationOverlay().screenToOverlay(point); } - +#endif + QReadLocker lock(&_lock); QMapIterator i(_overlaysHUD); i.toBack(); diff --git a/libraries/render-utils/src/AbstractViewStateInterface.h b/libraries/render-utils/src/AbstractViewStateInterface.h index 0d73614e7c..9f7042d325 100644 --- a/libraries/render-utils/src/AbstractViewStateInterface.h +++ b/libraries/render-utils/src/AbstractViewStateInterface.h @@ -45,7 +45,7 @@ public: virtual bool shouldRenderMesh(float largestDimension, float distanceToCamera) = 0; virtual float getSizeScale() const = 0; virtual int getBoundaryLevelAdjust() const = 0; - virtual PickRay computePickRay(float x, float y) = 0; + virtual PickRay computePickRay(float x, float y) const = 0; virtual const glm::vec3& getAvatarPosition() const = 0; }; diff --git a/libraries/render-utils/src/GlowEffect.cpp b/libraries/render-utils/src/GlowEffect.cpp index 2ba1d7df13..bb645ae0ba 100644 --- a/libraries/render-utils/src/GlowEffect.cpp +++ b/libraries/render-utils/src/GlowEffect.cpp @@ -30,7 +30,6 @@ GlowEffect::GlowEffect() _isOddFrame(false), _isFirstFrame(true), _intensity(0.0f), - _widget(NULL), _enabled(false) { } @@ -63,7 +62,7 @@ static ProgramObject* createProgram(const QString& name) { return program; } -void GlowEffect::init(QGLWidget* widget, bool enabled) { +void GlowEffect::init(bool enabled) { if (_initialized) { qCDebug(renderutils, "[ERROR] GlowEffeect is already initialized."); return; @@ -91,23 +90,10 @@ void GlowEffect::init(QGLWidget* widget, bool enabled) { _diffusionScaleLocation = _diffuseProgram->uniformLocation("diffusionScale"); _initialized = true; - _widget = widget; _enabled = enabled; } -int GlowEffect::getDeviceWidth() const { - return _widget->width() * (_widget->windowHandle() ? _widget->windowHandle()->devicePixelRatio() : 1.0f); -} - -int GlowEffect::getDeviceHeight() const { - return _widget->height() * (_widget->windowHandle() ? _widget->windowHandle()->devicePixelRatio() : 1.0f); -} - - void GlowEffect::prepare() { - DependencyManager::get()->getPrimaryFramebufferObject()->bind(); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - _isEmpty = true; _isOddFrame = !_isOddFrame; } @@ -124,24 +110,11 @@ void GlowEffect::end() { glBlendColor(0.0f, 0.0f, 0.0f, _intensity = _intensityStack.pop()); } -static void maybeBind(QOpenGLFramebufferObject* fbo) { - if (fbo) { - fbo->bind(); - } -} - -static void maybeRelease(QOpenGLFramebufferObject* fbo) { - if (fbo) { - fbo->release(); - } -} - -QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { +QOpenGLFramebufferObject* GlowEffect::render() { PerformanceTimer perfTimer("glowEffect"); auto textureCache = DependencyManager::get(); QOpenGLFramebufferObject* primaryFBO = textureCache->getPrimaryFramebufferObject(); - primaryFBO->release(); glBindTexture(GL_TEXTURE_2D, primaryFBO->texture()); glPushMatrix(); @@ -155,23 +128,19 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); - QOpenGLFramebufferObject* destFBO = toTexture ? - textureCache->getSecondaryFramebufferObject() : NULL; + QOpenGLFramebufferObject* destFBO = textureCache->getSecondaryFramebufferObject(); if (!_enabled || _isEmpty) { // copy the primary to the screen if (destFBO && QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) { QOpenGLFramebufferObject::blitFramebuffer(destFBO, primaryFBO); } else { - maybeBind(destFBO); - if (!destFBO) { - glViewport(0, 0, getDeviceWidth(), getDeviceHeight()); - } + destFBO->bind(); glEnable(GL_TEXTURE_2D); glDisable(GL_LIGHTING); renderFullscreenQuad(); glDisable(GL_TEXTURE_2D); glEnable(GL_LIGHTING); - maybeRelease(destFBO); + destFBO->release(); } } else { // diffuse into the secondary/tertiary (alternating between frames) @@ -205,21 +174,15 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { // add diffused texture to the primary glBindTexture(GL_TEXTURE_2D, newDiffusedFBO->texture()); - if (toTexture) { - destFBO = oldDiffusedFBO; - } - maybeBind(destFBO); - if (!destFBO) { - glViewport(0, 0, getDeviceWidth(), getDeviceHeight()); - } + destFBO = oldDiffusedFBO; + destFBO->bind(); _addSeparateProgram->bind(); renderFullscreenQuad(); _addSeparateProgram->release(); - maybeRelease(destFBO); + destFBO->release(); glBindTexture(GL_TEXTURE_2D, 0); glActiveTexture(GL_TEXTURE0); - } glPopMatrix(); diff --git a/libraries/render-utils/src/GlowEffect.h b/libraries/render-utils/src/GlowEffect.h index 895cd4bbce..65031aeb59 100644 --- a/libraries/render-utils/src/GlowEffect.h +++ b/libraries/render-utils/src/GlowEffect.h @@ -35,7 +35,7 @@ public: /// (either the secondary or the tertiary). QOpenGLFramebufferObject* getFreeFramebufferObject() const; - void init(QGLWidget* widget, bool enabled); + void init(bool enabled); /// Prepares the glow effect for rendering the current frame. To be called before rendering the scene. void prepare(); @@ -53,7 +53,7 @@ public: /// Renders the glow effect. To be called after rendering the scene. /// \param toTexture whether to render to a texture, rather than to the frame buffer /// \return the framebuffer object to which we rendered, or NULL if to the frame buffer - QOpenGLFramebufferObject* render(bool toTexture = false); + QOpenGLFramebufferObject* render(); public slots: void toggleGlowEffect(bool enabled); @@ -81,7 +81,6 @@ private: float _intensity; QStack _intensityStack; - QGLWidget* _widget; bool _enabled; }; diff --git a/libraries/render-utils/src/OffscreenGlContext.cpp b/libraries/render-utils/src/OffscreenGlContext.cpp new file mode 100644 index 0000000000..96f0a93c3a --- /dev/null +++ b/libraries/render-utils/src/OffscreenGlContext.cpp @@ -0,0 +1,43 @@ +// +// OffscreenGlCanvas.cpp +// interface/src/renderer +// +// Created by Bradley Austin Davis on 2014/04/09. +// 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 "OffscreenGlContext.h" + +OffscreenGlContext::OffscreenGlContext() { +} + +void OffscreenGlContext::create(QOpenGLContext * sharedContext) { + QSurfaceFormat format; + format.setDepthBufferSize(16); + format.setStencilBufferSize(8); + format.setMajorVersion(4); + format.setMinorVersion(1); + format.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile); + + _context.setFormat(format); + if (nullptr != sharedContext) { + _context.setShareContext(sharedContext); + } + _context.create(); + + _offscreenSurface.setFormat(_context.format()); + _offscreenSurface.create(); +} + +bool OffscreenGlContext::makeCurrent() { + return _context.makeCurrent(&_offscreenSurface); +} + +void OffscreenGlContext::doneCurrent() { + _context.doneCurrent(); +} + diff --git a/libraries/render-utils/src/OffscreenGlContext.h b/libraries/render-utils/src/OffscreenGlContext.h new file mode 100644 index 0000000000..ef67a7fc9a --- /dev/null +++ b/libraries/render-utils/src/OffscreenGlContext.h @@ -0,0 +1,33 @@ +// +// OffscreenGlCanvas.h +// interface/src/renderer +// +// Created by Bradley Austin Davis on 2014/04/09. +// 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 +#ifndef hifi_OffscreenGlCanvas_h +#define hifi_OffscreenGlCanvas_h + +#include +#include + +class OffscreenGlContext : public QObject { +public: + OffscreenGlContext(); + void create(QOpenGLContext * sharedContext = nullptr); + bool makeCurrent(); + void doneCurrent(); + QOpenGLContext * getContext() { + return &_context; + } + +protected: + QOpenGLContext _context; + QOffscreenSurface _offscreenSurface; +}; + +#endif // hifi_OffscreenGlCanvas_h diff --git a/libraries/render-utils/src/TextureCache.cpp b/libraries/render-utils/src/TextureCache.cpp index 9b2a458231..f33d8590f5 100644 --- a/libraries/render-utils/src/TextureCache.cpp +++ b/libraries/render-utils/src/TextureCache.cpp @@ -39,8 +39,7 @@ TextureCache::TextureCache() : _secondaryFramebufferObject(NULL), _tertiaryFramebufferObject(NULL), _shadowFramebufferObject(NULL), - _frameBufferSize(100, 100), - _associatedWidget(NULL) + _frameBufferSize(100, 100) { const qint64 TEXTURE_DEFAULT_UNUSED_MAX_SIZE = DEFAULT_UNUSED_MAX_SIZE; setUnusedResourceCacheSize(TEXTURE_DEFAULT_UNUSED_MAX_SIZE); @@ -322,28 +321,6 @@ GLuint TextureCache::getShadowDepthTextureID() { return _shadowDepthTextureID; } -bool TextureCache::eventFilter(QObject* watched, QEvent* event) { - if (event->type() == QEvent::Resize) { - QSize size = static_cast(event)->size(); - if (_primaryFramebufferObject && _primaryFramebufferObject->size() != size) { - delete _primaryFramebufferObject; - _primaryFramebufferObject = NULL; - glDeleteTextures(1, &_primaryDepthTextureID); - glDeleteTextures(1, &_primaryNormalTextureID); - glDeleteTextures(1, &_primarySpecularTextureID); - } - if (_secondaryFramebufferObject && _secondaryFramebufferObject->size() != size) { - delete _secondaryFramebufferObject; - _secondaryFramebufferObject = NULL; - } - if (_tertiaryFramebufferObject && _tertiaryFramebufferObject->size() != size) { - delete _tertiaryFramebufferObject; - _tertiaryFramebufferObject = NULL; - } - } - return false; -} - QSharedPointer TextureCache::createResource(const QUrl& url, const QSharedPointer& fallback, bool delayLoad, const void* extra) { const TextureExtra* textureExtra = static_cast(extra); @@ -351,14 +328,6 @@ QSharedPointer TextureCache::createResource(const QUrl& url, &Resource::allReferencesCleared); } -void TextureCache::associateWithWidget(QGLWidget* widget) { - if (_associatedWidget) { - _associatedWidget->removeEventFilter(this); - } - _associatedWidget = widget; - _associatedWidget->installEventFilter(this); -} - QOpenGLFramebufferObject* TextureCache::createFramebufferObject() { QOpenGLFramebufferObject* fbo = new QOpenGLFramebufferObject(_frameBufferSize); diff --git a/libraries/render-utils/src/TextureCache.h b/libraries/render-utils/src/TextureCache.h index 3ea46a4421..0496617563 100644 --- a/libraries/render-utils/src/TextureCache.h +++ b/libraries/render-utils/src/TextureCache.h @@ -36,9 +36,6 @@ class TextureCache : public ResourceCache, public Dependency { SINGLETON_DEPENDENCY public: - - void associateWithWidget(QGLWidget* widget); - /// Sets the desired texture resolution for the framebuffer objects. void setFrameBufferSize(QSize frameBufferSize); const QSize& getFrameBufferSize() const { return _frameBufferSize; } @@ -88,8 +85,6 @@ public: /// Returns the ID of the shadow framebuffer object's depth texture. GLuint getShadowDepthTextureID(); - virtual bool eventFilter(QObject* watched, QEvent* event); - protected: virtual QSharedPointer createResource(const QUrl& url, @@ -119,7 +114,6 @@ private: GLuint _shadowDepthTextureID; QSize _frameBufferSize; - QGLWidget* _associatedWidget; }; /// A simple object wrapper for an OpenGL texture. From bdfb6449f7c26b97a58b4631185b48128e5b774a Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Sun, 12 Apr 2015 22:07:41 -0700 Subject: [PATCH 002/552] Working on decoupling rendering --- interface/CMakeLists.txt | 20 +- interface/src/Application.cpp | 370 ++++++++----- interface/src/Application.h | 34 +- interface/src/Camera.cpp | 49 +- interface/src/Camera.h | 18 - interface/src/GLCanvas.cpp | 12 +- interface/src/audio/AudioToolBox.cpp | 13 +- interface/src/audio/AudioToolBox.h | 7 +- interface/src/avatar/Head.cpp | 3 + interface/src/avatar/MyAvatar.cpp | 15 +- interface/src/devices/OculusManager.cpp | 3 +- interface/src/devices/TV3DManager.cpp | 23 +- interface/src/devices/TV3DManager.h | 3 +- interface/src/main.cpp | 5 +- interface/src/plugins/Plugin.cpp | 1 + interface/src/plugins/Plugin.h | 18 + interface/src/plugins/PluginManager.cpp | 1 + interface/src/plugins/PluginManager.h | 12 + .../src/plugins/render/HmdRenderPlugin.cpp | 11 + .../src/plugins/render/HmdRenderPlugin.h | 15 + .../src/plugins/render/LegacyRenderPlugin.cpp | 87 +++ .../src/plugins/render/LegacyRenderPlugin.h | 36 ++ .../src/plugins/render/NullRenderPlugin.cpp | 44 ++ .../src/plugins/render/NullRenderPlugin.h | 29 + .../plugins/render/OculusBaseRenderPlugin.cpp | 105 ++++ .../plugins/render/OculusBaseRenderPlugin.h | 40 ++ .../render/OculusDirectD3DRenderPlugin.cpp | 10 + .../render/OculusDirectD3DRenderPlugin.h | 12 + .../render/OculusDirectRenderPlugin.cpp | 10 + .../plugins/render/OculusDirectRenderPlugin.h | 12 + .../render/OculusExtendedRenderPlugin.cpp | 10 + .../render/OculusExtendedRenderPlugin.h | 12 + interface/src/plugins/render/RenderPlugin.cpp | 16 + interface/src/plugins/render/RenderPlugin.h | 82 +++ .../src/plugins/render/SimpleRenderPlugin.cpp | 13 + .../src/plugins/render/SimpleRenderPlugin.h | 56 ++ .../src/plugins/render/StereoRenderPlugin.cpp | 10 + .../src/plugins/render/StereoRenderPlugin.h | 17 + .../src/plugins/render/Tv3dRenderPlugin.cpp | 43 ++ .../src/plugins/render/Tv3dRenderPlugin.h | 26 + .../src/plugins/render/WindowRenderPlugin.cpp | 514 ++++++++++++++++++ .../src/plugins/render/WindowRenderPlugin.h | 40 ++ .../ControllerScriptingInterface.cpp | 3 +- .../scripting/WindowScriptingInterface.cpp | 2 +- interface/src/ui/ApplicationOverlay.cpp | 102 ++-- interface/src/ui/ApplicationOverlay.h | 20 +- interface/src/ui/DialogsManager.cpp | 12 +- interface/src/ui/DialogsManager.h | 7 +- interface/src/ui/HMDToolsDialog.cpp | 3 +- interface/src/ui/HMDToolsDialog.h | 3 +- interface/src/ui/NodeBounds.cpp | 3 +- interface/src/ui/PreferencesDialog.cpp | 13 +- interface/src/ui/RearMirrorTools.cpp | 21 +- interface/src/ui/RearMirrorTools.h | 15 +- interface/src/ui/Snapshot.cpp | 3 + interface/src/ui/Stats.cpp | 21 +- interface/src/ui/overlays/Overlays.cpp | 5 +- .../src/AbstractViewStateInterface.h | 2 +- libraries/render-utils/src/GlowEffect.cpp | 53 +- libraries/render-utils/src/GlowEffect.h | 5 +- .../render-utils/src/OffscreenGlContext.cpp | 43 ++ .../render-utils/src/OffscreenGlContext.h | 33 ++ libraries/render-utils/src/TextureCache.cpp | 33 +- libraries/render-utils/src/TextureCache.h | 6 - 64 files changed, 1830 insertions(+), 435 deletions(-) create mode 100644 interface/src/plugins/Plugin.cpp create mode 100644 interface/src/plugins/Plugin.h create mode 100644 interface/src/plugins/PluginManager.cpp create mode 100644 interface/src/plugins/PluginManager.h create mode 100644 interface/src/plugins/render/HmdRenderPlugin.cpp create mode 100644 interface/src/plugins/render/HmdRenderPlugin.h create mode 100644 interface/src/plugins/render/LegacyRenderPlugin.cpp create mode 100644 interface/src/plugins/render/LegacyRenderPlugin.h create mode 100644 interface/src/plugins/render/NullRenderPlugin.cpp create mode 100644 interface/src/plugins/render/NullRenderPlugin.h create mode 100644 interface/src/plugins/render/OculusBaseRenderPlugin.cpp create mode 100644 interface/src/plugins/render/OculusBaseRenderPlugin.h create mode 100644 interface/src/plugins/render/OculusDirectD3DRenderPlugin.cpp create mode 100644 interface/src/plugins/render/OculusDirectD3DRenderPlugin.h create mode 100644 interface/src/plugins/render/OculusDirectRenderPlugin.cpp create mode 100644 interface/src/plugins/render/OculusDirectRenderPlugin.h create mode 100644 interface/src/plugins/render/OculusExtendedRenderPlugin.cpp create mode 100644 interface/src/plugins/render/OculusExtendedRenderPlugin.h create mode 100644 interface/src/plugins/render/RenderPlugin.cpp create mode 100644 interface/src/plugins/render/RenderPlugin.h create mode 100644 interface/src/plugins/render/SimpleRenderPlugin.cpp create mode 100644 interface/src/plugins/render/SimpleRenderPlugin.h create mode 100644 interface/src/plugins/render/StereoRenderPlugin.cpp create mode 100644 interface/src/plugins/render/StereoRenderPlugin.h create mode 100644 interface/src/plugins/render/Tv3dRenderPlugin.cpp create mode 100644 interface/src/plugins/render/Tv3dRenderPlugin.h create mode 100644 interface/src/plugins/render/WindowRenderPlugin.cpp create mode 100644 interface/src/plugins/render/WindowRenderPlugin.h create mode 100644 libraries/render-utils/src/OffscreenGlContext.cpp create mode 100644 libraries/render-utils/src/OffscreenGlContext.h diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index f4f390607b..85a4b3ccee 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -36,8 +36,22 @@ endif () configure_file(InterfaceConfig.h.in "${PROJECT_BINARY_DIR}/includes/InterfaceConfig.h") configure_file(InterfaceVersion.h.in "${PROJECT_BINARY_DIR}/includes/InterfaceVersion.h") + +macro(GroupSources curdir) + file(GLOB children RELATIVE ${PROJECT_SOURCE_DIR}/${curdir} ${PROJECT_SOURCE_DIR}/${curdir}/*) + foreach(child ${children}) + if(IS_DIRECTORY ${PROJECT_SOURCE_DIR}/${curdir}/${child}) + GroupSources(${curdir}/${child}) + else() + string(REPLACE "/" "\\" groupname ${curdir}) + source_group(${groupname} FILES ${PROJECT_SOURCE_DIR}/${curdir}/${child}) + endif() + endforeach() +endmacro() + # grab the implementation and header files from src dirs file(GLOB_RECURSE INTERFACE_SRCS "src/*.cpp" "src/*.h") +GroupSources("src") # Add SpeechRecognizer if on Windows or OS X, otherwise remove if (WIN32) @@ -54,10 +68,14 @@ else () list(REMOVE_ITEM INTERFACE_SRCS ${SPEECHRECOGNIZER_CPP}) endif () -find_package(Qt5 COMPONENTS Gui Multimedia Network OpenGL Script Svg WebKitWidgets) +find_package(Qt5 COMPONENTS Gui Multimedia Network OpenGL Qml Quick Script Svg WebKitWidgets) # grab the ui files in resources/ui file (GLOB_RECURSE QT_UI_FILES ui/*.ui) +source_group("UI Files" FILES ${QT_UI_FILES}) + + + # have qt5 wrap them and generate the appropriate header files qt5_wrap_ui(QT_UI_HEADERS "${QT_UI_FILES}") diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 82447257fb..a9a5777f38 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -267,6 +267,7 @@ bool setupEssentials(int& argc, char** argv) { Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : QApplication(argc, argv), _dependencyManagerIsSetup(setupEssentials(argc, argv)), + _offscreenContext(new OffscreenGlContext()), _window(new MainWindow(desktop())), _toolWindow(NULL), _friendsWindow(NULL), @@ -476,18 +477,14 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : ResourceCache::setRequestLimit(3); - _window->setCentralWidget(_glWidget); - + _window->setCentralWidget(new QWidget()); _window->restoreGeometry(); - _window->setVisible(true); - _glWidget->setFocusPolicy(Qt::StrongFocus); - _glWidget->setFocus(); - - // enable mouse tracking; otherwise, we only get drag events - _glWidget->setMouseTracking(true); +#if 0 _fullscreenMenuWidget->setParent(_glWidget); +#endif + _menuBarHeight = Menu::getInstance()->height(); if (Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen)) { setFullscreen(true); // Initialize menu bar show/hide @@ -497,6 +494,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _toolWindow->setWindowFlags(_toolWindow->windowFlags() | Qt::WindowStaysOnTopHint); _toolWindow->setWindowTitle("Tools"); + _offscreenContext->create(); + _offscreenContext->makeCurrent(); + initializeGL(); // initialization continues in initializeGL when OpenGL context is ready // Tell our entity edit sender about our known jurisdictions @@ -629,9 +629,8 @@ Application::~Application() { _myAvatar = NULL; ModelEntityItem::cleanupLoadedAnimations(); - - // stop the glWidget frame timer so it doesn't call paintGL - _glWidget->stopFrameTimer(); + + getActiveRenderPlugin()->deactivate(); DependencyManager::destroy(); DependencyManager::destroy(); @@ -732,19 +731,14 @@ void Application::paintGL() { bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::paintGL()"); - // Set the desired FBO texture size. If it hasn't changed, this does nothing. - // Otherwise, it must rebuild the FBOs - if (OculusManager::isConnected()) { - DependencyManager::get()->setFrameBufferSize(OculusManager::getRenderTargetSize()); - } else { - QSize fbSize = _glWidget->getDeviceSize() * getRenderResolutionScale(); - DependencyManager::get()->setFrameBufferSize(fbSize); - } + _offscreenContext->makeCurrent(); + QSize fbSize = getActiveRenderPlugin()->getRecommendedFramebufferSize() * getRenderResolutionScale(); + DependencyManager::get()->setFrameBufferSize(fbSize); glEnable(GL_LINE_SMOOTH); if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) { - if (!OculusManager::isConnected()) { + if (!getActiveRenderPlugin()->isHmd()) { // If there isn't an HMD, match exactly to avatar's head _myCamera.setPosition(_myAvatar->getHead()->getEyePosition()); _myCamera.setRotation(_myAvatar->getHead()->getCameraOrientation()); @@ -753,17 +747,15 @@ void Application::paintGL() { _myCamera.setPosition(_myAvatar->getDefaultEyePosition()); _myCamera.setRotation(_myAvatar->getWorldAlignedOrientation()); } - } else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) { static const float THIRD_PERSON_CAMERA_DISTANCE = 1.5f; _myCamera.setPosition(_myAvatar->getDefaultEyePosition() + _myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, 1.0f) * THIRD_PERSON_CAMERA_DISTANCE * _myAvatar->getScale()); - if (OculusManager::isConnected()) { + if (getActiveRenderPlugin()->isHmd()) { _myCamera.setRotation(_myAvatar->getWorldAlignedOrientation()); } else { _myCamera.setRotation(_myAvatar->getHead()->getOrientation()); } - } else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { _myCamera.setRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f))); _myCamera.setPosition(_myAvatar->getDefaultEyePosition() + @@ -772,30 +764,17 @@ void Application::paintGL() { glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror); } - // Update camera position - if (!OculusManager::isConnected()) { - _myCamera.update(1.0f / _fps); - } - if (getShadowsEnabled()) { updateShadowMap(); } - if (OculusManager::isConnected()) { - //When in mirror mode, use camera rotation. Otherwise, use body rotation - if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { - OculusManager::display(_myCamera.getRotation(), _myCamera.getPosition(), _myCamera); - } else { - OculusManager::display(_myAvatar->getWorldAlignedOrientation(), _myAvatar->getDefaultEyePosition(), _myCamera); - } - _myCamera.update(1.0f / _fps); + DependencyManager::get()->prepare(); - } else if (TV3DManager::isConnected()) { - - TV3DManager::display(_myCamera); - - } else { - DependencyManager::get()->prepare(); + // Primary rendering pass + auto primaryFbo = DependencyManager::get()->getPrimaryFramebufferObject(); + primaryFbo->bind(); + { + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Viewport is assigned to the size of the framebuffer QSize size = DependencyManager::get()->getPrimaryFramebufferObject()->size(); @@ -809,20 +788,34 @@ void Application::paintGL() { if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) { _rearMirrorTools->render(true); - } else if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { - renderRearViewMirror(_mirrorViewRect); - } - - DependencyManager::get()->render(); - - { - PerformanceTimer perfTimer("renderOverlay"); - _applicationOverlay.renderOverlay(true); - _applicationOverlay.displayOverlayTexture(); + renderRearViewMirror(_mirrorViewRect); } } + primaryFbo->release(); + + QOpenGLFramebufferObject * finalFbo = DependencyManager::get()->render(); + finalFbo->bind(); + { + PerformanceTimer perfTimer("renderOverlay"); + _applicationOverlay.renderOverlay(); + _applicationOverlay.displayOverlayTexture(); + } + finalFbo->release(); + + // This might not be needed *right now*. We want to ensure that the FBO rendering + // has completed before we start trying to read from it in another context. However + // once we have multi-threaded rendering, this will almost certainly be critical, + // but may be better handled with a fence object + glFinish(); + + + _offscreenContext->doneCurrent(); + Q_ASSERT(!QOpenGLContext::currentContext()); + getActiveRenderPlugin()->render(finalFbo->texture()); + Q_ASSERT(!QOpenGLContext::currentContext()); + _offscreenContext->makeCurrent(); _frameCount++; } @@ -845,14 +838,23 @@ void Application::showEditEntitiesHelp() { } void Application::resetCamerasOnResizeGL(Camera& camera, int width, int height) { +#if 0 if (OculusManager::isConnected()) { OculusManager::configureCamera(camera, width, height); } else if (TV3DManager::isConnected()) { TV3DManager::configureCamera(camera, width, height); } else { +#endif camera.setAspectRatio((float)width / height); camera.setFieldOfView(_fieldOfView.get()); +#if 0 } +#endif +} + +void Application::resizeEvent(QResizeEvent * event) { + const QSize & newSize = event->size(); + resizeGL(newSize.width(), newSize.height()); } void Application::resizeGL(int width, int height) { @@ -911,6 +913,43 @@ bool Application::importSVOFromURL(const QString& urlString) { } bool Application::event(QEvent* event) { + switch (event->type()) { + case QEvent::MouseMove: + mouseMoveEvent((QMouseEvent*)event); + return true; + + case QEvent::MouseButtonPress: + mousePressEvent((QMouseEvent*)event); + return true; + + case QEvent::MouseButtonRelease: + mouseReleaseEvent((QMouseEvent*)event); + return true; + + case QEvent::KeyPress: + keyPressEvent((QKeyEvent*)event); + return true; + + case QEvent::KeyRelease: + keyReleaseEvent((QKeyEvent*)event); + return true; + + case QEvent::FocusIn: + //focusInEvent((QFocusEvent*)event); + //return true; + break; + + case QEvent::FocusOut: + focusOutEvent((QFocusEvent*)event); + return true; + + case QEvent::Resize: + resizeEvent((QResizeEvent *)event); + return true; + + default: + break; + } // handle custom URL if (event->type() == QEvent::FileOpen) { @@ -1102,9 +1141,11 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_J: if (isShifted) { _viewFrustum.setFocalLength(_viewFrustum.getFocalLength() - 0.1f); +#if 0 if (TV3DManager::isConnected()) { TV3DManager::configureCamera(_myCamera, _glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); } +#endif } else { _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(-0.001, 0, 0)); } @@ -1114,10 +1155,11 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_M: if (isShifted) { _viewFrustum.setFocalLength(_viewFrustum.getFocalLength() + 0.1f); +#if 0 if (TV3DManager::isConnected()) { TV3DManager::configureCamera(_myCamera, _glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); } - +#endif } else { _myCamera.setEyeOffsetPosition(_myCamera.getEyeOffsetPosition() + glm::vec3(0.001, 0, 0)); } @@ -1168,17 +1210,14 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_Space: { if (!event->isAutoRepeat()) { // this starts an HFActionEvent - HFActionEvent startActionEvent(HFActionEvent::startType(), - _myCamera.computePickRay(getTrueMouseX(), - getTrueMouseY())); + HFActionEvent startActionEvent(HFActionEvent::startType(), computePickRay()); sendEvent(this, &startActionEvent); } break; } case Qt::Key_Escape: { - OculusManager::abandonCalibration(); - + getActiveRenderPlugin()->abandonCalibration(); if (!event->isAutoRepeat()) { // this starts the HFCancelEvent HFBackEvent startBackEvent(HFBackEvent::startType()); @@ -1266,9 +1305,7 @@ void Application::keyReleaseEvent(QKeyEvent* event) { case Qt::Key_Space: { if (!event->isAutoRepeat()) { // this ends the HFActionEvent - HFActionEvent endActionEvent(HFActionEvent::endType(), - _myCamera.computePickRay(getTrueMouseX(), - getTrueMouseY())); + HFActionEvent endActionEvent(HFActionEvent::endType(), computePickRay()); sendEvent(this, &endActionEvent); } break; @@ -1362,7 +1399,7 @@ void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { // nobody handled this - make it an action event on the _window object HFActionEvent actionEvent(HFActionEvent::startType(), - _myCamera.computePickRay(event->x(), event->y())); + computePickRay(event->x(), event->y())); sendEvent(this, &actionEvent); } else if (event->button() == Qt::RightButton) { @@ -1397,7 +1434,7 @@ void Application::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) { // fire an action end event HFActionEvent actionEvent(HFActionEvent::endType(), - _myCamera.computePickRay(event->x(), event->y())); + computePickRay(event->x(), event->y())); sendEvent(this, &actionEvent); } } @@ -1569,11 +1606,13 @@ void Application::idle() { const float BIGGEST_DELTA_TIME_SECS = 0.25f; update(glm::clamp((float)timeSinceLastUpdate / 1000.0f, 0.0f, BIGGEST_DELTA_TIME_SECS)); } + { PerformanceTimer perfTimer("updateGL"); PerformanceWarning warn(showWarnings, "Application::idle()... updateGL()"); - _glWidget->updateGL(); + getActiveRenderPlugin()->idle(); } + { PerformanceTimer perfTimer("rest"); PerformanceWarning warn(showWarnings, "Application::idle()... rest of it"); @@ -1653,11 +1692,15 @@ void Application::setFullscreen(bool fullscreen) { } } + void Application::setEnable3DTVMode(bool enable3DTVMode) { +#if 0 resizeGL(_glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); +#endif } void Application::setEnableVRMode(bool enableVRMode) { +#if 0 if (Menu::getInstance()->isOptionChecked(MenuOption::EnableVRMode) != enableVRMode) { Menu::getInstance()->getActionForOption(MenuOption::EnableVRMode)->setChecked(enableVRMode); } @@ -1682,6 +1725,7 @@ void Application::setEnableVRMode(bool enableVRMode) { resizeGL(_glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); updateCursorVisibility(); +#endif } void Application::setLowVelocityFilter(bool lowVelocityFilter) { @@ -1689,44 +1733,36 @@ void Application::setLowVelocityFilter(bool lowVelocityFilter) { } bool Application::mouseOnScreen() const { - if (OculusManager::isConnected()) { - return getMouseX() >= 0 && getMouseX() <= _glWidget->getDeviceWidth() && - getMouseY() >= 0 && getMouseY() <= _glWidget->getDeviceHeight(); - } - return true; + return getActiveRenderPlugin()->isMouseOnScreen(); } int Application::getMouseX() const { - if (OculusManager::isConnected()) { - glm::vec2 pos = _applicationOverlay.screenToOverlay(glm::vec2(getTrueMouseX(), getTrueMouseY())); - return pos.x; - } - return getTrueMouseX(); + return getActiveRenderPlugin()->getUiMousePosition().x; } int Application::getMouseY() const { - if (OculusManager::isConnected()) { - glm::vec2 pos = _applicationOverlay.screenToOverlay(glm::vec2(getTrueMouseX(), getTrueMouseY())); - return pos.y; - } - return getTrueMouseY(); + return getActiveRenderPlugin()->getUiMousePosition().x; } int Application::getMouseDragStartedX() const { +#if 0 if (OculusManager::isConnected()) { glm::vec2 pos = _applicationOverlay.screenToOverlay(glm::vec2(getTrueMouseDragStartedX(), getTrueMouseDragStartedY())); return pos.x; } +#endif return getTrueMouseDragStartedX(); } int Application::getMouseDragStartedY() const { +#if 0 if (OculusManager::isConnected()) { glm::vec2 pos = _applicationOverlay.screenToOverlay(glm::vec2(getTrueMouseDragStartedX(), getTrueMouseDragStartedY())); return pos.y; } +#endif return getTrueMouseDragStartedY(); } @@ -1878,6 +1914,7 @@ void Application::init() { _mirrorCamera.setMode(CAMERA_MODE_MIRROR); +#if 0 OculusManager::connect(); if (OculusManager::isConnected()) { QMetaObject::invokeMethod(Menu::getInstance()->getActionForOption(MenuOption::Fullscreen), @@ -1891,6 +1928,7 @@ void Application::init() { "trigger", Qt::QueuedConnection); } +#endif _timerStart.start(); _lastTimeUpdated.start(); @@ -1955,19 +1993,20 @@ void Application::init() { _entityClipboardRenderer.setViewFrustum(getViewFrustum()); _entityClipboardRenderer.setTree(&_entityClipboard); - _rearMirrorTools = new RearMirrorTools(_glWidget, _mirrorViewRect); + _rearMirrorTools = new RearMirrorTools(_mirrorViewRect); connect(_rearMirrorTools, SIGNAL(closeView()), SLOT(closeMirrorView())); connect(_rearMirrorTools, SIGNAL(restoreView()), SLOT(restoreMirrorView())); connect(_rearMirrorTools, SIGNAL(shrinkView()), SLOT(shrinkMirrorView())); connect(_rearMirrorTools, SIGNAL(resetView()), SLOT(resetSensors())); +#if 0 // make sure our texture cache knows about window size changes DependencyManager::get()->associateWithWidget(_glWidget); +#endif // initialize the GlowEffect with our widget - DependencyManager::get()->init(_glWidget, - Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)); + DependencyManager::get()->init(Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect)); } void Application::closeMirrorView() { @@ -2018,7 +2057,7 @@ void Application::updateMouseRay() { // make sure the frustum is up-to-date loadViewFrustum(_myCamera, _viewFrustum); - PickRay pickRay = _myCamera.computePickRay(getTrueMouseX(), getTrueMouseY()); + PickRay pickRay = computePickRay(); _mouseRayOrigin = pickRay.origin; _mouseRayDirection = pickRay.direction; @@ -2043,6 +2082,7 @@ void Application::updateMyAvatarLookAtPosition() { bool isLookingAtSomeone = false; glm::vec3 lookAtSpot; if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { +#if 0 // When I am in mirror mode, just look right at the camera (myself) if (!OculusManager::isConnected()) { lookAtSpot = _myCamera.getPosition(); @@ -2053,7 +2093,7 @@ void Application::updateMyAvatarLookAtPosition() { lookAtSpot = OculusManager::getRightEyePosition(); } } - +#endif } else { AvatarSharedPointer lookingAt = _myAvatar->getLookAtTargetAvatar().toStrongRef(); if (lookingAt && _myAvatar != lookingAt.data()) { @@ -2138,6 +2178,7 @@ void Application::updateCamera(float deltaTime) { bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::updateCamera()"); +#if 0 if (!OculusManager::isConnected() && !TV3DManager::isConnected() && Menu::getInstance()->isOptionChecked(MenuOption::OffAxisProjection)) { FaceTracker* tracker = getActiveFaceTracker(); @@ -2149,6 +2190,8 @@ void Application::updateCamera(float deltaTime) { updateProjectionMatrix(); } } +#endif + } void Application::updateDialogs(float deltaTime) { @@ -2239,13 +2282,13 @@ void Application::update(float deltaTime) { PerformanceTimer perfTimer("overlays"); _overlays.update(deltaTime); } - +#if 0 { PerformanceTimer perfTimer("myAvatar"); updateMyAvatarLookAtPosition(); DependencyManager::get()->updateMyAvatar(deltaTime); // Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes } - +#endif { PerformanceTimer perfTimer("emitSimulating"); // let external parties know we're updating @@ -2561,16 +2604,12 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node } bool Application::isHMDMode() const { - if (OculusManager::isConnected()) { - return true; - } else { - return false; - } + return getActiveRenderPlugin()->isHmd(); } QRect Application::getDesirableApplicationGeometry() { QRect applicationGeometry = getWindow()->geometry(); - +#if 0 // If our parent window is on the HMD, then don't use its geometry, instead use // the "main screen" geometry. HMDToolsDialog* hmdTools = DependencyManager::get()->getHMDToolsDialog(); @@ -2588,6 +2627,7 @@ QRect Application::getDesirableApplicationGeometry() { applicationGeometry = betterScreen->geometry(); } } +#endif return applicationGeometry; } @@ -2786,8 +2826,6 @@ void Application::updateShadowMap() { } fbo->release(); - - glViewport(0, 0, _glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); activeRenderingThread = nullptr; } @@ -2826,10 +2864,6 @@ int Application::getBoundaryLevelAdjust() const { return DependencyManager::get()->getBoundaryLevelAdjust(); } -PickRay Application::computePickRay(float x, float y) { - return getCamera()->computePickRay(x, y); -} - QImage Application::renderAvatarBillboard() { DependencyManager::get()->getPrimaryFramebufferObject()->bind(); @@ -2837,9 +2871,11 @@ QImage Application::renderAvatarBillboard() { Glower glower; const int BILLBOARD_SIZE = 64; +#if 0 renderRearViewMirror(QRect(0, _glWidget->getDeviceHeight() - BILLBOARD_SIZE, BILLBOARD_SIZE, BILLBOARD_SIZE), true); +#endif QImage image(BILLBOARD_SIZE, BILLBOARD_SIZE, QImage::Format_ARGB32); glReadPixels(0, 0, BILLBOARD_SIZE, BILLBOARD_SIZE, GL_BGRA, GL_UNSIGNED_BYTE, image.bits()); @@ -3127,15 +3163,9 @@ void Application::getProjectionMatrix(glm::dmat4* projectionMatrix) { void Application::computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& nearVal, float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const { - - // allow 3DTV/Oculus to override parameters from camera _displayViewFrustum.computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); - if (OculusManager::isConnected()) { - OculusManager::overrideOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); - - } else if (TV3DManager::isConnected()) { - TV3DManager::overrideOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); - } + // allow 3DTV/Oculus to override parameters from camera + getActiveRenderPlugin()->overrideOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); } bool Application::getShadowsEnabled() { @@ -3148,32 +3178,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(const QRect& region, bool billboard) { // Grab current viewport to reset it at the end int viewport[4]; @@ -3214,7 +3218,6 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) { _mirrorCamera.setAspectRatio((float)region.width() / region.height()); _mirrorCamera.setRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI, 0.0f))); - _mirrorCamera.update(1.0f/_fps); // set the bounds of rear mirror view if (billboard) { @@ -3254,15 +3257,15 @@ void Application::resetSensors() { DependencyManager::get()->reset(); DependencyManager::get()->reset(); - OculusManager::reset(); - + getActiveRenderPlugin()->resetSensors(); //_leapmotion.reset(); +#if 0 QScreen* currentScreen = _window->windowHandle()->screen(); QWindow* mainWindow = _window->windowHandle(); QPoint windowCenter = mainWindow->geometry().center(); _glWidget->cursor().setPos(currentScreen, windowCenter); - +#endif _myAvatar->reset(); QMetaObject::invokeMethod(DependencyManager::get().data(), "reset", Qt::QueuedConnection); @@ -4021,7 +4024,7 @@ void Application::setPreviousScriptLocation(const QString& previousScriptLocatio void Application::loadDialog() { - QString fileNameString = QFileDialog::getOpenFileName(_glWidget, + QString fileNameString = QFileDialog::getOpenFileName(desktop(), tr("Open Script"), getPreviousScriptLocation(), tr("JavaScript Files (*.js)")); @@ -4062,7 +4065,7 @@ void Application::setScriptsLocation(const QString& scriptsLocation) { void Application::toggleLogDialog() { if (! _logDialog) { - _logDialog = new LogDialog(_glWidget, getLogger()); + _logDialog = new LogDialog(desktop(), getLogger()); } if (_logDialog->isVisible()) { @@ -4119,7 +4122,7 @@ void Application::parseVersionXml() { } if (!shouldSkipVersion(latestVersion) && applicationVersion() != latestVersion) { - new UpdateDialog(_glWidget, releaseNotes, latestVersion, downloadUrl); + new UpdateDialog(desktop(), releaseNotes, latestVersion, downloadUrl); } sender->deleteLater(); } @@ -4152,7 +4155,7 @@ void Application::takeSnapshot() { } if (!_snapshotShareDialog) { - _snapshotShareDialog = new SnapshotShareDialog(fileName, _glWidget); + _snapshotShareDialog = new SnapshotShareDialog(fileName, desktop()); } _snapshotShareDialog->show(); } @@ -4330,3 +4333,90 @@ void Application::friendsWindowClosed() { delete _friendsWindow; _friendsWindow = NULL; } + + +PickRay Application::computePickRay() const { + return computePickRay(getTrueMouseX(), getTrueMouseY()); +} + +PickRay Application::computeViewPickRay(float xRatio, float yRatio) const { + PickRay result; +#if 0 + if (OculusManager::isConnected()) { + Application::getInstance()->getApplicationOverlay().computeOculusPickRay(xRatio, yRatio, result.origin, result.direction); + } else { +#endif + Application::getInstance()->getViewFrustum()->computePickRay(xRatio, yRatio, result.origin, result.direction); +#if 0 + } +#endif + return result; +} + +PickRay Application::computePickRay(float x, float y) const { + glm::vec2 canvasSize = getCanvasSize(); + x /= canvasSize.x; + y /= canvasSize.y; + return computeViewPickRay(x, y); +} + +glm::ivec2 Application::getCanvasSize() const { + return getActiveRenderPlugin()->getCanvasSize(); +} + +QSize Application::getDeviceSize() const { + return getActiveRenderPlugin()->getRecommendedFramebufferSize(); // _glWidget->getDeviceSize(); +} + +void Application::resizeGL() { + auto size = getCanvasSize(); + return resizeGL(size.x, size.y); +} + +bool Application::hasFocus() const { + return getActiveRenderPlugin()->hasFocus(); +} + +glm::vec2 Application::getViewportDimensions() const { + return toGlm(getDeviceSize()); +} + +int Application::getTrueMouseX() const { + return getActiveRenderPlugin()->getTrueMousePosition().x; +} + +int Application::getTrueMouseY() const { + return getActiveRenderPlugin()->getTrueMousePosition().y; +} + +bool Application::isThrottleRendering() const { + return getActiveRenderPlugin()->isThrottled(); +} + +#include "plugins/render/NullRenderPlugin.h" +#include "plugins/render/WindowRenderPlugin.h" +#include "plugins/render/LegacyRenderPlugin.h" + +static RenderPlugin * renderPlugin = nullptr; + +RenderPlugin * Application::getActiveRenderPlugin() { + if (nullptr == renderPlugin) { + //renderPlugin = new WindowRenderPlugin(); + renderPlugin = new LegacyRenderPlugin(); + renderPlugin->init(); + renderPlugin->activate(); + connect(renderPlugin, &RenderPlugin::requestRender, this, [&] { + this->paintGL(); + }); + connect(renderPlugin, &RenderPlugin::recommendedFramebufferSizeChanged, this, [&](const QSize & size) { + DependencyManager::get()->setFrameBufferSize(size * getRenderResolutionScale()); + this->resizeGL(size.width(), size.height()); + }); + _offscreenContext->makeCurrent(); + } + return renderPlugin; +} + +const RenderPlugin * Application::getActiveRenderPlugin() const { + return ((Application*)this)->getActiveRenderPlugin(); +} diff --git a/interface/src/Application.h b/interface/src/Application.h index cf047f02d4..40db775f60 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -36,6 +36,8 @@ #include #include #include +#include + #include "AudioClient.h" #include "Bookmarks.h" @@ -70,6 +72,7 @@ #include "octree/OctreeFade.h" #include "octree/OctreePacketProcessor.h" #include "UndoStackScriptingInterface.h" +#include "plugins/render/RenderPlugin.h" class QGLWidget; @@ -154,6 +157,8 @@ public: void paintGL(); void resizeGL(int width, int height); + void resizeEvent(QResizeEvent * size); + void keyPressEvent(QKeyEvent* event); void keyReleaseEvent(QKeyEvent* event); @@ -174,8 +179,14 @@ public: bool event(QEvent* event); bool eventFilter(QObject* object, QEvent* event); - GLCanvas* getGLWidget() { return _glWidget; } - bool isThrottleRendering() const { return _glWidget->isThrottleRendering(); } + glm::ivec2 getCanvasSize() const; + QSize getDeviceSize() const; + bool hasFocus() const; + PickRay computePickRay() const; + PickRay computeViewPickRay(float xRatio, float yRatio) const; + void resizeGL(); + + bool isThrottleRendering() const; Camera* getCamera() { return &_myCamera; } // Represents the current view frustum of the avatar. @@ -201,8 +212,8 @@ public: bool mouseOnScreen() const; int getMouseX() const; int getMouseY() const; - int getTrueMouseX() const { return _glWidget->mapFromGlobal(QCursor::pos()).x(); } - int getTrueMouseY() const { return _glWidget->mapFromGlobal(QCursor::pos()).y(); } + int getTrueMouseX() const; + int getTrueMouseY() const; int getMouseDragStartedX() const; int getMouseDragStartedY() const; int getTrueMouseDragStartedX() const { return _mouseDragStartedX; } @@ -271,15 +282,17 @@ public: virtual QThread* getMainThread() { return thread(); } virtual float getSizeScale() const; virtual int getBoundaryLevelAdjust() const; - virtual PickRay computePickRay(float x, float y); + virtual PickRay computePickRay(float x, float y) const; virtual const glm::vec3& getAvatarPosition() const { return _myAvatar->getPosition(); } + RenderPlugin * getActiveRenderPlugin(); + const RenderPlugin * getActiveRenderPlugin() const; NodeBounds& getNodeBoundsDisplay() { return _nodeBoundsDisplay; } FileLogger* getLogger() { return _logger; } - glm::vec2 getViewportDimensions() const { return glm::vec2(_glWidget->getDeviceWidth(), - _glWidget->getDeviceHeight()); } + glm::vec2 getViewportDimensions() const; + NodeToJurisdictionMap& getEntityServerJurisdictions() { return _entityServerJurisdictions; } void skipVersion(QString latestVersion); @@ -411,8 +424,6 @@ private slots: void setEnableVRMode(bool enableVRMode); void cameraMenuChanged(); - glm::vec2 getScaledScreenPoint(glm::vec2 projectedPoint); - void closeMirrorView(); void restoreMirrorView(); void shrinkMirrorView(); @@ -471,6 +482,9 @@ private: int sendNackPackets(); bool _dependencyManagerIsSetup; + + OffscreenGlContext* _offscreenContext{ new OffscreenGlContext() }; + MainWindow* _window; ToolWindow* _toolWindow; @@ -611,7 +625,7 @@ private: QThread _settingsThread; QTimer _settingsTimer; - GLCanvas* _glWidget = new GLCanvas(); // our GLCanvas has a couple extra features + void checkSkeleton(); diff --git a/interface/src/Camera.cpp b/interface/src/Camera.cpp index e334fd7c65..40ce59ffdb 100644 --- a/interface/src/Camera.cpp +++ b/interface/src/Camera.cpp @@ -55,42 +55,24 @@ Camera::Camera() : _farClip(DEFAULT_FAR_CLIP), // default _hmdPosition(), _hmdRotation(), - _scale(1.0f), - _isKeepLookingAt(false), - _lookingAt(0.0f, 0.0f, 0.0f) + _scale(1.0f) { } -void Camera::update(float deltaTime) { - if (_isKeepLookingAt) { - lookAt(_lookingAt); - } - return; -} - void Camera::setPosition(const glm::vec3& position) { _position = position; } void Camera::setRotation(const glm::quat& rotation) { _rotation = rotation; - if (_isKeepLookingAt) { - lookAt(_lookingAt); - } } void Camera::setHmdPosition(const glm::vec3& hmdPosition) { _hmdPosition = hmdPosition; - if (_isKeepLookingAt) { - lookAt(_lookingAt); - } } void Camera::setHmdRotation(const glm::quat& hmdRotation) { _hmdRotation = hmdRotation; - if (_isKeepLookingAt) { - lookAt(_lookingAt); - } } float Camera::getFarClip() const { @@ -121,21 +103,6 @@ void Camera::setFarClip(float f) { _farClip = f; } -PickRay Camera::computePickRay(float x, float y) { - auto glCanvas = Application::getInstance()->getGLWidget(); - return computeViewPickRay(x / glCanvas->width(), y / glCanvas->height()); -} - -PickRay Camera::computeViewPickRay(float xRatio, float yRatio) { - PickRay result; - if (OculusManager::isConnected()) { - Application::getInstance()->getApplicationOverlay().computeOculusPickRay(xRatio, yRatio, result.origin, result.direction); - } else { - Application::getInstance()->getViewFrustum()->computePickRay(xRatio, yRatio, result.origin, result.direction); - } - return result; -} - void Camera::setModeString(const QString& mode) { CameraMode targetMode = stringToMode(mode); @@ -164,17 +131,3 @@ void Camera::setModeString(const QString& mode) { QString Camera::getModeString() const { return modeToString(_mode); } - -void Camera::lookAt(const glm::vec3& lookAt) { - glm::vec3 up = IDENTITY_UP; - glm::mat4 lookAtMatrix = glm::lookAt(_position, lookAt, up); - glm::quat rotation = glm::quat_cast(lookAtMatrix); - rotation.w = -rotation.w; // Rosedale approved - _rotation = rotation; -} - -void Camera::keepLookingAt(const glm::vec3& point) { - lookAt(point); - _isKeepLookingAt = true; - _lookingAt = point; -} diff --git a/interface/src/Camera.h b/interface/src/Camera.h index 7c6951b920..216ddcae61 100644 --- a/interface/src/Camera.h +++ b/interface/src/Camera.h @@ -41,8 +41,6 @@ public: void initialize(); // instantly put the camera at the ideal position and rotation. - void update( float deltaTime ); - void setRotation(const glm::quat& rotation); void setHmdPosition(const glm::vec3& hmdPosition); void setHmdRotation(const glm::quat& hmdRotation); @@ -77,20 +75,6 @@ public slots: void setOrientation(const glm::quat& orientation) { setRotation(orientation); } glm::quat getOrientation() const { return getRotation(); } - - PickRay computePickRay(float x, float y); - PickRay computeViewPickRay(float xRatio, float yRatio); - - // These only work on independent cameras - /// one time change to what the camera is looking at - void lookAt(const glm::vec3& value); - - /// fix what the camera is looking at, and keep the camera looking at this even if position changes - void keepLookingAt(const glm::vec3& value); - - /// stops the keep looking at feature, doesn't change what's being looked at, but will stop camera from - /// continuing to update it's orientation to keep looking at the item - void stopLooking() { _isKeepLookingAt = false; } signals: void modeUpdated(const QString& newMode); @@ -108,8 +92,6 @@ private: glm::vec3 _hmdPosition; glm::quat _hmdRotation; float _scale; - bool _isKeepLookingAt; - glm::vec3 _lookingAt; }; #endif // hifi_Camera_h diff --git a/interface/src/GLCanvas.cpp b/interface/src/GLCanvas.cpp index 12a10681ce..a8b3a29a98 100644 --- a/interface/src/GLCanvas.cpp +++ b/interface/src/GLCanvas.cpp @@ -60,21 +60,27 @@ void GLCanvas::initializeGL() { void GLCanvas::paintGL() { if (!_throttleRendering && !Application::getInstance()->getWindow()->isMinimized()) { +#if 0 //Need accurate frame timing for the oculus rift if (OculusManager::isConnected()) { OculusManager::beginFrameTiming(); } - +#endif Application::getInstance()->paintGL(); +#if 0 if (!OculusManager::isConnected()) { +#endif + swapBuffers(); +#if 0 } else { if (OculusManager::allowSwap()) { swapBuffers(); } OculusManager::endFrameTiming(); } +#endif } } @@ -134,17 +140,21 @@ void GLCanvas::activeChanged(Qt::ApplicationState state) { void GLCanvas::throttleRender() { _frameTimer.start(_idleRenderInterval); if (!Application::getInstance()->getWindow()->isMinimized()) { +#if 0 //Need accurate frame timing for the oculus rift if (OculusManager::isConnected()) { OculusManager::beginFrameTiming(); } +#endif Application::getInstance()->paintGL(); swapBuffers(); +#if 0 if (OculusManager::isConnected()) { OculusManager::endFrameTiming(); } +#endif } } diff --git a/interface/src/audio/AudioToolBox.cpp b/interface/src/audio/AudioToolBox.cpp index 330e7bc194..5d1b12b5a7 100644 --- a/interface/src/audio/AudioToolBox.cpp +++ b/interface/src/audio/AudioToolBox.cpp @@ -38,15 +38,14 @@ bool AudioToolBox::mousePressEvent(int x, int y) { void AudioToolBox::render(int x, int y, bool boxed) { glEnable(GL_TEXTURE_2D); - auto glCanvas = Application::getInstance()->getGLWidget(); if (_micTextureId == 0) { - _micTextureId = glCanvas->bindTexture(QImage(PathUtils::resourcesPath() + "images/mic.svg")); + _micTextureId = new QOpenGLTexture(QImage(PathUtils::resourcesPath() + "images/mic.svg")); } if (_muteTextureId == 0) { - _muteTextureId = glCanvas->bindTexture(QImage(PathUtils::resourcesPath() + "images/mic-mute.svg")); + _muteTextureId = new QOpenGLTexture(QImage(PathUtils::resourcesPath() + "images/mic-mute.svg")); } if (_boxTextureId == 0) { - _boxTextureId = glCanvas->bindTexture(QImage(PathUtils::resourcesPath() + "images/audio-box.svg")); + _boxTextureId = new QOpenGLTexture(QImage(PathUtils::resourcesPath() + "images/audio-box.svg")); } auto audioIO = DependencyManager::get(); @@ -60,7 +59,7 @@ void AudioToolBox::render(int x, int y, bool boxed) { QRect boxBounds = QRect(x - BOX_LEFT_PADDING, y - BOX_TOP_PADDING, BOX_WIDTH, BOX_HEIGHT); - glBindTexture(GL_TEXTURE_2D, _boxTextureId); + _boxTextureId->bind(); glm::vec4 quadColor; @@ -81,10 +80,10 @@ void AudioToolBox::render(int x, int y, bool boxed) { _iconBounds = QRect(x, y, MUTE_ICON_SIZE, MUTE_ICON_SIZE); if (!audioIO->isMuted()) { - glBindTexture(GL_TEXTURE_2D, _micTextureId); + _micTextureId->bind(); iconColor = 1.0f; } else { - glBindTexture(GL_TEXTURE_2D, _muteTextureId); + _muteTextureId->bind(); // Make muted icon pulsate static const float PULSE_MIN = 0.4f; diff --git a/interface/src/audio/AudioToolBox.h b/interface/src/audio/AudioToolBox.h index 526de89b9c..8ace687b9b 100644 --- a/interface/src/audio/AudioToolBox.h +++ b/interface/src/audio/AudioToolBox.h @@ -14,6 +14,7 @@ #include #include +#include class AudioToolBox : public Dependency { SINGLETON_DEPENDENCY @@ -24,9 +25,9 @@ public: protected: AudioToolBox(); private: - GLuint _micTextureId = 0; - GLuint _muteTextureId = 0; - GLuint _boxTextureId = 0; + QOpenGLTexture* _micTextureId = 0; + QOpenGLTexture* _muteTextureId = 0; + QOpenGLTexture* _boxTextureId = 0; int _boxQuadID = GeometryCache::UNKNOWN_ID; QRect _iconBounds; qint64 _iconPulseTimeReference = 0; diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index b90b693139..af5455653a 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -289,9 +289,12 @@ glm::quat Head::getCameraOrientation() const { // to change the driving direction while in Oculus mode. It is used to support driving toward where you're // head is looking. Note that in oculus mode, your actual camera view and where your head is looking is not // always the same. +#if 0 if (OculusManager::isConnected()) { return getOrientation(); } +#endif + Avatar* owningAvatar = static_cast(_owningAvatar); return owningAvatar->getWorldAlignedOrientation() * glm::quat(glm::radians(glm::vec3(_basePitch, 0.0f, 0.0f))); } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 6b70577754..48f6a9a75f 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -230,6 +230,7 @@ void MyAvatar::simulate(float deltaTime) { void MyAvatar::updateFromTrackers(float deltaTime) { glm::vec3 estimatedPosition, estimatedRotation; +#if 0 if (isPlaying() && !OculusManager::isConnected()) { return; } @@ -301,6 +302,7 @@ void MyAvatar::updateFromTrackers(float deltaTime) { -MAX_LEAN, MAX_LEAN)); head->setLeanForward(glm::clamp(glm::degrees(atanf(relativePosition.z * _leanScale / TORSO_LENGTH)), -MAX_LEAN, MAX_LEAN)); +#endif } @@ -829,11 +831,15 @@ void MyAvatar::updateLookAtTargetAvatar() { howManyLookingAtMe++; // Have that avatar look directly at my camera // Philip TODO: correct to look at left/right eye +#if 0 if (OculusManager::isConnected()) { avatar->getHead()->setCorrectedLookAtPosition(OculusManager::getLeftEyePosition()); } else { +#endif avatar->getHead()->setCorrectedLookAtPosition(Application::getInstance()->getViewFrustum()->getPosition()); +#if 0 } +#endif } else { avatar->getHead()->clearCorrectedLookAtPosition(); } @@ -1017,6 +1023,7 @@ void MyAvatar::renderBody(ViewFrustum* renderFrustum, RenderArgs::RenderMode ren renderFrustum->setNearClip(DEFAULT_NEAR_CLIP); } else { float clipDistance = _skeletonModel.getHeadClipDistance(); +#if 0 if (OculusManager::isConnected()) { // If avatar is horizontally in front of camera, increase clip distance by the amount it is in front. glm::vec3 cameraToAvatar = _position - cameraPos; @@ -1027,6 +1034,7 @@ void MyAvatar::renderBody(ViewFrustum* renderFrustum, RenderArgs::RenderMode ren clipDistance += headOffset; } } +#endif renderFrustum->setNearClip(clipDistance); } } @@ -1061,11 +1069,13 @@ void MyAvatar::updateOrientation(float deltaTime) { // Gather rotation information from keyboard const float TIME_BETWEEN_HMD_TURNS = 0.5f; const float HMD_TURN_DEGREES = 22.5f; +#if 0 if (!OculusManager::isConnected()) { // Smoothly rotate body with arrow keys if not in HMD _bodyYawDelta -= _driveKeys[ROT_RIGHT] * YAW_SPEED * deltaTime; _bodyYawDelta += _driveKeys[ROT_LEFT] * YAW_SPEED * deltaTime; } else { +#endif // Jump turns if in HMD if (_driveKeys[ROT_RIGHT] || _driveKeys[ROT_LEFT]) { if (_turningKeyPressTime == 0.0f) { @@ -1079,7 +1089,9 @@ void MyAvatar::updateOrientation(float deltaTime) { } else { _turningKeyPressTime = 0.0f; } +#if 0 } +#endif getHead()->setBasePitch(getHead()->getBasePitch() + (_driveKeys[ROT_UP] - _driveKeys[ROT_DOWN]) * PITCH_SPEED * deltaTime); // update body orientation by movement inputs @@ -1095,6 +1107,7 @@ void MyAvatar::updateOrientation(float deltaTime) { float MINIMUM_ROTATION_RATE = 2.0f; if (fabs(_bodyYawDelta) < MINIMUM_ROTATION_RATE) { _bodyYawDelta = 0.0f; } +#if 0 if (OculusManager::isConnected()) { // these angles will be in radians float yaw, pitch, roll; @@ -1117,7 +1130,7 @@ void MyAvatar::updateOrientation(float deltaTime) { } } - +#endif } glm::vec3 MyAvatar::applyKeyboardMotor(float deltaTime, const glm::vec3& localVelocity, bool isHovering) { diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index d56ece12fb..22ac44c5d4 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -9,7 +9,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // - +#if 0 #include "InterfaceConfig.h" #include "OculusManager.h" @@ -860,3 +860,4 @@ int OculusManager::getHMDScreen() { return hmdScreenIndex; } +#endif \ No newline at end of file diff --git a/interface/src/devices/TV3DManager.cpp b/interface/src/devices/TV3DManager.cpp index f082c6de47..e64a547dc1 100644 --- a/interface/src/devices/TV3DManager.cpp +++ b/interface/src/devices/TV3DManager.cpp @@ -35,18 +35,15 @@ bool TV3DManager::isConnected() { } void TV3DManager::connect() { - auto glCanvas = Application::getInstance()->getGLWidget(); - int width = glCanvas->getDeviceWidth(); - int height = glCanvas->getDeviceHeight(); + auto deviceSize = qApp->getDeviceSize(); Camera& camera = *Application::getInstance()->getCamera(); - - configureCamera(camera, width, height); + configureCamera(camera, deviceSize.width(), deviceSize.height()); } // The basic strategy of this stereoscopic rendering is explained here: // http://www.orthostereo.com/geometryopengl.html -void TV3DManager::setFrustum(Camera& whichCamera) { +void TV3DManager::setFrustum(const Camera& whichCamera) { const double DTR = 0.0174532925; // degree to radians const double IOD = 0.05; //intraocular distance double fovy = whichCamera.getFieldOfView(); // field of view in y-axis @@ -70,7 +67,9 @@ void TV3DManager::setFrustum(Camera& whichCamera) { _rightEye.modelTranslation = -IOD / 2; } -void TV3DManager::configureCamera(Camera& whichCamera, int screenWidth, int screenHeight) { +void TV3DManager::configureCamera(Camera& whichCamera_, int screenWidth, int screenHeight) { + const Camera& whichCamera = whichCamera_; + if (screenHeight == 0) { screenHeight = 1; // prevent divide by 0 } @@ -93,8 +92,7 @@ void TV3DManager::display(Camera& whichCamera) { // left eye portal int portalX = 0; int portalY = 0; - auto glCanvas = Application::getInstance()->getGLWidget(); - QSize deviceSize = glCanvas->getDeviceSize() * + QSize deviceSize = qApp->getDeviceSize() * Application::getInstance()->getRenderResolutionScale(); int portalW = deviceSize.width() / 2; int portalH = deviceSize.height(); @@ -103,7 +101,7 @@ void TV3DManager::display(Camera& whichCamera) { // We only need to render the overlays to a texture once, then we just render the texture as a quad // PrioVR will only work if renderOverlay is called, calibration is connected to Application::renderingOverlay() - applicationOverlay.renderOverlay(true); + applicationOverlay.renderOverlay(); DependencyManager::get()->prepare(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -134,7 +132,9 @@ void TV3DManager::display(Camera& whichCamera) { eyeCamera.setEyeOffsetPosition(glm::vec3(-_activeEye->modelTranslation,0,0)); Application::getInstance()->displaySide(eyeCamera, false, RenderArgs::MONO); +#if 0 applicationOverlay.displayOverlayTexture3DTV(whichCamera, _aspect, fov); +#endif _activeEye = NULL; } glPopMatrix(); @@ -162,8 +162,9 @@ void TV3DManager::display(Camera& whichCamera) { glLoadIdentity(); eyeCamera.setEyeOffsetPosition(glm::vec3(-_activeEye->modelTranslation,0,0)); Application::getInstance()->displaySide(eyeCamera, false, RenderArgs::MONO); - +#if 0 applicationOverlay.displayOverlayTexture3DTV(whichCamera, _aspect, fov); +#endif _activeEye = NULL; } glPopMatrix(); diff --git a/interface/src/devices/TV3DManager.h b/interface/src/devices/TV3DManager.h index 2b2b9e0aa1..e68f1fc14e 100644 --- a/interface/src/devices/TV3DManager.h +++ b/interface/src/devices/TV3DManager.h @@ -11,7 +11,6 @@ #ifndef hifi_TV3DManager_h #define hifi_TV3DManager_h - #include #include @@ -37,7 +36,7 @@ public: 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(Camera& whichCamera); + static void setFrustum(const Camera& whichCamera); static int _screenWidth; static int _screenHeight; static double _aspect; diff --git a/interface/src/main.cpp b/interface/src/main.cpp index b4486ceb2b..cf4f00fc5a 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -94,11 +94,14 @@ int main(int argc, const char* argv[]) { usecTimestampNowForceClockSkew(clockSkew); qCDebug(interfaceapp, "clockSkewOption=%s clockSkew=%d", clockSkewOption, clockSkew); } + +#if 0 // Oculus initialization MUST PRECEDE OpenGL context creation. // The nature of the Application constructor means this has to be either here, // or in the main window ctor, before GL startup. OculusManager::init(); - +#endif + int exitCode; { QSettings::setDefaultFormat(QSettings::IniFormat); diff --git a/interface/src/plugins/Plugin.cpp b/interface/src/plugins/Plugin.cpp new file mode 100644 index 0000000000..d882c538b4 --- /dev/null +++ b/interface/src/plugins/Plugin.cpp @@ -0,0 +1 @@ +#include "Plugin.h" diff --git a/interface/src/plugins/Plugin.h b/interface/src/plugins/Plugin.h new file mode 100644 index 0000000000..d22fc52c3d --- /dev/null +++ b/interface/src/plugins/Plugin.h @@ -0,0 +1,18 @@ +#pragma once + +#include +#include + +class Plugin : public QObject { +public: + virtual const QString & getName() = 0; + virtual bool isSupported() { return true; } + + virtual void init() {} + virtual void deinit() {} + + virtual void activate() {} + virtual void deactivate() {} + + virtual void idle() {} +}; diff --git a/interface/src/plugins/PluginManager.cpp b/interface/src/plugins/PluginManager.cpp new file mode 100644 index 0000000000..7f631abd64 --- /dev/null +++ b/interface/src/plugins/PluginManager.cpp @@ -0,0 +1 @@ +#include "PluginManager.h" diff --git a/interface/src/plugins/PluginManager.h b/interface/src/plugins/PluginManager.h new file mode 100644 index 0000000000..96cb777235 --- /dev/null +++ b/interface/src/plugins/PluginManager.h @@ -0,0 +1,12 @@ +#pragma once + +#include "plugins/Plugin.h" +#include "plugins/render/RenderPlugin.h" +#include +#include + +class PluginManager : public QObject { +public: + static PluginManager * getInstance(); + const QList> getRenderPlugins(); +}; diff --git a/interface/src/plugins/render/HmdRenderPlugin.cpp b/interface/src/plugins/render/HmdRenderPlugin.cpp new file mode 100644 index 0000000000..eb2efcc8a8 --- /dev/null +++ b/interface/src/plugins/render/HmdRenderPlugin.cpp @@ -0,0 +1,11 @@ +// +// HmdRenderPlugin.cpp +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "HmdRenderPlugin.h" diff --git a/interface/src/plugins/render/HmdRenderPlugin.h b/interface/src/plugins/render/HmdRenderPlugin.h new file mode 100644 index 0000000000..aa158a1f52 --- /dev/null +++ b/interface/src/plugins/render/HmdRenderPlugin.h @@ -0,0 +1,15 @@ +// +// HmdRenderPlugin.h +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "StereoRenderPlugin.h" + +class HmdRenderPlugin : public StereoRenderPlugin { + virtual bool isHmd() const final { return true; } +}; diff --git a/interface/src/plugins/render/LegacyRenderPlugin.cpp b/interface/src/plugins/render/LegacyRenderPlugin.cpp new file mode 100644 index 0000000000..6d46c6d3f5 --- /dev/null +++ b/interface/src/plugins/render/LegacyRenderPlugin.cpp @@ -0,0 +1,87 @@ +// +// LegacyRenderPlugin.cpp +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "Application.h" +#include "LegacyRenderPlugin.h" +#include "MainWindow.h" +#include + +const QString LegacyRenderPlugin::NAME("LegacyRenderPlugin"); + +const QString & LegacyRenderPlugin::getName() { + return NAME; +} + +static QWidget * oldWidget = nullptr; + +void LegacyRenderPlugin::activate() { + _window = new GLCanvas(); + QGLFormat format(QGL::NoDepthBuffer | QGL::NoStencilBuffer); + _window->setContext(new QGLContext(format), + QGLContext::fromOpenGLContext(QOpenGLContext::currentContext())); + _window->makeCurrent(); + oldWidget = qApp->getWindow()->centralWidget(); + qApp->getWindow()->setCentralWidget(_window); + _window->doneCurrent(); + _window->setFocusPolicy(Qt::StrongFocus); + _window->setFocus(); + _window->setMouseTracking(true); +} + +void LegacyRenderPlugin::deactivate() { + qApp->getWindow()->setCentralWidget(oldWidget); + // stop the glWidget frame timer so it doesn't call paintGL + _window->stopFrameTimer(); + _window->doneCurrent(); + _window->deleteLater(); + _window = nullptr; +} + +QSize LegacyRenderPlugin::getRecommendedFramebufferSize() const { + return _window->getDeviceSize(); +} + +void LegacyRenderPlugin::makeCurrent() { + _window->makeCurrent(); + QSize windowSize = _window->size(); + glViewport(0, 0, windowSize.width(), windowSize.height()); +} + +void LegacyRenderPlugin::doneCurrent() { + _window->doneCurrent(); +} + +void LegacyRenderPlugin::swapBuffers() { + _window->swapBuffers(); + glFinish(); +} + +void LegacyRenderPlugin::idle() { + _window->updateGL(); +} + +glm::ivec2 LegacyRenderPlugin::getCanvasSize() const { + return toGlm(_window->size()); +} + +bool LegacyRenderPlugin::hasFocus() const { + return _window->hasFocus(); +} + +PickRay LegacyRenderPlugin::computePickRay(const glm::vec2 & pos) const { + return PickRay(); +} + +bool isMouseOnScreen() { + return false; +} + +bool LegacyRenderPlugin::isThrottled() { + return _window->isThrottleRendering(); +} \ No newline at end of file diff --git a/interface/src/plugins/render/LegacyRenderPlugin.h b/interface/src/plugins/render/LegacyRenderPlugin.h new file mode 100644 index 0000000000..68161f6c7d --- /dev/null +++ b/interface/src/plugins/render/LegacyRenderPlugin.h @@ -0,0 +1,36 @@ +// +// LegacyRenderPlugin.h +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "SimpleRenderPlugin.h" +#include "GLCanvas.h" + +class LegacyRenderPlugin : public SimpleRenderPlugin { + Q_OBJECT +public: + static const QString NAME; + virtual const QString & getName(); + + virtual void activate(); + virtual void deactivate(); + + virtual QSize getRecommendedFramebufferSize() const; + virtual glm::ivec2 getCanvasSize() const; + virtual bool hasFocus() const; + virtual PickRay computePickRay(const glm::vec2 & pos) const; + virtual bool isMouseOnScreen() const { return true; } + virtual bool isThrottled(); + +protected: + virtual void makeCurrent(); + virtual void doneCurrent(); + virtual void swapBuffers(); + virtual void idle(); +}; diff --git a/interface/src/plugins/render/NullRenderPlugin.cpp b/interface/src/plugins/render/NullRenderPlugin.cpp new file mode 100644 index 0000000000..f2221a5767 --- /dev/null +++ b/interface/src/plugins/render/NullRenderPlugin.cpp @@ -0,0 +1,44 @@ +// +// NullRenderPlugin.cpp +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "NullRenderPlugin.h" + +const QString NullRenderPlugin::NAME("NullRenderPlugin"); + +const QString & NullRenderPlugin::getName() { + return NAME; +} + +QSize NullRenderPlugin::getRecommendedFramebufferSize() const { + return QSize(100, 100); +} + +glm::ivec2 NullRenderPlugin::getCanvasSize() const { + return glm::ivec2(100, 100); +} + +bool NullRenderPlugin::hasFocus() const { + return false; +} + +glm::ivec2 NullRenderPlugin::getRelativeMousePosition() const { + return glm::ivec2(); +} + +glm::ivec2 NullRenderPlugin::getTrueMousePosition() const { + return glm::ivec2(); +} + +PickRay NullRenderPlugin::computePickRay(const glm::vec2 & pos) const { + return PickRay(); +} + +bool NullRenderPlugin::isMouseOnScreen() { + return false; +} diff --git a/interface/src/plugins/render/NullRenderPlugin.h b/interface/src/plugins/render/NullRenderPlugin.h new file mode 100644 index 0000000000..dfe0e5a0bf --- /dev/null +++ b/interface/src/plugins/render/NullRenderPlugin.h @@ -0,0 +1,29 @@ +// +// NullRenderPlugin.h +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "RenderPlugin.h" + +class NullRenderPlugin : public RenderPlugin { +public: + static const QString NAME; + + virtual ~NullRenderPlugin() final {} + virtual const QString & getName(); + + virtual QSize getRecommendedFramebufferSize() 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(); + +}; diff --git a/interface/src/plugins/render/OculusBaseRenderPlugin.cpp b/interface/src/plugins/render/OculusBaseRenderPlugin.cpp new file mode 100644 index 0000000000..700143c177 --- /dev/null +++ b/interface/src/plugins/render/OculusBaseRenderPlugin.cpp @@ -0,0 +1,105 @@ +// +// OculusBaseRenderPlugin.cpp +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "OculusBaseRenderPlugin.h" + +#include + +bool OculusBaseRenderPlugin::sdkInitialized = false; + +bool OculusBaseRenderPlugin::enableSdk() { + sdkInitialized = ovr_Initialize(); + return sdkInitialized; +} + +void OculusBaseRenderPlugin::disableSdk() { + ovr_Shutdown(); + sdkInitialized = false; +} + +void OculusBaseRenderPlugin::withSdkActive(std::function f) { + bool activateSdk = !sdkInitialized; + if (activateSdk && !enableSdk()) { + return; + } + f(); + if (activateSdk) { + disableSdk(); + } +} + +bool OculusBaseRenderPlugin::isSupported() { + bool attached = false; + withSdkActive([&] { + attached = ovrHmd_Detect(); + }); + return attached; +} + +void OculusBaseRenderPlugin::activate() { + enableSdk(); +} + +void OculusBaseRenderPlugin::deactivate() { + disableSdk(); +} + + +#if 0 +// Set the desired FBO texture size. If it hasn't changed, this does nothing. +// Otherwise, it must rebuild the FBOs +if (OculusManager::isConnected()) { + DependencyManager::get()->setFrameBufferSize(OculusManager::getRenderTargetSize()); +} else { +#endif + +#if 0 + // Update camera position + if (!OculusManager::isConnected()) { + _myCamera.update(1.0f / _fps); + } +#endif + +#if 0 + if (OculusManager::isConnected()) { + //When in mirror mode, use camera rotation. Otherwise, use body rotation + if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { + OculusManager::display(_myCamera.getRotation(), _myCamera.getPosition(), _myCamera); + } else { + OculusManager::display(_myAvatar->getWorldAlignedOrientation(), _myAvatar->getDefaultEyePosition(), _myCamera); + } + _myCamera.update(1.0f / _fps); + +#endif + +#if 0 + OculusManager::abandonCalibration(); +#endif + +#if 0 + if (OculusManager::isConnected()) { + return getMouseX() >= 0 && getMouseX() <= _glWidget->getDeviceWidth() && + getMouseY() >= 0 && getMouseY() <= _glWidget->getDeviceHeight(); + } +#endif + +#if 0 + if (OculusManager::isConnected()) { + glm::vec2 pos = _applicationOverlay.screenToOverlay(glm::vec2(getTrueMouseX(), getTrueMouseY())); + return pos.x; + } +#endif +#if 0 + if (OculusManager::isConnected()) { + glm::vec2 pos = _applicationOverlay.screenToOverlay(glm::vec2(getTrueMouseX(), getTrueMouseY())); + return pos.y; + } +#endif + + diff --git a/interface/src/plugins/render/OculusBaseRenderPlugin.h b/interface/src/plugins/render/OculusBaseRenderPlugin.h new file mode 100644 index 0000000000..aa937bf12a --- /dev/null +++ b/interface/src/plugins/render/OculusBaseRenderPlugin.h @@ -0,0 +1,40 @@ +// +// OculusBaseRenderPlugin.h +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "HmdRenderPlugin.h" +#include + +class OculusBaseRenderPlugin : public HmdRenderPlugin { +public: + virtual bool isSupported(); + + virtual void init(); + virtual void deinit(); + + virtual void activate(); + virtual void deactivate(); + + virtual void overrideOffAxisFrustum( + float& left, float& right, float& bottom, float& top, + float& nearVal, float& farVal, + glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const; + + +protected: + virtual bool isRiftPresent(); + virtual bool isDirectMode(); + + static bool sdkInitialized; + + static void withSdkActive(std::function f); + static bool enableSdk(); + static void disableSdk(); +}; diff --git a/interface/src/plugins/render/OculusDirectD3DRenderPlugin.cpp b/interface/src/plugins/render/OculusDirectD3DRenderPlugin.cpp new file mode 100644 index 0000000000..fab4fd104f --- /dev/null +++ b/interface/src/plugins/render/OculusDirectD3DRenderPlugin.cpp @@ -0,0 +1,10 @@ +// +// OculusDirectD3DRenderPlugin.cpp +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "OculusDirectD3DRenderPlugin.h" diff --git a/interface/src/plugins/render/OculusDirectD3DRenderPlugin.h b/interface/src/plugins/render/OculusDirectD3DRenderPlugin.h new file mode 100644 index 0000000000..3874481e69 --- /dev/null +++ b/interface/src/plugins/render/OculusDirectD3DRenderPlugin.h @@ -0,0 +1,12 @@ +// +// OculusDirectD3DRenderPlugin.h +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "OculusBaseRenderPlugin.h" diff --git a/interface/src/plugins/render/OculusDirectRenderPlugin.cpp b/interface/src/plugins/render/OculusDirectRenderPlugin.cpp new file mode 100644 index 0000000000..cd96ff0fad --- /dev/null +++ b/interface/src/plugins/render/OculusDirectRenderPlugin.cpp @@ -0,0 +1,10 @@ +// +// OculusDirectRenderPlugin.cpp +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "OculusDirectRenderPlugin.h" diff --git a/interface/src/plugins/render/OculusDirectRenderPlugin.h b/interface/src/plugins/render/OculusDirectRenderPlugin.h new file mode 100644 index 0000000000..afa72cb92e --- /dev/null +++ b/interface/src/plugins/render/OculusDirectRenderPlugin.h @@ -0,0 +1,12 @@ +// +// OculusDirectRenderPlugin.h +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "OculusBaseRenderPlugin.h" diff --git a/interface/src/plugins/render/OculusExtendedRenderPlugin.cpp b/interface/src/plugins/render/OculusExtendedRenderPlugin.cpp new file mode 100644 index 0000000000..5ed0c5cacf --- /dev/null +++ b/interface/src/plugins/render/OculusExtendedRenderPlugin.cpp @@ -0,0 +1,10 @@ +// +// OculusExtendedRenderPlugin.cpp +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "OculusExtendedRenderPlugin.h" diff --git a/interface/src/plugins/render/OculusExtendedRenderPlugin.h b/interface/src/plugins/render/OculusExtendedRenderPlugin.h new file mode 100644 index 0000000000..a9e9a51f0c --- /dev/null +++ b/interface/src/plugins/render/OculusExtendedRenderPlugin.h @@ -0,0 +1,12 @@ +// +// OculusExtendedRenderPlugin.h +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "OculusBaseRenderPlugin.h" diff --git a/interface/src/plugins/render/RenderPlugin.cpp b/interface/src/plugins/render/RenderPlugin.cpp new file mode 100644 index 0000000000..11052aca11 --- /dev/null +++ b/interface/src/plugins/render/RenderPlugin.cpp @@ -0,0 +1,16 @@ +// +// RenderPlugin.cpp +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "RenderPlugin.h" + +bool RenderPlugin::isMouseOnScreen() const { + glm::ivec2 mousePosition = getTrueMousePosition(); + return (glm::all(glm::greaterThanEqual(mousePosition, glm::ivec2(0))) && + glm::all(glm::lessThanEqual(mousePosition, glm::ivec2(getCanvasSize())))); +} \ No newline at end of file diff --git a/interface/src/plugins/render/RenderPlugin.h b/interface/src/plugins/render/RenderPlugin.h new file mode 100644 index 0000000000..e29fd20be2 --- /dev/null +++ b/interface/src/plugins/render/RenderPlugin.h @@ -0,0 +1,82 @@ +// +// RenderPlugin.h +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "plugins/Plugin.h" + +#include + +#include +#include +#include + +class RenderPlugin : public Plugin { + Q_OBJECT +public: + virtual bool isHmd() const { return false; } + virtual bool isStereo() const { return false; } + virtual bool isThrottled() const { return false; } + + // Rendering support + virtual void preRender() {}; + virtual void render(int finalSceneTexture) {}; + virtual void postRender() {}; + + // Pointer support + + // Does the rendering surface have current focus? + virtual bool hasFocus() const = 0; + // The size of the rendering surface + virtual QSize getRecommendedFramebufferSize() const = 0; + // The size of the window (differs from the framebuffers size in instances like Retina macs) + virtual glm::ivec2 getCanvasSize() const = 0; + + // The mouse position relative to the window (or proxy window) surface + virtual glm::ivec2 getTrueMousePosition() const = 0; + + // The mouse position relative to the UI elements + virtual glm::ivec2 getUiMousePosition() const { + return trueMouseToUiMouse(getTrueMousePosition()); + } + + // Convert from screen mouse coordinates to UI mouse coordinates + virtual glm::ivec2 trueMouseToUiMouse(const glm::ivec2 & position) const { return position; }; + + virtual PickRay computePickRay(const glm::vec2 & pos) const = 0; + virtual bool isMouseOnScreen() const; + virtual void overrideOffAxisFrustum( + float& left, float& right, float& bottom, float& top, + float& nearVal, float& farVal, + glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const { } + + + // HMD specific methods + // TODO move these into another class + virtual glm::mat4 headPose() const { + static const glm::mat4 pose; return pose; + } + virtual glm::quat headOrientation() const { + static const glm::quat orientation; return orientation; + } + virtual glm::vec3 headTranslation() const { + static const glm::vec3 tranlsation; return tranlsation; + } + virtual void abandonCalibration() {} + virtual void resetSensors() {} + +signals: + void recommendedFramebufferSizeChanged(const QSize & size); + void requestRender(); + +protected: + virtual void makeCurrent() {} + virtual void doneCurrent() {} + virtual void swapBuffers() {} +}; diff --git a/interface/src/plugins/render/SimpleRenderPlugin.cpp b/interface/src/plugins/render/SimpleRenderPlugin.cpp new file mode 100644 index 0000000000..40c80f48d6 --- /dev/null +++ b/interface/src/plugins/render/SimpleRenderPlugin.cpp @@ -0,0 +1,13 @@ +// +// SimpleRenderPlugin.cpp +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "SimpleRenderPlugin.h" +#include +#include + diff --git a/interface/src/plugins/render/SimpleRenderPlugin.h b/interface/src/plugins/render/SimpleRenderPlugin.h new file mode 100644 index 0000000000..8a8ee7edd4 --- /dev/null +++ b/interface/src/plugins/render/SimpleRenderPlugin.h @@ -0,0 +1,56 @@ +// +// SimpleRenderPlugin.h +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "RenderPlugin.h" +#include +#include +#include + +template +class SimpleRenderPlugin : public RenderPlugin { +public: + virtual void render(int finalSceneTexture) { + makeCurrent(); + + glDisable(GL_LIGHTING); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glEnable(GL_TEXTURE_2D); + glBindTexture(GL_TEXTURE_2D, finalSceneTexture); + renderFullscreenQuad(); + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_TEXTURE_2D); + + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + glEnable(GL_LIGHTING); + + swapBuffers(); + doneCurrent(); + } + + virtual glm::ivec2 getUiMousePosition() const { + return getTrueMousePosition(); + } + + virtual glm::ivec2 getTrueMousePosition() const { + return toGlm(_window->mapFromGlobal(QCursor::pos())); + } + +protected: + T * _window; +}; diff --git a/interface/src/plugins/render/StereoRenderPlugin.cpp b/interface/src/plugins/render/StereoRenderPlugin.cpp new file mode 100644 index 0000000000..705133dcc4 --- /dev/null +++ b/interface/src/plugins/render/StereoRenderPlugin.cpp @@ -0,0 +1,10 @@ +// +// StereoRenderPlugin.cpp +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "StereoRenderPlugin.h" diff --git a/interface/src/plugins/render/StereoRenderPlugin.h b/interface/src/plugins/render/StereoRenderPlugin.h new file mode 100644 index 0000000000..69504e2ccf --- /dev/null +++ b/interface/src/plugins/render/StereoRenderPlugin.h @@ -0,0 +1,17 @@ +// +// StereoRenderPlugin.h +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "RenderPlugin.h" + +class StereoRenderPlugin : public RenderPlugin { + virtual bool isStereo() const final { return true; } +}; + diff --git a/interface/src/plugins/render/Tv3dRenderPlugin.cpp b/interface/src/plugins/render/Tv3dRenderPlugin.cpp new file mode 100644 index 0000000000..750d1a1743 --- /dev/null +++ b/interface/src/plugins/render/Tv3dRenderPlugin.cpp @@ -0,0 +1,43 @@ +// +// Tv3dRenderPlugin.cpp +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "Tv3dRenderPlugin.h" + +const QString Tv3dRenderPlugin::NAME("Tv3dRenderPlugin"); + +const QString & Tv3dRenderPlugin::getName() { + return NAME; +} + + +void Tv3dRenderPlugin::overrideOffAxisFrustum( + float& left, float& right, float& bottom, float& top, + float& nearVal, float& farVal, + glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const { + +#if 0 + if (_activeEye) { + left = _activeEye->left; + right = _activeEye->right; + bottom = _activeEye->bottom; + top = _activeEye->top; + } +#endif + +} + + +#if 0 + } else if (TV3DManager::isConnected()) { + + TV3DManager::display(_myCamera); + + } else { +#endif diff --git a/interface/src/plugins/render/Tv3dRenderPlugin.h b/interface/src/plugins/render/Tv3dRenderPlugin.h new file mode 100644 index 0000000000..ba25526f6c --- /dev/null +++ b/interface/src/plugins/render/Tv3dRenderPlugin.h @@ -0,0 +1,26 @@ +// +// Tv3dRenderPlugin.h +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "StereoRenderPlugin.h" + +class Tv3dRenderPlugin : public StereoRenderPlugin { + Q_OBJECT +public: + static const QString NAME; + virtual const QString & getName(); + + virtual void overrideOffAxisFrustum( + float& left, float& right, float& bottom, float& top, + float& nearVal, float& farVal, + glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const; + +}; diff --git a/interface/src/plugins/render/WindowRenderPlugin.cpp b/interface/src/plugins/render/WindowRenderPlugin.cpp new file mode 100644 index 0000000000..78a0849bba --- /dev/null +++ b/interface/src/plugins/render/WindowRenderPlugin.cpp @@ -0,0 +1,514 @@ +// +// WindowRenderPlugin.cpp +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "WindowRenderPlugin.h" +#include "RenderUtil.h" + +#include + +WindowRenderPlugin::WindowRenderPlugin() { + connect(&_timer, &QTimer::timeout, this, [&] { + emit requestRender(); + }); +} + +const QString WindowRenderPlugin::NAME("WindowRenderPlugin"); + +const QString & WindowRenderPlugin::getName() { + return NAME; +} + +void WindowRenderPlugin::activate() { + Q_ASSERT(nullptr == _window); + + _context = new QOpenGLContext; + + _window = new QWindow; + _window->setSurfaceType(QSurface::OpenGLSurface); + _window->installEventFilter(this); + glMatrixMode(0); + { + QSurfaceFormat format; + format.setDepthBufferSize(0); + format.setStencilBufferSize(0); + format.setVersion(4, 1); + // Ugh.... + format.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile); + _window->setFormat(format); + _context->setFormat(format); + } + + _context->setShareContext(QOpenGLContext::currentContext()); + _context->create(); + + _window->show(); + + _timer.start(8); +} + +void WindowRenderPlugin::deactivate() { + _timer.stop(); + _context->doneCurrent(); + _context->deleteLater(); + _context = nullptr; + _window->hide(); + _window->destroy(); + _window = nullptr; +} + +bool WindowRenderPlugin::eventFilter(QObject* object, QEvent* event) { + switch (event->type()) { + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::KeyPress: + case QEvent::KeyRelease: + case QEvent::FocusIn: + case QEvent::FocusOut: + case QEvent::Resize: + case QEvent::MouseMove: + QCoreApplication::sendEvent(QCoreApplication::instance(), event); + break; + default: + break; + } + return false; +} + +QSize WindowRenderPlugin::getRecommendedFramebufferSize() const { + return _window->size(); +} + +void WindowRenderPlugin::makeCurrent() { + _context->makeCurrent(_window); + QSize windowSize = _window->size(); + glViewport(0, 0, windowSize.width(), windowSize.height()); +} + +void WindowRenderPlugin::doneCurrent() { + _context->doneCurrent(); +} + +void WindowRenderPlugin::swapBuffers() { + _context->swapBuffers(_window); +} + + +#if 0 + +// +// MainWindow.h +// interface +// +// Created by Mohammed Nafees on 04/06/2014. +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// +// 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__MainWindow__ +#define __hifi__MainWindow__ + +#include +#include + +#include + +#define MSECS_PER_FRAME_WHEN_THROTTLED 66 + +class MainWindow : public QWindow { +public: + explicit MainWindow(QWindow* parent = NULL); + + // Some helpers for compatiblity with QMainWindow + void activateWindow() { + requestActivate(); + } + + bool isMinimized() const { + return windowState() == Qt::WindowMinimized; + } + + void stopFrameTimer(); + + bool isThrottleRendering() const; + + int getDeviceWidth() const; + int getDeviceHeight() const; + QSize getDeviceSize() const { return QSize(getDeviceWidth(), getDeviceHeight()); } + + /* + + + + private slots: + void activeChanged(Qt::ApplicationState state); + void throttleRender(); + bool eventFilter(QObject*, QEvent* event); + */ + public slots: + void restoreGeometry(); + void saveGeometry(); + +signals: + void windowGeometryChanged(QRect geometry); + void windowShown(bool shown); + +protected: + virtual void moveEvent(QMoveEvent* event); + virtual void resizeEvent(QResizeEvent* event); + virtual void showEvent(QShowEvent* event); + virtual void hideEvent(QHideEvent* event); + virtual void changeEvent(QEvent* event); + virtual void windowStateChanged(Qt::WindowState windowState); + virtual void activeChanged(); + + virtual void initializeGL(); + virtual void paintGL(); + virtual void resizeGL(int width, int height); + +private: + Setting::Handle _windowGeometry; + Setting::Handle _windowState; + Qt::WindowState _lastState{ Qt::WindowNoState }; + QOpenGLContext * _context{ nullptr }; + QTimer _frameTimer; + bool _throttleRendering{ false }; + int _idleRenderInterval{ MSECS_PER_FRAME_WHEN_THROTTLED }; +}; + +#endif /* defined(__hifi__MainWindow__) */ + + + + +// +// MainWindow.cpp +// interface +// +// Created by Mohammed Nafees on 04/06/2014. +// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Application.h" + +#include "MainWindow.h" +#include "Menu.h" +#include "Util.h" + +#include + + +MainWindow::MainWindow(QWindow * parent) : +QWindow(parent), +_windowGeometry("WindowGeometry"), +_windowState("WindowState", 0) { + setSurfaceType(QSurface::OpenGLSurface); + + QSurfaceFormat format; + // Qt Quick may need a depth and stencil buffer. Always make sure these are available. + format.setDepthBufferSize(16); + format.setStencilBufferSize(8); + format.setVersion(4, 1); + // Ugh.... + format.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile); + setFormat(format); + + _context = new QOpenGLContext; + _context->setFormat(format); + _context->create(); + + show(); +} + +void MainWindow::restoreGeometry() { + QRect geometry = _windowGeometry.get(qApp->desktop()->availableGeometry()); + setGeometry(geometry); + + // Restore to maximized or full screen after restoring to windowed so that going windowed goes to good position and sizes. + int state = _windowState.get(Qt::WindowNoState) & ~Qt::WindowActive; + if (state != Qt::WindowNoState) { + setWindowState((Qt::WindowState)state); + } +} + +void MainWindow::saveGeometry() { + // Did not use geometry() on purpose, + // see http://doc.qt.io/qt-5/qsettings.html#restoring-the-state-of-a-gui-application + _windowState.set((int)windowState()); + + // Save position and size only if windowed so that have good values for windowed after starting maximized or full screen. + if (windowState() == Qt::WindowNoState) { + _windowGeometry.set(geometry()); + } +} + +void MainWindow::moveEvent(QMoveEvent* event) { + emit windowGeometryChanged(QRect(event->pos(), size())); + QWindow::moveEvent(event); +} + +void MainWindow::resizeEvent(QResizeEvent* event) { + emit windowGeometryChanged(QRect(QPoint(x(), y()), event->size())); + QWindow::resizeEvent(event); +} + +void MainWindow::showEvent(QShowEvent* event) { + if (event->spontaneous()) { + emit windowShown(true); + } + QWindow::showEvent(event); +} + +void MainWindow::hideEvent(QHideEvent* event) { + if (event->spontaneous()) { + emit windowShown(false); + } + QWindow::hideEvent(event); +} + +void MainWindow::windowStateChanged(Qt::WindowState windowState) { + // If we're changing from minimized to non-minimized or vice versas, emit + // a windowShown signal (i.e. don't emit the signal if we're going from + // fullscreen to nostate + if ((_lastState == Qt::WindowMinimized) ^ (windowState == Qt::WindowMinimized)) { + emit windowShown(windowState != Qt::WindowMinimized); + } + + bool fullscreen = windowState == Qt::WindowFullScreen; + if (fullscreen != Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen)) { + Menu::getInstance()->setIsOptionChecked(MenuOption::Fullscreen, fullscreen); + } + + _lastState = windowState; + QWindow::windowStateChanged(windowState); +} + +void MainWindow::activeChanged() { + if (isActive()) { + emit windowShown(true); + } else { + emit windowShown(false); + } + QWindow::activeChanged(); +} + +void MainWindow::stopFrameTimer() { + _frameTimer.stop(); +} + +bool MainWindow::isThrottleRendering() const { + return _throttleRendering || isMinimized(); +} + + +int MainWindow::getDeviceWidth() const { + return width() * devicePixelRatio(); +} + +int MainWindow::getDeviceHeight() const { + return height() * devicePixelRatio(); +} + + + +void MainWindow::initializeGL() { + Application::getInstance()->initializeGL(); + // setAttribute(Qt::WA_AcceptTouchEvents); + // setAcceptDrops(true); + connect(Application::getInstance(), SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SLOT(activeChanged(Qt::ApplicationState))); + connect(&_frameTimer, SIGNAL(timeout()), this, SLOT(throttleRender())); +} + +void GLCanvas::resizeGL(int width, int height) { + Application::getInstance()->resizeGL(width, height); +} + +void GLCanvas::paintGL() { + if (!_throttleRendering && !Application::getInstance()->getWindow()->isMinimized()) { + //Need accurate frame timing for the oculus rift + if (OculusManager::isConnected()) { + OculusManager::beginFrameTiming(); + } + + Application::getInstance()->paintGL(); + + if (!OculusManager::isConnected()) { + swapBuffers(); + } else { + if (OculusManager::allowSwap()) { + swapBuffers(); + } + OculusManager::endFrameTiming(); + } + } +} + + + +/* + +GLCanvas::GLCanvas() : QGLWidget(QGL::NoDepthBuffer | QGL::NoStencilBuffer), +#ifdef Q_OS_LINUX +// Cause GLCanvas::eventFilter to be called. +// It wouldn't hurt to do this on Mac and PC too; but apparently it's only needed on linux. +qApp->installEventFilter(this); +#endif +} + +void GLCanvas::keyPressEvent(QKeyEvent* event) { +Application::getInstance()->keyPressEvent(event); +} + +void GLCanvas::keyReleaseEvent(QKeyEvent* event) { +Application::getInstance()->keyReleaseEvent(event); +} + +void GLCanvas::focusOutEvent(QFocusEvent* event) { +Application::getInstance()->focusOutEvent(event); +} + +void GLCanvas::mouseMoveEvent(QMouseEvent* event) { +Application::getInstance()->mouseMoveEvent(event); +} + +void GLCanvas::mousePressEvent(QMouseEvent* event) { +Application::getInstance()->mousePressEvent(event); +} + +void GLCanvas::mouseReleaseEvent(QMouseEvent* event) { +Application::getInstance()->mouseReleaseEvent(event); +} + +void GLCanvas::activeChanged(Qt::ApplicationState state) { +switch (state) { +case Qt::ApplicationActive: +// If we're active, stop the frame timer and the throttle. +_frameTimer.stop(); +_throttleRendering = false; +break; + +case Qt::ApplicationSuspended: +case Qt::ApplicationHidden: +// If we're hidden or are about to suspend, don't render anything. +_throttleRendering = false; +_frameTimer.stop(); +break; + +default: +// Otherwise, throttle. +if (!_throttleRendering && !Application::getInstance()->isAboutToQuit()) { +_frameTimer.start(_idleRenderInterval); +_throttleRendering = true; +} +break; +} +} + +void GLCanvas::throttleRender() { +_frameTimer.start(_idleRenderInterval); +if (!Application::getInstance()->getWindow()->isMinimized()) { +//Need accurate frame timing for the oculus rift +if (OculusManager::isConnected()) { +OculusManager::beginFrameTiming(); +} + +Application::getInstance()->paintGL(); +swapBuffers(); + +if (OculusManager::isConnected()) { +OculusManager::endFrameTiming(); +} +} +} + +int updateTime = 0; +bool GLCanvas::event(QEvent* event) { +switch (event->type()) { +case QEvent::TouchBegin: +Application::getInstance()->touchBeginEvent(static_cast(event)); +event->accept(); +return true; +case QEvent::TouchEnd: +Application::getInstance()->touchEndEvent(static_cast(event)); +return true; +case QEvent::TouchUpdate: +Application::getInstance()->touchUpdateEvent(static_cast(event)); +return true; +default: +break; +} +return QGLWidget::event(event); +} + +void GLCanvas::wheelEvent(QWheelEvent* event) { +Application::getInstance()->wheelEvent(event); +} + +void GLCanvas::dragEnterEvent(QDragEnterEvent* event) { +const QMimeData* mimeData = event->mimeData(); +foreach(QUrl url, mimeData->urls()) { +auto urlString = url.toString(); +if (Application::getInstance()->canAcceptURL(urlString)) { +event->acceptProposedAction(); +break; +} +} +} + +void GLCanvas::dropEvent(QDropEvent* event) { +Application::getInstance()->dropEvent(event); +} + +// Pressing Alt (and Meta) key alone activates the menubar because its style inherits the +// SHMenuBarAltKeyNavigation from QWindowsStyle. This makes it impossible for a scripts to +// receive keyPress events for the Alt (and Meta) key in a reliable manner. +// +// This filter catches events before QMenuBar can steal the keyboard focus. +// The idea was borrowed from +// http://www.archivum.info/qt-interest@trolltech.com/2006-09/00053/Re-(Qt4)-Alt-key-focus-QMenuBar-(solved).html + +bool GLCanvas::eventFilter(QObject*, QEvent* event) { +switch (event->type()) { +case QEvent::KeyPress: +case QEvent::KeyRelease: +case QEvent::ShortcutOverride: +{ +QKeyEvent* keyEvent = static_cast(event); +if (keyEvent->key() == Qt::Key_Alt || keyEvent->key() == Qt::Key_Meta) { +if (event->type() == QEvent::KeyPress) { +keyPressEvent(keyEvent); +} else if (event->type() == QEvent::KeyRelease) { +keyReleaseEvent(keyEvent); +} else { +QGLWidget::event(event); +} +return true; +} +} +default: +break; +} +return false; +} + +*/ +#endif diff --git a/interface/src/plugins/render/WindowRenderPlugin.h b/interface/src/plugins/render/WindowRenderPlugin.h new file mode 100644 index 0000000000..ec485e4d6e --- /dev/null +++ b/interface/src/plugins/render/WindowRenderPlugin.h @@ -0,0 +1,40 @@ +// +// WindowRenderPlugin.h +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "SimpleRenderPlugin.h" + +#include +#include +#include + +class WindowRenderPlugin : public SimpleRenderPlugin { + Q_OBJECT +public: + static const QString NAME; + + WindowRenderPlugin(); + + virtual const QString & getName(); + + virtual void activate(); + virtual void deactivate(); + virtual bool eventFilter(QObject* object, QEvent* event); + virtual QSize getRecommendedFramebufferSize() const; + +protected: + virtual void makeCurrent(); + virtual void doneCurrent(); + virtual void swapBuffers(); + +private: + QTimer _timer; + QOpenGLContext * _context{ nullptr }; +}; diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index 7d6012c880..5f12d73b37 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -286,8 +286,7 @@ void ControllerScriptingInterface::releaseJoystick(int joystickIndex) { } glm::vec2 ControllerScriptingInterface::getViewportDimensions() const { - auto glCanvas = Application::getInstance()->getGLWidget(); - return glm::vec2(glCanvas->width(), glCanvas->height()); + return Application::getInstance()->getCanvasSize(); } AbstractInputController* ControllerScriptingInterface::createInputController(const QString& deviceName, const QString& tracker) { diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index 6ed3e48274..5e1ac7c436 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -41,7 +41,7 @@ WebWindowClass* WindowScriptingInterface::doCreateWebWindow(const QString& title } QScriptValue WindowScriptingInterface::hasFocus() { - return Application::getInstance()->getGLWidget()->hasFocus(); + return Application::getInstance()->hasFocus(); } void WindowScriptingInterface::setFocus() { diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index f08df229cc..aae8371378 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -12,6 +12,7 @@ #include "InterfaceConfig.h" #include +#include #include #include @@ -132,7 +133,7 @@ void ApplicationOverlay::renderReticle(glm::quat orientation, float alpha) { } ApplicationOverlay::ApplicationOverlay() : - _textureFov(glm::radians(DEFAULT_OCULUS_UI_ANGULAR_SIZE)), + _textureFov(glm::radians(DEFAULT_HMD_UI_ANGULAR_SIZE)), _textureAspectRatio(1.0f), _lastMouseMove(0), _magnifier(true), @@ -167,13 +168,13 @@ ApplicationOverlay::~ApplicationOverlay() { } // Renders the overlays either to a texture or to the screen -void ApplicationOverlay::renderOverlay(bool renderToTexture) { +void ApplicationOverlay::renderOverlay() { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()"); Overlays& overlays = qApp->getOverlays(); - auto glCanvas = Application::getInstance()->getGLWidget(); - _textureFov = glm::radians(_oculusUIAngularSize); - _textureAspectRatio = (float)glCanvas->getDeviceWidth() / (float)glCanvas->getDeviceHeight(); + _textureFov = glm::radians(_hmdUIAngularSize); + glm::vec2 canvasSize = Application::getInstance()->getCanvasSize(); + _textureAspectRatio = canvasSize.x / canvasSize.y;; //Handle fading and deactivation/activation of UI @@ -183,17 +184,15 @@ void ApplicationOverlay::renderOverlay(bool renderToTexture) { glDisable(GL_LIGHTING); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - if (renderToTexture) { - _overlays.buildFramebufferObject(); - _overlays.bind(); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - } - + _overlays.buildFramebufferObject(); + _overlays.bind(); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glPushMatrix(); { const float NEAR_CLIP = -10000; const float FAR_CLIP = 10000; glLoadIdentity(); - glOrtho(0, glCanvas->width(), glCanvas->height(), 0, NEAR_CLIP, FAR_CLIP); + glOrtho(0, canvasSize.x, canvasSize.y, 0, NEAR_CLIP, FAR_CLIP); glMatrixMode(GL_MODELVIEW); @@ -217,10 +216,7 @@ void ApplicationOverlay::renderOverlay(bool renderToTexture) { glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); - - if (renderToTexture) { - _overlays.release(); - } + _overlays.release(); } // Draws the FBO texture for the screen @@ -228,7 +224,6 @@ void ApplicationOverlay::displayOverlayTexture() { if (_alpha == 0.0f) { return; } - auto glCanvas = Application::getInstance()->getGLWidget(); glEnable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0); @@ -237,15 +232,15 @@ void ApplicationOverlay::displayOverlayTexture() { glMatrixMode(GL_PROJECTION); glPushMatrix(); { glLoadIdentity(); - glOrtho(0, glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight(), 0, -1.0, 1.0); + glOrtho(0, 1, 1, 0, -1.0, 1.0); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glEnable(GL_BLEND); - glm::vec2 topLeft(0.0f, 0.0f); - glm::vec2 bottomRight(glCanvas->getDeviceWidth(), glCanvas->getDeviceHeight()); - glm::vec2 texCoordTopLeft(0.0f, 1.0f); - glm::vec2 texCoordBottomRight(1.0f, 0.0f); + static const glm::vec2 topLeft(0); + static const glm::vec2 bottomRight(1); + static const glm::vec2 texCoordTopLeft(0.0f, 1.0f); + static const glm::vec2 texCoordBottomRight(1.0f, 0.0f); DependencyManager::get()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, glm::vec4(1.0f, 1.0f, 1.0f, _alpha)); @@ -255,6 +250,7 @@ void ApplicationOverlay::displayOverlayTexture() { glDisable(GL_TEXTURE_2D); } +#if 0 // Draws the FBO texture for Oculus rift. void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) { if (_alpha == 0.0f) { @@ -440,10 +436,10 @@ void ApplicationOverlay::computeOculusPickRay(float x, float y, glm::vec3& origi origin = myAvatar->getEyePosition(); direction = cursorPos - origin; } +#endif //Caculate the click location using one of the sixense controllers. Scale is not applied QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const { - auto glCanvas = Application::getInstance()->getGLWidget(); MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); glm::vec3 tip = myAvatar->getLaserPointerTipPosition(palm); @@ -454,8 +450,7 @@ QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const { glm::vec3 tipPos = invOrientation * (tip - eyePos); QPoint rv; - - if (OculusManager::isConnected()) { + if (qApp->getActiveRenderPlugin()->isHmd()) { float t; //We back the ray up by dir to ensure that it will not start inside the UI. @@ -473,9 +468,10 @@ QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const { float u = asin(collisionPos.x) / (_textureFov)+0.5f; float v = 1.0 - (asin(collisionPos.y) / (_textureFov)+0.5f); + auto size = qApp->getActiveRenderPlugin()->getCanvasSize(); - rv.setX(u * glCanvas->width()); - rv.setY(v * glCanvas->height()); + rv.setX(u * size.x); + rv.setY(v * size.y); } } else { //if they did not click on the overlay, just set the coords to INT_MAX @@ -492,8 +488,9 @@ QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const { ndcSpacePos = glm::vec3(clipSpacePos) / clipSpacePos.w; } - rv.setX(((ndcSpacePos.x + 1.0) / 2.0) * glCanvas->width()); - rv.setY((1.0 - ((ndcSpacePos.y + 1.0) / 2.0)) * glCanvas->height()); + glm::ivec2 canvasSize = Application::getInstance()->getCanvasSize(); + rv.setX(((ndcSpacePos.x + 1.0) / 2.0) * canvasSize.x); + rv.setY((1.0 - ((ndcSpacePos.y + 1.0) / 2.0)) * canvasSize.y); } return rv; } @@ -518,28 +515,29 @@ bool ApplicationOverlay::calculateRayUICollisionPoint(const glm::vec3& position, //Renders optional pointers void ApplicationOverlay::renderPointers() { - auto glCanvas = Application::getInstance()->getGLWidget(); //lazily load crosshair texture if (_crosshairTexture == 0) { - _crosshairTexture = glCanvas->bindTexture(QImage(PathUtils::resourcesPath() + "images/sixense-reticle.png")); + _crosshairTexture = new QOpenGLTexture(QImage(PathUtils::resourcesPath() + "images/sixense-reticle.png")); } glEnable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, _crosshairTexture); - - if (OculusManager::isConnected() && !qApp->getLastMouseMoveWasSimulated() && !qApp->isMouseHidden()) { + _crosshairTexture->bind(); + + if (qApp->getActiveRenderPlugin()->isHmd() && !qApp->getLastMouseMoveWasSimulated() && !qApp->isMouseHidden()) { + glm::ivec2 trueMouse = qApp->getActiveRenderPlugin()->getTrueMousePosition(); //If we are in oculus, render reticle later if (_lastMouseMove == 0) { _lastMouseMove = usecTimestampNow(); } - QPoint position = QPoint(qApp->getTrueMouseX(), qApp->getTrueMouseY()); + QPoint position(trueMouse.x, trueMouse.y); static const int MAX_IDLE_TIME = 3; if (_reticlePosition[MOUSE] != position) { _lastMouseMove = usecTimestampNow(); } else if (usecTimestampNow() - _lastMouseMove > MAX_IDLE_TIME * USECS_PER_SECOND) { +#if 0 float pitch = 0.0f, yaw = 0.0f, roll = 0.0f; // radians OculusManager::getEulerAngles(yaw, pitch, roll); glm::quat orientation(glm::vec3(pitch, yaw, roll)); @@ -557,6 +555,7 @@ void ApplicationOverlay::renderPointers() { } else { qDebug() << "No collision point"; } +#endif } _reticlePosition[MOUSE] = position; @@ -564,7 +563,7 @@ void ApplicationOverlay::renderPointers() { _magActive[MOUSE] = _magnifier; _reticleActive[LEFT_CONTROLLER] = false; _reticleActive[RIGHT_CONTROLLER] = false; - } else if (qApp->getLastMouseMoveWasSimulated() && Menu::getInstance()->isOptionChecked(MenuOption::SixenseMouseInput)) { + } else if (qApp->getLastMouseMoveWasSimulated() && Menu::getInstance()->isOptionChecked(MenuOption::SixenseMouseInput)) { _lastMouseMove = 0; //only render controller pointer if we aren't already rendering a mouse pointer _reticleActive[MOUSE] = false; @@ -576,6 +575,7 @@ void ApplicationOverlay::renderPointers() { } void ApplicationOverlay::renderControllerPointers() { +#if 0 auto glCanvas = Application::getInstance()->getGLWidget(); MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); @@ -683,10 +683,12 @@ void ApplicationOverlay::renderControllerPointers() { glm::vec4(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], 1.0f)); } +#endif + } void ApplicationOverlay::renderPointersOculus(const glm::vec3& eyePos) { - glBindTexture(GL_TEXTURE_2D, _crosshairTexture); + _crosshairTexture->bind(); glDisable(GL_DEPTH_TEST); glMatrixMode(GL_MODELVIEW); @@ -723,10 +725,10 @@ void ApplicationOverlay::renderMagnifier(glm::vec2 magPos, float sizeMult, bool if (!_magnifier) { return; } - auto glCanvas = Application::getInstance()->getGLWidget(); + auto canvasSize = Application::getInstance()->getCanvasSize(); - const int widgetWidth = glCanvas->width(); - const int widgetHeight = glCanvas->height(); + const int widgetWidth = canvasSize.x; + const int widgetHeight = canvasSize.y; const float halfWidth = (MAGNIFY_WIDTH / _textureAspectRatio) * sizeMult / 2.0f; const float halfHeight = MAGNIFY_HEIGHT * sizeMult / 2.0f; @@ -788,6 +790,7 @@ void ApplicationOverlay::renderMagnifier(glm::vec2 magPos, float sizeMult, bool } void ApplicationOverlay::renderAudioMeter() { +#if 0 auto glCanvas = Application::getInstance()->getGLWidget(); auto audio = DependencyManager::get(); @@ -900,13 +903,13 @@ void ApplicationOverlay::renderAudioMeter() { audioLevel, AUDIO_METER_HEIGHT, quadColor, _audioBlueQuad); } +#endif } void ApplicationOverlay::renderStatsAndLogs() { Application* application = Application::getInstance(); QSharedPointer bandwidthRecorder = DependencyManager::get(); - auto glCanvas = Application::getInstance()->getGLWidget(); const OctreePacketProcessor& octreePacketProcessor = application->getOctreePacketProcessor(); NodeBounds& nodeBoundsDisplay = application->getNodeBoundsDisplay(); @@ -934,13 +937,17 @@ void ApplicationOverlay::renderStatsAndLogs() { int timerBottom = (Menu::getInstance()->isOptionChecked(MenuOption::Stats)) ? 80 : 20; - drawText(glCanvas->width() - 100, glCanvas->height() - timerBottom, + + auto size = qApp->getActiveRenderPlugin()->getCanvasSize(); +// auto glCanvas = Application::getInstance()->getGLWidget(); + drawText(size.x - 100, size.y - timerBottom, 0.30f, 0.0f, 0, frameTimer.toUtf8().constData(), WHITE_TEXT); } nodeBoundsDisplay.drawOverlay(); } void ApplicationOverlay::renderDomainConnectionStatusBorder() { +#if 0 auto nodeList = DependencyManager::get(); if (nodeList && !nodeList->getDomainHandler().isConnected()) { @@ -969,6 +976,7 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder() { geometryCache->renderVertices(gpu::LINE_STRIP, _domainStatusBorder); } +#endif } ApplicationOverlay::TexturedHemisphere::TexturedHemisphere() : @@ -1088,7 +1096,7 @@ void ApplicationOverlay::TexturedHemisphere::cleanupVBO() { } void ApplicationOverlay::TexturedHemisphere::buildFramebufferObject() { - QSize size = Application::getInstance()->getGLWidget()->getDeviceSize(); + QSize size = Application::getInstance()->getDeviceSize(); if (_framebufferObject != NULL && size == _framebufferObject->size()) { // Already build return; @@ -1159,7 +1167,7 @@ glm::vec3 ApplicationOverlay::sphericalToDirection(glm::vec2 sphericalPos) const } glm::vec2 ApplicationOverlay::screenToSpherical(glm::vec2 screenPos) const { - QSize screenSize = Application::getInstance()->getGLWidget()->getDeviceSize(); + QSize screenSize = Application::getInstance()->getDeviceSize(); float yaw = -(screenPos.x / screenSize.width() - 0.5f) * MOUSE_YAW_RANGE; float pitch = (screenPos.y / screenSize.height() - 0.5f) * MOUSE_PITCH_RANGE; @@ -1167,7 +1175,7 @@ glm::vec2 ApplicationOverlay::screenToSpherical(glm::vec2 screenPos) const { } glm::vec2 ApplicationOverlay::sphericalToScreen(glm::vec2 sphericalPos) const { - QSize screenSize = Application::getInstance()->getGLWidget()->getDeviceSize(); + QSize screenSize = Application::getInstance()->getDeviceSize(); float x = (-sphericalPos.x / MOUSE_YAW_RANGE + 0.5f) * screenSize.width(); float y = (sphericalPos.y / MOUSE_PITCH_RANGE + 0.5f) * screenSize.height(); @@ -1175,7 +1183,7 @@ glm::vec2 ApplicationOverlay::sphericalToScreen(glm::vec2 sphericalPos) const { } glm::vec2 ApplicationOverlay::sphericalToOverlay(glm::vec2 sphericalPos) const { - QSize screenSize = Application::getInstance()->getGLWidget()->getDeviceSize(); + QSize screenSize = Application::getInstance()->getDeviceSize(); float x = (-sphericalPos.x / (_textureFov * _textureAspectRatio) + 0.5f) * screenSize.width(); float y = (sphericalPos.y / _textureFov + 0.5f) * screenSize.height(); @@ -1183,7 +1191,7 @@ glm::vec2 ApplicationOverlay::sphericalToOverlay(glm::vec2 sphericalPos) const { } glm::vec2 ApplicationOverlay::overlayToSpherical(glm::vec2 overlayPos) const { - QSize screenSize = Application::getInstance()->getGLWidget()->getDeviceSize(); + QSize screenSize = Application::getInstance()->getDeviceSize(); float yaw = -(overlayPos.x / screenSize.width() - 0.5f) * _textureFov * _textureAspectRatio; float pitch = (overlayPos.y / screenSize.height() - 0.5f) * _textureFov; diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index cc424d0c8f..5cb042b300 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -15,12 +15,13 @@ class Camera; class Overlays; class QOpenGLFramebufferObject; +class QOpenGLTexture; const float MAGNIFY_WIDTH = 220.0f; const float MAGNIFY_HEIGHT = 100.0f; const float MAGNIFY_MULT = 2.0f; -const float DEFAULT_OCULUS_UI_ANGULAR_SIZE = 72.0f; +const float DEFAULT_HMD_UI_ANGULAR_SIZE = 72.0f; // Handles the drawing of the overlays to the screen class ApplicationOverlay { @@ -28,21 +29,24 @@ public: ApplicationOverlay(); ~ApplicationOverlay(); - void renderOverlay(bool renderToTexture = false); + void renderOverlay(); + void displayOverlayTexture(); +#if 0 void displayOverlayTextureOculus(Camera& whichCamera); void displayOverlayTexture3DTV(Camera& whichCamera, float aspectRatio, float fov); - void computeOculusPickRay(float x, float y, glm::vec3& origin, glm::vec3& direction) const; +#endif + QPoint getPalmClickLocation(const PalmData *palm) const; bool calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction, glm::vec3& result) const; bool hasMagnifier() const { return _magnifier; } void toggleMagnifier() { _magnifier = !_magnifier; } - float getOculusUIAngularSize() const { return _oculusUIAngularSize; } - void setOculusUIAngularSize(float oculusUIAngularSize) { _oculusUIAngularSize = oculusUIAngularSize; } - + float getHmdUIAngularSize() const { return _hmdUIAngularSize; } + void setHmdUIAngularSize(float hmdUIAngularSize) { _hmdUIAngularSize = hmdUIAngularSize; } + // Converter from one frame of reference to another. // Frame of reference: // Direction: Ray that represents the spherical values @@ -91,7 +95,7 @@ private: VerticesIndices _vbo; }; - float _oculusUIAngularSize = DEFAULT_OCULUS_UI_ANGULAR_SIZE; + float _hmdUIAngularSize = DEFAULT_HMD_UI_ANGULAR_SIZE; void renderReticle(glm::quat orientation, float alpha); void renderPointers();; @@ -121,7 +125,7 @@ private: float _oculusUIRadius; float _trailingAudioLoudness; - GLuint _crosshairTexture; + QOpenGLTexture * _crosshairTexture; int _reticleQuad; int _magnifierQuad; diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp index 701ceb0189..971f75b4ea 100644 --- a/interface/src/ui/DialogsManager.cpp +++ b/interface/src/ui/DialogsManager.cpp @@ -56,10 +56,11 @@ void DialogsManager::showLoginDialog() { void DialogsManager::octreeStatsDetails() { if (!_octreeStatsDialog) { _octreeStatsDialog = new OctreeStatsDialog(qApp->getWindow(), qApp->getOcteeSceneStats()); - +#if 0 if (_hmdToolsDialog) { _hmdToolsDialog->watchWindow(_octreeStatsDialog->windowHandle()); } +#endif connect(_octreeStatsDialog, SIGNAL(closed()), _octreeStatsDialog, SLOT(deleteLater())); _octreeStatsDialog->show(); } @@ -107,11 +108,12 @@ void DialogsManager::bandwidthDetails() { if (! _bandwidthDialog) { _bandwidthDialog = new BandwidthDialog(qApp->getWindow()); connect(_bandwidthDialog, SIGNAL(closed()), _bandwidthDialog, SLOT(deleteLater())); - +#if 0 if (_hmdToolsDialog) { _hmdToolsDialog->watchWindow(_bandwidthDialog->windowHandle()); } - +#endif + _bandwidthDialog->show(); } _bandwidthDialog->raise(); @@ -133,6 +135,7 @@ void DialogsManager::toggleToolWindow() { } void DialogsManager::hmdTools(bool showTools) { +#if 0 if (showTools) { if (!_hmdToolsDialog) { maybeCreateDialog(_hmdToolsDialog); @@ -144,11 +147,14 @@ void DialogsManager::hmdTools(bool showTools) { hmdToolsClosed(); } qApp->getWindow()->activateWindow(); +#endif } void DialogsManager::hmdToolsClosed() { +#if 0 Menu::getInstance()->getActionForOption(MenuOption::HMDTools)->setChecked(false); _hmdToolsDialog->hide(); +#endif } void DialogsManager::showScriptEditor() { diff --git a/interface/src/ui/DialogsManager.h b/interface/src/ui/DialogsManager.h index 897215cbff..8f4bbb3b08 100644 --- a/interface/src/ui/DialogsManager.h +++ b/interface/src/ui/DialogsManager.h @@ -40,7 +40,7 @@ class DialogsManager : public QObject, public Dependency { public: QPointer getBandwidthDialog() const { return _bandwidthDialog; } - QPointer getHMDToolsDialog() const { return _hmdToolsDialog; } +// QPointer getHMDToolsDialog() const { return _hmdToolsDialog; } QPointer getLodToolsDialog() const { return _lodToolsDialog; } QPointer getOctreeStatsDialog() const { return _octreeStatsDialog; } @@ -75,9 +75,12 @@ private: member = new T(parent); Q_CHECK_PTR(member); +#if 0 if (_hmdToolsDialog && member->windowHandle()) { _hmdToolsDialog->watchWindow(member->windowHandle()); } +#endif + } } @@ -88,7 +91,7 @@ private: QPointer _cachesSizeDialog; QPointer _diskCacheEditor; QPointer _ircInfoBox; - QPointer _hmdToolsDialog; +// QPointer _hmdToolsDialog; QPointer _lodToolsDialog; QPointer _loginDialog; QPointer _octreeStatsDialog; diff --git a/interface/src/ui/HMDToolsDialog.cpp b/interface/src/ui/HMDToolsDialog.cpp index 4a899a641e..dfe45866e1 100644 --- a/interface/src/ui/HMDToolsDialog.cpp +++ b/interface/src/ui/HMDToolsDialog.cpp @@ -8,6 +8,7 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#if 0 #include #include @@ -340,4 +341,4 @@ void HMDWindowWatcher::windowScreenChanged(QScreen* screen) { } } - +#endif diff --git a/interface/src/ui/HMDToolsDialog.h b/interface/src/ui/HMDToolsDialog.h index 10dc1c5c80..86bfc7bf1a 100644 --- a/interface/src/ui/HMDToolsDialog.h +++ b/interface/src/ui/HMDToolsDialog.h @@ -11,7 +11,7 @@ #ifndef hifi_HMDToolsDialog_h #define hifi_HMDToolsDialog_h - +#if 0 #include class HMDWindowWatcher; @@ -84,5 +84,6 @@ private: QRect _previousRect; QScreen* _previousScreen; }; +#endif #endif // hifi_HMDToolsDialog_h diff --git a/interface/src/ui/NodeBounds.cpp b/interface/src/ui/NodeBounds.cpp index f0f4d432db..c56b5d32c6 100644 --- a/interface/src/ui/NodeBounds.cpp +++ b/interface/src/ui/NodeBounds.cpp @@ -39,8 +39,7 @@ void NodeBounds::draw() { // Compute ray to find selected nodes later on. We can't use the pre-computed ray in Application because it centers // itself after the cursor disappears. Application* application = Application::getInstance(); - PickRay pickRay = application->getCamera()->computePickRay(application->getTrueMouseX(), - application->getTrueMouseY()); + PickRay pickRay = application->computePickRay(); // Variables to keep track of the selected node and properties to draw the cube later if needed Node* selectedNode = NULL; diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index bd32fc7c34..5d6adbad4d 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -192,9 +192,9 @@ void PreferencesDialog::loadPreferences() { ui.avatarScaleSpin->setValue(myAvatar->getScale()); ui.maxOctreePPSSpin->setValue(qApp->getOctreeQuery().getMaxOctreePacketsPerSecond()); - +#if 0 ui.oculusUIAngularSizeSpin->setValue(qApp->getApplicationOverlay().getOculusUIAngularSize()); - +#endif SixenseManager& sixense = SixenseManager::getInstance(); ui.sixenseReticleMoveSpeedSpin->setValue(sixense.getReticleMoveSpeed()); ui.invertSixenseButtonsCheckBox->setChecked(sixense.getInvertButtons()); @@ -266,8 +266,7 @@ void PreferencesDialog::savePreferences() { myAvatar->setLeanScale(ui.leanScaleSpin->value()); myAvatar->setClampedTargetScale(ui.avatarScaleSpin->value()); - auto glCanvas = Application::getInstance()->getGLWidget(); - Application::getInstance()->resizeGL(glCanvas->width(), glCanvas->height()); + Application::getInstance()->resizeGL(); DependencyManager::get()->getMyAvatar()->setRealWorldFieldOfView(ui.realWorldFieldOfViewSpin->value()); @@ -280,9 +279,9 @@ void PreferencesDialog::savePreferences() { faceshift->setHostname(ui.faceshiftHostnameEdit->text()); qApp->getOctreeQuery().setMaxOctreePacketsPerSecond(ui.maxOctreePPSSpin->value()); - +#if 0 qApp->getApplicationOverlay().setOculusUIAngularSize(ui.oculusUIAngularSizeSpin->value()); - +#endif SixenseManager& sixense = SixenseManager::getInstance(); sixense.setReticleMoveSpeed(ui.sixenseReticleMoveSpeedSpin->value()); sixense.setInvertButtons(ui.invertSixenseButtonsCheckBox->isChecked()); @@ -305,7 +304,7 @@ void PreferencesDialog::savePreferences() { audio->setOutputStarveDetectionThreshold(ui.outputStarveDetectionThresholdSpinner->value()); audio->setOutputStarveDetectionPeriod(ui.outputStarveDetectionPeriodSpinner->value()); - Application::getInstance()->resizeGL(glCanvas->width(), glCanvas->height()); + Application::getInstance()->resizeGL(); // LOD items auto lodManager = DependencyManager::get(); diff --git a/interface/src/ui/RearMirrorTools.cpp b/interface/src/ui/RearMirrorTools.cpp index a215d20148..830ceea507 100644 --- a/interface/src/ui/RearMirrorTools.cpp +++ b/interface/src/ui/RearMirrorTools.cpp @@ -28,16 +28,15 @@ const char ZOOM_LEVEL_SETTINGS[] = "ZoomLevel"; Setting::Handle RearMirrorTools::rearViewZoomLevel(QStringList() << SETTINGS_GROUP_NAME << ZOOM_LEVEL_SETTINGS, ZoomLevel::HEAD); -RearMirrorTools::RearMirrorTools(QGLWidget* parent, QRect& bounds) : - _parent(parent), +RearMirrorTools::RearMirrorTools(QRect& bounds) : _bounds(bounds), _windowed(false), _fullScreen(false) { - _closeTextureId = _parent->bindTexture(QImage(PathUtils::resourcesPath() + "images/close.svg")); + _closeTextureId = new QOpenGLTexture(QImage(PathUtils::resourcesPath() + "images/close.svg")); - _zoomHeadTextureId = _parent->bindTexture(QImage(PathUtils::resourcesPath() + "images/plus.svg")); - _zoomBodyTextureId = _parent->bindTexture(QImage(PathUtils::resourcesPath() + "images/minus.svg")); + _zoomHeadTextureId = new QOpenGLTexture(QImage(PathUtils::resourcesPath() + "images/plus.svg")); + _zoomBodyTextureId = new QOpenGLTexture(QImage(PathUtils::resourcesPath() + "images/minus.svg")); _shrinkIconRect = QRect(ICON_PADDING, ICON_PADDING, ICON_SIZE, ICON_SIZE); _closeIconRect = QRect(_bounds.left() + ICON_PADDING, _bounds.top() + ICON_PADDING, ICON_SIZE, ICON_SIZE); @@ -47,6 +46,7 @@ RearMirrorTools::RearMirrorTools(QGLWidget* parent, QRect& bounds) : } void RearMirrorTools::render(bool fullScreen) { +#if 0 if (fullScreen) { _fullScreen = true; displayIcon(_parent->geometry(), _shrinkIconRect, _closeTextureId); @@ -62,6 +62,7 @@ void RearMirrorTools::render(bool fullScreen) { displayIcon(_bounds, _bodyZoomIconRect, _zoomBodyTextureId, zoomLevel == BODY); } } +#endif } bool RearMirrorTools::mousePressEvent(int x, int y) { @@ -99,7 +100,7 @@ bool RearMirrorTools::mousePressEvent(int x, int y) { return false; } -void RearMirrorTools::displayIcon(QRect bounds, QRect iconBounds, GLuint textureId, bool selected) { +void RearMirrorTools::displayIcon(QRect bounds, QRect iconBounds, QOpenGLTexture * texture, bool selected) { glMatrixMode(GL_PROJECTION); glPushMatrix(); @@ -116,13 +117,13 @@ void RearMirrorTools::displayIcon(QRect bounds, QRect iconBounds, GLuint texture } else { quadColor = glm::vec4(1, 1, 1, 1); } - - glBindTexture(GL_TEXTURE_2D, textureId); + + texture->bind(); glm::vec2 topLeft(iconBounds.left(), iconBounds.top()); glm::vec2 bottomRight(iconBounds.right(), iconBounds.bottom()); - glm::vec2 texCoordTopLeft(0.0f, 1.0f); - glm::vec2 texCoordBottomRight(1.0f, 0.0f); + static const glm::vec2 texCoordTopLeft(0.0f, 1.0f); + static const glm::vec2 texCoordBottomRight(1.0f, 0.0f); DependencyManager::get()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, quadColor); diff --git a/interface/src/ui/RearMirrorTools.h b/interface/src/ui/RearMirrorTools.h index 8a76134627..d38afdbdfb 100644 --- a/interface/src/ui/RearMirrorTools.h +++ b/interface/src/ui/RearMirrorTools.h @@ -14,8 +14,7 @@ #include "InterfaceConfig.h" -#include - +#include #include enum ZoomLevel { @@ -26,7 +25,7 @@ enum ZoomLevel { class RearMirrorTools : public QObject { Q_OBJECT public: - RearMirrorTools(QGLWidget* parent, QRect& bounds); + RearMirrorTools(QRect& bounds); void render(bool fullScreen); bool mousePressEvent(int x, int y); @@ -39,12 +38,10 @@ signals: void restoreView(); private: - QGLWidget* _parent; QRect _bounds; - GLuint _closeTextureId; - GLuint _resetTextureId; - GLuint _zoomBodyTextureId; - GLuint _zoomHeadTextureId; + QOpenGLTexture * _closeTextureId; + QOpenGLTexture * _zoomBodyTextureId; + QOpenGLTexture *_zoomHeadTextureId; QRect _closeIconRect; QRect _resetIconRect; @@ -55,7 +52,7 @@ private: bool _windowed; bool _fullScreen; - void displayIcon(QRect bounds, QRect iconBounds, GLuint textureId, bool selected = false); + void displayIcon(QRect bounds, QRect iconBounds, QOpenGLTexture * textureId, bool selected = false); }; #endif // hifi_RearMirrorTools_h diff --git a/interface/src/ui/Snapshot.cpp b/interface/src/ui/Snapshot.cpp index 5a3109ff64..350d4c8d90 100644 --- a/interface/src/ui/Snapshot.cpp +++ b/interface/src/ui/Snapshot.cpp @@ -94,6 +94,7 @@ QTemporaryFile* Snapshot::saveTempSnapshot() { } QFile* Snapshot::savedFileForSnapshot(bool isTemporary) { +#if 0 auto glCanvas = Application::getInstance()->getGLWidget(); QImage shot = glCanvas->grabFrameBuffer(); @@ -157,6 +158,8 @@ QFile* Snapshot::savedFileForSnapshot(bool isTemporary) { return imageTempFile; } +#endif + return nullptr; } diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index ec225dde72..f94e268d2d 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -57,8 +57,8 @@ Stats::Stats(): _octreeStatsWidth(STATS_OCTREE_MIN_WIDTH), _lastHorizontalOffset(0) { - auto glCanvas = Application::getInstance()->getGLWidget(); - resetWidth(glCanvas->width(), 0); + auto canvasSize = Application::getInstance()->getCanvasSize(); + resetWidth(canvasSize.x, 0); } void Stats::toggleExpanded() { @@ -68,7 +68,8 @@ void Stats::toggleExpanded() { // called on mouse click release // check for clicks over stats in order to expand or contract them void Stats::checkClick(int mouseX, int mouseY, int mouseDragStartedX, int mouseDragStartedY, int horizontalOffset) { - auto glCanvas = Application::getInstance()->getGLWidget(); +// auto glCanvas = Application::getInstance()->getGLWidget(); + auto canvasSize = Application::getInstance()->getCanvasSize(); if (0 != glm::compMax(glm::abs(glm::ivec2(mouseX - mouseDragStartedX, mouseY - mouseDragStartedY)))) { // not worried about dragging on stats @@ -115,7 +116,7 @@ void Stats::checkClick(int mouseX, int mouseY, int mouseDragStartedX, int mouseD // top-right stats click lines = _expanded ? 11 : 3; statsHeight = lines * STATS_PELS_PER_LINE + 10; - statsWidth = glCanvas->width() - statsX; + statsWidth = canvasSize.x - statsX; if (mouseX > statsX && mouseX < statsX + statsWidth && mouseY > statsY && mouseY < statsY + statsHeight) { toggleExpanded(); return; @@ -123,8 +124,8 @@ void Stats::checkClick(int mouseX, int mouseY, int mouseDragStartedX, int mouseD } void Stats::resetWidth(int width, int horizontalOffset) { - auto glCanvas = Application::getInstance()->getGLWidget(); - int extraSpace = glCanvas->width() - horizontalOffset -2 + auto canvasSize = Application::getInstance()->getCanvasSize(); + int extraSpace = canvasSize.x - horizontalOffset - 2 - STATS_GENERAL_MIN_WIDTH - (Menu::getInstance()->isOptionChecked(MenuOption::TestPing) ? STATS_PING_MIN_WIDTH -1 : 0) - STATS_GEO_MIN_WIDTH @@ -148,7 +149,7 @@ void Stats::resetWidth(int width, int horizontalOffset) { _pingStatsWidth += (int) extraSpace / panels; } _geoStatsWidth += (int) extraSpace / panels; - _octreeStatsWidth += glCanvas->width() - + _octreeStatsWidth += canvasSize.x - (_generalStatsWidth + _pingStatsWidth + _geoStatsWidth + 3); } } @@ -197,7 +198,7 @@ void Stats::display( int outKbitsPerSecond, int voxelPacketsToProcess) { - auto glCanvas = Application::getInstance()->getGLWidget(); + auto canvasSize = Application::getInstance()->getCanvasSize(); unsigned int backgroundColor = 0x33333399; int verticalOffset = 0, lines = 0; @@ -211,7 +212,7 @@ void Stats::display( QSharedPointer bandwidthRecorder = DependencyManager::get(); if (_lastHorizontalOffset != horizontalOffset) { - resetWidth(glCanvas->width(), horizontalOffset); + resetWidth(canvasSize.x, horizontalOffset); _lastHorizontalOffset = horizontalOffset; } @@ -461,7 +462,7 @@ void Stats::display( lines = _expanded ? 10 : 2; - drawBackground(backgroundColor, horizontalOffset, 0, glCanvas->width() - horizontalOffset, + drawBackground(backgroundColor, horizontalOffset, 0, canvasSize.x - horizontalOffset, (lines + 1) * STATS_PELS_PER_LINE); horizontalOffset += 5; diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 158deb00ff..ba7726877a 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -291,10 +291,13 @@ void Overlays::deleteOverlay(unsigned int id) { unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) { glm::vec2 pointCopy = point; + +#if 0 if (OculusManager::isConnected()) { pointCopy = Application::getInstance()->getApplicationOverlay().screenToOverlay(point); } - +#endif + QReadLocker lock(&_lock); QMapIterator i(_overlaysHUD); i.toBack(); diff --git a/libraries/render-utils/src/AbstractViewStateInterface.h b/libraries/render-utils/src/AbstractViewStateInterface.h index 0d73614e7c..9f7042d325 100644 --- a/libraries/render-utils/src/AbstractViewStateInterface.h +++ b/libraries/render-utils/src/AbstractViewStateInterface.h @@ -45,7 +45,7 @@ public: virtual bool shouldRenderMesh(float largestDimension, float distanceToCamera) = 0; virtual float getSizeScale() const = 0; virtual int getBoundaryLevelAdjust() const = 0; - virtual PickRay computePickRay(float x, float y) = 0; + virtual PickRay computePickRay(float x, float y) const = 0; virtual const glm::vec3& getAvatarPosition() const = 0; }; diff --git a/libraries/render-utils/src/GlowEffect.cpp b/libraries/render-utils/src/GlowEffect.cpp index 2ba1d7df13..bb645ae0ba 100644 --- a/libraries/render-utils/src/GlowEffect.cpp +++ b/libraries/render-utils/src/GlowEffect.cpp @@ -30,7 +30,6 @@ GlowEffect::GlowEffect() _isOddFrame(false), _isFirstFrame(true), _intensity(0.0f), - _widget(NULL), _enabled(false) { } @@ -63,7 +62,7 @@ static ProgramObject* createProgram(const QString& name) { return program; } -void GlowEffect::init(QGLWidget* widget, bool enabled) { +void GlowEffect::init(bool enabled) { if (_initialized) { qCDebug(renderutils, "[ERROR] GlowEffeect is already initialized."); return; @@ -91,23 +90,10 @@ void GlowEffect::init(QGLWidget* widget, bool enabled) { _diffusionScaleLocation = _diffuseProgram->uniformLocation("diffusionScale"); _initialized = true; - _widget = widget; _enabled = enabled; } -int GlowEffect::getDeviceWidth() const { - return _widget->width() * (_widget->windowHandle() ? _widget->windowHandle()->devicePixelRatio() : 1.0f); -} - -int GlowEffect::getDeviceHeight() const { - return _widget->height() * (_widget->windowHandle() ? _widget->windowHandle()->devicePixelRatio() : 1.0f); -} - - void GlowEffect::prepare() { - DependencyManager::get()->getPrimaryFramebufferObject()->bind(); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - _isEmpty = true; _isOddFrame = !_isOddFrame; } @@ -124,24 +110,11 @@ void GlowEffect::end() { glBlendColor(0.0f, 0.0f, 0.0f, _intensity = _intensityStack.pop()); } -static void maybeBind(QOpenGLFramebufferObject* fbo) { - if (fbo) { - fbo->bind(); - } -} - -static void maybeRelease(QOpenGLFramebufferObject* fbo) { - if (fbo) { - fbo->release(); - } -} - -QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { +QOpenGLFramebufferObject* GlowEffect::render() { PerformanceTimer perfTimer("glowEffect"); auto textureCache = DependencyManager::get(); QOpenGLFramebufferObject* primaryFBO = textureCache->getPrimaryFramebufferObject(); - primaryFBO->release(); glBindTexture(GL_TEXTURE_2D, primaryFBO->texture()); glPushMatrix(); @@ -155,23 +128,19 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); - QOpenGLFramebufferObject* destFBO = toTexture ? - textureCache->getSecondaryFramebufferObject() : NULL; + QOpenGLFramebufferObject* destFBO = textureCache->getSecondaryFramebufferObject(); if (!_enabled || _isEmpty) { // copy the primary to the screen if (destFBO && QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) { QOpenGLFramebufferObject::blitFramebuffer(destFBO, primaryFBO); } else { - maybeBind(destFBO); - if (!destFBO) { - glViewport(0, 0, getDeviceWidth(), getDeviceHeight()); - } + destFBO->bind(); glEnable(GL_TEXTURE_2D); glDisable(GL_LIGHTING); renderFullscreenQuad(); glDisable(GL_TEXTURE_2D); glEnable(GL_LIGHTING); - maybeRelease(destFBO); + destFBO->release(); } } else { // diffuse into the secondary/tertiary (alternating between frames) @@ -205,21 +174,15 @@ QOpenGLFramebufferObject* GlowEffect::render(bool toTexture) { // add diffused texture to the primary glBindTexture(GL_TEXTURE_2D, newDiffusedFBO->texture()); - if (toTexture) { - destFBO = oldDiffusedFBO; - } - maybeBind(destFBO); - if (!destFBO) { - glViewport(0, 0, getDeviceWidth(), getDeviceHeight()); - } + destFBO = oldDiffusedFBO; + destFBO->bind(); _addSeparateProgram->bind(); renderFullscreenQuad(); _addSeparateProgram->release(); - maybeRelease(destFBO); + destFBO->release(); glBindTexture(GL_TEXTURE_2D, 0); glActiveTexture(GL_TEXTURE0); - } glPopMatrix(); diff --git a/libraries/render-utils/src/GlowEffect.h b/libraries/render-utils/src/GlowEffect.h index 895cd4bbce..65031aeb59 100644 --- a/libraries/render-utils/src/GlowEffect.h +++ b/libraries/render-utils/src/GlowEffect.h @@ -35,7 +35,7 @@ public: /// (either the secondary or the tertiary). QOpenGLFramebufferObject* getFreeFramebufferObject() const; - void init(QGLWidget* widget, bool enabled); + void init(bool enabled); /// Prepares the glow effect for rendering the current frame. To be called before rendering the scene. void prepare(); @@ -53,7 +53,7 @@ public: /// Renders the glow effect. To be called after rendering the scene. /// \param toTexture whether to render to a texture, rather than to the frame buffer /// \return the framebuffer object to which we rendered, or NULL if to the frame buffer - QOpenGLFramebufferObject* render(bool toTexture = false); + QOpenGLFramebufferObject* render(); public slots: void toggleGlowEffect(bool enabled); @@ -81,7 +81,6 @@ private: float _intensity; QStack _intensityStack; - QGLWidget* _widget; bool _enabled; }; diff --git a/libraries/render-utils/src/OffscreenGlContext.cpp b/libraries/render-utils/src/OffscreenGlContext.cpp new file mode 100644 index 0000000000..96f0a93c3a --- /dev/null +++ b/libraries/render-utils/src/OffscreenGlContext.cpp @@ -0,0 +1,43 @@ +// +// OffscreenGlCanvas.cpp +// interface/src/renderer +// +// Created by Bradley Austin Davis on 2014/04/09. +// 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 "OffscreenGlContext.h" + +OffscreenGlContext::OffscreenGlContext() { +} + +void OffscreenGlContext::create(QOpenGLContext * sharedContext) { + QSurfaceFormat format; + format.setDepthBufferSize(16); + format.setStencilBufferSize(8); + format.setMajorVersion(4); + format.setMinorVersion(1); + format.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile); + + _context.setFormat(format); + if (nullptr != sharedContext) { + _context.setShareContext(sharedContext); + } + _context.create(); + + _offscreenSurface.setFormat(_context.format()); + _offscreenSurface.create(); +} + +bool OffscreenGlContext::makeCurrent() { + return _context.makeCurrent(&_offscreenSurface); +} + +void OffscreenGlContext::doneCurrent() { + _context.doneCurrent(); +} + diff --git a/libraries/render-utils/src/OffscreenGlContext.h b/libraries/render-utils/src/OffscreenGlContext.h new file mode 100644 index 0000000000..ef67a7fc9a --- /dev/null +++ b/libraries/render-utils/src/OffscreenGlContext.h @@ -0,0 +1,33 @@ +// +// OffscreenGlCanvas.h +// interface/src/renderer +// +// Created by Bradley Austin Davis on 2014/04/09. +// 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 +#ifndef hifi_OffscreenGlCanvas_h +#define hifi_OffscreenGlCanvas_h + +#include +#include + +class OffscreenGlContext : public QObject { +public: + OffscreenGlContext(); + void create(QOpenGLContext * sharedContext = nullptr); + bool makeCurrent(); + void doneCurrent(); + QOpenGLContext * getContext() { + return &_context; + } + +protected: + QOpenGLContext _context; + QOffscreenSurface _offscreenSurface; +}; + +#endif // hifi_OffscreenGlCanvas_h diff --git a/libraries/render-utils/src/TextureCache.cpp b/libraries/render-utils/src/TextureCache.cpp index 9b2a458231..f33d8590f5 100644 --- a/libraries/render-utils/src/TextureCache.cpp +++ b/libraries/render-utils/src/TextureCache.cpp @@ -39,8 +39,7 @@ TextureCache::TextureCache() : _secondaryFramebufferObject(NULL), _tertiaryFramebufferObject(NULL), _shadowFramebufferObject(NULL), - _frameBufferSize(100, 100), - _associatedWidget(NULL) + _frameBufferSize(100, 100) { const qint64 TEXTURE_DEFAULT_UNUSED_MAX_SIZE = DEFAULT_UNUSED_MAX_SIZE; setUnusedResourceCacheSize(TEXTURE_DEFAULT_UNUSED_MAX_SIZE); @@ -322,28 +321,6 @@ GLuint TextureCache::getShadowDepthTextureID() { return _shadowDepthTextureID; } -bool TextureCache::eventFilter(QObject* watched, QEvent* event) { - if (event->type() == QEvent::Resize) { - QSize size = static_cast(event)->size(); - if (_primaryFramebufferObject && _primaryFramebufferObject->size() != size) { - delete _primaryFramebufferObject; - _primaryFramebufferObject = NULL; - glDeleteTextures(1, &_primaryDepthTextureID); - glDeleteTextures(1, &_primaryNormalTextureID); - glDeleteTextures(1, &_primarySpecularTextureID); - } - if (_secondaryFramebufferObject && _secondaryFramebufferObject->size() != size) { - delete _secondaryFramebufferObject; - _secondaryFramebufferObject = NULL; - } - if (_tertiaryFramebufferObject && _tertiaryFramebufferObject->size() != size) { - delete _tertiaryFramebufferObject; - _tertiaryFramebufferObject = NULL; - } - } - return false; -} - QSharedPointer TextureCache::createResource(const QUrl& url, const QSharedPointer& fallback, bool delayLoad, const void* extra) { const TextureExtra* textureExtra = static_cast(extra); @@ -351,14 +328,6 @@ QSharedPointer TextureCache::createResource(const QUrl& url, &Resource::allReferencesCleared); } -void TextureCache::associateWithWidget(QGLWidget* widget) { - if (_associatedWidget) { - _associatedWidget->removeEventFilter(this); - } - _associatedWidget = widget; - _associatedWidget->installEventFilter(this); -} - QOpenGLFramebufferObject* TextureCache::createFramebufferObject() { QOpenGLFramebufferObject* fbo = new QOpenGLFramebufferObject(_frameBufferSize); diff --git a/libraries/render-utils/src/TextureCache.h b/libraries/render-utils/src/TextureCache.h index 3ea46a4421..0496617563 100644 --- a/libraries/render-utils/src/TextureCache.h +++ b/libraries/render-utils/src/TextureCache.h @@ -36,9 +36,6 @@ class TextureCache : public ResourceCache, public Dependency { SINGLETON_DEPENDENCY public: - - void associateWithWidget(QGLWidget* widget); - /// Sets the desired texture resolution for the framebuffer objects. void setFrameBufferSize(QSize frameBufferSize); const QSize& getFrameBufferSize() const { return _frameBufferSize; } @@ -88,8 +85,6 @@ public: /// Returns the ID of the shadow framebuffer object's depth texture. GLuint getShadowDepthTextureID(); - virtual bool eventFilter(QObject* watched, QEvent* event); - protected: virtual QSharedPointer createResource(const QUrl& url, @@ -119,7 +114,6 @@ private: GLuint _shadowDepthTextureID; QSize _frameBufferSize; - QGLWidget* _associatedWidget; }; /// A simple object wrapper for an OpenGL texture. From ba4ae3762d2a4e2bf5983e7b74a4e669560b2905 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 30 Apr 2015 22:01:03 -0700 Subject: [PATCH 003/552] Working on merging in master --- CMakeLists.txt | 1 + cmake/externals/openvr/CMakeLists.txt | 38 +++++++ cmake/modules/FindOpenVR.cmake | 24 +++++ interface/CMakeLists.txt | 5 + interface/src/Application.cpp | 100 ++++-------------- interface/src/Application.h | 3 +- interface/src/main.cpp | 3 + interface/src/plugins/render/RenderPlugin.h | 5 + interface/src/ui/ApplicationOverlay.cpp | 3 +- libraries/render-utils/src/GlowEffect.cpp | 10 +- .../render-utils/src/OffscreenGlContext.h | 4 +- libraries/render-utils/src/TextureCache.cpp | 29 +---- libraries/shared/src/GLMHelpers.cpp | 4 + libraries/shared/src/GLMHelpers.h | 1 + 14 files changed, 111 insertions(+), 119 deletions(-) create mode 100644 cmake/externals/openvr/CMakeLists.txt create mode 100644 cmake/modules/FindOpenVR.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index b271664c35..58dee5ab27 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -176,6 +176,7 @@ option(GET_GVERB "Get Gverb library automatically as external project" 1) option(GET_SOXR "Get Soxr library automatically as external project" 1) option(GET_TBB "Get Threading Building Blocks library automatically as external project" 1) option(GET_LIBOVR "Get LibOVR library automatically as external project" 1) +option(GET_OPENVR "Get OpenVR library automatically as external project" 1) option(USE_NSIGHT "Attempt to find the nSight libraries" 1) option(GET_VHACD "Get V-HACD library automatically as external project" 1) diff --git a/cmake/externals/openvr/CMakeLists.txt b/cmake/externals/openvr/CMakeLists.txt new file mode 100644 index 0000000000..c5b15f4ea3 --- /dev/null +++ b/cmake/externals/openvr/CMakeLists.txt @@ -0,0 +1,38 @@ +include(ExternalProject) +include(SelectLibraryConfigurations) + +set(EXTERNAL_NAME OpenVR) + +string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) + +ExternalProject_Add( + ${EXTERNAL_NAME} + URL https://github.com/ValveSoftware/openvr/archive/0.9.0.zip + URL_MD5 4fbde7759f604aaa68b9c40d628cc34a + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + LOG_DOWNLOAD 1 +) + +ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) + +set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/openvr-0.9.0/headers CACHE TYPE INTERNAL) + +if (WIN32) + + # FIXME need to account for different architectures + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/openvr-0.9.0/lib/win32/openvr_api.lib CACHE TYPE INTERNAL) + +elseif(APPLE) + + # FIXME need to account for different architectures + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/openvr-0.9.0/lib/osx32/libopenvr_api.dylib CACHE TYPE INTERNAL) + +elseif(NOT ANDROID) + + # FIXME need to account for different architectures + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/openvr-0.9.0/lib/linux32/libopenvr_api.so CACHE TYPE INTERNAL) + +endif() + diff --git a/cmake/modules/FindOpenVR.cmake b/cmake/modules/FindOpenVR.cmake new file mode 100644 index 0000000000..9104fc514f --- /dev/null +++ b/cmake/modules/FindOpenVR.cmake @@ -0,0 +1,24 @@ +# +# FindLibOVR.cmake +# +# Try to find the LibOVR library to use the Oculus + +# Once done this will define +# +# OPENVR_FOUND - system found LibOVR +# OPENVR_INCLUDE_DIRS - the LibOVR include directory +# OPENVR_LIBRARIES - Link this to use LibOVR +# +# Distributed under the Apache License, Version 2.0. +# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +# + + +if (NOT ANDROID) + + include(FindPackageHandleStandardArgs) + find_package_handle_standard_args(OPENVR DEFAULT_MSG OPENVR_INCLUDE_DIRS OPENVR_LIBRARIES) + +endif (NOT ANDROID) + +mark_as_advanced(OPENVR_INCLUDE_DIRS OPENVR_LIBRARIES OPENVR_SEARCH_DIRS) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 4b989ec6c1..0b2cfa5427 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -136,6 +136,11 @@ find_package(LibOVR REQUIRED) target_include_directories(${TARGET_NAME} PRIVATE ${LIBOVR_INCLUDE_DIRS}) target_link_libraries(${TARGET_NAME} ${LIBOVR_LIBRARIES}) +add_dependency_external_projects(OpenVR) +find_package(OpenVR REQUIRED) +target_include_directories(${TARGET_NAME} PRIVATE ${LIBOVR_INCLUDE_DIRS}) +target_link_libraries(${TARGET_NAME} ${LIBOVR_LIBRARIES}) + find_package(Bullet REQUIRED) target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${BULLET_INCLUDE_DIRS}) target_link_libraries(${TARGET_NAME} ${BULLET_LIBRARIES}) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4348f50f25..d514ee2837 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -114,6 +114,8 @@ #include "gpu/Batch.h" #include "gpu/GLBackend.h" +#include "plugins/render/RenderPlugin.h" + #include "scripting/AccountScriptingInterface.h" #include "scripting/AudioDeviceScriptingInterface.h" #include "scripting/ClipboardScriptingInterface.h" @@ -584,7 +586,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : this->installEventFilter(this); // The offscreen UI needs to intercept the mouse and keyboard // events coming from the onscreen window - _glWidget->installEventFilter(DependencyManager::get().data()); + //_glWidget->installEventFilter(DependencyManager::get().data()); } @@ -726,7 +728,7 @@ void Application::initializeGL() { // texture resources initializeUi(); qCDebug(interfaceapp, "Initialized Offscreen UI."); - _glWidget->makeCurrent(); + _offscreenContext->makeCurrent(); // call Menu getInstance static method to set up the menu // Needs to happen AFTER the QML UI initialization @@ -770,30 +772,24 @@ void Application::initializeUi() { VrMenu::registerType(); auto offscreenUi = DependencyManager::get(); - offscreenUi->create(_glWidget->context()->contextHandle()); - offscreenUi->resize(_glWidget->size()); + offscreenUi->create(_offscreenContext->getContext()); + offscreenUi->resize(fromGlm(getActiveRenderPlugin()->getCanvasSize())); offscreenUi->setProxyWindow(_window->windowHandle()); offscreenUi->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/")); offscreenUi->load("Root.qml"); offscreenUi->load("RootMenu.qml"); VrMenu::load(); VrMenu::executeQueuedLambdas(); - offscreenUi->setMouseTranslator([this](const QPointF& p){ - if (OculusManager::isConnected()) { - glm::vec2 pos = _applicationOverlay.screenToOverlay(toGlm(p)); - return QPointF(pos.x, pos.y); - } - return QPointF(p); - }); + offscreenUi->setMouseTranslator(getActiveRenderPlugin()->getMouseTranslator()); offscreenUi->resume(); connect(_window, &MainWindow::windowGeometryChanged, [this](const QRect & r){ static qreal oldDevicePixelRatio = 0; - qreal devicePixelRatio = _glWidget->devicePixelRatio(); + qreal devicePixelRatio = getActiveRenderPlugin()->devicePixelRatio(); if (devicePixelRatio != oldDevicePixelRatio) { oldDevicePixelRatio = devicePixelRatio; qDebug() << "Device pixel ratio changed, triggering GL resize"; - resizeGL(_glWidget->width(), - _glWidget->height()); + auto canvasSize = getActiveRenderPlugin()->getCanvasSize(); + resizeGL(canvasSize.x, canvasSize.y); } }); } @@ -846,8 +842,9 @@ void Application::paintGL() { DependencyManager::get()->prepare(); // Primary rendering pass - auto primaryFbo = DependencyManager::get()->getPrimaryFramebufferObject(); - primaryFbo->bind(); + auto primaryFbo = DependencyManager::get()->getPrimaryFramebuffer(); + auto finalFbo = primaryFbo; + glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFbo)); { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -864,32 +861,18 @@ void Application::paintGL() { if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) { _rearMirrorTools->render(true); } else if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { -<<<<<<< HEAD renderRearViewMirror(_mirrorViewRect); -======= - renderRearViewMirror(_mirrorViewRect); } - DependencyManager::get()->render(); - + finalFbo = DependencyManager::get()->render(); { PerformanceTimer perfTimer("renderOverlay"); _applicationOverlay.renderOverlay(); + glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(finalFbo)); _applicationOverlay.displayOverlayTexture(); ->>>>>>> master + glBindFramebuffer(GL_FRAMEBUFFER, 0); } } - primaryFbo->release(); - - QOpenGLFramebufferObject * finalFbo = DependencyManager::get()->render(); - - finalFbo->bind(); - { - PerformanceTimer perfTimer("renderOverlay"); - _applicationOverlay.renderOverlay(); - _applicationOverlay.displayOverlayTexture(); - } - finalFbo->release(); // This might not be needed *right now*. We want to ensure that the FBO rendering // has completed before we start trying to read from it in another context. However @@ -899,7 +882,7 @@ void Application::paintGL() { _offscreenContext->doneCurrent(); Q_ASSERT(!QOpenGLContext::currentContext()); - getActiveRenderPlugin()->render(finalFbo->texture()); + getActiveRenderPlugin()->render(gpu::GLBackend::getTextureID(finalFbo->getRenderBuffer(0))); Q_ASSERT(!QOpenGLContext::currentContext()); _offscreenContext->makeCurrent(); _frameCount++; @@ -951,8 +934,9 @@ void Application::resizeGL(int width, int height) { updateProjectionMatrix(); glLoadIdentity(); + auto canvasSize = getActiveRenderPlugin()->getCanvasSize(); auto offscreenUi = DependencyManager::get(); - offscreenUi->resize(_glWidget->size()); + offscreenUi->resize(fromGlm(canvasSize)); // update Stats width // let's set horizontal offset to give stats some margin to mirror @@ -1003,43 +987,6 @@ bool Application::importSVOFromURL(const QString& urlString) { bool Application::event(QEvent* event) { switch (event->type()) { -<<<<<<< HEAD - case QEvent::MouseMove: - mouseMoveEvent((QMouseEvent*)event); - return true; - - case QEvent::MouseButtonPress: - mousePressEvent((QMouseEvent*)event); - return true; - - case QEvent::MouseButtonRelease: - mouseReleaseEvent((QMouseEvent*)event); - return true; - - case QEvent::KeyPress: - keyPressEvent((QKeyEvent*)event); - return true; - - case QEvent::KeyRelease: - keyReleaseEvent((QKeyEvent*)event); - return true; - - case QEvent::FocusIn: - //focusInEvent((QFocusEvent*)event); - //return true; - break; - - case QEvent::FocusOut: - focusOutEvent((QFocusEvent*)event); - return true; - - case QEvent::Resize: - resizeEvent((QResizeEvent *)event); - return true; - - default: - break; -======= case Lambda: ((LambdaEvent*)event)->call(); return true; @@ -1080,7 +1027,6 @@ bool Application::event(QEvent* event) { return true; default: break; ->>>>>>> master } // handle custom URL @@ -2990,13 +2936,7 @@ void Application::updateShadowMap() { glMatrixMode(GL_MODELVIEW); } -<<<<<<< HEAD - fbo->release(); -======= - // fbo->release(); - - glViewport(0, 0, _glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); ->>>>>>> master +// glViewport(0, 0, _glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); activeRenderingThread = nullptr; } diff --git a/interface/src/Application.h b/interface/src/Application.h index 507cd0e77c..6e4cb524e6 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -74,9 +74,8 @@ #include "octree/OctreeFade.h" #include "octree/OctreePacketProcessor.h" #include "UndoStackScriptingInterface.h" -#include "plugins/render/RenderPlugin.h" - +class RenderPlugin; class QGLWidget; class QKeyEvent; class QMouseEvent; diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 487f507ee2..6eb46071b8 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -115,7 +115,10 @@ int main(int argc, const char* argv[]) { exitCode = app.exec(); } +#if 0 OculusManager::deinit(); +#endif + #ifdef Q_OS_WIN ReleaseMutex(mutex); #endif diff --git a/interface/src/plugins/render/RenderPlugin.h b/interface/src/plugins/render/RenderPlugin.h index 3f8de27a7b..6a8328ee48 100644 --- a/interface/src/plugins/render/RenderPlugin.h +++ b/interface/src/plugins/render/RenderPlugin.h @@ -13,6 +13,8 @@ #include +#include + #include #include #include @@ -46,6 +48,8 @@ public: return trueMouseToUiMouse(getTrueMousePosition()); } + virtual std::function getMouseTranslator() { return [](const QPointF& p) { return p; }; }; + // Convert from screen mouse coordinates to UI mouse coordinates virtual glm::ivec2 trueMouseToUiMouse(const glm::ivec2 & position) const { return position; }; @@ -69,6 +73,7 @@ public: } virtual void abandonCalibration() {} virtual void resetSensors() {} + virtual float devicePixelRatio() { return 1.0; } signals: void recommendedFramebufferSizeChanged(const QSize & size); diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index a260a1b452..adb6492964 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -27,6 +27,7 @@ #include "Application.h" #include "ApplicationOverlay.h" #include "devices/OculusManager.h" +#include "plugins/render/RenderPlugin.h" #include "Util.h" #include "ui/Stats.h" @@ -934,7 +935,6 @@ void ApplicationOverlay::renderAudioMeter() { } void ApplicationOverlay::renderStatsAndLogs() { -#if 0 Application* application = Application::getInstance(); QSharedPointer bandwidthRecorder = DependencyManager::get(); @@ -972,7 +972,6 @@ void ApplicationOverlay::renderStatsAndLogs() { 0.30f, 0.0f, 0, frameTimer.toUtf8().constData(), WHITE_TEXT); } nodeBoundsDisplay.drawOverlay(); -#endif } void ApplicationOverlay::renderDomainConnectionStatusBorder() { diff --git a/libraries/render-utils/src/GlowEffect.cpp b/libraries/render-utils/src/GlowEffect.cpp index 33a91829f5..8672bfa7fc 100644 --- a/libraries/render-utils/src/GlowEffect.cpp +++ b/libraries/render-utils/src/GlowEffect.cpp @@ -139,7 +139,7 @@ gpu::FramebufferPointer GlowEffect::render() { glDisable(GL_DEPTH_TEST); glDepthMask(GL_FALSE); - gpu::FramebufferPointer destFBO = textureCache->getSecondaryFramebuffer() + gpu::FramebufferPointer destFBO = textureCache->getSecondaryFramebuffer(); if (!_enabled || _isEmpty) { // copy the primary to the screen if (destFBO && QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()) { @@ -147,13 +147,13 @@ gpu::FramebufferPointer GlowEffect::render() { glBindFramebuffer(GL_DRAW_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(destFBO)); glBlitFramebuffer(0, 0, framebufferSize.width(), framebufferSize.height(), 0, 0, framebufferSize.width(), framebufferSize.height(), GL_COLOR_BUFFER_BIT, GL_NEAREST); } else { - destFBO->bind(); + glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(destFBO)); glEnable(GL_TEXTURE_2D); glDisable(GL_LIGHTING); renderFullscreenQuad(); glDisable(GL_TEXTURE_2D); glEnable(GL_LIGHTING); - destFBO->release(); + glBindFramebuffer(GL_FRAMEBUFFER, 0); } } else { // diffuse into the secondary/tertiary (alternating between frames) @@ -188,11 +188,11 @@ gpu::FramebufferPointer GlowEffect::render() { glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(newDiffusedFBO->getRenderBuffer(0))); destFBO = oldDiffusedFBO; - destFBO->bind(); + glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(destFBO)); _addSeparateProgram->bind(); renderFullscreenQuad(); _addSeparateProgram->release(); - destFBO->release(); + glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindTexture(GL_TEXTURE_2D, 0); glActiveTexture(GL_TEXTURE0); diff --git a/libraries/render-utils/src/OffscreenGlContext.h b/libraries/render-utils/src/OffscreenGlContext.h index ef67a7fc9a..c0d22b268f 100644 --- a/libraries/render-utils/src/OffscreenGlContext.h +++ b/libraries/render-utils/src/OffscreenGlContext.h @@ -9,8 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #pragma once -#ifndef hifi_OffscreenGlCanvas_h -#define hifi_OffscreenGlCanvas_h +#ifndef hifi_OffscreenGlContext_h +#define hifi_OffscreenGlContext_h #include #include diff --git a/libraries/render-utils/src/TextureCache.cpp b/libraries/render-utils/src/TextureCache.cpp index 63ca43725b..c7aa4b586c 100644 --- a/libraries/render-utils/src/TextureCache.cpp +++ b/libraries/render-utils/src/TextureCache.cpp @@ -32,8 +32,7 @@ TextureCache::TextureCache() : _permutationNormalTexture(0), _whiteTexture(0), _blueTexture(0), - _frameBufferSize(100, 100), - _associatedWidget(NULL) + _frameBufferSize(100, 100) { const qint64 TEXTURE_DEFAULT_UNUSED_MAX_SIZE = DEFAULT_UNUSED_MAX_SIZE; setUnusedResourceCacheSize(TEXTURE_DEFAULT_UNUSED_MAX_SIZE); @@ -290,24 +289,6 @@ GLuint TextureCache::getShadowDepthTextureID() { return gpu::GLBackend::getTextureID(_shadowTexture); } -bool TextureCache::eventFilter(QObject* watched, QEvent* event) { - if (event->type() == QEvent::Resize) { - QSize size = static_cast(event)->size(); - if (_frameBufferSize != size) { - _primaryFramebuffer.reset(); - _primaryColorTexture.reset(); - _primaryDepthTexture.reset(); - _primaryNormalTexture.reset(); - _primarySpecularTexture.reset(); - - _secondaryFramebuffer.reset(); - - _tertiaryFramebuffer.reset(); - } - } - return false; -} - QSharedPointer TextureCache::createResource(const QUrl& url, const QSharedPointer& fallback, bool delayLoad, const void* extra) { const TextureExtra* textureExtra = static_cast(extra); @@ -315,14 +296,6 @@ QSharedPointer TextureCache::createResource(const QUrl& url, &Resource::allReferencesCleared); } -void TextureCache::associateWithWidget(QGLWidget* widget) { - if (_associatedWidget) { - _associatedWidget->removeEventFilter(this); - } - _associatedWidget = widget; - _associatedWidget->installEventFilter(this); -} - Texture::Texture() { } diff --git a/libraries/shared/src/GLMHelpers.cpp b/libraries/shared/src/GLMHelpers.cpp index 5d1b70275c..89fd15e179 100644 --- a/libraries/shared/src/GLMHelpers.cpp +++ b/libraries/shared/src/GLMHelpers.cpp @@ -336,6 +336,10 @@ QMatrix4x4 fromGlm(const glm::mat4 & m) { return QMatrix4x4(&m[0][0]).transposed(); } +QSize fromGlm(const glm::ivec2 & v) { + return QSize(v.x, v.y); +} + QRectF glmToRect(const glm::vec2 & pos, const glm::vec2 & size) { QRectF result(pos.x, pos.y, size.x, size.y); return result; diff --git a/libraries/shared/src/GLMHelpers.h b/libraries/shared/src/GLMHelpers.h index dda57a9cd9..a710ba759b 100644 --- a/libraries/shared/src/GLMHelpers.h +++ b/libraries/shared/src/GLMHelpers.h @@ -112,6 +112,7 @@ glm::vec2 toGlm(const QPointF & pt); glm::vec3 toGlm(const xColor & color); glm::vec4 toGlm(const QColor & color); +QSize fromGlm(const glm::ivec2 & v); QMatrix4x4 fromGlm(const glm::mat4 & m); QRectF glmToRect(const glm::vec2 & pos, const glm::vec2 & size); From a482fa0a6d27321438464d54bc3087d94af5948a Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 1 May 2015 10:35:15 -0700 Subject: [PATCH 004/552] Working on plugin rendering model: --- interface/src/Application.cpp | 8 +++++--- interface/src/GLCanvas.cpp | 11 +++-------- interface/src/avatar/MyAvatar.cpp | 18 ++++++++++-------- .../src/plugins/render/LegacyRenderPlugin.cpp | 5 +++++ 4 files changed, 23 insertions(+), 19 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index d514ee2837..567e50df23 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1067,6 +1067,8 @@ bool Application::eventFilter(QObject* object, QEvent* event) { } } + // auto offscreenUi = DependencyManager::get(); + // return offscreenUi->eventFilter(object, event); return false; } @@ -1434,7 +1436,7 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) { if (!_lastMouseMoveWasSimulated) { _lastMouseMove = usecTimestampNow(); } - + if (_aboutToQuit) { return; } @@ -3001,7 +3003,7 @@ ViewFrustum* Application::getViewFrustum() { #ifdef DEBUG if (QThread::currentThread() == activeRenderingThread) { // FIXME, should this be an assert? - qWarning() << "Calling Application::getViewFrustum() from the active rendering thread, did you mean Application::getDisplayViewFrustum()?"; + //qWarning() << "Calling Application::getViewFrustum() from the active rendering thread, did you mean Application::getDisplayViewFrustum()?"; } #endif return &_viewFrustum; @@ -3011,7 +3013,7 @@ ViewFrustum* Application::getDisplayViewFrustum() { #ifdef DEBUG if (QThread::currentThread() != activeRenderingThread) { // FIXME, should this be an assert? - qWarning() << "Calling Application::getDisplayViewFrustum() from outside the active rendering thread or outside rendering, did you mean Application::getViewFrustum()?"; + //qWarning() << "Calling Application::getDisplayViewFrustum() from outside the active rendering thread or outside rendering, did you mean Application::getViewFrustum()?"; } #endif return &_displayViewFrustum; diff --git a/interface/src/GLCanvas.cpp b/interface/src/GLCanvas.cpp index a5bf009102..c79e726a66 100644 --- a/interface/src/GLCanvas.cpp +++ b/interface/src/GLCanvas.cpp @@ -67,13 +67,10 @@ void GLCanvas::paintGL() { } #endif Application::getInstance()->paintGL(); - + #if 0 if (!OculusManager::isConnected()) { -#endif - swapBuffers(); -#if 0 } else { if (OculusManager::allowSwap()) { swapBuffers(); @@ -121,13 +118,11 @@ void GLCanvas::throttleRender() { if (OculusManager::isConnected()) { OculusManager::beginFrameTiming(); } -#endif - makeCurrent(); +#endif Application::getInstance()->paintGL(); - swapBuffers(); - #if 0 + swapBuffers(); if (OculusManager::isConnected()) { OculusManager::endFrameTiming(); } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 7f004970d5..2c772c76b7 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -34,6 +34,7 @@ #include #include "Application.h" +#include "plugins/render/RenderPlugin.h" #include "AvatarManager.h" #include "Environment.h" #include "Menu.h" @@ -230,13 +231,15 @@ void MyAvatar::simulate(float deltaTime) { void MyAvatar::updateFromTrackers(float deltaTime) { glm::vec3 estimatedPosition, estimatedRotation; -#if 0 - if (isPlaying() && !OculusManager::isConnected()) { + auto renderPlugin = qApp->getActiveRenderPlugin(); + bool inHmd = renderPlugin->isHmd(); + + if (isPlaying() && inHmd) { return; } - - if (OculusManager::isConnected()) { - estimatedPosition = OculusManager::getRelativePosition(); + + if (inHmd) { + estimatedPosition = renderPlugin->headTranslation(); estimatedPosition.x *= -1.0f; _trackedHeadPosition = estimatedPosition; @@ -274,7 +277,7 @@ void MyAvatar::updateFromTrackers(float deltaTime) { Head* head = getHead(); - if (OculusManager::isConnected() || isPlaying()) { + if (inHmd || isPlaying()) { head->setDeltaPitch(estimatedRotation.x); head->setDeltaYaw(estimatedRotation.y); } else { @@ -294,7 +297,7 @@ void MyAvatar::updateFromTrackers(float deltaTime) { // NOTE: this is kinda a hack, it's the same hack we use to make the head tilt. But it's not really a mirror // it just makes you feel like you're looking in a mirror because the body movements of the avatar appear to // match your body movements. - if (OculusManager::isConnected() && Application::getInstance()->getCamera()->getMode() == CAMERA_MODE_MIRROR) { + if (inHmd && Application::getInstance()->getCamera()->getMode() == CAMERA_MODE_MIRROR) { relativePosition.x = -relativePosition.x; } @@ -302,7 +305,6 @@ void MyAvatar::updateFromTrackers(float deltaTime) { -MAX_LEAN, MAX_LEAN)); head->setLeanForward(glm::clamp(glm::degrees(atanf(relativePosition.z * _leanScale / TORSO_LENGTH)), -MAX_LEAN, MAX_LEAN)); -#endif } diff --git a/interface/src/plugins/render/LegacyRenderPlugin.cpp b/interface/src/plugins/render/LegacyRenderPlugin.cpp index 6d46c6d3f5..93170517b3 100644 --- a/interface/src/plugins/render/LegacyRenderPlugin.cpp +++ b/interface/src/plugins/render/LegacyRenderPlugin.cpp @@ -32,9 +32,14 @@ void LegacyRenderPlugin::activate() { _window->setFocusPolicy(Qt::StrongFocus); _window->setFocus(); _window->setMouseTracking(true); + + _window->installEventFilter(qApp); + _window->installEventFilter(DependencyManager::get().data()); } void LegacyRenderPlugin::deactivate() { + _window->removeEventFilter(DependencyManager::get().data()); + _window->removeEventFilter(qApp); qApp->getWindow()->setCentralWidget(oldWidget); // stop the glWidget frame timer so it doesn't call paintGL _window->stopFrameTimer(); From d8415ce79bf6c920b5791764c9db4ce3769e9100 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 1 May 2015 15:14:50 -0700 Subject: [PATCH 005/552] Working on display plugins --- interface/CMakeLists.txt | 2 +- interface/src/Application.cpp | 211 +++++++++++++----- interface/src/Application.h | 17 +- interface/src/Menu.cpp | 18 +- interface/src/Menu.h | 4 +- interface/src/avatar/MyAvatar.cpp | 56 ++--- interface/src/plugins/PluginManager.h | 4 +- .../{RenderPlugin.cpp => DisplayPlugin.cpp} | 6 +- .../{RenderPlugin.h => DisplayPlugin.h} | 4 +- ...dRenderPlugin.cpp => HmdDisplayPlugin.cpp} | 4 +- .../{HmdRenderPlugin.h => HmdDisplayPlugin.h} | 6 +- ...nderPlugin.cpp => LegacyDisplayPlugin.cpp} | 30 +-- ...cyRenderPlugin.h => LegacyDisplayPlugin.h} | 6 +- .../src/plugins/render/NullDisplayPlugin.cpp | 44 ++++ ...NullRenderPlugin.h => NullDisplayPlugin.h} | 8 +- .../src/plugins/render/NullRenderPlugin.cpp | 44 ---- ...Plugin.cpp => OculusBaseDisplayPlugin.cpp} | 18 +- ...nderPlugin.h => OculusBaseDisplayPlugin.h} | 6 +- ...n.cpp => OculusDirectD3DDisplayPlugin.cpp} | 4 +- ...lugin.h => OculusDirectD3DDisplayPlugin.h} | 4 +- ...ugin.cpp => OculusDirectDisplayPlugin.cpp} | 4 +- ...erPlugin.h => OculusDirectDisplayPlugin.h} | 4 +- ...in.cpp => OculusExtendedDisplayPlugin.cpp} | 4 +- ...Plugin.h => OculusExtendedDisplayPlugin.h} | 4 +- ...nderPlugin.cpp => SimpleDisplayPlugin.cpp} | 4 +- ...leRenderPlugin.h => SimpleDisplayPlugin.h} | 6 +- ...nderPlugin.cpp => StereoDisplayPlugin.cpp} | 4 +- ...eoRenderPlugin.h => StereoDisplayPlugin.h} | 6 +- ...RenderPlugin.cpp => Tv3dDisplayPlugin.cpp} | 10 +- ...Tv3dRenderPlugin.h => Tv3dDisplayPlugin.h} | 6 +- ...nderPlugin.cpp => WindowDisplayPlugin.cpp} | 24 +- ...owRenderPlugin.h => WindowDisplayPlugin.h} | 8 +- interface/src/ui/ApplicationOverlay.cpp | 12 +- .../script-engine/src/MenuItemProperties.cpp | 9 +- libraries/shared/src/GLMHelpers.h | 4 + 35 files changed, 350 insertions(+), 255 deletions(-) rename interface/src/plugins/render/{RenderPlugin.cpp => DisplayPlugin.cpp} (82%) rename interface/src/plugins/render/{RenderPlugin.h => DisplayPlugin.h} (97%) rename interface/src/plugins/render/{HmdRenderPlugin.cpp => HmdDisplayPlugin.cpp} (81%) rename interface/src/plugins/render/{HmdRenderPlugin.h => HmdDisplayPlugin.h} (74%) rename interface/src/plugins/render/{LegacyRenderPlugin.cpp => LegacyDisplayPlugin.cpp} (71%) rename interface/src/plugins/render/{LegacyRenderPlugin.h => LegacyDisplayPlugin.h} (87%) create mode 100644 interface/src/plugins/render/NullDisplayPlugin.cpp rename interface/src/plugins/render/{NullRenderPlugin.h => NullDisplayPlugin.h} (83%) delete mode 100644 interface/src/plugins/render/NullRenderPlugin.cpp rename interface/src/plugins/render/{OculusBaseRenderPlugin.cpp => OculusBaseDisplayPlugin.cpp} (84%) rename interface/src/plugins/render/{OculusBaseRenderPlugin.h => OculusBaseDisplayPlugin.h} (88%) rename interface/src/plugins/render/{OculusExtendedRenderPlugin.cpp => OculusDirectD3DDisplayPlugin.cpp} (75%) rename interface/src/plugins/render/{OculusDirectD3DRenderPlugin.h => OculusDirectD3DDisplayPlugin.h} (78%) rename interface/src/plugins/render/{OculusDirectRenderPlugin.cpp => OculusDirectDisplayPlugin.cpp} (77%) rename interface/src/plugins/render/{OculusDirectRenderPlugin.h => OculusDirectDisplayPlugin.h} (79%) rename interface/src/plugins/render/{OculusDirectD3DRenderPlugin.cpp => OculusExtendedDisplayPlugin.cpp} (76%) rename interface/src/plugins/render/{OculusExtendedRenderPlugin.h => OculusExtendedDisplayPlugin.h} (78%) rename interface/src/plugins/render/{SimpleRenderPlugin.cpp => SimpleDisplayPlugin.cpp} (82%) rename interface/src/plugins/render/{SimpleRenderPlugin.h => SimpleDisplayPlugin.h} (92%) rename interface/src/plugins/render/{StereoRenderPlugin.cpp => StereoDisplayPlugin.cpp} (80%) rename interface/src/plugins/render/{StereoRenderPlugin.h => StereoDisplayPlugin.h} (75%) rename interface/src/plugins/render/{Tv3dRenderPlugin.cpp => Tv3dDisplayPlugin.cpp} (77%) rename interface/src/plugins/render/{Tv3dRenderPlugin.h => Tv3dDisplayPlugin.h} (83%) rename interface/src/plugins/render/{WindowRenderPlugin.cpp => WindowDisplayPlugin.cpp} (95%) rename interface/src/plugins/render/{WindowRenderPlugin.h => WindowDisplayPlugin.h} (83%) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 0b2cfa5427..9dbed9a6ee 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -44,7 +44,7 @@ macro(GroupSources curdir) GroupSources(${curdir}/${child}) else() string(REPLACE "/" "\\" groupname ${curdir}) - source_group(${groupname} FILES ${PROJECT_SOURCE_DIR}/${curdir}/${child}) + source_group(${groupname} FILES ${PROJECT_SOURCE_DIR}/${curdir}/${child}) endif() endforeach() endmacro() diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 567e50df23..e6695dafd7 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -114,7 +114,7 @@ #include "gpu/Batch.h" #include "gpu/GLBackend.h" -#include "plugins/render/RenderPlugin.h" +#include "plugins/render/DisplayPlugin.h" #include "scripting/AccountScriptingInterface.h" #include "scripting/AudioDeviceScriptingInterface.h" @@ -660,7 +660,7 @@ Application::~Application() { ModelEntityItem::cleanupLoadedAnimations(); - getActiveRenderPlugin()->deactivate(); + getActiveDisplayPlugin()->deactivate(); DependencyManager::destroy(); DependencyManager::destroy(); @@ -773,22 +773,22 @@ void Application::initializeUi() { auto offscreenUi = DependencyManager::get(); offscreenUi->create(_offscreenContext->getContext()); - offscreenUi->resize(fromGlm(getActiveRenderPlugin()->getCanvasSize())); + offscreenUi->resize(fromGlm(getActiveDisplayPlugin()->getCanvasSize())); offscreenUi->setProxyWindow(_window->windowHandle()); offscreenUi->setBaseUrl(QUrl::fromLocalFile(PathUtils::resourcesPath() + "/qml/")); offscreenUi->load("Root.qml"); offscreenUi->load("RootMenu.qml"); VrMenu::load(); VrMenu::executeQueuedLambdas(); - offscreenUi->setMouseTranslator(getActiveRenderPlugin()->getMouseTranslator()); + offscreenUi->setMouseTranslator(getActiveDisplayPlugin()->getMouseTranslator()); offscreenUi->resume(); connect(_window, &MainWindow::windowGeometryChanged, [this](const QRect & r){ static qreal oldDevicePixelRatio = 0; - qreal devicePixelRatio = getActiveRenderPlugin()->devicePixelRatio(); + qreal devicePixelRatio = getActiveDisplayPlugin()->devicePixelRatio(); if (devicePixelRatio != oldDevicePixelRatio) { oldDevicePixelRatio = devicePixelRatio; qDebug() << "Device pixel ratio changed, triggering GL resize"; - auto canvasSize = getActiveRenderPlugin()->getCanvasSize(); + auto canvasSize = getActiveDisplayPlugin()->getCanvasSize(); resizeGL(canvasSize.x, canvasSize.y); } }); @@ -803,18 +803,18 @@ void Application::paintGL() { PerformanceWarning warn(showWarnings, "Application::paintGL()"); _offscreenContext->makeCurrent(); - QSize fbSize = getActiveRenderPlugin()->getRecommendedFramebufferSize() * getRenderResolutionScale(); + QSize fbSize = getActiveDisplayPlugin()->getRecommendedFramebufferSize() * getRenderResolutionScale(); DependencyManager::get()->setFrameBufferSize(fbSize); glEnable(GL_LINE_SMOOTH); if (_myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) { - if (!getActiveRenderPlugin()->isHmd()) { - // If there isn't an HMD, match exactly to avatar's head + if (getActiveDisplayPlugin()->isHmd()) { + // For an HMD, set the base position and orientation to that of the avatar body _myCamera.setPosition(_myAvatar->getHead()->getEyePosition()); _myCamera.setRotation(_myAvatar->getHead()->getCameraOrientation()); } else { - // For an HMD, set the base position and orientation to that of the avatar body + // If there isn't an HMD, match exactly to avatar's head _myCamera.setPosition(_myAvatar->getDefaultEyePosition()); _myCamera.setRotation(_myAvatar->getWorldAlignedOrientation()); } @@ -822,7 +822,7 @@ void Application::paintGL() { static const float THIRD_PERSON_CAMERA_DISTANCE = 1.5f; _myCamera.setPosition(_myAvatar->getDefaultEyePosition() + _myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, 1.0f) * THIRD_PERSON_CAMERA_DISTANCE * _myAvatar->getScale()); - if (getActiveRenderPlugin()->isHmd()) { + if (getActiveDisplayPlugin()->isHmd()) { _myCamera.setRotation(_myAvatar->getWorldAlignedOrientation()); } else { _myCamera.setRotation(_myAvatar->getHead()->getOrientation()); @@ -882,7 +882,7 @@ void Application::paintGL() { _offscreenContext->doneCurrent(); Q_ASSERT(!QOpenGLContext::currentContext()); - getActiveRenderPlugin()->render(gpu::GLBackend::getTextureID(finalFbo->getRenderBuffer(0))); + getActiveDisplayPlugin()->render(gpu::GLBackend::getTextureID(finalFbo->getRenderBuffer(0))); Q_ASSERT(!QOpenGLContext::currentContext()); _offscreenContext->makeCurrent(); _frameCount++; @@ -934,7 +934,7 @@ void Application::resizeGL(int width, int height) { updateProjectionMatrix(); glLoadIdentity(); - auto canvasSize = getActiveRenderPlugin()->getCanvasSize(); + auto canvasSize = getActiveDisplayPlugin()->getCanvasSize(); auto offscreenUi = DependencyManager::get(); offscreenUi->resize(fromGlm(canvasSize)); @@ -1306,7 +1306,7 @@ void Application::keyPressEvent(QKeyEvent* event) { break; } case Qt::Key_Escape: { - getActiveRenderPlugin()->abandonCalibration(); + getActiveDisplayPlugin()->abandonCalibration(); if (!event->isAutoRepeat()) { // this starts the HFCancelEvent HFBackEvent startBackEvent(HFBackEvent::startType()); @@ -1441,8 +1441,8 @@ void Application::mouseMoveEvent(QMouseEvent* event, unsigned int deviceID) { return; } - if (Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen) - && !Menu::getInstance()->isOptionChecked(MenuOption::EnableVRMode)) { + + if (Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen)) { // Show/hide menu bar in fullscreen if (event->globalY() > _menuBarHeight) { _fullscreenMenuWidget->setFixedHeight(0); @@ -1720,7 +1720,7 @@ void Application::idle() { { PerformanceTimer perfTimer("updateGL"); PerformanceWarning warn(showWarnings, "Application::idle()... updateGL()"); - getActiveRenderPlugin()->idle(); + getActiveDisplayPlugin()->idle(); } { @@ -1753,7 +1753,7 @@ void Application::setFullscreen(bool fullscreen) { // app menu in a fullscreen window. However the OSX mechanism hides the // application menu for fullscreen apps, so the check is not required. #ifndef Q_OS_MAC - if (Menu::getInstance()->isOptionChecked(MenuOption::EnableVRMode)) { + if (getActiveDisplayPlugin()->isHmd()) { if (fullscreen) { // Menu hide() disables menu commands, and show() after hide() doesn't work with Rift VR display. // So set height instead. @@ -1843,15 +1843,15 @@ void Application::setLowVelocityFilter(bool lowVelocityFilter) { } bool Application::mouseOnScreen() const { - return getActiveRenderPlugin()->isMouseOnScreen(); + return getActiveDisplayPlugin()->isMouseOnScreen(); } int Application::getMouseX() const { - return getActiveRenderPlugin()->getUiMousePosition().x; + return getActiveDisplayPlugin()->getUiMousePosition().x; } int Application::getMouseY() const { - return getActiveRenderPlugin()->getUiMousePosition().x; + return getActiveDisplayPlugin()->getUiMousePosition().x; } int Application::getMouseDragStartedX() const { @@ -2332,9 +2332,7 @@ void Application::updateCursor(float deltaTime) { } void Application::updateCursorVisibility() { - if (!_cursorVisible || - Menu::getInstance()->isOptionChecked(MenuOption::EnableVRMode) || - Menu::getInstance()->isOptionChecked(MenuOption::Enable3DTVMode)) { + if (!_cursorVisible || getActiveDisplayPlugin()->isStereo()) { _window->setCursor(Qt::BlankCursor); } else { _window->unsetCursor(); @@ -2714,7 +2712,7 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node } bool Application::isHMDMode() const { - return getActiveRenderPlugin()->isHmd(); + return getActiveDisplayPlugin()->isHmd(); } QRect Application::getDesirableApplicationGeometry() { @@ -3287,7 +3285,7 @@ void Application::computeOffAxisFrustum(float& left, float& right, float& bottom float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const { _displayViewFrustum.computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); // allow 3DTV/Oculus to override parameters from camera - getActiveRenderPlugin()->overrideOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); + getActiveDisplayPlugin()->overrideOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); } bool Application::getShadowsEnabled() { @@ -3378,7 +3376,7 @@ void Application::resetSensors() { DependencyManager::get()->reset(); DependencyManager::get()->reset(); - getActiveRenderPlugin()->resetSensors(); + getActiveDisplayPlugin()->resetSensors(); //_leapmotion.reset(); #if 0 @@ -4461,12 +4459,12 @@ PickRay Application::computePickRay(float x, float y) const { return computeViewPickRay(x, y); } -glm::ivec2 Application::getCanvasSize() const { - return getActiveRenderPlugin()->getCanvasSize(); +glm::uvec2 Application::getCanvasSize() const { + return getActiveDisplayPlugin()->getCanvasSize(); } QSize Application::getDeviceSize() const { - return getActiveRenderPlugin()->getRecommendedFramebufferSize(); // _glWidget->getDeviceSize(); + return getActiveDisplayPlugin()->getRecommendedFramebufferSize(); // _glWidget->getDeviceSize(); } void Application::resizeGL() { @@ -4475,49 +4473,150 @@ void Application::resizeGL() { } bool Application::hasFocus() const { - return getActiveRenderPlugin()->hasFocus(); + return getActiveDisplayPlugin()->hasFocus(); } glm::vec2 Application::getViewportDimensions() const { return toGlm(getDeviceSize()); } + +glm::ivec2 Application::getTrueMousePosition() const { + return getActiveDisplayPlugin()->getTrueMousePosition(); +} +glm::quat Application::getHeadOrientation() const { + return getActiveDisplayPlugin()->headOrientation(); +} +glm::vec3 Application::getHeadPosition() const { + return getActiveDisplayPlugin()->headTranslation(); +} + int Application::getTrueMouseX() const { - return getActiveRenderPlugin()->getTrueMousePosition().x; + return getActiveDisplayPlugin()->getTrueMousePosition().x; } int Application::getTrueMouseY() const { - return getActiveRenderPlugin()->getTrueMousePosition().y; + return getActiveDisplayPlugin()->getTrueMousePosition().y; } bool Application::isThrottleRendering() const { - return getActiveRenderPlugin()->isThrottled(); + return getActiveDisplayPlugin()->isThrottled(); } -#include "plugins/render/NullRenderPlugin.h" -#include "plugins/render/WindowRenderPlugin.h" -#include "plugins/render/LegacyRenderPlugin.h" -static RenderPlugin * renderPlugin = nullptr; +using DisplayPluginPointer = QSharedPointer; -RenderPlugin * Application::getActiveRenderPlugin() { - if (nullptr == renderPlugin) { - //renderPlugin = new WindowRenderPlugin(); - renderPlugin = new LegacyRenderPlugin(); - renderPlugin->init(); - renderPlugin->activate(); - connect(renderPlugin, &RenderPlugin::requestRender, this, [&] { - this->paintGL(); - }); - connect(renderPlugin, &RenderPlugin::recommendedFramebufferSizeChanged, this, [&](const QSize & size) { - DependencyManager::get()->setFrameBufferSize(size * getRenderResolutionScale()); - this->resizeGL(size.width(), size.height()); - }); +#include "plugins/render/NullDisplayPlugin.h" +#include "plugins/render/WindowDisplayPlugin.h" +#include "plugins/render/LegacyDisplayPlugin.h" +#include "plugins/render/OculusDirectD3DDisplayPlugin.h" + +static DisplayPluginPointer _displayPlugin{ nullptr }; + +DisplayPlugin * Application::getActiveDisplayPlugin() { + if (nullptr == _displayPlugin) { + updateDisplayMode(); + Q_ASSERT(_displayPlugin); + } + return _displayPlugin.data(); +} + +const DisplayPlugin * Application::getActiveDisplayPlugin() const { + return ((Application*)this)->getActiveDisplayPlugin(); +} + + +/* + +QAction* action = NULL; +QAction* actionBefore = NULL; + +if (menuItemLocation >= 0 && destinationMenu->actions().size() > menuItemLocation) { +actionBefore = destinationMenu->actions()[menuItemLocation]; +} + +if (!actionBefore) { +if (receiver && member) { +action = destinationMenu->addAction(actionName, receiver, member, shortcut); +} else { +action = destinationMenu->addAction(actionName); +action->setShortcut(shortcut); +} +} else { +action = new QAction(actionName, destinationMenu); +action->setShortcut(shortcut); +destinationMenu->insertAction(actionBefore, action); + +if (receiver && member) { +connect(action, SIGNAL(triggered()), receiver, member); +} +} +action->setMenuRole(role); + +*/ +static void addDisplayPluginToMenu(DisplayPluginPointer displayPlugin, bool active = false) { + auto menu = Menu::getInstance(); + MenuItemProperties item(MenuOption::OutputMenu, displayPlugin->getName(), "", true, active); + item.isSeparator = false; + Q_ASSERT(!menu->menuItemExists(MenuOption::OutputMenu, item.menuItemName)); + menu->addMenuItem(item); + Q_ASSERT(menu->menuItemExists(MenuOption::OutputMenu, item.menuItemName)); +} + +using DisplayPluginList = QVector; + +// FIXME move to a plugin manager class +static const DisplayPluginList & getDisplayPlugins() { + static DisplayPluginList RENDER_PLUGINS; + static bool init = false; + if (!init) { + DisplayPluginPointer displayPlugin = DisplayPluginPointer(new LegacyDisplayPlugin()); // new WindowDisplayPlugin(); + if (displayPlugin->isSupported()) { + displayPlugin->init(); + RENDER_PLUGINS.push_back(DisplayPluginPointer(displayPlugin)); + QObject::connect(displayPlugin.data(), &DisplayPlugin::requestRender, [] { + qApp->paintGL(); + }); + QObject::connect(displayPlugin.data(), &DisplayPlugin::recommendedFramebufferSizeChanged, [](const QSize & size) { + DependencyManager::get()->setFrameBufferSize(size * qApp->getRenderResolutionScale()); + qApp->resizeGL(size.width(), size.height()); + }); + addDisplayPluginToMenu(displayPlugin, true); + } + + displayPlugin = DisplayPluginPointer(new NullDisplayPlugin()); + if (displayPlugin->isSupported()) { +#ifdef DEBUG + addDisplayPluginToMenu(displayPlugin); +#endif + displayPlugin->init(); + RENDER_PLUGINS.push_back(DisplayPluginPointer(displayPlugin)); + } + } + return RENDER_PLUGINS; +} + +void Application::updateDisplayMode() { + auto menu = Menu::getInstance(); + DisplayPluginPointer newDisplayPlugin; + foreach(DisplayPluginPointer displayPlugin, getDisplayPlugins()) { + QString name = displayPlugin->getName(); + QAction* action = menu->getActionForOption(name); + if (action->isChecked()) { + newDisplayPlugin = displayPlugin; + break; + } + } + if (_displayPlugin != newDisplayPlugin) { + if (_displayPlugin) { + _displayPlugin->deactivate(); + } + _offscreenContext->makeCurrent(); + _displayPlugin = newDisplayPlugin; + if (_displayPlugin) { + _displayPlugin->activate(); + } _offscreenContext->makeCurrent(); } - return renderPlugin; -} - -const RenderPlugin * Application::getActiveRenderPlugin() const { - return ((Application*)this)->getActiveRenderPlugin(); + Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin"); } diff --git a/interface/src/Application.h b/interface/src/Application.h index 6e4cb524e6..e55f61e832 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -75,7 +75,7 @@ #include "octree/OctreePacketProcessor.h" #include "UndoStackScriptingInterface.h" -class RenderPlugin; +class DisplayPlugin; class QGLWidget; class QKeyEvent; class QMouseEvent; @@ -184,7 +184,7 @@ public: bool event(QEvent* event); bool eventFilter(QObject* object, QEvent* event); - glm::ivec2 getCanvasSize() const; + glm::uvec2 getCanvasSize() const; QSize getDeviceSize() const; bool hasFocus() const; PickRay computePickRay() const; @@ -217,6 +217,7 @@ public: bool mouseOnScreen() const; int getMouseX() const; int getMouseY() const; + glm::ivec2 getTrueMousePosition() const; int getTrueMouseX() const; int getTrueMouseY() const; int getMouseDragStartedX() const; @@ -290,8 +291,11 @@ public: virtual int getBoundaryLevelAdjust() const; virtual PickRay computePickRay(float x, float y) const; virtual const glm::vec3& getAvatarPosition() const { return _myAvatar->getPosition(); } - RenderPlugin * getActiveRenderPlugin(); - const RenderPlugin * getActiveRenderPlugin() const; + + private: + DisplayPlugin * getActiveDisplayPlugin(); + const DisplayPlugin * getActiveDisplayPlugin() const; + public: NodeBounds& getNodeBoundsDisplay() { return _nodeBoundsDisplay; } @@ -320,7 +324,9 @@ public: // rendering of several elements depend on that // TODO: carry that information on the Camera as a setting bool isHMDMode() const; - + glm::quat getHeadOrientation() const; + glm::vec3 getHeadPosition() const; + QRect getDesirableApplicationGeometry(); RunningScriptsWidget* getRunningScriptsWidget() { return _runningScriptsWidget; } @@ -366,6 +372,7 @@ public slots: void nodeAdded(SharedNodePointer node); void nodeKilled(SharedNodePointer node); void packetSent(quint64 length); + void updateDisplayMode(); QVector pasteEntities(float x, float y, float z); bool exportEntities(const QString& filename, const QVector& entityIDs); diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 90a9d3b22c..cfacbc3fd1 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -233,6 +233,11 @@ Menu::Menu() { avatar, SLOT(updateMotionBehavior())); MenuWrapper* viewMenu = addMenu("View"); + { + MenuWrapper* displayModeMenu = addMenu(MenuOption::OutputMenu); + QActionGroup* displayModeGroup = new QActionGroup(displayModeMenu); + displayModeGroup->setExclusive(true); + } addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Fullscreen, @@ -265,16 +270,9 @@ Menu::Menu() { dialogsManager.data(), SLOT(hmdTools(bool))); - addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::EnableVRMode, 0, - false, - qApp, - SLOT(setEnableVRMode(bool))); - - addCheckableActionToQMenuAndActionHash(viewMenu, MenuOption::Enable3DTVMode, 0, - false, - qApp, - SLOT(setEnable3DTVMode(bool))); - + addActionToQMenuAndActionHash(editMenu, MenuOption::Attachments, 0, + dialogsManager.data(), SLOT(editAttachments())); + MenuWrapper* nodeBordersMenu = viewMenu->addMenu("Server Borders"); NodeBounds& nodeBounds = qApp->getNodeBoundsDisplay(); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 7d105687ab..20e2d7e428 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -181,8 +181,7 @@ namespace MenuOption { const QString EditEntitiesHelp = "Edit Entities Help..."; const QString Enable3DTVMode = "Enable 3DTV Mode"; const QString EnableCharacterController = "Enable avatar collisions"; - const QString EnableGlowEffect = "Enable Glow Effect (Warning: Poor Oculus Performance)"; - const QString EnableVRMode = "Enable VR Mode"; + const QString EnableGlowEffect = "Enable Glow Effect"; const QString ExpandMyAvatarSimulateTiming = "Expand /myAvatar/simulation"; const QString ExpandMyAvatarTiming = "Expand /myAvatar"; const QString ExpandOtherAvatarTiming = "Expand /otherAvatar"; @@ -215,6 +214,7 @@ namespace MenuOption { const QString OctreeStats = "Entity Statistics"; const QString OffAxisProjection = "Off-Axis Projection"; const QString OnlyDisplayTopTen = "Only Display Top Ten"; + const QString OutputMenu = "View>Display Mode"; const QString PackageModel = "Package Model..."; const QString Pair = "Pair"; const QString PhysicsShowOwned = "Highlight Simulation Ownership"; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 2c772c76b7..424882712c 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -34,7 +34,7 @@ #include #include "Application.h" -#include "plugins/render/RenderPlugin.h" +#include "plugins/render/DisplayPlugin.h" #include "AvatarManager.h" #include "Environment.h" #include "Menu.h" @@ -231,15 +231,14 @@ void MyAvatar::simulate(float deltaTime) { void MyAvatar::updateFromTrackers(float deltaTime) { glm::vec3 estimatedPosition, estimatedRotation; - auto renderPlugin = qApp->getActiveRenderPlugin(); - bool inHmd = renderPlugin->isHmd(); + bool inHmd = qApp->isHMDMode(); if (isPlaying() && inHmd) { return; } if (inHmd) { - estimatedPosition = renderPlugin->headTranslation(); + estimatedPosition = qApp->getHeadPosition(); estimatedPosition.x *= -1.0f; _trackedHeadPosition = estimatedPosition; @@ -886,15 +885,13 @@ void MyAvatar::updateLookAtTargetAvatar() { howManyLookingAtMe++; // Have that avatar look directly at my camera // Philip TODO: correct to look at left/right eye -#if 0 - if (OculusManager::isConnected()) { - avatar->getHead()->setCorrectedLookAtPosition(OculusManager::getLeftEyePosition()); - } else { -#endif + if (qApp->isHMDMode()) { + avatar->getHead()->setCorrectedLookAtPosition(Application::getInstance()->getViewFrustum()->getPosition()); + // FIXME what is the point of this? + // avatar->getHead()->setCorrectedLookAtPosition(OculusManager::getLeftEyePosition()); + } else { avatar->getHead()->setCorrectedLookAtPosition(Application::getInstance()->getViewFrustum()->getPosition()); -#if 0 } -#endif } else { avatar->getHead()->clearCorrectedLookAtPosition(); } @@ -1185,8 +1182,7 @@ void MyAvatar::renderBody(ViewFrustum* renderFrustum, RenderArgs::RenderMode ren renderFrustum->setNearClip(DEFAULT_NEAR_CLIP); } else { float clipDistance = _skeletonModel.getHeadClipDistance(); -#if 0 - if (OculusManager::isConnected()) { + if (qApp->isHMDMode()) { // If avatar is horizontally in front of camera, increase clip distance by the amount it is in front. glm::vec3 cameraToAvatar = _position - cameraPos; cameraToAvatar.y = 0.0f; @@ -1196,7 +1192,6 @@ void MyAvatar::renderBody(ViewFrustum* renderFrustum, RenderArgs::RenderMode ren clipDistance += headOffset; } } -#endif renderFrustum->setNearClip(clipDistance); } } @@ -1231,13 +1226,11 @@ void MyAvatar::updateOrientation(float deltaTime) { // Gather rotation information from keyboard const float TIME_BETWEEN_HMD_TURNS = 0.5f; const float HMD_TURN_DEGREES = 22.5f; -#if 0 - if (!OculusManager::isConnected()) { + if (!qApp->isHMDMode()) { // Smoothly rotate body with arrow keys if not in HMD _bodyYawDelta -= _driveKeys[ROT_RIGHT] * YAW_SPEED * deltaTime; _bodyYawDelta += _driveKeys[ROT_LEFT] * YAW_SPEED * deltaTime; } else { -#endif // Jump turns if in HMD if (_driveKeys[ROT_RIGHT] || _driveKeys[ROT_LEFT]) { if (_turningKeyPressTime == 0.0f) { @@ -1251,9 +1244,7 @@ void MyAvatar::updateOrientation(float deltaTime) { } else { _turningKeyPressTime = 0.0f; } -#if 0 } -#endif getHead()->setBasePitch(getHead()->getBasePitch() + (_driveKeys[ROT_UP] - _driveKeys[ROT_DOWN]) * PITCH_SPEED * deltaTime); // update body orientation by movement inputs @@ -1269,30 +1260,23 @@ void MyAvatar::updateOrientation(float deltaTime) { float MINIMUM_ROTATION_RATE = 2.0f; if (fabs(_bodyYawDelta) < MINIMUM_ROTATION_RATE) { _bodyYawDelta = 0.0f; } -#if 0 - if (OculusManager::isConnected()) { + if (qApp->isHMDMode()) { // these angles will be in radians - float yaw, pitch, roll; - OculusManager::getEulerAngles(yaw, pitch, roll); + glm::quat orientation = qApp->getHeadOrientation(); // ... so they need to be converted to degrees before we do math... - yaw *= DEGREES_PER_RADIAN; - pitch *= DEGREES_PER_RADIAN; - roll *= DEGREES_PER_RADIAN; - + glm::vec3 euler = glm::eulerAngles(orientation) * DEGREES_PER_RADIAN; + //Invert yaw and roll when in mirror mode - Head* head = getHead(); if (Application::getInstance()->getCamera()->getMode() == CAMERA_MODE_MIRROR) { - head->setBaseYaw(-yaw); - head->setBasePitch(pitch); - head->setBaseRoll(-roll); - } else { - head->setBaseYaw(yaw); - head->setBasePitch(pitch); - head->setBaseRoll(roll); + YAW(euler) *= -1.0; + ROLL(euler) *= -1.0; } + Head* head = getHead(); + head->setBaseYaw(YAW(euler)); + head->setBasePitch(PITCH(euler)); + head->setBaseRoll(ROLL(euler)); } -#endif } glm::vec3 MyAvatar::applyKeyboardMotor(float deltaTime, const glm::vec3& localVelocity, bool isHovering) { diff --git a/interface/src/plugins/PluginManager.h b/interface/src/plugins/PluginManager.h index 96cb777235..2d8ab9a9f4 100644 --- a/interface/src/plugins/PluginManager.h +++ b/interface/src/plugins/PluginManager.h @@ -1,12 +1,12 @@ #pragma once #include "plugins/Plugin.h" -#include "plugins/render/RenderPlugin.h" +#include "plugins/render/DisplayPlugin.h" #include #include class PluginManager : public QObject { public: static PluginManager * getInstance(); - const QList> getRenderPlugins(); + const QList> getDisplayPlugins(); }; diff --git a/interface/src/plugins/render/RenderPlugin.cpp b/interface/src/plugins/render/DisplayPlugin.cpp similarity index 82% rename from interface/src/plugins/render/RenderPlugin.cpp rename to interface/src/plugins/render/DisplayPlugin.cpp index 11052aca11..d9d649019f 100644 --- a/interface/src/plugins/render/RenderPlugin.cpp +++ b/interface/src/plugins/render/DisplayPlugin.cpp @@ -1,5 +1,5 @@ // -// RenderPlugin.cpp +// DisplayPlugin.cpp // // Created by Bradley Austin Davis on 2014/04/13. // Copyright 2015 High Fidelity, Inc. @@ -7,9 +7,9 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "RenderPlugin.h" +#include "DisplayPlugin.h" -bool RenderPlugin::isMouseOnScreen() const { +bool DisplayPlugin::isMouseOnScreen() const { glm::ivec2 mousePosition = getTrueMousePosition(); return (glm::all(glm::greaterThanEqual(mousePosition, glm::ivec2(0))) && glm::all(glm::lessThanEqual(mousePosition, glm::ivec2(getCanvasSize())))); diff --git a/interface/src/plugins/render/RenderPlugin.h b/interface/src/plugins/render/DisplayPlugin.h similarity index 97% rename from interface/src/plugins/render/RenderPlugin.h rename to interface/src/plugins/render/DisplayPlugin.h index 6a8328ee48..399f12b244 100644 --- a/interface/src/plugins/render/RenderPlugin.h +++ b/interface/src/plugins/render/DisplayPlugin.h @@ -1,5 +1,5 @@ // -// RenderPlugin.h +// DisplayPlugin.h // // Created by Bradley Austin Davis on 2014/04/13. // Copyright 2015 High Fidelity, Inc. @@ -19,7 +19,7 @@ #include #include -class RenderPlugin : public Plugin { +class DisplayPlugin : public Plugin { Q_OBJECT public: virtual bool isHmd() const { return false; } diff --git a/interface/src/plugins/render/HmdRenderPlugin.cpp b/interface/src/plugins/render/HmdDisplayPlugin.cpp similarity index 81% rename from interface/src/plugins/render/HmdRenderPlugin.cpp rename to interface/src/plugins/render/HmdDisplayPlugin.cpp index eb2efcc8a8..bfe4a088fa 100644 --- a/interface/src/plugins/render/HmdRenderPlugin.cpp +++ b/interface/src/plugins/render/HmdDisplayPlugin.cpp @@ -1,5 +1,5 @@ // -// HmdRenderPlugin.cpp +// HmdDisplayPlugin.cpp // // Created by Bradley Austin Davis on 2014/04/13. // Copyright 2015 High Fidelity, Inc. @@ -8,4 +8,4 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "HmdRenderPlugin.h" +#include "HmdDisplayPlugin.h" diff --git a/interface/src/plugins/render/HmdRenderPlugin.h b/interface/src/plugins/render/HmdDisplayPlugin.h similarity index 74% rename from interface/src/plugins/render/HmdRenderPlugin.h rename to interface/src/plugins/render/HmdDisplayPlugin.h index aa158a1f52..1156bafcda 100644 --- a/interface/src/plugins/render/HmdRenderPlugin.h +++ b/interface/src/plugins/render/HmdDisplayPlugin.h @@ -1,5 +1,5 @@ // -// HmdRenderPlugin.h +// HmdDisplayPlugin.h // // Created by Bradley Austin Davis on 2014/04/13. // Copyright 2015 High Fidelity, Inc. @@ -8,8 +8,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #pragma once -#include "StereoRenderPlugin.h" +#include "StereoDisplayPlugin.h" -class HmdRenderPlugin : public StereoRenderPlugin { +class HmdDisplayPlugin : public StereoDisplayPlugin { virtual bool isHmd() const final { return true; } }; diff --git a/interface/src/plugins/render/LegacyRenderPlugin.cpp b/interface/src/plugins/render/LegacyDisplayPlugin.cpp similarity index 71% rename from interface/src/plugins/render/LegacyRenderPlugin.cpp rename to interface/src/plugins/render/LegacyDisplayPlugin.cpp index 93170517b3..79cc433543 100644 --- a/interface/src/plugins/render/LegacyRenderPlugin.cpp +++ b/interface/src/plugins/render/LegacyDisplayPlugin.cpp @@ -1,5 +1,5 @@ // -// LegacyRenderPlugin.cpp +// LegacyDisplayPlugin.cpp // // Created by Bradley Austin Davis on 2014/04/13. // Copyright 2015 High Fidelity, Inc. @@ -8,19 +8,19 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #include "Application.h" -#include "LegacyRenderPlugin.h" +#include "LegacyDisplayPlugin.h" #include "MainWindow.h" #include -const QString LegacyRenderPlugin::NAME("LegacyRenderPlugin"); +const QString LegacyDisplayPlugin::NAME("2D Monitor (GL Windgets)"); -const QString & LegacyRenderPlugin::getName() { +const QString & LegacyDisplayPlugin::getName() { return NAME; } static QWidget * oldWidget = nullptr; -void LegacyRenderPlugin::activate() { +void LegacyDisplayPlugin::activate() { _window = new GLCanvas(); QGLFormat format(QGL::NoDepthBuffer | QGL::NoStencilBuffer); _window->setContext(new QGLContext(format), @@ -37,7 +37,7 @@ void LegacyRenderPlugin::activate() { _window->installEventFilter(DependencyManager::get().data()); } -void LegacyRenderPlugin::deactivate() { +void LegacyDisplayPlugin::deactivate() { _window->removeEventFilter(DependencyManager::get().data()); _window->removeEventFilter(qApp); qApp->getWindow()->setCentralWidget(oldWidget); @@ -48,38 +48,38 @@ void LegacyRenderPlugin::deactivate() { _window = nullptr; } -QSize LegacyRenderPlugin::getRecommendedFramebufferSize() const { +QSize LegacyDisplayPlugin::getRecommendedFramebufferSize() const { return _window->getDeviceSize(); } -void LegacyRenderPlugin::makeCurrent() { +void LegacyDisplayPlugin::makeCurrent() { _window->makeCurrent(); QSize windowSize = _window->size(); glViewport(0, 0, windowSize.width(), windowSize.height()); } -void LegacyRenderPlugin::doneCurrent() { +void LegacyDisplayPlugin::doneCurrent() { _window->doneCurrent(); } -void LegacyRenderPlugin::swapBuffers() { +void LegacyDisplayPlugin::swapBuffers() { _window->swapBuffers(); glFinish(); } -void LegacyRenderPlugin::idle() { +void LegacyDisplayPlugin::idle() { _window->updateGL(); } -glm::ivec2 LegacyRenderPlugin::getCanvasSize() const { +glm::ivec2 LegacyDisplayPlugin::getCanvasSize() const { return toGlm(_window->size()); } -bool LegacyRenderPlugin::hasFocus() const { +bool LegacyDisplayPlugin::hasFocus() const { return _window->hasFocus(); } -PickRay LegacyRenderPlugin::computePickRay(const glm::vec2 & pos) const { +PickRay LegacyDisplayPlugin::computePickRay(const glm::vec2 & pos) const { return PickRay(); } @@ -87,6 +87,6 @@ bool isMouseOnScreen() { return false; } -bool LegacyRenderPlugin::isThrottled() { +bool LegacyDisplayPlugin::isThrottled() { return _window->isThrottleRendering(); } \ No newline at end of file diff --git a/interface/src/plugins/render/LegacyRenderPlugin.h b/interface/src/plugins/render/LegacyDisplayPlugin.h similarity index 87% rename from interface/src/plugins/render/LegacyRenderPlugin.h rename to interface/src/plugins/render/LegacyDisplayPlugin.h index 68161f6c7d..9654278dcd 100644 --- a/interface/src/plugins/render/LegacyRenderPlugin.h +++ b/interface/src/plugins/render/LegacyDisplayPlugin.h @@ -1,5 +1,5 @@ // -// LegacyRenderPlugin.h +// LegacyDisplayPlugin.h // // Created by Bradley Austin Davis on 2014/04/13. // Copyright 2015 High Fidelity, Inc. @@ -9,10 +9,10 @@ // #pragma once -#include "SimpleRenderPlugin.h" +#include "SimpleDisplayPlugin.h" #include "GLCanvas.h" -class LegacyRenderPlugin : public SimpleRenderPlugin { +class LegacyDisplayPlugin : public SimpleDisplayPlugin { Q_OBJECT public: static const QString NAME; diff --git a/interface/src/plugins/render/NullDisplayPlugin.cpp b/interface/src/plugins/render/NullDisplayPlugin.cpp new file mode 100644 index 0000000000..97683a1100 --- /dev/null +++ b/interface/src/plugins/render/NullDisplayPlugin.cpp @@ -0,0 +1,44 @@ +// +// NullDisplayPlugin.cpp +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "NullDisplayPlugin.h" + +const QString NullDisplayPlugin::NAME("NullDisplayPlugin"); + +const QString & NullDisplayPlugin::getName() { + return NAME; +} + +QSize NullDisplayPlugin::getRecommendedFramebufferSize() const { + return QSize(100, 100); +} + +glm::ivec2 NullDisplayPlugin::getCanvasSize() const { + return glm::ivec2(100, 100); +} + +bool NullDisplayPlugin::hasFocus() const { + return false; +} + +glm::ivec2 NullDisplayPlugin::getRelativeMousePosition() const { + return glm::ivec2(); +} + +glm::ivec2 NullDisplayPlugin::getTrueMousePosition() const { + return glm::ivec2(); +} + +PickRay NullDisplayPlugin::computePickRay(const glm::vec2 & pos) const { + return PickRay(); +} + +bool NullDisplayPlugin::isMouseOnScreen() { + return false; +} diff --git a/interface/src/plugins/render/NullRenderPlugin.h b/interface/src/plugins/render/NullDisplayPlugin.h similarity index 83% rename from interface/src/plugins/render/NullRenderPlugin.h rename to interface/src/plugins/render/NullDisplayPlugin.h index dfe0e5a0bf..c434ddd3f5 100644 --- a/interface/src/plugins/render/NullRenderPlugin.h +++ b/interface/src/plugins/render/NullDisplayPlugin.h @@ -1,5 +1,5 @@ // -// NullRenderPlugin.h +// NullDisplayPlugin.h // // Created by Bradley Austin Davis on 2014/04/13. // Copyright 2015 High Fidelity, Inc. @@ -9,13 +9,13 @@ // #pragma once -#include "RenderPlugin.h" +#include "DisplayPlugin.h" -class NullRenderPlugin : public RenderPlugin { +class NullDisplayPlugin : public DisplayPlugin { public: static const QString NAME; - virtual ~NullRenderPlugin() final {} + virtual ~NullDisplayPlugin() final {} virtual const QString & getName(); virtual QSize getRecommendedFramebufferSize() const; diff --git a/interface/src/plugins/render/NullRenderPlugin.cpp b/interface/src/plugins/render/NullRenderPlugin.cpp deleted file mode 100644 index f2221a5767..0000000000 --- a/interface/src/plugins/render/NullRenderPlugin.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// -// NullRenderPlugin.cpp -// -// Created by Bradley Austin Davis on 2014/04/13. -// 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 "NullRenderPlugin.h" - -const QString NullRenderPlugin::NAME("NullRenderPlugin"); - -const QString & NullRenderPlugin::getName() { - return NAME; -} - -QSize NullRenderPlugin::getRecommendedFramebufferSize() const { - return QSize(100, 100); -} - -glm::ivec2 NullRenderPlugin::getCanvasSize() const { - return glm::ivec2(100, 100); -} - -bool NullRenderPlugin::hasFocus() const { - return false; -} - -glm::ivec2 NullRenderPlugin::getRelativeMousePosition() const { - return glm::ivec2(); -} - -glm::ivec2 NullRenderPlugin::getTrueMousePosition() const { - return glm::ivec2(); -} - -PickRay NullRenderPlugin::computePickRay(const glm::vec2 & pos) const { - return PickRay(); -} - -bool NullRenderPlugin::isMouseOnScreen() { - return false; -} diff --git a/interface/src/plugins/render/OculusBaseRenderPlugin.cpp b/interface/src/plugins/render/OculusBaseDisplayPlugin.cpp similarity index 84% rename from interface/src/plugins/render/OculusBaseRenderPlugin.cpp rename to interface/src/plugins/render/OculusBaseDisplayPlugin.cpp index fd1bdfb6af..2d423424eb 100644 --- a/interface/src/plugins/render/OculusBaseRenderPlugin.cpp +++ b/interface/src/plugins/render/OculusBaseDisplayPlugin.cpp @@ -1,5 +1,5 @@ // -// OculusBaseRenderPlugin.cpp +// OculusBaseDisplayPlugin.cpp // // Created by Bradley Austin Davis on 2014/04/13. // Copyright 2015 High Fidelity, Inc. @@ -7,23 +7,23 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "OculusBaseRenderPlugin.h" +#include "OculusBaseDisplayPlugin.h" #include -bool OculusBaseRenderPlugin::sdkInitialized = false; +bool OculusBaseDisplayPlugin::sdkInitialized = false; -bool OculusBaseRenderPlugin::enableSdk() { +bool OculusBaseDisplayPlugin::enableSdk() { sdkInitialized = ovr_Initialize(); return sdkInitialized; } -void OculusBaseRenderPlugin::disableSdk() { +void OculusBaseDisplayPlugin::disableSdk() { ovr_Shutdown(); sdkInitialized = false; } -void OculusBaseRenderPlugin::withSdkActive(std::function f) { +void OculusBaseDisplayPlugin::withSdkActive(std::function f) { bool activateSdk = !sdkInitialized; if (activateSdk && !enableSdk()) { return; @@ -34,7 +34,7 @@ void OculusBaseRenderPlugin::withSdkActive(std::function f) { } } -bool OculusBaseRenderPlugin::isSupported() { +bool OculusBaseDisplayPlugin::isSupported() { bool attached = false; withSdkActive([&] { attached = ovrHmd_Detect(); @@ -42,11 +42,11 @@ bool OculusBaseRenderPlugin::isSupported() { return attached; } -void OculusBaseRenderPlugin::activate() { +void OculusBaseDisplayPlugin::activate() { enableSdk(); } -void OculusBaseRenderPlugin::deactivate() { +void OculusBaseDisplayPlugin::deactivate() { disableSdk(); } diff --git a/interface/src/plugins/render/OculusBaseRenderPlugin.h b/interface/src/plugins/render/OculusBaseDisplayPlugin.h similarity index 88% rename from interface/src/plugins/render/OculusBaseRenderPlugin.h rename to interface/src/plugins/render/OculusBaseDisplayPlugin.h index aa937bf12a..7eb0a42a19 100644 --- a/interface/src/plugins/render/OculusBaseRenderPlugin.h +++ b/interface/src/plugins/render/OculusBaseDisplayPlugin.h @@ -1,5 +1,5 @@ // -// OculusBaseRenderPlugin.h +// OculusBaseDisplayPlugin.h // // Created by Bradley Austin Davis on 2014/04/13. // Copyright 2015 High Fidelity, Inc. @@ -9,10 +9,10 @@ // #pragma once -#include "HmdRenderPlugin.h" +#include "HmdDisplayPlugin.h" #include -class OculusBaseRenderPlugin : public HmdRenderPlugin { +class OculusBaseDisplayPlugin : public HmdDisplayPlugin { public: virtual bool isSupported(); diff --git a/interface/src/plugins/render/OculusExtendedRenderPlugin.cpp b/interface/src/plugins/render/OculusDirectD3DDisplayPlugin.cpp similarity index 75% rename from interface/src/plugins/render/OculusExtendedRenderPlugin.cpp rename to interface/src/plugins/render/OculusDirectD3DDisplayPlugin.cpp index 5ed0c5cacf..ec1b9a1986 100644 --- a/interface/src/plugins/render/OculusExtendedRenderPlugin.cpp +++ b/interface/src/plugins/render/OculusDirectD3DDisplayPlugin.cpp @@ -1,5 +1,5 @@ // -// OculusExtendedRenderPlugin.cpp +// OculusDirectD3DDisplayPlugin.cpp // // Created by Bradley Austin Davis on 2014/04/13. // Copyright 2015 High Fidelity, Inc. @@ -7,4 +7,4 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "OculusExtendedRenderPlugin.h" +#include "OculusDirectD3DDisplayPlugin.h" diff --git a/interface/src/plugins/render/OculusDirectD3DRenderPlugin.h b/interface/src/plugins/render/OculusDirectD3DDisplayPlugin.h similarity index 78% rename from interface/src/plugins/render/OculusDirectD3DRenderPlugin.h rename to interface/src/plugins/render/OculusDirectD3DDisplayPlugin.h index 3874481e69..531e779a3b 100644 --- a/interface/src/plugins/render/OculusDirectD3DRenderPlugin.h +++ b/interface/src/plugins/render/OculusDirectD3DDisplayPlugin.h @@ -1,5 +1,5 @@ // -// OculusDirectD3DRenderPlugin.h +// OculusDirectD3DDisplayPlugin.h // // Created by Bradley Austin Davis on 2014/04/13. // Copyright 2015 High Fidelity, Inc. @@ -9,4 +9,4 @@ // #pragma once -#include "OculusBaseRenderPlugin.h" +#include "OculusBaseDisplayPlugin.h" diff --git a/interface/src/plugins/render/OculusDirectRenderPlugin.cpp b/interface/src/plugins/render/OculusDirectDisplayPlugin.cpp similarity index 77% rename from interface/src/plugins/render/OculusDirectRenderPlugin.cpp rename to interface/src/plugins/render/OculusDirectDisplayPlugin.cpp index cd96ff0fad..569597f2cc 100644 --- a/interface/src/plugins/render/OculusDirectRenderPlugin.cpp +++ b/interface/src/plugins/render/OculusDirectDisplayPlugin.cpp @@ -1,5 +1,5 @@ // -// OculusDirectRenderPlugin.cpp +// OculusDirectDisplayPlugin.cpp // // Created by Bradley Austin Davis on 2014/04/13. // Copyright 2015 High Fidelity, Inc. @@ -7,4 +7,4 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "OculusDirectRenderPlugin.h" +#include "OculusDirectDisplayPlugin.h" diff --git a/interface/src/plugins/render/OculusDirectRenderPlugin.h b/interface/src/plugins/render/OculusDirectDisplayPlugin.h similarity index 79% rename from interface/src/plugins/render/OculusDirectRenderPlugin.h rename to interface/src/plugins/render/OculusDirectDisplayPlugin.h index afa72cb92e..5f3fc911c7 100644 --- a/interface/src/plugins/render/OculusDirectRenderPlugin.h +++ b/interface/src/plugins/render/OculusDirectDisplayPlugin.h @@ -1,5 +1,5 @@ // -// OculusDirectRenderPlugin.h +// OculusDirectDisplayPlugin.h // // Created by Bradley Austin Davis on 2014/04/13. // Copyright 2015 High Fidelity, Inc. @@ -9,4 +9,4 @@ // #pragma once -#include "OculusBaseRenderPlugin.h" +#include "OculusBaseDisplayPlugin.h" diff --git a/interface/src/plugins/render/OculusDirectD3DRenderPlugin.cpp b/interface/src/plugins/render/OculusExtendedDisplayPlugin.cpp similarity index 76% rename from interface/src/plugins/render/OculusDirectD3DRenderPlugin.cpp rename to interface/src/plugins/render/OculusExtendedDisplayPlugin.cpp index fab4fd104f..cbef7d11f3 100644 --- a/interface/src/plugins/render/OculusDirectD3DRenderPlugin.cpp +++ b/interface/src/plugins/render/OculusExtendedDisplayPlugin.cpp @@ -1,5 +1,5 @@ // -// OculusDirectD3DRenderPlugin.cpp +// OculusExtendedDisplayPlugin.cpp // // Created by Bradley Austin Davis on 2014/04/13. // Copyright 2015 High Fidelity, Inc. @@ -7,4 +7,4 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "OculusDirectD3DRenderPlugin.h" +#include "OculusExtendedDisplayPlugin.h" diff --git a/interface/src/plugins/render/OculusExtendedRenderPlugin.h b/interface/src/plugins/render/OculusExtendedDisplayPlugin.h similarity index 78% rename from interface/src/plugins/render/OculusExtendedRenderPlugin.h rename to interface/src/plugins/render/OculusExtendedDisplayPlugin.h index a9e9a51f0c..674a79bd5a 100644 --- a/interface/src/plugins/render/OculusExtendedRenderPlugin.h +++ b/interface/src/plugins/render/OculusExtendedDisplayPlugin.h @@ -1,5 +1,5 @@ // -// OculusExtendedRenderPlugin.h +// OculusExtendedDisplayPlugin.h // // Created by Bradley Austin Davis on 2014/04/13. // Copyright 2015 High Fidelity, Inc. @@ -9,4 +9,4 @@ // #pragma once -#include "OculusBaseRenderPlugin.h" +#include "OculusBaseDisplayPlugin.h" diff --git a/interface/src/plugins/render/SimpleRenderPlugin.cpp b/interface/src/plugins/render/SimpleDisplayPlugin.cpp similarity index 82% rename from interface/src/plugins/render/SimpleRenderPlugin.cpp rename to interface/src/plugins/render/SimpleDisplayPlugin.cpp index 40c80f48d6..d68a32b1ea 100644 --- a/interface/src/plugins/render/SimpleRenderPlugin.cpp +++ b/interface/src/plugins/render/SimpleDisplayPlugin.cpp @@ -1,5 +1,5 @@ // -// SimpleRenderPlugin.cpp +// SimpleDisplayPlugin.cpp // // Created by Bradley Austin Davis on 2014/04/13. // Copyright 2015 High Fidelity, Inc. @@ -7,7 +7,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 "SimpleRenderPlugin.h" +#include "SimpleDisplayPlugin.h" #include #include diff --git a/interface/src/plugins/render/SimpleRenderPlugin.h b/interface/src/plugins/render/SimpleDisplayPlugin.h similarity index 92% rename from interface/src/plugins/render/SimpleRenderPlugin.h rename to interface/src/plugins/render/SimpleDisplayPlugin.h index 8a8ee7edd4..55ce69b323 100644 --- a/interface/src/plugins/render/SimpleRenderPlugin.h +++ b/interface/src/plugins/render/SimpleDisplayPlugin.h @@ -1,5 +1,5 @@ // -// SimpleRenderPlugin.h +// SimpleDisplayPlugin.h // // Created by Bradley Austin Davis on 2014/04/13. // Copyright 2015 High Fidelity, Inc. @@ -9,13 +9,13 @@ // #pragma once -#include "RenderPlugin.h" +#include "DisplayPlugin.h" #include #include #include template -class SimpleRenderPlugin : public RenderPlugin { +class SimpleDisplayPlugin : public DisplayPlugin { public: virtual void render(int finalSceneTexture) { makeCurrent(); diff --git a/interface/src/plugins/render/StereoRenderPlugin.cpp b/interface/src/plugins/render/StereoDisplayPlugin.cpp similarity index 80% rename from interface/src/plugins/render/StereoRenderPlugin.cpp rename to interface/src/plugins/render/StereoDisplayPlugin.cpp index 705133dcc4..25070a4967 100644 --- a/interface/src/plugins/render/StereoRenderPlugin.cpp +++ b/interface/src/plugins/render/StereoDisplayPlugin.cpp @@ -1,5 +1,5 @@ // -// StereoRenderPlugin.cpp +// StereoDisplayPlugin.cpp // // Created by Bradley Austin Davis on 2014/04/13. // Copyright 2015 High Fidelity, Inc. @@ -7,4 +7,4 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "StereoRenderPlugin.h" +#include "StereoDisplayPlugin.h" diff --git a/interface/src/plugins/render/StereoRenderPlugin.h b/interface/src/plugins/render/StereoDisplayPlugin.h similarity index 75% rename from interface/src/plugins/render/StereoRenderPlugin.h rename to interface/src/plugins/render/StereoDisplayPlugin.h index 69504e2ccf..e3944ff878 100644 --- a/interface/src/plugins/render/StereoRenderPlugin.h +++ b/interface/src/plugins/render/StereoDisplayPlugin.h @@ -1,5 +1,5 @@ // -// StereoRenderPlugin.h +// StereoDisplayPlugin.h // // Created by Bradley Austin Davis on 2014/04/13. // Copyright 2015 High Fidelity, Inc. @@ -9,9 +9,9 @@ // #pragma once -#include "RenderPlugin.h" +#include "DisplayPlugin.h" -class StereoRenderPlugin : public RenderPlugin { +class StereoDisplayPlugin : public DisplayPlugin { virtual bool isStereo() const final { return true; } }; diff --git a/interface/src/plugins/render/Tv3dRenderPlugin.cpp b/interface/src/plugins/render/Tv3dDisplayPlugin.cpp similarity index 77% rename from interface/src/plugins/render/Tv3dRenderPlugin.cpp rename to interface/src/plugins/render/Tv3dDisplayPlugin.cpp index 750d1a1743..b86e20831f 100644 --- a/interface/src/plugins/render/Tv3dRenderPlugin.cpp +++ b/interface/src/plugins/render/Tv3dDisplayPlugin.cpp @@ -1,5 +1,5 @@ // -// Tv3dRenderPlugin.cpp +// Tv3dDisplayPlugin.cpp // // Created by Bradley Austin Davis on 2014/04/13. // Copyright 2015 High Fidelity, Inc. @@ -8,16 +8,16 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "Tv3dRenderPlugin.h" +#include "Tv3dDisplayPlugin.h" -const QString Tv3dRenderPlugin::NAME("Tv3dRenderPlugin"); +const QString Tv3dDisplayPlugin::NAME("Tv3dDisplayPlugin"); -const QString & Tv3dRenderPlugin::getName() { +const QString & Tv3dDisplayPlugin::getName() { return NAME; } -void Tv3dRenderPlugin::overrideOffAxisFrustum( +void Tv3dDisplayPlugin::overrideOffAxisFrustum( float& left, float& right, float& bottom, float& top, float& nearVal, float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const { diff --git a/interface/src/plugins/render/Tv3dRenderPlugin.h b/interface/src/plugins/render/Tv3dDisplayPlugin.h similarity index 83% rename from interface/src/plugins/render/Tv3dRenderPlugin.h rename to interface/src/plugins/render/Tv3dDisplayPlugin.h index ba25526f6c..5c178b7260 100644 --- a/interface/src/plugins/render/Tv3dRenderPlugin.h +++ b/interface/src/plugins/render/Tv3dDisplayPlugin.h @@ -1,5 +1,5 @@ // -// Tv3dRenderPlugin.h +// Tv3dDisplayPlugin.h // // Created by Bradley Austin Davis on 2014/04/13. // Copyright 2015 High Fidelity, Inc. @@ -10,9 +10,9 @@ #pragma once -#include "StereoRenderPlugin.h" +#include "StereoDisplayPlugin.h" -class Tv3dRenderPlugin : public StereoRenderPlugin { +class Tv3dDisplayPlugin : public StereoDisplayPlugin { Q_OBJECT public: static const QString NAME; diff --git a/interface/src/plugins/render/WindowRenderPlugin.cpp b/interface/src/plugins/render/WindowDisplayPlugin.cpp similarity index 95% rename from interface/src/plugins/render/WindowRenderPlugin.cpp rename to interface/src/plugins/render/WindowDisplayPlugin.cpp index 78a0849bba..4c786d9f63 100644 --- a/interface/src/plugins/render/WindowRenderPlugin.cpp +++ b/interface/src/plugins/render/WindowDisplayPlugin.cpp @@ -1,5 +1,5 @@ // -// WindowRenderPlugin.cpp +// WindowDisplayPlugin.cpp // // Created by Bradley Austin Davis on 2014/04/13. // Copyright 2015 High Fidelity, Inc. @@ -7,24 +7,24 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "WindowRenderPlugin.h" +#include "WindowDisplayPlugin.h" #include "RenderUtil.h" #include -WindowRenderPlugin::WindowRenderPlugin() { +WindowDisplayPlugin::WindowDisplayPlugin() { connect(&_timer, &QTimer::timeout, this, [&] { emit requestRender(); }); } -const QString WindowRenderPlugin::NAME("WindowRenderPlugin"); +const QString WindowDisplayPlugin::NAME("WindowDisplayPlugin"); -const QString & WindowRenderPlugin::getName() { +const QString & WindowDisplayPlugin::getName() { return NAME; } -void WindowRenderPlugin::activate() { +void WindowDisplayPlugin::activate() { Q_ASSERT(nullptr == _window); _context = new QOpenGLContext; @@ -52,7 +52,7 @@ void WindowRenderPlugin::activate() { _timer.start(8); } -void WindowRenderPlugin::deactivate() { +void WindowDisplayPlugin::deactivate() { _timer.stop(); _context->doneCurrent(); _context->deleteLater(); @@ -62,7 +62,7 @@ void WindowRenderPlugin::deactivate() { _window = nullptr; } -bool WindowRenderPlugin::eventFilter(QObject* object, QEvent* event) { +bool WindowDisplayPlugin::eventFilter(QObject* object, QEvent* event) { switch (event->type()) { case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: @@ -80,21 +80,21 @@ bool WindowRenderPlugin::eventFilter(QObject* object, QEvent* event) { return false; } -QSize WindowRenderPlugin::getRecommendedFramebufferSize() const { +QSize WindowDisplayPlugin::getRecommendedFramebufferSize() const { return _window->size(); } -void WindowRenderPlugin::makeCurrent() { +void WindowDisplayPlugin::makeCurrent() { _context->makeCurrent(_window); QSize windowSize = _window->size(); glViewport(0, 0, windowSize.width(), windowSize.height()); } -void WindowRenderPlugin::doneCurrent() { +void WindowDisplayPlugin::doneCurrent() { _context->doneCurrent(); } -void WindowRenderPlugin::swapBuffers() { +void WindowDisplayPlugin::swapBuffers() { _context->swapBuffers(_window); } diff --git a/interface/src/plugins/render/WindowRenderPlugin.h b/interface/src/plugins/render/WindowDisplayPlugin.h similarity index 83% rename from interface/src/plugins/render/WindowRenderPlugin.h rename to interface/src/plugins/render/WindowDisplayPlugin.h index ec485e4d6e..9fc28c77d9 100644 --- a/interface/src/plugins/render/WindowRenderPlugin.h +++ b/interface/src/plugins/render/WindowDisplayPlugin.h @@ -1,5 +1,5 @@ // -// WindowRenderPlugin.h +// WindowDisplayPlugin.h // // Created by Bradley Austin Davis on 2014/04/13. // Copyright 2015 High Fidelity, Inc. @@ -9,18 +9,18 @@ // #pragma once -#include "SimpleRenderPlugin.h" +#include "SimpleDisplayPlugin.h" #include #include #include -class WindowRenderPlugin : public SimpleRenderPlugin { +class WindowDisplayPlugin : public SimpleDisplayPlugin { Q_OBJECT public: static const QString NAME; - WindowRenderPlugin(); + WindowDisplayPlugin(); virtual const QString & getName(); diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index adb6492964..81ad9cbc2c 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -27,7 +27,7 @@ #include "Application.h" #include "ApplicationOverlay.h" #include "devices/OculusManager.h" -#include "plugins/render/RenderPlugin.h" +#include "plugins/render/DisplayPlugin.h" #include "Util.h" #include "ui/Stats.h" @@ -478,7 +478,7 @@ QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const { glm::vec3 tipPos = invOrientation * (tip - eyePos); QPoint rv; - if (qApp->getActiveRenderPlugin()->isHmd()) { + if (qApp->isHMDMode()) { float t; //We back the ray up by dir to ensure that it will not start inside the UI. @@ -496,7 +496,7 @@ QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const { float u = asin(collisionPos.x) / (_textureFov)+0.5f; float v = 1.0 - (asin(collisionPos.y) / (_textureFov)+0.5f); - auto size = qApp->getActiveRenderPlugin()->getCanvasSize(); + auto size = qApp->getCanvasSize(); rv.setX(u * size.x); rv.setY(v * size.y); @@ -553,8 +553,8 @@ void ApplicationOverlay::renderPointers() { glActiveTexture(GL_TEXTURE0); _crosshairTexture->bind(); - if (qApp->getActiveRenderPlugin()->isHmd() && !qApp->getLastMouseMoveWasSimulated() && !qApp->isMouseHidden()) { - glm::ivec2 trueMouse = qApp->getActiveRenderPlugin()->getTrueMousePosition(); + if (qApp->isHMDMode() && !qApp->getLastMouseMoveWasSimulated() && !qApp->isMouseHidden()) { + glm::ivec2 trueMouse = qApp->getTrueMousePosition(); //If we are in oculus, render reticle later if (_lastMouseMove == 0) { _lastMouseMove = usecTimestampNow(); @@ -966,7 +966,7 @@ void ApplicationOverlay::renderStatsAndLogs() { (Menu::getInstance()->isOptionChecked(MenuOption::Stats)) ? 80 : 20; - auto size = qApp->getActiveRenderPlugin()->getCanvasSize(); + auto size = qApp->getCanvasSize(); // auto glCanvas = Application::getInstance()->getGLWidget(); drawText(size.x - 100, size.y - timerBottom, 0.30f, 0.0f, 0, frameTimer.toUtf8().constData(), WHITE_TEXT); diff --git a/libraries/script-engine/src/MenuItemProperties.cpp b/libraries/script-engine/src/MenuItemProperties.cpp index 97fbdef1fa..48670e314d 100644 --- a/libraries/script-engine/src/MenuItemProperties.cpp +++ b/libraries/script-engine/src/MenuItemProperties.cpp @@ -23,7 +23,8 @@ MenuItemProperties::MenuItemProperties() : beforeItem(""), afterItem(""), isCheckable(false), - isChecked(false) + isChecked(false), + isSeparator(false) { }; @@ -38,7 +39,8 @@ MenuItemProperties::MenuItemProperties(const QString& menuName, const QString& m beforeItem(""), afterItem(""), isCheckable(checkable), - isChecked(checked) + isChecked(checked), + isSeparator(false) { } @@ -53,7 +55,8 @@ MenuItemProperties::MenuItemProperties(const QString& menuName, const QString& m beforeItem(""), afterItem(""), isCheckable(checkable), - isChecked(checked) + isChecked(checked), + isSeparator(false) { } diff --git a/libraries/shared/src/GLMHelpers.h b/libraries/shared/src/GLMHelpers.h index a710ba759b..a06f6f26cf 100644 --- a/libraries/shared/src/GLMHelpers.h +++ b/libraries/shared/src/GLMHelpers.h @@ -117,4 +117,8 @@ QMatrix4x4 fromGlm(const glm::mat4 & m); QRectF glmToRect(const glm::vec2 & pos, const glm::vec2 & size); +#define YAW(euler) euler.y +#define PITCH(euler) euler.x +#define ROLL(euler) euler.z + #endif // hifi_GLMHelpers_h From 0d509ceeea27946032cd0c4e08464f5e2bdf532b Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Wed, 6 May 2015 15:07:31 -0700 Subject: [PATCH 006/552] Working on merging --- interface/src/Application.h | 12 +++-- interface/src/plugins/render/DisplayPlugin.h | 6 +-- interface/src/ui/ApplicationOverlay.cpp | 52 ++++++++++---------- 3 files changed, 37 insertions(+), 33 deletions(-) diff --git a/interface/src/Application.h b/interface/src/Application.h index 6f42d82b54..84231f1bd5 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -221,15 +221,19 @@ public: const glm::vec3& getMouseRayOrigin() const { return _mouseRayOrigin; } const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; } bool mouseOnScreen() const; + glm::ivec2 getMouse(); int getMouseX() const; int getMouseY() const; glm::ivec2 getTrueMousePosition() const; - int getTrueMouseX() const; - int getTrueMouseY() const; + int getTrueMouseX() const { return getTrueMousePosition().x; } + int getTrueMouseY() const { return getTrueMousePosition().y; } int getMouseDragStartedX() const; int getMouseDragStartedY() const; - int getTrueMouseDragStartedX() const { return _mouseDragStartedX; } - int getTrueMouseDragStartedY() const { return _mouseDragStartedY; } + const glm::ivec2 & getTrueMouseDragStarted() const { return _mouseDragStarted; } + int getTrueMouseDragStartedX() const { return getTrueMouseDragStarted().x; } + int getTrueMouseDragStartedY() const { return getTrueMouseDragStarted().y; } + + bool getLastMouseMoveWasSimulated() const { return _lastMouseMoveWasSimulated; } FaceTracker* getActiveFaceTracker(); diff --git a/interface/src/plugins/render/DisplayPlugin.h b/interface/src/plugins/render/DisplayPlugin.h index 399f12b244..a0a409bd7e 100644 --- a/interface/src/plugins/render/DisplayPlugin.h +++ b/interface/src/plugins/render/DisplayPlugin.h @@ -27,9 +27,9 @@ public: virtual bool isThrottled() const { return false; } // Rendering support - virtual void preRender() {}; - virtual void render(int finalSceneTexture) {}; - virtual void postRender() {}; + virtual void preDisplay() {}; + virtual void display(int finalSceneTexture) {}; + virtual void postDisplay() {}; // Pointer support diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index c06f0ff843..89b37bc0cc 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -400,6 +400,7 @@ void ApplicationOverlay::displayOverlayTextureStereo(Camera& whichCamera, float const GLfloat halfQuadWidth = halfQuadHeight * aspectRatio; const GLfloat quadWidth = halfQuadWidth * 2.0f; const GLfloat quadHeight = halfQuadHeight * 2.0f; + vec2 quadSize(quadWidth, quadHeight); GLfloat x = -halfQuadWidth; GLfloat y = -halfQuadHeight; @@ -426,15 +427,16 @@ void ApplicationOverlay::displayOverlayTextureStereo(Camera& whichCamera, float const float reticleSize = 40.0f / canvasSize.x * quadWidth; x -= reticleSize / 2.0f; y += reticleSize / 2.0f; - const float mouseX = (qApp->getMouseX() / (float)canvasSize.x) * quadWidth; - const float mouseY = (1.0 - (qApp->getMouseY() / (float)canvasSize.y)) * quadHeight; - + vec2 mouse = qApp->getMouse(); + mouse /= canvasSize; + mouse.y = 1.0 - mouse.y; + mouse *= quadSize; glm::vec4 reticleColor = { RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2], 1.0f }; - DependencyManager::get()->renderQuad(glm::vec3(x + mouseX, y + mouseY, -distance), - glm::vec3(x + mouseX + reticleSize, y + mouseY, -distance), - glm::vec3(x + mouseX + reticleSize, y + mouseY - reticleSize, -distance), - glm::vec3(x + mouseX, y + mouseY - reticleSize, -distance), + DependencyManager::get()->renderQuad(glm::vec3(x + mouse.x, y + mouse.y, -distance), + glm::vec3(x + mouse.x + reticleSize, y + mouse.y, -distance), + glm::vec3(x + mouse.x + reticleSize, y + mouse.y - reticleSize, -distance), + glm::vec3(x + mouse.x, y + mouse.y - reticleSize, -distance), glm::vec2(0.0f, 0.0f), glm::vec2(1.0f, 0.0f), glm::vec2(1.0f, 1.0f), glm::vec2(0.0f, 1.0f), reticleColor, _reticleQuad); @@ -465,7 +467,6 @@ void ApplicationOverlay::computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origi origin = myAvatar->getEyePosition(); direction = cursorDir - origin; } -#endif //Caculate the click location using one of the sixense controllers. Scale is not applied QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const { @@ -495,11 +496,8 @@ QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const { rv.setX(INT_MAX); rv.setY(INT_MAX); } else { - float u = asin(collisionPos.x) / (_textureFov)+0.5f; float v = 1.0 - (asin(collisionPos.y) / (_textureFov)+0.5f); - auto size = qApp->getCanvasSize(); - rv.setX(u * canvasSize.x); rv.setY(v * canvasSize.y); } @@ -559,6 +557,7 @@ void ApplicationOverlay::renderPointers() { if (_lastMouseMove == 0) { _lastMouseMove = usecTimestampNow(); } + auto trueMouse = qApp->getTrueMousePosition(); QPoint position(trueMouse.x, trueMouse.y); static const int MAX_IDLE_TIME = 3; @@ -665,29 +664,30 @@ void ApplicationOverlay::renderControllerPointers() { continue; } - auto canvasSize = qApp->getCanvasSize(); - int mouseX, mouseY; + glm::ivec2 canvasSize = qApp->getCanvasSize(); + glm::ivec2 mouse; if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseLasers)) { QPoint res = getPalmClickLocation(palmData); - mouseX = res.x(); - mouseY = res.y(); + mouse = ivec2(res.x(), res.y()); } else { // Get directon relative to avatar orientation glm::vec3 direction = glm::inverse(myAvatar->getOrientation()) * palmData->getFingerDirection(); - + // Get the angles, scaled between (-0.5,0.5) - float xAngle = (atan2(direction.z, direction.x) + M_PI_2); - float yAngle = 0.5f - ((atan2(direction.z, direction.y) + M_PI_2)); + vec2 angles((atan2(direction.z, direction.x) + M_PI_2), + 0.5f - ((atan2(direction.z, direction.y) + M_PI_2))); // Get the pixel range over which the xAngle and yAngle are scaled float cursorRange = canvasSize.x * SixenseManager::getInstance().getCursorPixelRangeMult(); - - mouseX = (canvasSize.x / 2.0f + cursorRange * xAngle); - mouseY = (canvasSize.y / 2.0f + cursorRange * yAngle); + mouse = canvasSize; + mouse /= 2.0; + mouse += cursorRange * angles; } //If the cursor is out of the screen then don't render it - if (mouseX < 0 || mouseX >= canvasSize.x || mouseY < 0 || mouseY >= canvasSize.y) { + + if (glm::any(glm::lessThan(mouse, canvasSize)) || + glm::any(glm::greaterThanEqual(mouse, canvasSize))) { _reticleActive[index] = false; continue; } @@ -696,12 +696,12 @@ void ApplicationOverlay::renderControllerPointers() { const float reticleSize = 40.0f; - mouseX -= reticleSize / 2.0f; - mouseY += reticleSize / 2.0f; + mouse.x -= reticleSize / 2.0f; + mouse.y += reticleSize / 2.0f; - glm::vec2 topLeft(mouseX, mouseY); - glm::vec2 bottomRight(mouseX + reticleSize, mouseY - reticleSize); + glm::vec2 topLeft(mouse); + glm::vec2 bottomRight(mouse.x + reticleSize, mouse.y - reticleSize); glm::vec2 texCoordTopLeft(0.0f, 0.0f); glm::vec2 texCoordBottomRight(1.0f, 1.0f); From b73ce81a2d3eb4cd811d1fd7a3a48cc01cff8645 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Wed, 6 May 2015 22:28:34 -0700 Subject: [PATCH 007/552] Working on plugin architecture --- interface/CMakeLists.txt | 6 +- interface/src/Application.cpp | 127 +++++------------- interface/src/Application.h | 21 +-- interface/src/plugins/render/DisplayPlugin.h | 4 +- .../plugins/render/LegacyDisplayPlugin.cpp | 2 +- .../src/plugins/render/LegacyDisplayPlugin.h | 4 +- .../src/plugins/render/NullDisplayPlugin.cpp | 2 +- .../src/plugins/render/NullDisplayPlugin.h | 4 +- 8 files changed, 56 insertions(+), 114 deletions(-) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 9dbed9a6ee..84079dc3b4 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -74,8 +74,6 @@ find_package(Qt5 COMPONENTS Gui Multimedia Network OpenGL Qml Quick Script Svg W file (GLOB_RECURSE QT_UI_FILES ui/*.ui) source_group("UI Files" FILES ${QT_UI_FILES}) - - # have qt5 wrap them and generate the appropriate header files qt5_wrap_ui(QT_UI_HEADERS "${QT_UI_FILES}") @@ -138,8 +136,8 @@ target_link_libraries(${TARGET_NAME} ${LIBOVR_LIBRARIES}) add_dependency_external_projects(OpenVR) find_package(OpenVR REQUIRED) -target_include_directories(${TARGET_NAME} PRIVATE ${LIBOVR_INCLUDE_DIRS}) -target_link_libraries(${TARGET_NAME} ${LIBOVR_LIBRARIES}) +target_include_directories(${TARGET_NAME} PRIVATE ${OPENVR_INCLUDE_DIRS}) +target_link_libraries(${TARGET_NAME} ${OPENVR_LIBRARIES}) find_package(Bullet REQUIRED) target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${BULLET_INCLUDE_DIRS}) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 781d4d31ed..6b60c3b437 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -290,7 +290,6 @@ bool setupEssentials(int& argc, char** argv) { Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : QApplication(argc, argv), _dependencyManagerIsSetup(setupEssentials(argc, argv)), - _offscreenContext(new OffscreenGlContext()), _window(new MainWindow(desktop())), _toolWindow(NULL), _friendsWindow(NULL), @@ -319,8 +318,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _cursorVisible(true), _lastMouseMove(usecTimestampNow()), _lastMouseMoveWasSimulated(false), - _touchAvgX(0.0f), - _touchAvgY(0.0f), _isTouchPressed(false), _mousePressed(false), _enableProcessOctreeThread(true), @@ -501,7 +498,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : ResourceCache::setRequestLimit(3); _window->setCentralWidget(new QWidget()); + _window->restoreGeometry(); + _window->setVisible(true); #if 0 @@ -592,7 +591,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : this->installEventFilter(this); // The offscreen UI needs to intercept the mouse and keyboard // events coming from the onscreen window - _glWidget->installEventFilter(DependencyManager::get().data()); + this->installEventFilter(DependencyManager::get().data()); // initialize our face trackers after loading the menu settings auto faceshiftTracker = DependencyManager::get(); @@ -810,18 +809,14 @@ void Application::initializeUi() { void Application::paintGL() { PROFILE_RANGE(__FUNCTION__); - _glWidget->makeCurrent(); + _offscreenContext->makeCurrent(); PerformanceTimer perfTimer("paintGL"); - //Need accurate frame timing for the oculus rift - if (OculusManager::isConnected()) { - OculusManager::beginFrameTiming(); - } + getActiveDisplayPlugin()->preDisplay(); PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings)); bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::paintGL()"); - _offscreenContext->makeCurrent(); QSize fbSize = getActiveDisplayPlugin()->getRecommendedFramebufferSize() * getRenderResolutionScale(); DependencyManager::get()->setFrameBufferSize(fbSize); @@ -888,7 +883,8 @@ void Application::paintGL() { glPopMatrix(); if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) { - _rearMirrorTools->render(true, _glWidget->mapFromGlobal(QCursor::pos())); + glm::vec2 mpos = getActiveDisplayPlugin()->getUiMousePosition(); + _rearMirrorTools->render(true, QPoint(mpos.x, mpos.y)); } else if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { renderRearViewMirror(_mirrorViewRect); } @@ -1460,8 +1456,7 @@ void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { _keyboardMouseDevice.mousePressEvent(event); if (event->button() == Qt::LeftButton) { - _mouseDragStartedX = getTrueMouseX(); - _mouseDragStartedY = getTrueMouseY(); + _mouseDragStarted = getTrueMousePosition(); _mousePressed = true; if (mouseOnScreen()) { @@ -1563,22 +1558,18 @@ void Application::touchUpdateEvent(QTouchEvent* event) { bool validTouch = false; if (activeWindow() == _window) { const QList& tPoints = event->touchPoints(); - _touchAvgX = 0.0f; - _touchAvgY = 0.0f; + _touchAvg = glm::vec2(0); int numTouches = tPoints.count(); if (numTouches > 1) { for (int i = 0; i < numTouches; ++i) { - _touchAvgX += tPoints[i].pos().x(); - _touchAvgY += tPoints[i].pos().y(); + _touchAvg += toGlm(tPoints[i].pos()); } - _touchAvgX /= (float)(numTouches); - _touchAvgY /= (float)(numTouches); + _touchAvg /= numTouches; validTouch = true; } } if (!_isTouchPressed) { - _touchDragStartedAvgX = _touchAvgX; - _touchDragStartedAvgY = _touchAvgY; + _touchDragStartedAvg = _touchAvg; } _isTouchPressed = validTouch; } @@ -1614,8 +1605,7 @@ void Application::touchEndEvent(QTouchEvent* event) { _keyboardMouseDevice.touchEndEvent(event); // put any application specific touch behavior below here.. - _touchDragStartedAvgX = _touchAvgX; - _touchDragStartedAvgY = _touchAvgY; + _touchDragStartedAvg = _touchAvg; _isTouchPressed = false; } @@ -1736,13 +1726,11 @@ void Application::idle() { const float BIGGEST_DELTA_TIME_SECS = 0.25f; update(glm::clamp((float)timeSinceLastUpdate / 1000.0f, 0.0f, BIGGEST_DELTA_TIME_SECS)); } - { PerformanceTimer perfTimer("updateGL"); PerformanceWarning warn(showWarnings, "Application::idle()... updateGL()"); getActiveDisplayPlugin()->idle(); } - { PerformanceTimer perfTimer("rest"); PerformanceWarning warn(showWarnings, "Application::idle()... rest of it"); @@ -1822,15 +1810,12 @@ void Application::setFullscreen(bool fullscreen) { } } - -void Application::setEnable3DTVMode(bool enable3DTVMode) { #if 0 +void Application::setEnable3DTVMode(bool enable3DTVMode) { resizeGL(_glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); -#endif } void Application::setEnableVRMode(bool enableVRMode) { -#if 0 if (Menu::getInstance()->isOptionChecked(MenuOption::EnableVRMode) != enableVRMode) { Menu::getInstance()->getActionForOption(MenuOption::EnableVRMode)->setChecked(enableVRMode); } @@ -1855,8 +1840,8 @@ void Application::setEnableVRMode(bool enableVRMode) { resizeGL(_glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); updateCursorVisibility(); -#endif } +#endif void Application::setLowVelocityFilter(bool lowVelocityFilter) { SixenseManager::getInstance().setLowVelocityFilter(lowVelocityFilter); @@ -1875,16 +1860,15 @@ int Application::getMouseY() const { } ivec2 Application::getMouseDragStarted() const { - return getActiveDisplaylugin()->trueMouseToUiMouse( - glm::ivec2(getTrueMouseDragStartedX(), getTrueMouseDragStartedY())); + return getActiveDisplayPlugin()->trueMouseToUiMouse(getTrueMouseDragStarted()); } int Application::getMouseDragStartedX() const { - return getMouseDragStarted().x; + return getMouseDragStarted().x; } int Application::getMouseDragStartedY() const { - return getMouseDragStarted().y; + return getMouseDragStarted().y; } FaceTracker* Application::getActiveFaceTracker() { @@ -2221,9 +2205,8 @@ void Application::updateMyAvatarLookAtPosition() { bool isLookingAtSomeone = false; glm::vec3 lookAtSpot; if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { -#if 0 // When I am in mirror mode, just look right at the camera (myself) - if (!OculusManager::isConnected()) { + if (!isHMDMode()) { lookAtSpot = _myCamera.getPosition(); } else { if (_myAvatar->isLookingAtLeftEye()) { @@ -2232,7 +2215,7 @@ void Application::updateMyAvatarLookAtPosition() { lookAtSpot = OculusManager::getRightEyePosition(); } } -#endif + } else { AvatarSharedPointer lookingAt = _myAvatar->getLookAtTargetAvatar().toStrongRef(); if (lookingAt && _myAvatar != lookingAt.data()) { @@ -3190,12 +3173,12 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs _stars.render(theCamera.getFieldOfView(), theCamera.getAspectRatio(), theCamera.getNearClip(), alpha); } - // draw the sky dome - if (!selfAvatarOnly && Menu::getInstance()->isOptionChecked(MenuOption::Atmosphere)) { - PerformanceTimer perfTimer("atmosphere"); - PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), - "Application::displaySide() ... atmosphere..."); - _environment.renderAtmospheres(theCamera); + // draw the sky dome + if (!selfAvatarOnly && Menu::getInstance()->isOptionChecked(MenuOption::Atmosphere)) { + PerformanceTimer perfTimer("atmosphere"); + PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), + "Application::displaySide() ... atmosphere..."); + _environment.renderAtmospheres(theCamera); } } @@ -3444,7 +3427,8 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) { glPopMatrix(); if (!billboard) { - _rearMirrorTools->render(false, _glWidget->mapFromGlobal(QCursor::pos())); + glm::vec2 mpos = getActiveDisplayPlugin()->getUiMousePosition(); + _rearMirrorTools->render(false, QPoint(mpos.x, mpos.y)); } // reset Viewport and projection matrix @@ -4320,6 +4304,7 @@ void Application::skipVersion(QString latestVersion) { } void Application::takeSnapshot() { +#if 0 QMediaPlayer* player = new QMediaPlayer(); QFileInfo inf = QFileInfo(PathUtils::resourcesPath() + "sounds/snap.wav"); player->setMedia(QUrl::fromLocalFile(inf.absoluteFilePath())); @@ -4336,6 +4321,8 @@ void Application::takeSnapshot() { _snapshotShareDialog = new SnapshotShareDialog(fileName, desktop()); } _snapshotShareDialog->show(); +#endif + } void Application::setVSyncEnabled() { @@ -4524,7 +4511,7 @@ glm::uvec2 Application::getCanvasSize() const { } QSize Application::getDeviceSize() const { - return getActiveDisplayPlugin()->getRecommendedFramebufferSize(); // _glWidget->getDeviceSize(); + return getActiveDisplayPlugin()->getDeviceSize(); } void Application::resizeGL() { @@ -4544,21 +4531,15 @@ glm::vec2 Application::getViewportDimensions() const { glm::ivec2 Application::getTrueMousePosition() const { return getActiveDisplayPlugin()->getTrueMousePosition(); } + glm::quat Application::getHeadOrientation() const { return getActiveDisplayPlugin()->headOrientation(); } + glm::vec3 Application::getHeadPosition() const { return getActiveDisplayPlugin()->headTranslation(); } -int Application::getTrueMouseX() const { - return getActiveDisplayPlugin()->getTrueMousePosition().x; -} - -int Application::getTrueMouseY() const { - return getActiveDisplayPlugin()->getTrueMousePosition().y; -} - bool Application::isThrottleRendering() const { return getActiveDisplayPlugin()->isThrottled(); } @@ -4659,43 +4640,3 @@ void Application::initPlugins() { void Application::shutdownPlugins() { OculusManager::deinit(); } - -glm::vec3 Application::getHeadPosition() const { - return OculusManager::getRelativePosition(); -} - -glm::quat Application::getHeadOrientation() const { - return OculusManager::getOrientation(); -} - -glm::uvec2 Application::getCanvasSize() const { - return glm::uvec2(_glWidget->width(), _glWidget->height()); -} - -QSize Application::getDeviceSize() const { - return _glWidget->getDeviceSize(); -} - -int Application::getTrueMouseX() const { - return _glWidget->mapFromGlobal(QCursor::pos()).x(); -} - -int Application::getTrueMouseY() const { - return _glWidget->mapFromGlobal(QCursor::pos()).y(); -} - -bool Application::isThrottleRendering() const { - return _glWidget->isThrottleRendering(); -} - -PickRay Application::computePickRay() const { - return computePickRay(getTrueMouseX(), getTrueMouseY()); -} - -bool Application::hasFocus() const { - return _glWidget->hasFocus(); -} - -void Application::resizeGL() { - this->resizeGL(_glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); -} diff --git a/interface/src/Application.h b/interface/src/Application.h index 84231f1bd5..990ccdbd6a 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -40,7 +40,6 @@ #include #include - #include "AudioClient.h" #include "Bookmarks.h" #include "Camera.h" @@ -221,14 +220,19 @@ public: const glm::vec3& getMouseRayOrigin() const { return _mouseRayOrigin; } const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; } bool mouseOnScreen() const; - glm::ivec2 getMouse(); - int getMouseX() const; - int getMouseY() const; + + glm::ivec2 getMouse() const; + int getMouseX() const { return getMouse().x; } + int getMouseY() const { return getMouse().y; } + glm::ivec2 getTrueMousePosition() const; int getTrueMouseX() const { return getTrueMousePosition().x; } int getTrueMouseY() const { return getTrueMousePosition().y; } + + glm::ivec2 getMouseDragStarted() const; int getMouseDragStartedX() const; int getMouseDragStartedY() const; + const glm::ivec2 & getTrueMouseDragStarted() const { return _mouseDragStarted; } int getTrueMouseDragStartedX() const { return getTrueMouseDragStarted().x; } int getTrueMouseDragStartedY() const { return getTrueMouseDragStarted().y; } @@ -586,18 +590,15 @@ private: Environment _environment; bool _cursorVisible; - int _mouseDragStartedX; - int _mouseDragStartedY; + glm::ivec2 _mouseDragStarted; quint64 _lastMouseMove; bool _lastMouseMoveWasSimulated; glm::vec3 _mouseRayOrigin; glm::vec3 _mouseRayDirection; - float _touchAvgX; - float _touchAvgY; - float _touchDragStartedAvgX; - float _touchDragStartedAvgY; + glm::vec2 _touchAvg; + glm::vec2 _touchDragStartedAvg; bool _isTouchPressed; // true if multitouch has been pressed (clear when finished) bool _mousePressed; // true if mouse has been pressed (clear when finished) diff --git a/interface/src/plugins/render/DisplayPlugin.h b/interface/src/plugins/render/DisplayPlugin.h index a0a409bd7e..3c1f710354 100644 --- a/interface/src/plugins/render/DisplayPlugin.h +++ b/interface/src/plugins/render/DisplayPlugin.h @@ -36,7 +36,9 @@ public: // Does the rendering surface have current focus? virtual bool hasFocus() const = 0; // The size of the rendering surface - virtual QSize getRecommendedFramebufferSize() const = 0; + virtual QSize getDeviceSize() const = 0; + // The size of the rendering target (may be larger than the device size due to distortion) + virtual QSize getRecommendedFramebufferSize() const { return getDeviceSize(); }; // The size of the window (differs from the framebuffers size in instances like Retina macs) virtual glm::ivec2 getCanvasSize() const = 0; diff --git a/interface/src/plugins/render/LegacyDisplayPlugin.cpp b/interface/src/plugins/render/LegacyDisplayPlugin.cpp index 79cc433543..30c42d29c3 100644 --- a/interface/src/plugins/render/LegacyDisplayPlugin.cpp +++ b/interface/src/plugins/render/LegacyDisplayPlugin.cpp @@ -48,7 +48,7 @@ void LegacyDisplayPlugin::deactivate() { _window = nullptr; } -QSize LegacyDisplayPlugin::getRecommendedFramebufferSize() const { +QSize LegacyDisplayPlugin::getDeviceSize() const { return _window->getDeviceSize(); } diff --git a/interface/src/plugins/render/LegacyDisplayPlugin.h b/interface/src/plugins/render/LegacyDisplayPlugin.h index 9654278dcd..2565554297 100644 --- a/interface/src/plugins/render/LegacyDisplayPlugin.h +++ b/interface/src/plugins/render/LegacyDisplayPlugin.h @@ -21,12 +21,12 @@ public: virtual void activate(); virtual void deactivate(); - virtual QSize getRecommendedFramebufferSize() const; + virtual QSize getDeviceSize() const; virtual glm::ivec2 getCanvasSize() const; virtual bool hasFocus() const; virtual PickRay computePickRay(const glm::vec2 & pos) const; virtual bool isMouseOnScreen() const { return true; } - virtual bool isThrottled(); + virtual bool isThrottled() const; protected: virtual void makeCurrent(); diff --git a/interface/src/plugins/render/NullDisplayPlugin.cpp b/interface/src/plugins/render/NullDisplayPlugin.cpp index 97683a1100..0bd964f34b 100644 --- a/interface/src/plugins/render/NullDisplayPlugin.cpp +++ b/interface/src/plugins/render/NullDisplayPlugin.cpp @@ -15,7 +15,7 @@ const QString & NullDisplayPlugin::getName() { return NAME; } -QSize NullDisplayPlugin::getRecommendedFramebufferSize() const { +QSize NullDisplayPlugin::getDeviceSize() const { return QSize(100, 100); } diff --git a/interface/src/plugins/render/NullDisplayPlugin.h b/interface/src/plugins/render/NullDisplayPlugin.h index c434ddd3f5..47f5dc7288 100644 --- a/interface/src/plugins/render/NullDisplayPlugin.h +++ b/interface/src/plugins/render/NullDisplayPlugin.h @@ -18,12 +18,12 @@ public: virtual ~NullDisplayPlugin() final {} virtual const QString & getName(); - virtual QSize getRecommendedFramebufferSize() const; + 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(); + virtual bool isMouseOnScreen() const; }; From 5e821b44470ad14ca020361df5efa19d7afb5e11 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Thu, 7 May 2015 17:40:39 -0700 Subject: [PATCH 008/552] Updating plugins --- cmake/externals/openvr/CMakeLists.txt | 8 +- interface/src/Application.cpp | 95 +++-- interface/src/Application.h | 3 - interface/src/GLCanvas.cpp | 1 - interface/src/devices/OculusManager.h | 2 + interface/src/devices/SixenseManager.cpp | 3 +- interface/src/devices/TV3DManager.cpp | 5 +- interface/src/plugins/render/DisplayPlugin.h | 21 +- .../plugins/render/LegacyDisplayPlugin.cpp | 30 +- .../src/plugins/render/LegacyDisplayPlugin.h | 1 + .../src/plugins/render/NullDisplayPlugin.cpp | 2 +- .../src/plugins/render/NullDisplayPlugin.h | 3 + .../render/OculusDirectD3DDisplayPlugin.cpp | 10 - .../render/OculusDirectD3DDisplayPlugin.h | 12 - .../render/OculusDirectDisplayPlugin.cpp | 10 - .../render/OculusDirectDisplayPlugin.h | 12 - ...playPlugin.cpp => OculusDisplayPlugin.cpp} | 52 ++- ...eDisplayPlugin.h => OculusDisplayPlugin.h} | 12 +- .../render/OculusExtendedDisplayPlugin.cpp | 10 - .../render/OculusExtendedDisplayPlugin.h | 12 - .../plugins/render/SimpleDisplayPlugin.cpp | 77 +++- .../src/plugins/render/SimpleDisplayPlugin.h | 42 +-- interface/src/ui/ApplicationOverlay.cpp | 73 +++- interface/src/ui/ApplicationOverlay.h | 47 +-- interface/src/ui/DialogsManager.cpp | 1 - interface/src/ui/DialogsManager.h | 2 - interface/src/ui/HMDToolsDialog.cpp | 347 ------------------ interface/src/ui/HMDToolsDialog.h | 89 ----- interface/src/ui/PreferencesDialog.cpp | 8 +- interface/src/ui/overlays/Overlays.cpp | 1 - .../src/DeferredLightingEffect.cpp | 102 ++--- 31 files changed, 322 insertions(+), 771 deletions(-) delete mode 100644 interface/src/plugins/render/OculusDirectD3DDisplayPlugin.cpp delete mode 100644 interface/src/plugins/render/OculusDirectD3DDisplayPlugin.h delete mode 100644 interface/src/plugins/render/OculusDirectDisplayPlugin.cpp delete mode 100644 interface/src/plugins/render/OculusDirectDisplayPlugin.h rename interface/src/plugins/render/{OculusBaseDisplayPlugin.cpp => OculusDisplayPlugin.cpp} (69%) rename interface/src/plugins/render/{OculusBaseDisplayPlugin.h => OculusDisplayPlugin.h} (71%) delete mode 100644 interface/src/plugins/render/OculusExtendedDisplayPlugin.cpp delete mode 100644 interface/src/plugins/render/OculusExtendedDisplayPlugin.h delete mode 100644 interface/src/ui/HMDToolsDialog.cpp delete mode 100644 interface/src/ui/HMDToolsDialog.h diff --git a/cmake/externals/openvr/CMakeLists.txt b/cmake/externals/openvr/CMakeLists.txt index c5b15f4ea3..b5cd477c02 100644 --- a/cmake/externals/openvr/CMakeLists.txt +++ b/cmake/externals/openvr/CMakeLists.txt @@ -17,22 +17,22 @@ ExternalProject_Add( ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) -set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/openvr-0.9.0/headers CACHE TYPE INTERNAL) +set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/headers CACHE TYPE INTERNAL) if (WIN32) # FIXME need to account for different architectures - set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/openvr-0.9.0/lib/win32/openvr_api.lib CACHE TYPE INTERNAL) + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/lib/win32/openvr_api.lib CACHE TYPE INTERNAL) elseif(APPLE) # FIXME need to account for different architectures - set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/openvr-0.9.0/lib/osx32/libopenvr_api.dylib CACHE TYPE INTERNAL) + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/lib/osx32/libopenvr_api.dylib CACHE TYPE INTERNAL) elseif(NOT ANDROID) # FIXME need to account for different architectures - set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/openvr-0.9.0/lib/linux32/libopenvr_api.so CACHE TYPE INTERNAL) + set(${EXTERNAL_NAME_UPPER}_LIBRARIES ${SOURCE_DIR}/lib/linux32/libopenvr_api.so CACHE TYPE INTERNAL) endif() diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0b98fdae6b..8f47962b24 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -109,8 +109,6 @@ #include "devices/Leapmotion.h" #include "devices/RealSense.h" #include "devices/MIDIManager.h" -#include "devices/OculusManager.h" -#include "devices/TV3DManager.h" #include "gpu/Batch.h" #include "gpu/GLBackend.h" @@ -589,9 +587,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : #endif this->installEventFilter(this); - // The offscreen UI needs to intercept the mouse and keyboard - // events coming from the onscreen window - this->installEventFilter(DependencyManager::get().data()); // initialize our face trackers after loading the menu settings auto faceshiftTracker = DependencyManager::get(); @@ -808,14 +803,18 @@ void Application::initializeUi() { void Application::paintGL() { PROFILE_RANGE(__FUNCTION__); - _offscreenContext->makeCurrent(); + auto displayPlugin = getActiveDisplayPlugin(); + displayPlugin->preRender(); PerformanceTimer perfTimer("paintGL"); - getActiveDisplayPlugin()->preDisplay(); + + _offscreenContext->makeCurrent(); + Q_ASSERT(_offscreenContext->getContext() == QOpenGLContext::currentContext()); PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings)); bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::paintGL()"); resizeGL(); + Q_ASSERT(_offscreenContext->getContext() == QOpenGLContext::currentContext()); glEnable(GL_LINE_SMOOTH); @@ -850,9 +849,10 @@ void Application::paintGL() { (_myAvatar->getOrientation() * glm::quat(glm::vec3(0.0f, _rotateMirror, 0.0f))) * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_FULLSCREEN_DISTANCE * _scaleMirror); } + Q_ASSERT(_offscreenContext->getContext() == QOpenGLContext::currentContext()); // Update camera position - if (!OculusManager::isConnected()) { + if (!isHMDMode()) { _myCamera.update(1.0f / _fps); } @@ -887,19 +887,9 @@ void Application::paintGL() { } finalFbo = DependencyManager::get()->render(); - - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - glBindFramebuffer(GL_READ_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(finalFbo)); - glBlitFramebuffer(0, 0, _renderResolution.x, _renderResolution.y, - 0, 0, _glWidget->getDeviceSize().width(), _glWidget->getDeviceSize().height(), - GL_COLOR_BUFFER_BIT, GL_NEAREST); - { PerformanceTimer perfTimer("renderOverlay"); _applicationOverlay.renderOverlay(); - glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(finalFbo)); - _applicationOverlay.displayOverlayTexture(); - glBindFramebuffer(GL_FRAMEBUFFER, 0); } } @@ -909,9 +899,14 @@ void Application::paintGL() { // but may be better handled with a fence object glFinish(); + _offscreenContext->doneCurrent(); Q_ASSERT(!QOpenGLContext::currentContext()); - getActiveDisplayPlugin()->display(gpu::GLBackend::getTextureID(finalFbo->getRenderBuffer(0))); + displayPlugin->preDisplay(); + + displayPlugin->display(gpu::GLBackend::getTextureID(finalFbo->getRenderBuffer(0)), finalFbo->getSize(), + _applicationOverlay.getOverlayTexture(), getCanvasSize()); + displayPlugin->finishFrame(); Q_ASSERT(!QOpenGLContext::currentContext()); _offscreenContext->makeCurrent(); _frameCount++; @@ -944,32 +939,32 @@ void Application::showEditEntitiesHelp() { } void Application::resetCamerasOnResizeGL(Camera& camera, const glm::uvec2& size) { +#if 0 if (OculusManager::isConnected()) { OculusManager::configureCamera(camera, size.x, size.y); } else if (TV3DManager::isConnected()) { TV3DManager::configureCamera(camera, size.x, size.y); } else { - camera.setAspectRatio(aspect(size)); +#endif + camera.setAspectRatio(aspect(size)); camera.setFieldOfView(_fieldOfView.get()); +#if 0 } +#endif } void Application::resizeEvent(QResizeEvent * event) { - const QSize & newSize = event->size(); - resizeGL(newSize.width(), newSize.height()); + resizeGL(); } void Application::resizeGL() { // Set the desired FBO texture size. If it hasn't changed, this does nothing. // Otherwise, it must rebuild the FBOs - QSize renderSize; - if (OculusManager::isConnected()) { - renderSize = OculusManager::getRenderTargetSize(); - } else { - renderSize = _glWidget->getDeviceSize() * getRenderResolutionScale(); - } + QSize framebufferSize = getActiveDisplayPlugin()->getRecommendedFramebufferSize(); + QSize renderSize = framebufferSize * getRenderResolutionScale(); + if (_renderResolution == toGlm(renderSize)) { - return; + return; } _renderResolution = toGlm(renderSize); @@ -981,10 +976,9 @@ void Application::resizeGL() { updateProjectionMatrix(); glLoadIdentity(); - auto canvasSize = getActiveDisplayPlugin()->getCanvasSize(); auto offscreenUi = DependencyManager::get(); - offscreenUi->resize(fromGlm(canvasSize)); - _glWidget->makeCurrent(); + offscreenUi->resize(fromGlm(getCanvasSize())); + _offscreenContext->makeCurrent(); // update Stats width // let's set horizontal offset to give stats some margin to mirror @@ -1865,14 +1859,6 @@ bool Application::mouseOnScreen() const { return getActiveDisplayPlugin()->isMouseOnScreen(); } -int Application::getMouseX() const { - return getActiveDisplayPlugin()->getUiMousePosition().x; -} - -int Application::getMouseY() const { - return getActiveDisplayPlugin()->getUiMousePosition().x; -} - ivec2 Application::getMouseDragStarted() const { return getActiveDisplayPlugin()->trueMouseToUiMouse(getTrueMouseDragStarted()); } @@ -2050,6 +2036,7 @@ void Application::init() { DependencyManager::get()->toggleLoginDialog(); _environment.init(); + Q_ASSERT(_offscreenContext->getContext() == QOpenGLContext::currentContext()); DependencyManager::get()->init(this); DependencyManager::get()->init(this); @@ -2220,15 +2207,17 @@ void Application::updateMyAvatarLookAtPosition() { glm::vec3 lookAtSpot; if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { // When I am in mirror mode, just look right at the camera (myself) - if (!isHMDMode()) { - lookAtSpot = _myCamera.getPosition(); - } else { + lookAtSpot = _myCamera.getPosition(); +#if 0 + // FIXME is this really necessary? + if (isHMDMode()) { if (_myAvatar->isLookingAtLeftEye()) { lookAtSpot = OculusManager::getLeftEyePosition(); } else { lookAtSpot = OculusManager::getRightEyePosition(); } } +#endif } else { AvatarSharedPointer lookingAt = _myAvatar->getLookAtTargetAvatar().toStrongRef(); @@ -3279,6 +3268,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs PROFILE_RANGE("DeferredLighting"); PerformanceTimer perfTimer("lighting"); + Q_ASSERT(_offscreenContext->getContext() == QOpenGLContext::currentContext()); DependencyManager::get()->render(); } @@ -4533,11 +4523,6 @@ QSize Application::getDeviceSize() const { return getActiveDisplayPlugin()->getDeviceSize(); } -void Application::resizeGL() { - auto size = getCanvasSize(); - return resizeGL(size.x, size.y); -} - bool Application::hasFocus() const { return getActiveDisplayPlugin()->hasFocus(); } @@ -4546,7 +4531,6 @@ glm::vec2 Application::getViewportDimensions() const { return toGlm(getDeviceSize()); } - glm::ivec2 Application::getTrueMousePosition() const { return getActiveDisplayPlugin()->getTrueMousePosition(); } @@ -4569,7 +4553,7 @@ using DisplayPluginPointer = QSharedPointer; #include "plugins/render/NullDisplayPlugin.h" #include "plugins/render/WindowDisplayPlugin.h" #include "plugins/render/LegacyDisplayPlugin.h" -#include "plugins/render/OculusDirectD3DDisplayPlugin.h" +#include "plugins/render/OculusDisplayPlugin.h" static DisplayPluginPointer _displayPlugin{ nullptr }; @@ -4610,7 +4594,7 @@ static const DisplayPluginList & getDisplayPlugins() { }); QObject::connect(displayPlugin.data(), &DisplayPlugin::recommendedFramebufferSizeChanged, [](const QSize & size) { DependencyManager::get()->setFrameBufferSize(size * qApp->getRenderResolutionScale()); - qApp->resizeGL(size.width(), size.height()); + qApp->resizeGL(); }); addDisplayPluginToMenu(displayPlugin, true); } @@ -4653,9 +4637,18 @@ void Application::updateDisplayMode() { } void Application::initPlugins() { +#if 0 OculusManager::init(); +#endif } void Application::shutdownPlugins() { +#if 0 OculusManager::deinit(); +#endif } + + +glm::ivec2 Application::getMouse() const { + return getActiveDisplayPlugin()->getUiMousePosition(); +} \ No newline at end of file diff --git a/interface/src/Application.h b/interface/src/Application.h index 0626a8ae43..1eed6140d5 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -57,7 +57,6 @@ #include "scripting/ControllerScriptingInterface.h" #include "scripting/WebWindowClass.h" #include "ui/BandwidthDialog.h" -#include "ui/HMDToolsDialog.h" #include "ui/ModelsBrowser.h" #include "ui/NodeBounds.h" #include "ui/OctreeStatsDialog.h" @@ -453,8 +452,6 @@ private slots: friend class HMDToolsDialog; void setFullscreen(bool fullscreen); - void setEnable3DTVMode(bool enable3DTVMode); - void setEnableVRMode(bool enableVRMode); void cameraMenuChanged(); void closeMirrorView(); diff --git a/interface/src/GLCanvas.cpp b/interface/src/GLCanvas.cpp index 995e1908a9..066ae97ebf 100644 --- a/interface/src/GLCanvas.cpp +++ b/interface/src/GLCanvas.cpp @@ -47,7 +47,6 @@ int GLCanvas::getDeviceHeight() const { } void GLCanvas::initializeGL() { - Application::getInstance()->initializeGL(); setAttribute(Qt::WA_AcceptTouchEvents); setAcceptDrops(true); connect(Application::getInstance(), SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SLOT(activeChanged(Qt::ApplicationState))); diff --git a/interface/src/devices/OculusManager.h b/interface/src/devices/OculusManager.h index e41c6e8f9b..a4b73344a2 100644 --- a/interface/src/devices/OculusManager.h +++ b/interface/src/devices/OculusManager.h @@ -13,6 +13,7 @@ #ifndef hifi_OculusManager_h #define hifi_OculusManager_h +#if 0 #include #include @@ -215,5 +216,6 @@ inline ovrSizei ovrFromGlm(const glm::uvec2 & v) { inline ovrQuatf ovrFromGlm(const glm::quat & q) { return{ q.x, q.y, q.z, q.w }; } +#endif #endif // hifi_OculusManager_h diff --git a/interface/src/devices/SixenseManager.cpp b/interface/src/devices/SixenseManager.cpp index f1a762e64f..9d146b10f2 100644 --- a/interface/src/devices/SixenseManager.cpp +++ b/interface/src/devices/SixenseManager.cpp @@ -487,8 +487,7 @@ void SixenseManager::emulateMouse(PalmData* palm, int index) { triggerButton = Qt::LeftButton; } - if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseLasers) - || Menu::getInstance()->isOptionChecked(MenuOption::EnableVRMode)) { + if (Menu::getInstance()->isOptionChecked(MenuOption::SixenseLasers) || qApp->isHMDMode()) { pos = qApp->getApplicationOverlay().getPalmClickLocation(palm); } else { // Get directon relative to avatar orientation diff --git a/interface/src/devices/TV3DManager.cpp b/interface/src/devices/TV3DManager.cpp index bb715ba6e4..95e3da8375 100644 --- a/interface/src/devices/TV3DManager.cpp +++ b/interface/src/devices/TV3DManager.cpp @@ -130,7 +130,9 @@ void TV3DManager::display(Camera& whichCamera) { eyeCamera.setEyeOffsetPosition(glm::vec3(-_activeEye->modelTranslation,0,0)); Application::getInstance()->displaySide(eyeCamera, false, RenderArgs::MONO); +#if 0 applicationOverlay.displayOverlayTextureStereo(whichCamera, _aspect, fov); +#endif _activeEye = NULL; } glPopMatrix(); @@ -158,8 +160,9 @@ void TV3DManager::display(Camera& whichCamera) { glLoadIdentity(); eyeCamera.setEyeOffsetPosition(glm::vec3(-_activeEye->modelTranslation,0,0)); Application::getInstance()->displaySide(eyeCamera, false, RenderArgs::MONO); - +#if 0 applicationOverlay.displayOverlayTextureStereo(whichCamera, _aspect, fov); +#endif _activeEye = NULL; } glPopMatrix(); diff --git a/interface/src/plugins/render/DisplayPlugin.h b/interface/src/plugins/render/DisplayPlugin.h index 3c1f710354..7229a3dcef 100644 --- a/interface/src/plugins/render/DisplayPlugin.h +++ b/interface/src/plugins/render/DisplayPlugin.h @@ -12,9 +12,11 @@ #include "plugins/Plugin.h" #include - +#include #include +#include "gpu/GPUConfig.h" + #include #include #include @@ -27,11 +29,16 @@ public: virtual bool isThrottled() const { return false; } // Rendering support - virtual void preDisplay() {}; - virtual void display(int finalSceneTexture) {}; - virtual void postDisplay() {}; - - // Pointer support + virtual void preRender() {}; + virtual void preDisplay() { + makeCurrent(); + }; + virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize, + GLuint overlayTexture, const glm::uvec2& overlaySize) = 0; + virtual void finishFrame() { + swapBuffers(); + doneCurrent(); + }; // Does the rendering surface have current focus? virtual bool hasFocus() const = 0; @@ -50,7 +57,7 @@ public: return trueMouseToUiMouse(getTrueMousePosition()); } - virtual std::function getMouseTranslator() { return [](const QPointF& p) { return p; }; }; + virtual std::function getMouseTranslator() { return [](const QPointF& p) { return p; }; }; // Convert from screen mouse coordinates to UI mouse coordinates virtual glm::ivec2 trueMouseToUiMouse(const glm::ivec2 & position) const { return position; }; diff --git a/interface/src/plugins/render/LegacyDisplayPlugin.cpp b/interface/src/plugins/render/LegacyDisplayPlugin.cpp index 30c42d29c3..d5a3b2fc46 100644 --- a/interface/src/plugins/render/LegacyDisplayPlugin.cpp +++ b/interface/src/plugins/render/LegacyDisplayPlugin.cpp @@ -11,6 +11,7 @@ #include "LegacyDisplayPlugin.h" #include "MainWindow.h" #include +#include const QString LegacyDisplayPlugin::NAME("2D Monitor (GL Windgets)"); @@ -22,10 +23,17 @@ static QWidget * oldWidget = nullptr; void LegacyDisplayPlugin::activate() { _window = new GLCanvas(); - QGLFormat format(QGL::NoDepthBuffer | QGL::NoStencilBuffer); - _window->setContext(new QGLContext(format), - QGLContext::fromOpenGLContext(QOpenGLContext::currentContext())); + + QOpenGLContext * sourceContext = QOpenGLContext::currentContext(); + QSurfaceFormat format; + format.setOption(QSurfaceFormat::DebugContext); + QOpenGLContext * newContext = new QOpenGLContext(); + newContext->setFormat(format); + _window->setContext( + QGLContext::fromOpenGLContext(newContext), + QGLContext::fromOpenGLContext(sourceContext)); _window->makeCurrent(); + oldWidget = qApp->getWindow()->centralWidget(); qApp->getWindow()->setCentralWidget(_window); _window->doneCurrent(); @@ -35,12 +43,15 @@ void LegacyDisplayPlugin::activate() { _window->installEventFilter(qApp); _window->installEventFilter(DependencyManager::get().data()); + SimpleDisplayPlugin::activate(); } void LegacyDisplayPlugin::deactivate() { _window->removeEventFilter(DependencyManager::get().data()); _window->removeEventFilter(qApp); - qApp->getWindow()->setCentralWidget(oldWidget); + if (qApp->getWindow()) { + qApp->getWindow()->setCentralWidget(oldWidget); + } // stop the glWidget frame timer so it doesn't call paintGL _window->stopFrameTimer(); _window->doneCurrent(); @@ -54,8 +65,6 @@ QSize LegacyDisplayPlugin::getDeviceSize() const { void LegacyDisplayPlugin::makeCurrent() { _window->makeCurrent(); - QSize windowSize = _window->size(); - glViewport(0, 0, windowSize.width(), windowSize.height()); } void LegacyDisplayPlugin::doneCurrent() { @@ -64,7 +73,6 @@ void LegacyDisplayPlugin::doneCurrent() { void LegacyDisplayPlugin::swapBuffers() { _window->swapBuffers(); - glFinish(); } void LegacyDisplayPlugin::idle() { @@ -87,6 +95,12 @@ bool isMouseOnScreen() { return false; } -bool LegacyDisplayPlugin::isThrottled() { +void LegacyDisplayPlugin::preDisplay() { + SimpleDisplayPlugin::preDisplay(); + auto size = toGlm(_window->size()); + glViewport(0, 0, size.x, size.y); +} + +bool LegacyDisplayPlugin::isThrottled() const { return _window->isThrottleRendering(); } \ No newline at end of file diff --git a/interface/src/plugins/render/LegacyDisplayPlugin.h b/interface/src/plugins/render/LegacyDisplayPlugin.h index 2565554297..481667d3d4 100644 --- a/interface/src/plugins/render/LegacyDisplayPlugin.h +++ b/interface/src/plugins/render/LegacyDisplayPlugin.h @@ -27,6 +27,7 @@ public: virtual PickRay computePickRay(const glm::vec2 & pos) const; virtual bool isMouseOnScreen() const { return true; } virtual bool isThrottled() const; + virtual void preDisplay(); protected: virtual void makeCurrent(); diff --git a/interface/src/plugins/render/NullDisplayPlugin.cpp b/interface/src/plugins/render/NullDisplayPlugin.cpp index 0bd964f34b..9b5ab8ed0a 100644 --- a/interface/src/plugins/render/NullDisplayPlugin.cpp +++ b/interface/src/plugins/render/NullDisplayPlugin.cpp @@ -39,6 +39,6 @@ PickRay NullDisplayPlugin::computePickRay(const glm::vec2 & pos) const { return PickRay(); } -bool NullDisplayPlugin::isMouseOnScreen() { +bool NullDisplayPlugin::isMouseOnScreen() const { return false; } diff --git a/interface/src/plugins/render/NullDisplayPlugin.h b/interface/src/plugins/render/NullDisplayPlugin.h index 47f5dc7288..8a06febb7b 100644 --- a/interface/src/plugins/render/NullDisplayPlugin.h +++ b/interface/src/plugins/render/NullDisplayPlugin.h @@ -26,4 +26,7 @@ public: virtual PickRay computePickRay(const glm::vec2 & pos) const; virtual bool isMouseOnScreen() const; + virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize, + GLuint overlayTexture, const glm::uvec2& overlaySize) {}; + }; diff --git a/interface/src/plugins/render/OculusDirectD3DDisplayPlugin.cpp b/interface/src/plugins/render/OculusDirectD3DDisplayPlugin.cpp deleted file mode 100644 index ec1b9a1986..0000000000 --- a/interface/src/plugins/render/OculusDirectD3DDisplayPlugin.cpp +++ /dev/null @@ -1,10 +0,0 @@ -// -// OculusDirectD3DDisplayPlugin.cpp -// -// Created by Bradley Austin Davis on 2014/04/13. -// 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 "OculusDirectD3DDisplayPlugin.h" diff --git a/interface/src/plugins/render/OculusDirectD3DDisplayPlugin.h b/interface/src/plugins/render/OculusDirectD3DDisplayPlugin.h deleted file mode 100644 index 531e779a3b..0000000000 --- a/interface/src/plugins/render/OculusDirectD3DDisplayPlugin.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// OculusDirectD3DDisplayPlugin.h -// -// Created by Bradley Austin Davis on 2014/04/13. -// 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 "OculusBaseDisplayPlugin.h" diff --git a/interface/src/plugins/render/OculusDirectDisplayPlugin.cpp b/interface/src/plugins/render/OculusDirectDisplayPlugin.cpp deleted file mode 100644 index 569597f2cc..0000000000 --- a/interface/src/plugins/render/OculusDirectDisplayPlugin.cpp +++ /dev/null @@ -1,10 +0,0 @@ -// -// OculusDirectDisplayPlugin.cpp -// -// Created by Bradley Austin Davis on 2014/04/13. -// 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 "OculusDirectDisplayPlugin.h" diff --git a/interface/src/plugins/render/OculusDirectDisplayPlugin.h b/interface/src/plugins/render/OculusDirectDisplayPlugin.h deleted file mode 100644 index 5f3fc911c7..0000000000 --- a/interface/src/plugins/render/OculusDirectDisplayPlugin.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// OculusDirectDisplayPlugin.h -// -// Created by Bradley Austin Davis on 2014/04/13. -// 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 "OculusBaseDisplayPlugin.h" diff --git a/interface/src/plugins/render/OculusBaseDisplayPlugin.cpp b/interface/src/plugins/render/OculusDisplayPlugin.cpp similarity index 69% rename from interface/src/plugins/render/OculusBaseDisplayPlugin.cpp rename to interface/src/plugins/render/OculusDisplayPlugin.cpp index 2d423424eb..d32af59ebf 100644 --- a/interface/src/plugins/render/OculusBaseDisplayPlugin.cpp +++ b/interface/src/plugins/render/OculusDisplayPlugin.cpp @@ -1,5 +1,5 @@ // -// OculusBaseDisplayPlugin.cpp +// OculusDisplayPlugin.cpp // // Created by Bradley Austin Davis on 2014/04/13. // Copyright 2015 High Fidelity, Inc. @@ -7,50 +7,42 @@ // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include "OculusBaseDisplayPlugin.h" +#include "OculusDisplayPlugin.h" #include -bool OculusBaseDisplayPlugin::sdkInitialized = false; - -bool OculusBaseDisplayPlugin::enableSdk() { - sdkInitialized = ovr_Initialize(); - return sdkInitialized; -} - -void OculusBaseDisplayPlugin::disableSdk() { +bool OculusDisplayPlugin::isSupported() { + ovr_Initialize(); + bool result = false; + if (ovrHmd_Detect() != 0) { + result = true; + } ovr_Shutdown(); - sdkInitialized = false; + return result; } -void OculusBaseDisplayPlugin::withSdkActive(std::function f) { - bool activateSdk = !sdkInitialized; - if (activateSdk && !enableSdk()) { - return; - } - f(); - if (activateSdk) { - disableSdk(); - } +void OculusDisplayPlugin::activate() { } -bool OculusBaseDisplayPlugin::isSupported() { - bool attached = false; - withSdkActive([&] { - attached = ovrHmd_Detect(); - }); - return attached; +void OculusDisplayPlugin::deactivate() { } -void OculusBaseDisplayPlugin::activate() { - enableSdk(); +void OculusDisplayPlugin::init() { } -void OculusBaseDisplayPlugin::deactivate() { - disableSdk(); +void OculusDisplayPlugin::deinit() { } +void OculusDisplayPlugin::overrideOffAxisFrustum( + float& left, float& right, float& bottom, float& top, + float& nearVal, float& farVal, + glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const { + +} + + + #if 0 // Set the desired FBO texture size. If it hasn't changed, this does nothing. // Otherwise, it must rebuild the FBOs diff --git a/interface/src/plugins/render/OculusBaseDisplayPlugin.h b/interface/src/plugins/render/OculusDisplayPlugin.h similarity index 71% rename from interface/src/plugins/render/OculusBaseDisplayPlugin.h rename to interface/src/plugins/render/OculusDisplayPlugin.h index 7eb0a42a19..7b846ae569 100644 --- a/interface/src/plugins/render/OculusBaseDisplayPlugin.h +++ b/interface/src/plugins/render/OculusDisplayPlugin.h @@ -12,7 +12,7 @@ #include "HmdDisplayPlugin.h" #include -class OculusBaseDisplayPlugin : public HmdDisplayPlugin { +class OculusDisplayPlugin : public HmdDisplayPlugin { public: virtual bool isSupported(); @@ -27,14 +27,4 @@ public: float& nearVal, float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const; - -protected: - virtual bool isRiftPresent(); - virtual bool isDirectMode(); - - static bool sdkInitialized; - - static void withSdkActive(std::function f); - static bool enableSdk(); - static void disableSdk(); }; diff --git a/interface/src/plugins/render/OculusExtendedDisplayPlugin.cpp b/interface/src/plugins/render/OculusExtendedDisplayPlugin.cpp deleted file mode 100644 index cbef7d11f3..0000000000 --- a/interface/src/plugins/render/OculusExtendedDisplayPlugin.cpp +++ /dev/null @@ -1,10 +0,0 @@ -// -// OculusExtendedDisplayPlugin.cpp -// -// Created by Bradley Austin Davis on 2014/04/13. -// 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 "OculusExtendedDisplayPlugin.h" diff --git a/interface/src/plugins/render/OculusExtendedDisplayPlugin.h b/interface/src/plugins/render/OculusExtendedDisplayPlugin.h deleted file mode 100644 index 674a79bd5a..0000000000 --- a/interface/src/plugins/render/OculusExtendedDisplayPlugin.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// OculusExtendedDisplayPlugin.h -// -// Created by Bradley Austin Davis on 2014/04/13. -// 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 "OculusBaseDisplayPlugin.h" diff --git a/interface/src/plugins/render/SimpleDisplayPlugin.cpp b/interface/src/plugins/render/SimpleDisplayPlugin.cpp index d68a32b1ea..40e0ba4d87 100644 --- a/interface/src/plugins/render/SimpleDisplayPlugin.cpp +++ b/interface/src/plugins/render/SimpleDisplayPlugin.cpp @@ -8,6 +8,81 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // #include "SimpleDisplayPlugin.h" -#include #include +#include +#include +#include "DependencyManager.h" +#include "TextureCache.h" +#include "gpu/GLBackend.h" + + +void SimpleGlDisplayPlugin::activate() { + makeCurrent(); + doneCurrent(); +} + +void SimpleGlDisplayPlugin::display(GLuint sceneTexture, const glm::uvec2& sceneSize, + GLuint overlayTexture, const glm::uvec2& overlaySize) { + makeCurrent(); + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + + glClearColor(0, 0, 0, 1); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glEnable(GL_TEXTURE_2D); + + if (sceneTexture) { + glBindTexture(GL_TEXTURE_2D, sceneTexture); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); + glVertex2f(-1, -1); + glTexCoord2f(1, 0); + glVertex2f(+1, -1); + glTexCoord2f(1, 1); + glVertex2f(+1, +1); + glTexCoord2f(0, 1); + glVertex2f(-1, +1); + glEnd(); + } + + if (overlayTexture) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBindTexture(GL_TEXTURE_2D, overlayTexture); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); + glVertex2f(-1, -1); + glTexCoord2f(1, 0); + glVertex2f(+1, -1); + glTexCoord2f(1, 1); + glVertex2f(+1, +1); + glTexCoord2f(0, 1); + glVertex2f(-1, +1); + glEnd(); + } + + + glDisable(GL_BLEND); + + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_TEXTURE_2D); + Q_ASSERT(!glGetError()); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + glEnable(GL_LIGHTING); + glEnable(GL_DEPTH_TEST); + + glFinish(); + doneCurrent(); +} diff --git a/interface/src/plugins/render/SimpleDisplayPlugin.h b/interface/src/plugins/render/SimpleDisplayPlugin.h index 55ce69b323..aca9366b24 100644 --- a/interface/src/plugins/render/SimpleDisplayPlugin.h +++ b/interface/src/plugins/render/SimpleDisplayPlugin.h @@ -10,43 +10,23 @@ #pragma once #include "DisplayPlugin.h" + +#include + #include #include #include -template -class SimpleDisplayPlugin : public DisplayPlugin { +class SimpleGlDisplayPlugin : public DisplayPlugin { public: - virtual void render(int finalSceneTexture) { - makeCurrent(); - - glDisable(GL_LIGHTING); - glPushMatrix(); - glLoadIdentity(); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - - glEnable(GL_TEXTURE_2D); - glBindTexture(GL_TEXTURE_2D, finalSceneTexture); - renderFullscreenQuad(); - glBindTexture(GL_TEXTURE_2D, 0); - glDisable(GL_TEXTURE_2D); - - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - - glEnable(GL_LIGHTING); - - swapBuffers(); - doneCurrent(); - } - - virtual glm::ivec2 getUiMousePosition() const { - return getTrueMousePosition(); - } + virtual void activate(); + virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize, + GLuint overlayTexture, const glm::uvec2& overlaySize); +}; +template +class SimpleDisplayPlugin : public SimpleGlDisplayPlugin { +public: virtual glm::ivec2 getTrueMousePosition() const { return toGlm(_window->mapFromGlobal(QCursor::pos())); } diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index f6724bb942..62cdf45be7 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -136,12 +136,9 @@ void ApplicationOverlay::renderReticle(glm::quat orientation, float alpha) { } ApplicationOverlay::ApplicationOverlay() : - _textureFov(glm::radians(DEFAULT_HMD_UI_ANGULAR_SIZE)), - _textureAspectRatio(1.0f), _lastMouseMove(0), _magnifier(true), _alpha(1.0f), - _oculusUIRadius(1.0f), _trailingAudioLoudness(0.0f), _crosshairTexture(0), _previousBorderWidth(-1), @@ -184,25 +181,33 @@ ApplicationOverlay::ApplicationOverlay() : ApplicationOverlay::~ApplicationOverlay() { } +GLuint ApplicationOverlay::getOverlayTexture() { + if (!_framebufferObject) { + return 0; + } + return _framebufferObject->texture(); +} + // Renders the overlays either to a texture or to the screen void ApplicationOverlay::renderOverlay() { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()"); Overlays& overlays = qApp->getOverlays(); - _textureFov = glm::radians(_hmdUIAngularSize); - glm::vec2 size = qApp->getCanvasSize(); - _textureAspectRatio = aspect(size); + glm::uvec2 size = qApp->getCanvasSize(); + if (!_framebufferObject || size == toGlm(_framebufferObject->size())) { + if(_framebufferObject) { + delete _framebufferObject; + } + _framebufferObject = new QOpenGLFramebufferObject(QSize(size.x, size.y)); + } - //Handle fading and deactivation/activation of UI - // Render 2D overlay glMatrixMode(GL_PROJECTION); glDisable(GL_DEPTH_TEST); glDisable(GL_LIGHTING); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - _overlays.buildFramebufferObject(); - _overlays.bind(); + _framebufferObject->bind(); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glViewport(0, 0, size.x, size.y); @@ -227,6 +232,32 @@ void ApplicationOverlay::renderOverlay() { renderPointers(); renderDomainConnectionStatusBorder(); + static const glm::vec2 topLeft(-1, 1); + static const glm::vec2 bottomRight(1, -1); + static const glm::vec2 texCoordTopLeft(0.0f, 1.0f); + static const glm::vec2 texCoordBottomRight(1.0f, 0.0f); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + + + glEnable(GL_TEXTURE_2D); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, _newUiTexture); +// glBegin(GL_QUADS); +// glVertex2f(0, 0); +// glVertex2f(1, 0); +// glVertex2f(1, 1); +// glVertex2f(0, 1); +// glEnd(); + DependencyManager::get()->renderQuad( + topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, + glm::vec4(1.0f, 1.0f, 1.0f, _alpha)); + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_TEXTURE_2D); + + + _framebufferObject->bindDefault(); glMatrixMode(GL_PROJECTION); } glPopMatrix(); @@ -235,8 +266,6 @@ void ApplicationOverlay::renderOverlay() { glEnable(GL_DEPTH_TEST); glEnable(GL_LIGHTING); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); - - _overlays.release(); } // A quick and dirty solution for compositing the old overlay @@ -256,7 +285,7 @@ void with_each_texture(GLuint firstPassTexture, GLuint secondPassTexture, F f) { glBindTexture(GL_TEXTURE_2D, 0); glDisable(GL_TEXTURE_2D); } - +#if 0 // Draws the FBO texture for the screen void ApplicationOverlay::displayOverlayTexture() { if (_alpha == 0.0f) { @@ -454,6 +483,8 @@ void ApplicationOverlay::displayOverlayTextureStereo(Camera& whichCamera, float glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); glEnable(GL_LIGHTING); } +#endif + void ApplicationOverlay::computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction) { const MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); @@ -473,7 +504,6 @@ void ApplicationOverlay::computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origi //Caculate the click location using one of the sixense controllers. Scale is not applied QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const { MyAvatar* myAvatar = DependencyManager::get()->getMyAvatar(); - glm::vec3 tip = myAvatar->getLaserPointerTipPosition(palm); glm::vec3 eyePos = myAvatar->getHead()->getEyePosition(); glm::quat invOrientation = glm::inverse(myAvatar->getOrientation()); @@ -482,6 +512,7 @@ QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const { glm::vec3 tipPos = invOrientation * (tip - eyePos); QPoint rv; +#if 0 auto canvasSize = qApp->getCanvasSize(); if (qApp->isHMDMode()) { float t; @@ -521,6 +552,7 @@ QPoint ApplicationOverlay::getPalmClickLocation(const PalmData *palm) const { rv.setX(((ndcSpacePos.x + 1.0) / 2.0) * canvasSize.x); rv.setY((1.0 - ((ndcSpacePos.y + 1.0) / 2.0)) * canvasSize.y); } +#endif return rv; } @@ -534,11 +566,13 @@ bool ApplicationOverlay::calculateRayUICollisionPoint(const glm::vec3& position, glm::vec3 relativeDirection = glm::normalize(inverseOrientation * direction); float t; +#if 0 if (raySphereIntersect(relativeDirection, relativePosition, _oculusUIRadius * myAvatar->getScale(), &t)){ result = position + direction * t; return true; } - +#endif + return false; } @@ -748,6 +782,7 @@ void ApplicationOverlay::renderPointersOculus(const glm::vec3& eyePos) { //Renders a small magnification of the currently bound texture at the coordinates void ApplicationOverlay::renderMagnifier(glm::vec2 magPos, float sizeMult, bool showBorder) { +#if 0 if (!_magnifier) { return; } @@ -813,6 +848,7 @@ void ApplicationOverlay::renderMagnifier(glm::vec2 magPos, float sizeMult, bool magnifierColor, _magnifierQuad); } glPopMatrix(); +#endif } const int AUDIO_METER_GAP = 5; @@ -1023,7 +1059,7 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder() { geometryCache->renderVertices(gpu::LINE_STRIP, _domainStatusBorder); } } - +#if 0 ApplicationOverlay::TexturedHemisphere::TexturedHemisphere() : _vertices(0), _indices(0), @@ -1186,6 +1222,7 @@ void ApplicationOverlay::TexturedHemisphere::render() { GLuint ApplicationOverlay::TexturedHemisphere::getTexture() { return _framebufferObject->texture(); } +#endif glm::vec2 ApplicationOverlay::directionToSpherical(const glm::vec3& direction) { glm::vec2 result; @@ -1230,6 +1267,7 @@ glm::vec2 ApplicationOverlay::sphericalToScreen(const glm::vec2& sphericalPos) { glm::vec2 ApplicationOverlay::sphericalToOverlay(const glm::vec2& sphericalPos) const { glm::vec2 result = sphericalPos; +#if 0 result.x *= -1.0; result /= _textureFov; result.x /= _textureAspectRatio; @@ -1237,16 +1275,19 @@ glm::vec2 ApplicationOverlay::sphericalToOverlay(const glm::vec2& sphericalPos) result.x = (-sphericalPos.x / (_textureFov * _textureAspectRatio) + 0.5f); result.y = (sphericalPos.y / _textureFov + 0.5f); result *= qApp->getCanvasSize(); +#endif return result; } glm::vec2 ApplicationOverlay::overlayToSpherical(const glm::vec2& overlayPos) const { glm::vec2 result = overlayPos; +#if 0 result.x *= -1.0; result /= qApp->getCanvasSize(); result -= 0.5f; result *= _textureFov; result.x *= _textureAspectRatio; +#endif return result; } diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index 71a4876c67..45cf573a0e 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -34,19 +34,14 @@ public: ~ApplicationOverlay(); void renderOverlay(); - void displayOverlayTexture(); - void displayOverlayTextureStereo(Camera& whichCamera, float aspectRatio, float fov); - void displayOverlayTextureHmd(Camera& whichCamera); - + GLuint getOverlayTexture(); + QPoint getPalmClickLocation(const PalmData *palm) const; bool calculateRayUICollisionPoint(const glm::vec3& position, const glm::vec3& direction, glm::vec3& result) const; bool hasMagnifier() const { return _magnifier; } void toggleMagnifier() { _magnifier = !_magnifier; } - float getHmdUIAngularSize() const { return _hmdUIAngularSize; } - void setHmdUIAngularSize(float hmdUIAngularSize) { _hmdUIAngularSize = hmdUIAngularSize; } - // Converter from one frame of reference to another. // Frame of reference: // Direction: Ray that represents the spherical values @@ -67,36 +62,6 @@ public: static void computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction); private: - // Interleaved vertex data - struct TextureVertex { - glm::vec3 position; - glm::vec2 uv; - }; - - typedef QPair VerticesIndices; - class TexturedHemisphere { - public: - TexturedHemisphere(); - ~TexturedHemisphere(); - - void bind(); - void release(); - GLuint getTexture(); - - void buildFramebufferObject(); - void buildVBO(const float fov, const float aspectRatio, const int slices, const int stacks); - void render(); - - private: - void cleanupVBO(); - - GLuint _vertices; - GLuint _indices; - QOpenGLFramebufferObject* _framebufferObject; - VerticesIndices _vbo; - }; - - float _hmdUIAngularSize = DEFAULT_HMD_UI_ANGULAR_SIZE; void renderReticle(glm::quat orientation, float alpha); void renderPointers();; @@ -109,11 +74,6 @@ private: void renderCameraToggle(); void renderStatsAndLogs(); void renderDomainConnectionStatusBorder(); - - TexturedHemisphere _overlays; - - float _textureFov; - float _textureAspectRatio; enum Reticles { MOUSE, LEFT_CONTROLLER, RIGHT_CONTROLLER, NUMBER_OF_RETICLES }; bool _reticleActive[NUMBER_OF_RETICLES]; @@ -124,8 +84,8 @@ private: bool _magnifier; float _alpha = 1.0f; - float _oculusUIRadius; float _trailingAudioLoudness; + QOpenGLFramebufferObject* _framebufferObject{nullptr}; gpu::TexturePointer _crosshairTexture; GLuint _newUiTexture{ 0 }; @@ -145,7 +105,6 @@ private: glm::vec3 _previousMagnifierBottomRight; glm::vec3 _previousMagnifierTopLeft; glm::vec3 _previousMagnifierTopRight; - }; #endif // hifi_ApplicationOverlay_h diff --git a/interface/src/ui/DialogsManager.cpp b/interface/src/ui/DialogsManager.cpp index fe8afc5c0a..0455007ffc 100644 --- a/interface/src/ui/DialogsManager.cpp +++ b/interface/src/ui/DialogsManager.cpp @@ -24,7 +24,6 @@ #include "BandwidthDialog.h" #include "CachesSizeDialog.h" #include "DiskCacheEditor.h" -#include "HMDToolsDialog.h" #include "LodToolsDialog.h" #include "LoginDialog.h" #include "OctreeStatsDialog.h" diff --git a/interface/src/ui/DialogsManager.h b/interface/src/ui/DialogsManager.h index 2c8f77c4c6..83bfc05b6b 100644 --- a/interface/src/ui/DialogsManager.h +++ b/interface/src/ui/DialogsManager.h @@ -17,8 +17,6 @@ #include #include -#include "HMDToolsDialog.h" - class QAction; class AddressBarDialog; diff --git a/interface/src/ui/HMDToolsDialog.cpp b/interface/src/ui/HMDToolsDialog.cpp deleted file mode 100644 index ef2c179eb0..0000000000 --- a/interface/src/ui/HMDToolsDialog.cpp +++ /dev/null @@ -1,347 +0,0 @@ -// -// HMDToolsDialog.cpp -// interface/src/ui -// -// Created by Brad Hefta-Gaub on 7/19/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 -// -#if 0 - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "MainWindow.h" -#include "Menu.h" -#include "ui/DialogsManager.h" -#include "ui/HMDToolsDialog.h" -#include "devices/OculusManager.h" - -HMDToolsDialog::HMDToolsDialog(QWidget* parent) : - QDialog(parent, Qt::Window | Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint) , - _previousScreen(NULL), - _hmdScreen(NULL), - _hmdScreenNumber(-1), - _switchModeButton(NULL), - _debugDetails(NULL), - _previousDialogScreen(NULL), - _inHDMMode(false) -{ - this->setWindowTitle("HMD Tools"); - - // Create layouter - QFormLayout* form = new QFormLayout(); - const int WIDTH = 350; - - // Add a button to enter - _switchModeButton = new QPushButton("Enter HMD Mode"); - _switchModeButton->setFixedWidth(WIDTH); - form->addRow("", _switchModeButton); - connect(_switchModeButton,SIGNAL(clicked(bool)),this,SLOT(switchModeClicked(bool))); - - // Create a label with debug details... - _debugDetails = new QLabel(); - _debugDetails->setText(getDebugDetails()); - const int HEIGHT = 100; - _debugDetails->setFixedSize(WIDTH, HEIGHT); - form->addRow("", _debugDetails); - - this->QDialog::setLayout(form); - - _wasMoved = false; - _previousRect = Application::getInstance()->getWindow()->rect(); - Application::getInstance()->getWindow()->activateWindow(); - - // watch for our application window moving screens. If it does we want to update our screen details - QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); - connect(mainWindow, &QWindow::screenChanged, this, &HMDToolsDialog::applicationWindowScreenChanged); - - // watch for our dialog window moving screens. If it does we want to enforce our rules about - // what screens we're allowed on - watchWindow(windowHandle()); - auto dialogsManager = DependencyManager::get(); - if (Application::getInstance()->getRunningScriptsWidget()) { - watchWindow(Application::getInstance()->getRunningScriptsWidget()->windowHandle()); - } - if (Application::getInstance()->getToolWindow()) { - watchWindow(Application::getInstance()->getToolWindow()->windowHandle()); - } - if (dialogsManager->getBandwidthDialog()) { - watchWindow(dialogsManager->getBandwidthDialog()->windowHandle()); - } - if (dialogsManager->getOctreeStatsDialog()) { - watchWindow(dialogsManager->getOctreeStatsDialog()->windowHandle()); - } - if (dialogsManager->getLodToolsDialog()) { - watchWindow(dialogsManager->getLodToolsDialog()->windowHandle()); - } - - // when the application is about to quit, leave HDM mode - connect(Application::getInstance(), SIGNAL(beforeAboutToQuit()), this, SLOT(aboutToQuit())); - - // keep track of changes to the number of screens - connect(QApplication::desktop(), &QDesktopWidget::screenCountChanged, this, &HMDToolsDialog::screenCountChanged); -} - -HMDToolsDialog::~HMDToolsDialog() { - foreach(HMDWindowWatcher* watcher, _windowWatchers) { - delete watcher; - } - _windowWatchers.clear(); -} - -void HMDToolsDialog::applicationWindowScreenChanged(QScreen* screen) { - _debugDetails->setText(getDebugDetails()); -} - -QString HMDToolsDialog::getDebugDetails() const { - QString results; - - int hmdScreenNumber = OculusManager::getHMDScreen(); - if (hmdScreenNumber >= 0) { - results += "HMD Screen: " + QGuiApplication::screens()[hmdScreenNumber]->name() + "\n"; - } else { - results += "HMD Screen Name: Unknown\n"; - } - - int desktopPrimaryScreenNumber = QApplication::desktop()->primaryScreen(); - QScreen* desktopPrimaryScreen = QGuiApplication::screens()[desktopPrimaryScreenNumber]; - results += "Desktop's Primary Screen: " + desktopPrimaryScreen->name() + "\n"; - - results += "Application Primary Screen: " + QGuiApplication::primaryScreen()->name() + "\n"; - QScreen* mainWindowScreen = Application::getInstance()->getWindow()->windowHandle()->screen(); - results += "Application Main Window Screen: " + mainWindowScreen->name() + "\n"; - results += "Total Screens: " + QString::number(QApplication::desktop()->screenCount()) + "\n"; - - return results; -} - -void HMDToolsDialog::switchModeClicked(bool checked) { - if (!_inHDMMode) { - enterHDMMode(); - } else { - leaveHDMMode(); - } -} - -void HMDToolsDialog::enterHDMMode() { - if (!_inHDMMode) { - _switchModeButton->setText("Leave HMD Mode"); - _debugDetails->setText(getDebugDetails()); - - _hmdScreenNumber = OculusManager::getHMDScreen(); - - if (_hmdScreenNumber >= 0) { - QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); - _hmdScreen = QGuiApplication::screens()[_hmdScreenNumber]; - - _previousRect = Application::getInstance()->getWindow()->rect(); - _previousRect = QRect(mainWindow->mapToGlobal(_previousRect.topLeft()), - mainWindow->mapToGlobal(_previousRect.bottomRight())); - _previousScreen = mainWindow->screen(); - QRect rect = QApplication::desktop()->screenGeometry(_hmdScreenNumber); - mainWindow->setScreen(_hmdScreen); - mainWindow->setGeometry(rect); - - _wasMoved = true; - } - - - // if we're on a single screen setup, then hide our tools window when entering HMD mode - if (QApplication::desktop()->screenCount() == 1) { - close(); - } - - Application::getInstance()->setEnableVRMode(true); - - const int SLIGHT_DELAY = 500; - // If we go to fullscreen immediately, it ends up on the primary monitor, - // even though we've already moved the window. By adding this delay, the - // fullscreen target screen ends up correct. - QTimer::singleShot(SLIGHT_DELAY, this, [&]{ - Application::getInstance()->setFullscreen(true); - activateWindowAfterEnterMode(); - }); - - _inHDMMode = true; - } -} - -void HMDToolsDialog::activateWindowAfterEnterMode() { - Application::getInstance()->getWindow()->activateWindow(); - - // center the cursor on the main application window - centerCursorOnWidget(Application::getInstance()->getWindow()); -} - -void HMDToolsDialog::leaveHDMMode() { - if (_inHDMMode) { - _switchModeButton->setText("Enter HMD Mode"); - _debugDetails->setText(getDebugDetails()); - - Application::getInstance()->setEnableVRMode(false); - Application::getInstance()->setFullscreen(false); - Application::getInstance()->getWindow()->activateWindow(); - - if (_wasMoved) { - QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); - mainWindow->setScreen(_previousScreen); - mainWindow->setGeometry(_previousRect); - - const int SLIGHT_DELAY = 1500; - QTimer::singleShot(SLIGHT_DELAY, this, SLOT(moveWindowAfterLeaveMode())); - } - _wasMoved = false; - _inHDMMode = false; - } -} - -void HMDToolsDialog::moveWindowAfterLeaveMode() { - QWindow* mainWindow = Application::getInstance()->getWindow()->windowHandle(); - mainWindow->setScreen(_previousScreen); - mainWindow->setGeometry(_previousRect); - Application::getInstance()->getWindow()->activateWindow(); - Application::getInstance()->resetSensors(); -} - - -void HMDToolsDialog::reject() { - // Just regularly close upon ESC - close(); -} - -void HMDToolsDialog::closeEvent(QCloseEvent* event) { - // TODO: consider if we want to prevent closing of this window with event->ignore(); - this->QDialog::closeEvent(event); - emit closed(); -} - -void HMDToolsDialog::centerCursorOnWidget(QWidget* widget) { - QWindow* window = widget->windowHandle(); - QScreen* screen = window->screen(); - QPoint windowCenter = window->geometry().center(); - QCursor::setPos(screen, windowCenter); -} - -void HMDToolsDialog::showEvent(QShowEvent* event) { - // center the cursor on the hmd tools dialog - centerCursorOnWidget(this); -} - -void HMDToolsDialog::hideEvent(QHideEvent* event) { - // center the cursor on the main application window - centerCursorOnWidget(Application::getInstance()->getWindow()); -} - - -void HMDToolsDialog::aboutToQuit() { - if (_inHDMMode) { - leaveHDMMode(); - } -} - -void HMDToolsDialog::screenCountChanged(int newCount) { - if (!OculusManager::isConnected()) { - OculusManager::connect(); - } - int hmdScreenNumber = OculusManager::getHMDScreen(); - - if (_inHDMMode && _hmdScreenNumber != hmdScreenNumber) { - qDebug() << "HMD Display changed WHILE IN HMD MODE"; - leaveHDMMode(); - - // if there is a new best HDM screen then go back into HDM mode after done leaving - if (hmdScreenNumber >= 0) { - qDebug() << "Trying to go back into HDM Mode"; - const int SLIGHT_DELAY = 2000; - QTimer::singleShot(SLIGHT_DELAY, this, SLOT(enterHDMMode())); - } - } - _debugDetails->setText(getDebugDetails()); -} - -void HMDToolsDialog::watchWindow(QWindow* window) { - qDebug() << "HMDToolsDialog::watchWindow() window:" << window; - if (window && !_windowWatchers.contains(window)) { - HMDWindowWatcher* watcher = new HMDWindowWatcher(window, this); - _windowWatchers[window] = watcher; - } -} - - -HMDWindowWatcher::HMDWindowWatcher(QWindow* window, HMDToolsDialog* hmdTools) : - _window(window), - _hmdTools(hmdTools), - _previousScreen(NULL) -{ - connect(window, &QWindow::screenChanged, this, &HMDWindowWatcher::windowScreenChanged); - connect(window, &QWindow::xChanged, this, &HMDWindowWatcher::windowGeometryChanged); - connect(window, &QWindow::yChanged, this, &HMDWindowWatcher::windowGeometryChanged); - connect(window, &QWindow::widthChanged, this, &HMDWindowWatcher::windowGeometryChanged); - connect(window, &QWindow::heightChanged, this, &HMDWindowWatcher::windowGeometryChanged); -} - -HMDWindowWatcher::~HMDWindowWatcher() { -} - - -void HMDWindowWatcher::windowGeometryChanged(int arg) { - _previousRect = _window->geometry(); - _previousScreen = _window->screen(); -} - -void HMDWindowWatcher::windowScreenChanged(QScreen* screen) { - // if we have more than one screen, and a known hmdScreen then try to - // keep our dialog off of the hmdScreen - if (QApplication::desktop()->screenCount() > 1) { - - // we want to use a local variable here because we are not necesarily in HMD mode - int hmdScreenNumber = OculusManager::getHMDScreen(); - if (hmdScreenNumber >= 0) { - QScreen* hmdScreen = QGuiApplication::screens()[hmdScreenNumber]; - if (screen == hmdScreen) { - qDebug() << "HMD Tools: Whoa! What are you doing? You don't want to move me to the HMD Screen!"; - - // try to pick a better screen - QScreen* betterScreen = NULL; - - QScreen* lastApplicationScreen = _hmdTools->getLastApplicationScreen(); - QWindow* appWindow = Application::getInstance()->getWindow()->windowHandle(); - QScreen* appScreen = appWindow->screen(); - - if (_previousScreen && _previousScreen != hmdScreen) { - // first, if the previous dialog screen is not the HMD screen, then move it there. - betterScreen = _previousScreen; - } else if (appScreen != hmdScreen) { - // second, if the application screen is not the HMD screen, then move it there. - betterScreen = appScreen; - } else if (lastApplicationScreen && lastApplicationScreen != hmdScreen) { - // third, if the application screen is the HMD screen, we want to move it to - // the previous screen - betterScreen = lastApplicationScreen; - } else { - // last, if we can't use the previous screen the use the primary desktop screen - int desktopPrimaryScreenNumber = QApplication::desktop()->primaryScreen(); - QScreen* desktopPrimaryScreen = QGuiApplication::screens()[desktopPrimaryScreenNumber]; - betterScreen = desktopPrimaryScreen; - } - - if (betterScreen) { - _window->setScreen(betterScreen); - _window->setGeometry(_previousRect); - } - } - } - } -} - -#endif diff --git a/interface/src/ui/HMDToolsDialog.h b/interface/src/ui/HMDToolsDialog.h deleted file mode 100644 index 86bfc7bf1a..0000000000 --- a/interface/src/ui/HMDToolsDialog.h +++ /dev/null @@ -1,89 +0,0 @@ -// -// HMDToolsDialog.h -// interface/src/ui -// -// Created by Brad Hefta-Gaub on 7/19/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 -// - -#ifndef hifi_HMDToolsDialog_h -#define hifi_HMDToolsDialog_h -#if 0 -#include - -class HMDWindowWatcher; - -class HMDToolsDialog : public QDialog { - Q_OBJECT -public: - // Sets up the UI - HMDToolsDialog(QWidget* parent); - ~HMDToolsDialog(); - - QString getDebugDetails() const; - QScreen* getHMDScreen() const { return _hmdScreen; } - QScreen* getLastApplicationScreen() const { return _previousScreen; } - bool hasHMDScreen() const { return _hmdScreenNumber >= -1; } - void watchWindow(QWindow* window); - -signals: - void closed(); - -public slots: - void reject(); - void switchModeClicked(bool checked); - void activateWindowAfterEnterMode(); - void moveWindowAfterLeaveMode(); - void applicationWindowScreenChanged(QScreen* screen); - void aboutToQuit(); - void screenCountChanged(int newCount); - -protected: - virtual void closeEvent(QCloseEvent*); // Emits a 'closed' signal when this dialog is closed. - virtual void showEvent(QShowEvent* event); - virtual void hideEvent(QHideEvent* event); - -private: - void centerCursorOnWidget(QWidget* widget); - void enterHDMMode(); - void leaveHDMMode(); - - bool _wasMoved; - QRect _previousRect; - QScreen* _previousScreen; - QScreen* _hmdScreen; - int _hmdScreenNumber; - QPushButton* _switchModeButton; - QLabel* _debugDetails; - - QRect _previousDialogRect; - QScreen* _previousDialogScreen; - bool _inHDMMode; - - QHash _windowWatchers; -}; - - -class HMDWindowWatcher : public QObject { - Q_OBJECT -public: - // Sets up the UI - HMDWindowWatcher(QWindow* window, HMDToolsDialog* hmdTools); - ~HMDWindowWatcher(); - -public slots: - void windowScreenChanged(QScreen* screen); - void windowGeometryChanged(int arg); - -private: - QWindow* _window; - HMDToolsDialog* _hmdTools; - QRect _previousRect; - QScreen* _previousScreen; -}; -#endif - -#endif // hifi_HMDToolsDialog_h diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index ac436cbb10..20da050a8d 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -169,9 +169,9 @@ void PreferencesDialog::loadPreferences() { ui.avatarScaleSpin->setValue(myAvatar->getScale()); ui.maxOctreePPSSpin->setValue(qApp->getOctreeQuery().getMaxOctreePacketsPerSecond()); - +#if 0 ui.oculusUIAngularSizeSpin->setValue(qApp->getApplicationOverlay().getHmdUIAngularSize()); - +#endif SixenseManager& sixense = SixenseManager::getInstance(); ui.sixenseReticleMoveSpeedSpin->setValue(sixense.getReticleMoveSpeed()); ui.invertSixenseButtonsCheckBox->setChecked(sixense.getInvertButtons()); @@ -229,9 +229,9 @@ void PreferencesDialog::savePreferences() { faceshift->setHostname(ui.faceshiftHostnameEdit->text()); qApp->getOctreeQuery().setMaxOctreePacketsPerSecond(ui.maxOctreePPSSpin->value()); - +#if 0 qApp->getApplicationOverlay().setHmdUIAngularSize(ui.oculusUIAngularSizeSpin->value()); - +#endif SixenseManager& sixense = SixenseManager::getInstance(); sixense.setReticleMoveSpeed(ui.sixenseReticleMoveSpeedSpin->value()); sixense.setInvertButtons(ui.invertSixenseButtonsCheckBox->isChecked()); diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 8f96e63df3..192f782449 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -15,7 +15,6 @@ #include #include -#include #include #include "BillboardOverlay.h" diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index bddb1815bf..324ed69a96 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -268,16 +268,16 @@ void DeferredLightingEffect::render() { program->setUniformValue(locations->ambientSphere + i, *(((QVector4D*) &sh) + i)); } } - - if (locations->lightBufferUnit >= 0) { - gpu::Batch batch; - batch.setUniformBuffer(locations->lightBufferUnit, globalLight->getSchemaBuffer()); - gpu::GLBackend::renderBatch(batch); + + if (locations->lightBufferUnit >= 0) { + gpu::Batch batch; + batch.setUniformBuffer(locations->lightBufferUnit, globalLight->getSchemaBuffer()); + gpu::GLBackend::renderBatch(batch); } if (_atmosphere && (locations->atmosphereBufferUnit >= 0)) { - gpu::Batch batch; - batch.setUniformBuffer(locations->atmosphereBufferUnit, _atmosphere->getDataBuffer()); + gpu::Batch batch; + batch.setUniformBuffer(locations->atmosphereBufferUnit, _atmosphere->getDataBuffer()); gpu::GLBackend::renderBatch(batch); } glUniformMatrix4fv(locations->invViewMat, 1, false, reinterpret_cast< const GLfloat* >(&invViewMat)); @@ -334,11 +334,11 @@ void DeferredLightingEffect::render() { for (auto lightID : _pointLights) { auto light = _allocatedLights[lightID]; - - if (_pointLightLocations.lightBufferUnit >= 0) { - gpu::Batch batch; - batch.setUniformBuffer(_pointLightLocations.lightBufferUnit, light->getSchemaBuffer()); - gpu::GLBackend::renderBatch(batch); + + if (_pointLightLocations.lightBufferUnit >= 0) { + gpu::Batch batch; + batch.setUniformBuffer(_pointLightLocations.lightBufferUnit, light->getSchemaBuffer()); + gpu::GLBackend::renderBatch(batch); } glUniformMatrix4fv(_pointLightLocations.invViewMat, 1, false, reinterpret_cast< const GLfloat* >(&invViewMat)); @@ -380,10 +380,10 @@ void DeferredLightingEffect::render() { for (auto lightID : _spotLights) { auto light = _allocatedLights[lightID]; - if (_spotLightLocations.lightBufferUnit >= 0) { - gpu::Batch batch; - batch.setUniformBuffer(_spotLightLocations.lightBufferUnit, light->getSchemaBuffer()); - gpu::GLBackend::renderBatch(batch); + if (_spotLightLocations.lightBufferUnit >= 0) { + gpu::Batch batch; + batch.setUniformBuffer(_spotLightLocations.lightBufferUnit, light->getSchemaBuffer()); + gpu::GLBackend::renderBatch(batch); } glUniformMatrix4fv(_spotLightLocations.invViewMat, 1, false, reinterpret_cast< const GLfloat* >(&invViewMat)); @@ -482,6 +482,8 @@ void DeferredLightingEffect::render() { } void DeferredLightingEffect::loadLightProgram(const char* fragSource, bool limited, ProgramObject& program, LightLocations& locations) { + qDebug() << (limited ? deferred_light_limited_vert : deferred_light_vert); + qDebug() << fragSource; program.addShaderFromSourceCode(QGLShader::Vertex, (limited ? deferred_light_limited_vert : deferred_light_vert)); program.addShaderFromSourceCode(QGLShader::Fragment, fragSource); program.link(); @@ -502,42 +504,42 @@ void DeferredLightingEffect::loadLightProgram(const char* fragSource, bool limit locations.ambientSphere = program.uniformLocation("ambientSphere.L00"); locations.invViewMat = program.uniformLocation("invViewMat"); - GLint loc = -1; - -#if (GPU_FEATURE_PROFILE == GPU_CORE) - const GLint LIGHT_GPU_SLOT = 3; - loc = glGetUniformBlockIndex(program.programId(), "lightBuffer"); - if (loc >= 0) { - glUniformBlockBinding(program.programId(), loc, LIGHT_GPU_SLOT); - locations.lightBufferUnit = LIGHT_GPU_SLOT; - } else { - locations.lightBufferUnit = -1; - } -#else - loc = program.uniformLocation("lightBuffer"); - if (loc >= 0) { - locations.lightBufferUnit = loc; - } else { - locations.lightBufferUnit = -1; - } + GLint loc = -1; + +#if (GPU_FEATURE_PROFILE == GPU_CORE) + const GLint LIGHT_GPU_SLOT = 3; + loc = glGetUniformBlockIndex(program.programId(), "lightBuffer"); + if (loc >= 0) { + glUniformBlockBinding(program.programId(), loc, LIGHT_GPU_SLOT); + locations.lightBufferUnit = LIGHT_GPU_SLOT; + } else { + locations.lightBufferUnit = -1; + } +#else + loc = program.uniformLocation("lightBuffer"); + if (loc >= 0) { + locations.lightBufferUnit = loc; + } else { + locations.lightBufferUnit = -1; + } #endif -#if (GPU_FEATURE_PROFILE == GPU_CORE) - const GLint ATMOSPHERE_GPU_SLOT = 4; - loc = glGetUniformBlockIndex(program.programId(), "atmosphereBufferUnit"); - if (loc >= 0) { - glUniformBlockBinding(program.programId(), loc, ATMOSPHERE_GPU_SLOT); - locations.atmosphereBufferUnit = ATMOSPHERE_GPU_SLOT; - } else { - locations.atmosphereBufferUnit = -1; - } -#else - loc = program.uniformLocation("atmosphereBufferUnit"); - if (loc >= 0) { - locations.atmosphereBufferUnit = loc; - } else { - locations.atmosphereBufferUnit = -1; - } +#if (GPU_FEATURE_PROFILE == GPU_CORE) + const GLint ATMOSPHERE_GPU_SLOT = 4; + loc = glGetUniformBlockIndex(program.programId(), "atmosphereBufferUnit"); + if (loc >= 0) { + glUniformBlockBinding(program.programId(), loc, ATMOSPHERE_GPU_SLOT); + locations.atmosphereBufferUnit = ATMOSPHERE_GPU_SLOT; + } else { + locations.atmosphereBufferUnit = -1; + } +#else + loc = program.uniformLocation("atmosphereBufferUnit"); + if (loc >= 0) { + locations.atmosphereBufferUnit = loc; + } else { + locations.atmosphereBufferUnit = -1; + } #endif program.release(); From 5f12af75bdacdd9a77228053ec0ede87cb849276 Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Fri, 8 May 2015 11:11:46 -0700 Subject: [PATCH 009/552] Tweaking to match master --- cmake/modules/FindOpenVR.cmake | 5 +- interface/CMakeLists.txt | 1 - interface/src/audio/AudioToolBox.cpp | 2 +- interface/src/audio/AudioToolBox.h | 2 +- .../src/DeferredLightingEffect.cpp | 102 +++++++++--------- 5 files changed, 53 insertions(+), 59 deletions(-) diff --git a/cmake/modules/FindOpenVR.cmake b/cmake/modules/FindOpenVR.cmake index 9104fc514f..9cbe790a7f 100644 --- a/cmake/modules/FindOpenVR.cmake +++ b/cmake/modules/FindOpenVR.cmake @@ -13,12 +13,9 @@ # See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html # - if (NOT ANDROID) - include(FindPackageHandleStandardArgs) find_package_handle_standard_args(OPENVR DEFAULT_MSG OPENVR_INCLUDE_DIRS OPENVR_LIBRARIES) - -endif (NOT ANDROID) +endif() mark_as_advanced(OPENVR_INCLUDE_DIRS OPENVR_LIBRARIES OPENVR_SEARCH_DIRS) diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 84079dc3b4..66bb02bbca 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -73,7 +73,6 @@ find_package(Qt5 COMPONENTS Gui Multimedia Network OpenGL Qml Quick Script Svg W # grab the ui files in resources/ui file (GLOB_RECURSE QT_UI_FILES ui/*.ui) source_group("UI Files" FILES ${QT_UI_FILES}) - # have qt5 wrap them and generate the appropriate header files qt5_wrap_ui(QT_UI_HEADERS "${QT_UI_FILES}") diff --git a/interface/src/audio/AudioToolBox.cpp b/interface/src/audio/AudioToolBox.cpp index 5f70fbda00..85b8b19788 100644 --- a/interface/src/audio/AudioToolBox.cpp +++ b/interface/src/audio/AudioToolBox.cpp @@ -111,4 +111,4 @@ void AudioToolBox::render(int x, int y, int padding, bool boxed) { DependencyManager::get()->renderQuad(topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight, quadColor, _boxQuadID); glBindTexture(GL_TEXTURE_2D, 0); glDisable(GL_TEXTURE_2D); -} +} \ No newline at end of file diff --git a/interface/src/audio/AudioToolBox.h b/interface/src/audio/AudioToolBox.h index 8957037482..e07e6857aa 100644 --- a/interface/src/audio/AudioToolBox.h +++ b/interface/src/audio/AudioToolBox.h @@ -33,4 +33,4 @@ private: qint64 _iconPulseTimeReference = 0; }; -#endif // hifi_AudioToolBox_h +#endif // hifi_AudioToolBox_h \ No newline at end of file diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 324ed69a96..bddb1815bf 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -268,16 +268,16 @@ void DeferredLightingEffect::render() { program->setUniformValue(locations->ambientSphere + i, *(((QVector4D*) &sh) + i)); } } - - if (locations->lightBufferUnit >= 0) { - gpu::Batch batch; - batch.setUniformBuffer(locations->lightBufferUnit, globalLight->getSchemaBuffer()); - gpu::GLBackend::renderBatch(batch); + + if (locations->lightBufferUnit >= 0) { + gpu::Batch batch; + batch.setUniformBuffer(locations->lightBufferUnit, globalLight->getSchemaBuffer()); + gpu::GLBackend::renderBatch(batch); } if (_atmosphere && (locations->atmosphereBufferUnit >= 0)) { - gpu::Batch batch; - batch.setUniformBuffer(locations->atmosphereBufferUnit, _atmosphere->getDataBuffer()); + gpu::Batch batch; + batch.setUniformBuffer(locations->atmosphereBufferUnit, _atmosphere->getDataBuffer()); gpu::GLBackend::renderBatch(batch); } glUniformMatrix4fv(locations->invViewMat, 1, false, reinterpret_cast< const GLfloat* >(&invViewMat)); @@ -334,11 +334,11 @@ void DeferredLightingEffect::render() { for (auto lightID : _pointLights) { auto light = _allocatedLights[lightID]; - - if (_pointLightLocations.lightBufferUnit >= 0) { - gpu::Batch batch; - batch.setUniformBuffer(_pointLightLocations.lightBufferUnit, light->getSchemaBuffer()); - gpu::GLBackend::renderBatch(batch); + + if (_pointLightLocations.lightBufferUnit >= 0) { + gpu::Batch batch; + batch.setUniformBuffer(_pointLightLocations.lightBufferUnit, light->getSchemaBuffer()); + gpu::GLBackend::renderBatch(batch); } glUniformMatrix4fv(_pointLightLocations.invViewMat, 1, false, reinterpret_cast< const GLfloat* >(&invViewMat)); @@ -380,10 +380,10 @@ void DeferredLightingEffect::render() { for (auto lightID : _spotLights) { auto light = _allocatedLights[lightID]; - if (_spotLightLocations.lightBufferUnit >= 0) { - gpu::Batch batch; - batch.setUniformBuffer(_spotLightLocations.lightBufferUnit, light->getSchemaBuffer()); - gpu::GLBackend::renderBatch(batch); + if (_spotLightLocations.lightBufferUnit >= 0) { + gpu::Batch batch; + batch.setUniformBuffer(_spotLightLocations.lightBufferUnit, light->getSchemaBuffer()); + gpu::GLBackend::renderBatch(batch); } glUniformMatrix4fv(_spotLightLocations.invViewMat, 1, false, reinterpret_cast< const GLfloat* >(&invViewMat)); @@ -482,8 +482,6 @@ void DeferredLightingEffect::render() { } void DeferredLightingEffect::loadLightProgram(const char* fragSource, bool limited, ProgramObject& program, LightLocations& locations) { - qDebug() << (limited ? deferred_light_limited_vert : deferred_light_vert); - qDebug() << fragSource; program.addShaderFromSourceCode(QGLShader::Vertex, (limited ? deferred_light_limited_vert : deferred_light_vert)); program.addShaderFromSourceCode(QGLShader::Fragment, fragSource); program.link(); @@ -504,42 +502,42 @@ void DeferredLightingEffect::loadLightProgram(const char* fragSource, bool limit locations.ambientSphere = program.uniformLocation("ambientSphere.L00"); locations.invViewMat = program.uniformLocation("invViewMat"); - GLint loc = -1; - -#if (GPU_FEATURE_PROFILE == GPU_CORE) - const GLint LIGHT_GPU_SLOT = 3; - loc = glGetUniformBlockIndex(program.programId(), "lightBuffer"); - if (loc >= 0) { - glUniformBlockBinding(program.programId(), loc, LIGHT_GPU_SLOT); - locations.lightBufferUnit = LIGHT_GPU_SLOT; - } else { - locations.lightBufferUnit = -1; - } -#else - loc = program.uniformLocation("lightBuffer"); - if (loc >= 0) { - locations.lightBufferUnit = loc; - } else { - locations.lightBufferUnit = -1; - } + GLint loc = -1; + +#if (GPU_FEATURE_PROFILE == GPU_CORE) + const GLint LIGHT_GPU_SLOT = 3; + loc = glGetUniformBlockIndex(program.programId(), "lightBuffer"); + if (loc >= 0) { + glUniformBlockBinding(program.programId(), loc, LIGHT_GPU_SLOT); + locations.lightBufferUnit = LIGHT_GPU_SLOT; + } else { + locations.lightBufferUnit = -1; + } +#else + loc = program.uniformLocation("lightBuffer"); + if (loc >= 0) { + locations.lightBufferUnit = loc; + } else { + locations.lightBufferUnit = -1; + } #endif -#if (GPU_FEATURE_PROFILE == GPU_CORE) - const GLint ATMOSPHERE_GPU_SLOT = 4; - loc = glGetUniformBlockIndex(program.programId(), "atmosphereBufferUnit"); - if (loc >= 0) { - glUniformBlockBinding(program.programId(), loc, ATMOSPHERE_GPU_SLOT); - locations.atmosphereBufferUnit = ATMOSPHERE_GPU_SLOT; - } else { - locations.atmosphereBufferUnit = -1; - } -#else - loc = program.uniformLocation("atmosphereBufferUnit"); - if (loc >= 0) { - locations.atmosphereBufferUnit = loc; - } else { - locations.atmosphereBufferUnit = -1; - } +#if (GPU_FEATURE_PROFILE == GPU_CORE) + const GLint ATMOSPHERE_GPU_SLOT = 4; + loc = glGetUniformBlockIndex(program.programId(), "atmosphereBufferUnit"); + if (loc >= 0) { + glUniformBlockBinding(program.programId(), loc, ATMOSPHERE_GPU_SLOT); + locations.atmosphereBufferUnit = ATMOSPHERE_GPU_SLOT; + } else { + locations.atmosphereBufferUnit = -1; + } +#else + loc = program.uniformLocation("atmosphereBufferUnit"); + if (loc >= 0) { + locations.atmosphereBufferUnit = loc; + } else { + locations.atmosphereBufferUnit = -1; + } #endif program.release(); From ac93d2c7213a9d22f777c5826bf96930fd77c92a Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Thu, 21 May 2015 18:50:11 -0700 Subject: [PATCH 010/552] Working on display plugins --- cmake/externals/openvr/CMakeLists.txt | 4 +- interface/src/Application.cpp | 364 ++++++++++-------- interface/src/Application.h | 31 +- interface/src/avatar/MyAvatar.cpp | 2 +- interface/src/main.cpp | 5 +- interface/src/plugins/PluginManager.h | 2 +- .../{render => display}/DisplayPlugin.cpp | 0 .../{render => display}/DisplayPlugin.h | 17 +- .../{render => display}/HmdDisplayPlugin.cpp | 0 .../{render => display}/HmdDisplayPlugin.h | 0 .../LegacyDisplayPlugin.cpp | 21 +- .../{render => display}/LegacyDisplayPlugin.h | 3 - .../{render => display}/NullDisplayPlugin.cpp | 0 .../{render => display}/NullDisplayPlugin.h | 0 .../OculusDisplayPlugin.cpp | 0 .../{render => display}/OculusDisplayPlugin.h | 0 .../SimpleDisplayPlugin.cpp | 7 +- .../src/plugins/display/SimpleDisplayPlugin.h | 82 ++++ .../StereoDisplayPlugin.cpp | 0 .../{render => display}/StereoDisplayPlugin.h | 0 .../src/plugins/display/Tv3dDisplayPlugin.cpp | 278 +++++++++++++ .../src/plugins/display/Tv3dDisplayPlugin.h | 28 ++ .../WindowDisplayPlugin.cpp | 49 +-- .../{render => display}/WindowDisplayPlugin.h | 13 +- .../src/plugins/render/SimpleDisplayPlugin.h | 36 -- .../src/plugins/render/Tv3dDisplayPlugin.cpp | 43 --- .../src/plugins/render/Tv3dDisplayPlugin.h | 26 -- interface/src/ui/ApplicationOverlay.cpp | 4 +- interface/src/ui/ApplicationOverlay.h | 2 + interface/src/ui/overlays/Overlays.cpp | 2 +- libraries/render-utils/src/GlWindow.cpp | 77 ++++ libraries/render-utils/src/GlWindow.h | 29 ++ libraries/render-utils/src/GlowEffect.cpp | 3 +- .../render-utils/src/OffscreenGlCanvas.cpp | 22 +- .../render-utils/src/OffscreenGlCanvas.h | 6 + .../render-utils/src/OffscreenGlContext.cpp | 43 --- .../render-utils/src/OffscreenGlContext.h | 33 -- 37 files changed, 780 insertions(+), 452 deletions(-) rename interface/src/plugins/{render => display}/DisplayPlugin.cpp (100%) rename interface/src/plugins/{render => display}/DisplayPlugin.h (93%) rename interface/src/plugins/{render => display}/HmdDisplayPlugin.cpp (100%) rename interface/src/plugins/{render => display}/HmdDisplayPlugin.h (100%) rename interface/src/plugins/{render => display}/LegacyDisplayPlugin.cpp (89%) rename interface/src/plugins/{render => display}/LegacyDisplayPlugin.h (90%) rename interface/src/plugins/{render => display}/NullDisplayPlugin.cpp (100%) rename interface/src/plugins/{render => display}/NullDisplayPlugin.h (100%) rename interface/src/plugins/{render => display}/OculusDisplayPlugin.cpp (100%) rename interface/src/plugins/{render => display}/OculusDisplayPlugin.h (100%) rename interface/src/plugins/{render => display}/SimpleDisplayPlugin.cpp (93%) create mode 100644 interface/src/plugins/display/SimpleDisplayPlugin.h rename interface/src/plugins/{render => display}/StereoDisplayPlugin.cpp (100%) rename interface/src/plugins/{render => display}/StereoDisplayPlugin.h (100%) create mode 100644 interface/src/plugins/display/Tv3dDisplayPlugin.cpp create mode 100644 interface/src/plugins/display/Tv3dDisplayPlugin.h rename interface/src/plugins/{render => display}/WindowDisplayPlugin.cpp (91%) rename interface/src/plugins/{render => display}/WindowDisplayPlugin.h (65%) delete mode 100644 interface/src/plugins/render/SimpleDisplayPlugin.h delete mode 100644 interface/src/plugins/render/Tv3dDisplayPlugin.cpp delete mode 100644 interface/src/plugins/render/Tv3dDisplayPlugin.h create mode 100644 libraries/render-utils/src/GlWindow.cpp create mode 100644 libraries/render-utils/src/GlWindow.h delete mode 100644 libraries/render-utils/src/OffscreenGlContext.cpp delete mode 100644 libraries/render-utils/src/OffscreenGlContext.h diff --git a/cmake/externals/openvr/CMakeLists.txt b/cmake/externals/openvr/CMakeLists.txt index b5cd477c02..826c3dbb13 100644 --- a/cmake/externals/openvr/CMakeLists.txt +++ b/cmake/externals/openvr/CMakeLists.txt @@ -7,8 +7,8 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) ExternalProject_Add( ${EXTERNAL_NAME} - URL https://github.com/ValveSoftware/openvr/archive/0.9.0.zip - URL_MD5 4fbde7759f604aaa68b9c40d628cc34a + URL https://github.com/ValveSoftware/openvr/archive/0.9.1.zip + URL_MD5 f986f5a6815e9454c53c5bf58ce02fdc CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index acae517373..f72be6ac5b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -116,7 +116,7 @@ #include "gpu/Batch.h" #include "gpu/GLBackend.h" -#include "plugins/render/DisplayPlugin.h" +#include "plugins/display/DisplayPlugin.h" #include "scripting/AccountScriptingInterface.h" #include "scripting/AudioDeviceScriptingInterface.h" @@ -341,6 +341,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _maxOctreePPS(maxOctreePacketsPerSecond.get()), _lastFaceTrackerUpdate(0) { + _offscreenContext = new OffscreenGlCanvas(); setInstance(this); #ifdef Q_OS_WIN installNativeEventFilter(&MyNativeEventFilter::getInstance()); @@ -823,13 +824,10 @@ void Application::paintGL() { PerformanceTimer perfTimer("paintGL"); _offscreenContext->makeCurrent(); - Q_ASSERT(_offscreenContext->getContext() == QOpenGLContext::currentContext()); - PerformanceWarning::setSuppressShortTimings(Menu::getInstance()->isOptionChecked(MenuOption::SuppressShortTimings)); bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::paintGL()"); resizeGL(); - Q_ASSERT(_offscreenContext->getContext() == QOpenGLContext::currentContext()); { PerformanceTimer perfTimer("renderOverlay"); @@ -853,6 +851,7 @@ void Application::paintGL() { // is orthongonal to the (body's) Y axis _myCamera.setRotation(_myAvatar->getWorldAlignedOrientation()); } + } else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) { static const float THIRD_PERSON_CAMERA_DISTANCE = 1.5f; _myCamera.setPosition(_myAvatar->getDefaultEyePosition() + @@ -862,6 +861,7 @@ void Application::paintGL() { } else { _myCamera.setRotation(_myAvatar->getHead()->getOrientation()); } + } else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { _myCamera.setRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f))); _myCamera.setPosition(_myAvatar->getDefaultEyePosition() + @@ -890,26 +890,51 @@ void Application::paintGL() { auto primaryFbo = DependencyManager::get()->getPrimaryFramebuffer(); auto finalFbo = primaryFbo; glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFbo)); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); { - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - // Viewport is assigned to the size of the framebuffer QSize size = DependencyManager::get()->getFrameBufferSize(); - glViewport(0, 0, size.width(), size.height()); + if (displayPlugin->isStereo()) { + QRect r(QPoint(0, 0), QSize(size.width() / 2, size.height())); + glEnable(GL_SCISSOR_TEST); + for (int i = 0; i < 2; ++i) { + glViewport(r.x(), r.y(), r.width(), r.height()); + glScissor(r.x(), r.y(), r.width(), r.height()); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - displaySide(_myCamera); - glPopMatrix(); + glMatrixMode(GL_PROJECTION); + // FIXME Fetch the projection matrix from the plugin - if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) { - glm::vec2 mpos = getActiveDisplayPlugin()->getUiMousePosition(); - _rearMirrorTools->render(true, QPoint(mpos.x, mpos.y)); - } else if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { - renderRearViewMirror(_mirrorViewRect); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + Camera eyeCamera; + eyeCamera.setRotation(_myCamera.getRotation()); + eyeCamera.setPosition(_myCamera.getPosition()); + displaySide(eyeCamera); + glPopMatrix(); + if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) { + glm::vec2 mpos = getActiveDisplayPlugin()->getUiMousePosition(); + _rearMirrorTools->render(true, QPoint(mpos.x, mpos.y)); + } else if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { + renderRearViewMirror(_mirrorViewRect); + } + r.moveLeft(r.width()); + } + glDisable(GL_SCISSOR_TEST); + } else { + glViewport(0, 0, size.width(), size.height()); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + displaySide(_myCamera); + glPopMatrix(); + if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) { + glm::vec2 mpos = getActiveDisplayPlugin()->getUiMousePosition(); + _rearMirrorTools->render(true, QPoint(mpos.x, mpos.y)); + } else if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { + renderRearViewMirror(_mirrorViewRect); + } } - finalFbo = DependencyManager::get()->render(); } @@ -1123,8 +1148,6 @@ bool Application::eventFilter(QObject* object, QEvent* event) { } } - // auto offscreenUi = DependencyManager::get(); - // return offscreenUi->eventFilter(object, event); return false; } @@ -1876,14 +1899,6 @@ ivec2 Application::getMouseDragStarted() const { return getActiveDisplayPlugin()->trueMouseToUiMouse(getTrueMouseDragStarted()); } -int Application::getMouseDragStartedX() const { - return getMouseDragStarted().x; -} - -int Application::getMouseDragStartedY() const { - return getMouseDragStarted().y; -} - FaceTracker* Application::getActiveFaceTracker() { auto faceshift = DependencyManager::get(); auto dde = DependencyManager::get(); @@ -2460,7 +2475,7 @@ void Application::update(float deltaTime) { PerformanceTimer perfTimer("overlays"); _overlays.update(deltaTime); } - + { PerformanceTimer perfTimer("myAvatar"); updateMyAvatarLookAtPosition(); @@ -3422,8 +3437,6 @@ void Application::getProjectionMatrix(glm::dmat4* projectionMatrix) { void Application::computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& nearVal, float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const { _displayViewFrustum.computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); - // allow 3DTV/Oculus to override parameters from camera - getActiveDisplayPlugin()->overrideOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); } bool Application::getShadowsEnabled() { @@ -4573,136 +4586,10 @@ void Application::friendsWindowClosed() { _friendsWindow = NULL; } - void Application::postLambdaEvent(std::function f) { QCoreApplication::postEvent(this, new LambdaEvent(f)); } -PickRay Application::computePickRay() const { - return computePickRay(getTrueMouseX(), getTrueMouseY()); -} - -glm::uvec2 Application::getCanvasSize() const { - return getActiveDisplayPlugin()->getCanvasSize(); -} - -QSize Application::getDeviceSize() const { - return getActiveDisplayPlugin()->getDeviceSize(); -} - -bool Application::hasFocus() const { - return getActiveDisplayPlugin()->hasFocus(); -} - -glm::vec2 Application::getViewportDimensions() const { - return toGlm(getDeviceSize()); -} - -glm::ivec2 Application::getTrueMousePosition() const { - return getActiveDisplayPlugin()->getTrueMousePosition(); -} - -glm::quat Application::getHeadOrientation() const { - return getActiveDisplayPlugin()->headOrientation(); -} - -glm::vec3 Application::getHeadPosition() const { - return getActiveDisplayPlugin()->headTranslation(); -} - -bool Application::isThrottleRendering() const { - return getActiveDisplayPlugin()->isThrottled(); -} - - -using DisplayPluginPointer = QSharedPointer; - -#include "plugins/render/NullDisplayPlugin.h" -#include "plugins/render/WindowDisplayPlugin.h" -#include "plugins/render/LegacyDisplayPlugin.h" -#include "plugins/render/OculusDisplayPlugin.h" - -static DisplayPluginPointer _displayPlugin{ nullptr }; - -DisplayPlugin * Application::getActiveDisplayPlugin() { - if (nullptr == _displayPlugin) { - updateDisplayMode(); - Q_ASSERT(_displayPlugin); - } - return _displayPlugin.data(); -} - -const DisplayPlugin * Application::getActiveDisplayPlugin() const { - return ((Application*)this)->getActiveDisplayPlugin(); -} - -static void addDisplayPluginToMenu(DisplayPluginPointer displayPlugin, bool active = false) { - auto menu = Menu::getInstance(); - MenuItemProperties item(MenuOption::OutputMenu, displayPlugin->getName(), "", true, active); - item.isSeparator = false; - Q_ASSERT(!menu->menuItemExists(MenuOption::OutputMenu, item.menuItemName)); - menu->addMenuItem(item); - Q_ASSERT(menu->menuItemExists(MenuOption::OutputMenu, item.menuItemName)); -} - -using DisplayPluginList = QVector; - -// FIXME move to a plugin manager class -static const DisplayPluginList & getDisplayPlugins() { - static DisplayPluginList RENDER_PLUGINS; - static bool init = false; - if (!init) { - DisplayPluginPointer displayPlugin = DisplayPluginPointer(new LegacyDisplayPlugin()); // new WindowDisplayPlugin(); - if (displayPlugin->isSupported()) { - displayPlugin->init(); - RENDER_PLUGINS.push_back(DisplayPluginPointer(displayPlugin)); - QObject::connect(displayPlugin.data(), &DisplayPlugin::requestRender, [] { - qApp->paintGL(); - }); - QObject::connect(displayPlugin.data(), &DisplayPlugin::recommendedFramebufferSizeChanged, [](const QSize & size) { - DependencyManager::get()->setFrameBufferSize(size * qApp->getRenderResolutionScale()); - qApp->resizeGL(); - }); - addDisplayPluginToMenu(displayPlugin, true); - } - - displayPlugin = DisplayPluginPointer(new NullDisplayPlugin()); - if (displayPlugin->isSupported()) { -#ifdef DEBUG - addDisplayPluginToMenu(displayPlugin); -#endif - displayPlugin->init(); - RENDER_PLUGINS.push_back(DisplayPluginPointer(displayPlugin)); - } - } - return RENDER_PLUGINS; -} - -void Application::updateDisplayMode() { - auto menu = Menu::getInstance(); - DisplayPluginPointer newDisplayPlugin; - foreach(DisplayPluginPointer displayPlugin, getDisplayPlugins()) { - QString name = displayPlugin->getName(); - QAction* action = menu->getActionForOption(name); - if (action->isChecked()) { - newDisplayPlugin = displayPlugin; - break; - } - } - if (_displayPlugin != newDisplayPlugin) { - if (_displayPlugin) { - _displayPlugin->deactivate(); - } - _offscreenContext->makeCurrent(); - _displayPlugin = newDisplayPlugin; - if (_displayPlugin) { - _displayPlugin->activate(); - } - _offscreenContext->makeCurrent(); - } - Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin"); -} - void Application::initPlugins() { #if 0 OculusManager::init(); @@ -4715,9 +4602,40 @@ void Application::shutdownPlugins() { #endif } +glm::vec3 Application::getHeadPosition() const { + return getActiveDisplayPlugin()->headTranslation(); +} -glm::ivec2 Application::getMouse() const { - return getActiveDisplayPlugin()->getUiMousePosition(); +glm::quat Application::getHeadOrientation() const { + return getActiveDisplayPlugin()->headOrientation(); +} + +glm::uvec2 Application::getCanvasSize() const { + return getActiveDisplayPlugin()->getCanvasSize(); +} + +QSize Application::getDeviceSize() const { + return getActiveDisplayPlugin()->getDeviceSize(); +} + +PickRay Application::computePickRay() const { + return computePickRay(getTrueMouseX(), getTrueMouseY()); +} + +bool Application::isThrottleRendering() const { + return getActiveDisplayPlugin()->isThrottled(); +} + +bool Application::hasFocus() const { + return getActiveDisplayPlugin()->hasFocus(); +} + +glm::vec2 Application::getViewportDimensions() const { + return toGlm(getDeviceSize()); +} + +glm::ivec2 Application::getTrueMousePosition() const { + return getActiveDisplayPlugin()->getTrueMousePosition(); } void Application::setMaxOctreePacketsPerSecond(int maxOctreePPS) { @@ -4735,3 +4653,131 @@ qreal Application::getDevicePixelRatio() { return _window ? _window->windowHandle()->devicePixelRatio() : 1.0; } + + +using DisplayPluginPointer = QSharedPointer; + +#include "plugins/display/NullDisplayPlugin.h" +#include "plugins/display/WindowDisplayPlugin.h" +#include "plugins/display/LegacyDisplayPlugin.h" +#include "plugins/display/OculusDisplayPlugin.h" +#include "plugins/display/Tv3dDisplayPlugin.h" +#include "plugins/display/WindowDisplayPlugin.h" + +static DisplayPluginPointer _displayPlugin{ nullptr }; + +DisplayPlugin * Application::getActiveDisplayPlugin() { + if (nullptr == _displayPlugin) { + updateDisplayMode(); + Q_ASSERT(_displayPlugin); + } + return _displayPlugin.data(); +} + +const DisplayPlugin * Application::getActiveDisplayPlugin() const { + return ((Application*)this)->getActiveDisplayPlugin(); +} + +static void addDisplayPluginToMenu(DisplayPluginPointer displayPlugin, bool active = false) { + auto menu = Menu::getInstance(); + QString name = displayPlugin->getName(); + Q_ASSERT(!menu->menuItemExists(MenuOption::OutputMenu, name)); + + static QActionGroup* displayPluginGroup = nullptr; + if (!displayPluginGroup) { + displayPluginGroup = new QActionGroup(menu); + displayPluginGroup->setExclusive(true); + } + auto parent = menu->getMenu(MenuOption::OutputMenu); + auto action = menu->addActionToQMenuAndActionHash(parent, + name, 0, qApp, + SLOT(updateDisplayMode())); + action->setCheckable(true); + action->setChecked(active); + displayPluginGroup->addAction(action); + Q_ASSERT(menu->menuItemExists(MenuOption::OutputMenu, name)); +} + +using DisplayPluginList = QVector; + +// FIXME move to a plugin manager class +static const DisplayPluginList & getDisplayPlugins() { + static DisplayPluginList RENDER_PLUGINS; + static bool init = false; + if (!init) { + init = true; + DisplayPluginPointer displayPlugin = DisplayPluginPointer(new LegacyDisplayPlugin()); // new WindowDisplayPlugin(); + if (displayPlugin->isSupported()) { + displayPlugin->init(); + RENDER_PLUGINS.push_back(DisplayPluginPointer(displayPlugin)); + QObject::connect(displayPlugin.data(), &DisplayPlugin::requestRender, [] { + qApp->paintGL(); + }); + QObject::connect(displayPlugin.data(), &DisplayPlugin::recommendedFramebufferSizeChanged, [](const QSize & size) { + qApp->resizeGL(); + }); + addDisplayPluginToMenu(displayPlugin, true); + } + +#ifdef DEBUG + displayPlugin = DisplayPluginPointer(new NullDisplayPlugin()); + if (displayPlugin->isSupported()) { + addDisplayPluginToMenu(displayPlugin); + displayPlugin->init(); + RENDER_PLUGINS.push_back(DisplayPluginPointer(displayPlugin)); + } +#endif + + displayPlugin = DisplayPluginPointer(new Tv3dDisplayPlugin()); + if (displayPlugin->isSupported()) { + addDisplayPluginToMenu(displayPlugin); + displayPlugin->init(); + RENDER_PLUGINS.push_back(DisplayPluginPointer(displayPlugin)); + } + + displayPlugin = DisplayPluginPointer(new WindowDisplayPlugin()); + if (displayPlugin->isSupported()) { + addDisplayPluginToMenu(displayPlugin); + displayPlugin->init(); + RENDER_PLUGINS.push_back(DisplayPluginPointer(displayPlugin)); + QObject::connect(displayPlugin.data(), &DisplayPlugin::requestRender, [] { + qApp->paintGL(); + }); + QObject::connect(displayPlugin.data(), &DisplayPlugin::recommendedFramebufferSizeChanged, [](const QSize & size) { + qApp->resizeGL(); + }); + } + } + return RENDER_PLUGINS; +} + +void Application::updateDisplayMode() { + auto menu = Menu::getInstance(); + DisplayPluginPointer newDisplayPlugin; + foreach(DisplayPluginPointer displayPlugin, getDisplayPlugins()) { + QString name = displayPlugin->getName(); + QAction* action = menu->getActionForOption(name); + if (action->isChecked()) { + newDisplayPlugin = displayPlugin; + break; + } + } + if (_displayPlugin != newDisplayPlugin) { + if (newDisplayPlugin) { + _offscreenContext->makeCurrent(); + newDisplayPlugin->activate(); + _offscreenContext->makeCurrent(); + } + std::swap(newDisplayPlugin, _displayPlugin); + if (newDisplayPlugin) { + newDisplayPlugin->deactivate(); + _offscreenContext->makeCurrent(); + } + } + Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin"); +} + +glm::ivec2 Application::getMouse() const { + return getActiveDisplayPlugin()->getUiMousePosition(); +} + diff --git a/interface/src/Application.h b/interface/src/Application.h index 9114224a2d..5c03df953e 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -40,7 +40,6 @@ #include #include #include -#include #include "AudioClient.h" #include "Bookmarks.h" @@ -84,6 +83,7 @@ class QMouseEvent; class QSystemTrayIcon; class QTouchEvent; class QWheelEvent; +class OffscreenGlCanvas; class FaceTracker; class MainWindow; @@ -222,23 +222,22 @@ public: const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; } bool mouseOnScreen() const; - glm::ivec2 getMouse() const; - int getMouseX() const { return getMouse().x; } - int getMouseY() const { return getMouse().y; } + inline glm::ivec2 getMouse() const; + inline int getMouseX() const { return getMouse().x; } + inline int getMouseY() const { return getMouse().y; } - glm::ivec2 getTrueMousePosition() const; - int getTrueMouseX() const { return getTrueMousePosition().x; } - int getTrueMouseY() const { return getTrueMousePosition().y; } + inline glm::ivec2 getTrueMousePosition() const; + inline int getTrueMouseX() const { return getTrueMousePosition().x; } + inline int getTrueMouseY() const { return getTrueMousePosition().y; } - glm::ivec2 getMouseDragStarted() const; - int getMouseDragStartedX() const; - int getMouseDragStartedY() const; + inline glm::ivec2 getMouseDragStarted() const; + inline int getMouseDragStartedX() const { return getMouseDragStarted().x; } + inline int getMouseDragStartedY() const { return getMouseDragStarted().y; } - const glm::ivec2 & getTrueMouseDragStarted() const { return _mouseDragStarted; } - int getTrueMouseDragStartedX() const { return getTrueMouseDragStarted().x; } - int getTrueMouseDragStartedY() const { return getTrueMouseDragStarted().y; } + inline const glm::ivec2& getTrueMouseDragStarted() const { return _mouseDragStarted; } + inline int getTrueMouseDragStartedX() const { return getTrueMouseDragStarted().x; } + inline int getTrueMouseDragStartedY() const { return getTrueMouseDragStarted().y; } - bool getLastMouseMoveWasSimulated() const { return _lastMouseMoveWasSimulated; } FaceTracker* getActiveFaceTracker(); @@ -521,7 +520,7 @@ private: bool _dependencyManagerIsSetup; - OffscreenGlContext* _offscreenContext{ new OffscreenGlContext() }; + OffscreenGlCanvas* _offscreenContext; MainWindow* _window; @@ -666,8 +665,6 @@ private: QThread _settingsThread; QTimer _settingsTimer; - - void checkSkeleton(); QWidget* _fullscreenMenuWidget = new QWidget(); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 34c0215d80..0ba4d1637b 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -34,7 +34,7 @@ #include #include "Application.h" -#include "plugins/render/DisplayPlugin.h" +#include "plugins/display/DisplayPlugin.h" #include "AvatarManager.h" #include "Environment.h" #include "Menu.h" diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 58a2ce21d1..13ca17355b 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -92,7 +92,9 @@ int main(int argc, const char* argv[]) { usecTimestampNowForceClockSkew(clockSkew); qCDebug(interfaceapp, "clockSkewOption=%s clockSkew=%d", clockSkewOption, clockSkew); } - + // Oculus initialization MUST PRECEDE OpenGL context creation. + // The nature of the Application constructor means this has to be either here, + // or in the main window ctor, before GL startup. Application::initPlugins(); int exitCode; @@ -109,7 +111,6 @@ int main(int argc, const char* argv[]) { } Application::shutdownPlugins(); - #ifdef Q_OS_WIN ReleaseMutex(mutex); #endif diff --git a/interface/src/plugins/PluginManager.h b/interface/src/plugins/PluginManager.h index 2d8ab9a9f4..2526490eea 100644 --- a/interface/src/plugins/PluginManager.h +++ b/interface/src/plugins/PluginManager.h @@ -1,7 +1,7 @@ #pragma once #include "plugins/Plugin.h" -#include "plugins/render/DisplayPlugin.h" +#include "plugins/display/DisplayPlugin.h" #include #include diff --git a/interface/src/plugins/render/DisplayPlugin.cpp b/interface/src/plugins/display/DisplayPlugin.cpp similarity index 100% rename from interface/src/plugins/render/DisplayPlugin.cpp rename to interface/src/plugins/display/DisplayPlugin.cpp diff --git a/interface/src/plugins/render/DisplayPlugin.h b/interface/src/plugins/display/DisplayPlugin.h similarity index 93% rename from interface/src/plugins/render/DisplayPlugin.h rename to interface/src/plugins/display/DisplayPlugin.h index 111f0ecee5..b68edf5f6a 100644 --- a/interface/src/plugins/render/DisplayPlugin.h +++ b/interface/src/plugins/display/DisplayPlugin.h @@ -70,24 +70,31 @@ public: // Convert from screen mouse coordinates to UI mouse coordinates virtual glm::ivec2 trueMouseToUiMouse(const glm::ivec2 & position) const { return position; }; - virtual PickRay computePickRay(const glm::vec2 & pos) const = 0; + virtual PickRay computePickRay(const glm::vec2 & pos) const { + // FIXME make pure virtual + return PickRay(); + }; virtual bool isMouseOnScreen() const; - virtual void overrideOffAxisFrustum( - float& left, float& right, float& bottom, float& top, - float& nearVal, float& farVal, - glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const { } + + // Stereo specific methods + virtual glm::mat4 getProjection(Eye eye) const { + return glm::mat4(); + } // HMD specific methods // TODO move these into another class virtual glm::mat4 headPose() const { static const glm::mat4 pose; return pose; } + virtual glm::quat headOrientation() const { static const glm::quat orientation; return orientation; } + virtual glm::vec3 headTranslation() const { static const glm::vec3 tranlsation; return tranlsation; } + virtual void abandonCalibration() {} virtual void resetSensors() {} virtual float devicePixelRatio() { return 1.0; } diff --git a/interface/src/plugins/render/HmdDisplayPlugin.cpp b/interface/src/plugins/display/HmdDisplayPlugin.cpp similarity index 100% rename from interface/src/plugins/render/HmdDisplayPlugin.cpp rename to interface/src/plugins/display/HmdDisplayPlugin.cpp diff --git a/interface/src/plugins/render/HmdDisplayPlugin.h b/interface/src/plugins/display/HmdDisplayPlugin.h similarity index 100% rename from interface/src/plugins/render/HmdDisplayPlugin.h rename to interface/src/plugins/display/HmdDisplayPlugin.h diff --git a/interface/src/plugins/render/LegacyDisplayPlugin.cpp b/interface/src/plugins/display/LegacyDisplayPlugin.cpp similarity index 89% rename from interface/src/plugins/render/LegacyDisplayPlugin.cpp rename to interface/src/plugins/display/LegacyDisplayPlugin.cpp index d5a3b2fc46..00d922c37a 100644 --- a/interface/src/plugins/render/LegacyDisplayPlugin.cpp +++ b/interface/src/plugins/display/LegacyDisplayPlugin.cpp @@ -27,6 +27,8 @@ void LegacyDisplayPlugin::activate() { QOpenGLContext * sourceContext = QOpenGLContext::currentContext(); QSurfaceFormat format; format.setOption(QSurfaceFormat::DebugContext); + + QOpenGLContext * newContext = new QOpenGLContext(); newContext->setFormat(format); _window->setContext( @@ -49,9 +51,10 @@ void LegacyDisplayPlugin::activate() { void LegacyDisplayPlugin::deactivate() { _window->removeEventFilter(DependencyManager::get().data()); _window->removeEventFilter(qApp); - if (qApp->getWindow()) { - qApp->getWindow()->setCentralWidget(oldWidget); - } + // FIXME, during shutdown, this causes an NPE. Need to deactivate the plugin before the main window is destroyed. +// if (qApp->getWindow()) { +// qApp->getWindow()->setCentralWidget(oldWidget); +// } // stop the glWidget frame timer so it doesn't call paintGL _window->stopFrameTimer(); _window->doneCurrent(); @@ -63,18 +66,6 @@ QSize LegacyDisplayPlugin::getDeviceSize() const { return _window->getDeviceSize(); } -void LegacyDisplayPlugin::makeCurrent() { - _window->makeCurrent(); -} - -void LegacyDisplayPlugin::doneCurrent() { - _window->doneCurrent(); -} - -void LegacyDisplayPlugin::swapBuffers() { - _window->swapBuffers(); -} - void LegacyDisplayPlugin::idle() { _window->updateGL(); } diff --git a/interface/src/plugins/render/LegacyDisplayPlugin.h b/interface/src/plugins/display/LegacyDisplayPlugin.h similarity index 90% rename from interface/src/plugins/render/LegacyDisplayPlugin.h rename to interface/src/plugins/display/LegacyDisplayPlugin.h index 481667d3d4..33ea6187c3 100644 --- a/interface/src/plugins/render/LegacyDisplayPlugin.h +++ b/interface/src/plugins/display/LegacyDisplayPlugin.h @@ -30,8 +30,5 @@ public: virtual void preDisplay(); protected: - virtual void makeCurrent(); - virtual void doneCurrent(); - virtual void swapBuffers(); virtual void idle(); }; diff --git a/interface/src/plugins/render/NullDisplayPlugin.cpp b/interface/src/plugins/display/NullDisplayPlugin.cpp similarity index 100% rename from interface/src/plugins/render/NullDisplayPlugin.cpp rename to interface/src/plugins/display/NullDisplayPlugin.cpp diff --git a/interface/src/plugins/render/NullDisplayPlugin.h b/interface/src/plugins/display/NullDisplayPlugin.h similarity index 100% rename from interface/src/plugins/render/NullDisplayPlugin.h rename to interface/src/plugins/display/NullDisplayPlugin.h diff --git a/interface/src/plugins/render/OculusDisplayPlugin.cpp b/interface/src/plugins/display/OculusDisplayPlugin.cpp similarity index 100% rename from interface/src/plugins/render/OculusDisplayPlugin.cpp rename to interface/src/plugins/display/OculusDisplayPlugin.cpp diff --git a/interface/src/plugins/render/OculusDisplayPlugin.h b/interface/src/plugins/display/OculusDisplayPlugin.h similarity index 100% rename from interface/src/plugins/render/OculusDisplayPlugin.h rename to interface/src/plugins/display/OculusDisplayPlugin.h diff --git a/interface/src/plugins/render/SimpleDisplayPlugin.cpp b/interface/src/plugins/display/SimpleDisplayPlugin.cpp similarity index 93% rename from interface/src/plugins/render/SimpleDisplayPlugin.cpp rename to interface/src/plugins/display/SimpleDisplayPlugin.cpp index 40e0ba4d87..af02b0e1ce 100644 --- a/interface/src/plugins/render/SimpleDisplayPlugin.cpp +++ b/interface/src/plugins/display/SimpleDisplayPlugin.cpp @@ -35,10 +35,11 @@ void SimpleGlDisplayPlugin::display(GLuint sceneTexture, const glm::uvec2& scene glPushMatrix(); glLoadIdentity(); - glClearColor(0, 0, 0, 1); + glClearColor(0, 0, 1, 1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_TEXTURE_2D); + glViewport(0, 0, getDeviceSize().width(), getDeviceSize().height()); if (sceneTexture) { glBindTexture(GL_TEXTURE_2D, sceneTexture); glBegin(GL_QUADS); @@ -74,7 +75,7 @@ void SimpleGlDisplayPlugin::display(GLuint sceneTexture, const glm::uvec2& scene glBindTexture(GL_TEXTURE_2D, 0); glDisable(GL_TEXTURE_2D); - Q_ASSERT(!glGetError()); + //Q_ASSERT(!glGetError()); glMatrixMode(GL_PROJECTION); glPopMatrix(); glMatrixMode(GL_MODELVIEW); @@ -84,5 +85,5 @@ void SimpleGlDisplayPlugin::display(GLuint sceneTexture, const glm::uvec2& scene glEnable(GL_DEPTH_TEST); glFinish(); - doneCurrent(); } + diff --git a/interface/src/plugins/display/SimpleDisplayPlugin.h b/interface/src/plugins/display/SimpleDisplayPlugin.h new file mode 100644 index 0000000000..036b50d44a --- /dev/null +++ b/interface/src/plugins/display/SimpleDisplayPlugin.h @@ -0,0 +1,82 @@ +// +// SimpleDisplayPlugin.h +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "DisplayPlugin.h" + +#include + +#include +#include +#include +#include + +class SimpleGlDisplayPlugin : public DisplayPlugin { +public: + virtual void activate(); + virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize, + GLuint overlayTexture, const glm::uvec2& overlaySize); +}; + +template +class SimpleDisplayPlugin : public SimpleGlDisplayPlugin { +public: + virtual glm::ivec2 getTrueMousePosition() const { + return toGlm(_window->mapFromGlobal(QCursor::pos())); + } + +protected: + void makeCurrent() final { + _window->makeCurrent(); + } + + void doneCurrent() final { + _window->doneCurrent(); + } + + void swapBuffers() final { + _window->swapBuffers(); + } + +protected: + T * _window{ nullptr }; +}; + + +class GlWindowDisplayPlugin : public SimpleDisplayPlugin { +public: + virtual void activate() { + Q_ASSERT(nullptr == _window); + _window = new GlWindow(QOpenGLContext::currentContext()); + } + + virtual void deactivate() { + Q_ASSERT(nullptr != _window); + _window->hide(); + _window->destroy(); + _window->deleteLater(); + _window = nullptr; + } + + virtual QSize getDeviceSize() const final { + return _window->geometry().size() * _window->devicePixelRatio(); + } + + virtual glm::ivec2 getCanvasSize() const final { + return toGlm(_window->geometry().size()); + } + + virtual bool hasFocus() const { + return _window->isActive(); + } + + +}; + diff --git a/interface/src/plugins/render/StereoDisplayPlugin.cpp b/interface/src/plugins/display/StereoDisplayPlugin.cpp similarity index 100% rename from interface/src/plugins/render/StereoDisplayPlugin.cpp rename to interface/src/plugins/display/StereoDisplayPlugin.cpp diff --git a/interface/src/plugins/render/StereoDisplayPlugin.h b/interface/src/plugins/display/StereoDisplayPlugin.h similarity index 100% rename from interface/src/plugins/render/StereoDisplayPlugin.h rename to interface/src/plugins/display/StereoDisplayPlugin.h diff --git a/interface/src/plugins/display/Tv3dDisplayPlugin.cpp b/interface/src/plugins/display/Tv3dDisplayPlugin.cpp new file mode 100644 index 0000000000..0173a6fc33 --- /dev/null +++ b/interface/src/plugins/display/Tv3dDisplayPlugin.cpp @@ -0,0 +1,278 @@ +// +// Tv3dDisplayPlugin.cpp +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "Tv3dDisplayPlugin.h" +#include + +const QString Tv3dDisplayPlugin::NAME("Tv3dDisplayPlugin"); + +const QString & Tv3dDisplayPlugin::getName() { + return NAME; +} + +void Tv3dDisplayPlugin::display( + GLuint sceneTexture, const glm::uvec2& sceneSize, + GLuint overlayTexture, const glm::uvec2& overlaySize) { + makeCurrent(); + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + + glClearColor(0, 0, 0, 1); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glEnable(GL_TEXTURE_2D); + + if (sceneTexture) { + glBindTexture(GL_TEXTURE_2D, sceneTexture); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); + glVertex2f(-1, -1); + glTexCoord2f(1, 0); + glVertex2f(+1, -1); + glTexCoord2f(1, 1); + glVertex2f(+1, +1); + glTexCoord2f(0, 1); + glVertex2f(-1, +1); + glEnd(); + } + + if (overlayTexture) { + glEnable(GL_BLEND); + glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); + glBindTexture(GL_TEXTURE_2D, overlayTexture); + + QSize size = getDeviceSize(); + QRect r(QPoint(0, 0), QSize(size.width() / 2, size.height())); + for (int i = 0; i < 2; ++i) { + glViewport(r.x(), r.y(), r.width(), r.height()); + glScissor(r.x(), r.y(), r.width(), r.height()); + + glBegin(GL_QUADS); + glTexCoord2f(0, 0); + glVertex2f(-1, -1); + glTexCoord2f(1, 0); + glVertex2f(+1, -1); + glTexCoord2f(1, 1); + glVertex2f(+1, +1); + glTexCoord2f(0, 1); + glVertex2f(-1, +1); + glEnd(); + + r.moveLeft(r.width()); + } + + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_BLEND); + } + glDisable(GL_TEXTURE_2D); + Q_ASSERT(!glGetError()); + + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + glEnable(GL_LIGHTING); + glEnable(GL_DEPTH_TEST); + + glFinish(); +} + +/* +void Tv3dDisplayPlugin::activate() { + GlWindowDisplayPlugin::activate(); + _window->setFlags(Qt::FramelessWindowHint); + _window->setPosition(100, 100); + _window->resize(512, 512); + _window->setVisible(true); + _window->show(); +} + +void Tv3dDisplayPlugin::deactivate() { + GlWindowDisplayPlugin::deactivate(); +} +*/ + +/* +glm::ivec2 LegacyDisplayPlugin::getCanvasSize() const { + return toGlm(_window->size()); +} + +bool LegacyDisplayPlugin::hasFocus() const { + return _window->hasFocus(); +} + +PickRay LegacyDisplayPlugin::computePickRay(const glm::vec2 & pos) const { + return PickRay(); +} + +bool isMouseOnScreen() { + return false; +} + +void LegacyDisplayPlugin::preDisplay() { + SimpleDisplayPlugin::preDisplay(); + auto size = toGlm(_window->size()); + glViewport(0, 0, size.x, size.y); +} + +bool LegacyDisplayPlugin::isThrottled() const { + return _window->isThrottleRendering(); + + + */ + +#if 0 + +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(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(); + 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(); + qApp->displaySide(eyeCamera, false, RenderArgs::MONO); +#if 0 + qApp->getApplicationOverlay().displayOverlayTextureStereo(whichCamera, _aspect, fov); +#endif + _activeEye = NULL; + }, [&] { + // render right side view + portalX = deviceSize.width() / 2; + }); + glPopMatrix(); + glDisable(GL_SCISSOR_TEST); + + auto finalFbo = DependencyManager::get()->render(); + 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; + } +} + +#endif diff --git a/interface/src/plugins/display/Tv3dDisplayPlugin.h b/interface/src/plugins/display/Tv3dDisplayPlugin.h new file mode 100644 index 0000000000..5dbfc543b8 --- /dev/null +++ b/interface/src/plugins/display/Tv3dDisplayPlugin.h @@ -0,0 +1,28 @@ +// +// Tv3dDisplayPlugin.h +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "SimpleDisplayPlugin.h" +#include "LegacyDisplayPlugin.h" + +class Tv3dDisplayPlugin : public LegacyDisplayPlugin { + Q_OBJECT +public: + static const QString NAME; + virtual const QString & getName(); + + virtual bool isStereo() const final { return true; } + void display(GLuint sceneTexture, const glm::uvec2& sceneSize, + GLuint overlayTexture, const glm::uvec2& overlaySize); + //virtual bool isMouseOnScreen() const { return true; } + //virtual bool isThrottled() const; + //virtual void preDisplay(); +}; diff --git a/interface/src/plugins/render/WindowDisplayPlugin.cpp b/interface/src/plugins/display/WindowDisplayPlugin.cpp similarity index 91% rename from interface/src/plugins/render/WindowDisplayPlugin.cpp rename to interface/src/plugins/display/WindowDisplayPlugin.cpp index 4c786d9f63..662c527821 100644 --- a/interface/src/plugins/render/WindowDisplayPlugin.cpp +++ b/interface/src/plugins/display/WindowDisplayPlugin.cpp @@ -25,41 +25,15 @@ const QString & WindowDisplayPlugin::getName() { } void WindowDisplayPlugin::activate() { - Q_ASSERT(nullptr == _window); - - _context = new QOpenGLContext; - - _window = new QWindow; - _window->setSurfaceType(QSurface::OpenGLSurface); + GlWindowDisplayPlugin::activate(); _window->installEventFilter(this); - glMatrixMode(0); - { - QSurfaceFormat format; - format.setDepthBufferSize(0); - format.setStencilBufferSize(0); - format.setVersion(4, 1); - // Ugh.... - format.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile); - _window->setFormat(format); - _context->setFormat(format); - } - - _context->setShareContext(QOpenGLContext::currentContext()); - _context->create(); - _window->show(); - _timer.start(8); } void WindowDisplayPlugin::deactivate() { _timer.stop(); - _context->doneCurrent(); - _context->deleteLater(); - _context = nullptr; - _window->hide(); - _window->destroy(); - _window = nullptr; + GlWindowDisplayPlugin::deactivate(); } bool WindowDisplayPlugin::eventFilter(QObject* object, QEvent* event) { @@ -80,25 +54,6 @@ bool WindowDisplayPlugin::eventFilter(QObject* object, QEvent* event) { return false; } -QSize WindowDisplayPlugin::getRecommendedFramebufferSize() const { - return _window->size(); -} - -void WindowDisplayPlugin::makeCurrent() { - _context->makeCurrent(_window); - QSize windowSize = _window->size(); - glViewport(0, 0, windowSize.width(), windowSize.height()); -} - -void WindowDisplayPlugin::doneCurrent() { - _context->doneCurrent(); -} - -void WindowDisplayPlugin::swapBuffers() { - _context->swapBuffers(_window); -} - - #if 0 // diff --git a/interface/src/plugins/render/WindowDisplayPlugin.h b/interface/src/plugins/display/WindowDisplayPlugin.h similarity index 65% rename from interface/src/plugins/render/WindowDisplayPlugin.h rename to interface/src/plugins/display/WindowDisplayPlugin.h index 9fc28c77d9..1b1d3f81b9 100644 --- a/interface/src/plugins/render/WindowDisplayPlugin.h +++ b/interface/src/plugins/display/WindowDisplayPlugin.h @@ -11,11 +11,10 @@ #include "SimpleDisplayPlugin.h" -#include -#include +#include #include -class WindowDisplayPlugin : public SimpleDisplayPlugin { +class WindowDisplayPlugin : public GlWindowDisplayPlugin { Q_OBJECT public: static const QString NAME; @@ -27,14 +26,6 @@ public: virtual void activate(); virtual void deactivate(); virtual bool eventFilter(QObject* object, QEvent* event); - virtual QSize getRecommendedFramebufferSize() const; - -protected: - virtual void makeCurrent(); - virtual void doneCurrent(); - virtual void swapBuffers(); - private: QTimer _timer; - QOpenGLContext * _context{ nullptr }; }; diff --git a/interface/src/plugins/render/SimpleDisplayPlugin.h b/interface/src/plugins/render/SimpleDisplayPlugin.h deleted file mode 100644 index aca9366b24..0000000000 --- a/interface/src/plugins/render/SimpleDisplayPlugin.h +++ /dev/null @@ -1,36 +0,0 @@ -// -// SimpleDisplayPlugin.h -// -// Created by Bradley Austin Davis on 2014/04/13. -// 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 "DisplayPlugin.h" - -#include - -#include -#include -#include - -class SimpleGlDisplayPlugin : public DisplayPlugin { -public: - virtual void activate(); - virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize, - GLuint overlayTexture, const glm::uvec2& overlaySize); -}; - -template -class SimpleDisplayPlugin : public SimpleGlDisplayPlugin { -public: - virtual glm::ivec2 getTrueMousePosition() const { - return toGlm(_window->mapFromGlobal(QCursor::pos())); - } - -protected: - T * _window; -}; diff --git a/interface/src/plugins/render/Tv3dDisplayPlugin.cpp b/interface/src/plugins/render/Tv3dDisplayPlugin.cpp deleted file mode 100644 index b86e20831f..0000000000 --- a/interface/src/plugins/render/Tv3dDisplayPlugin.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// -// Tv3dDisplayPlugin.cpp -// -// Created by Bradley Austin Davis on 2014/04/13. -// 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 "Tv3dDisplayPlugin.h" - -const QString Tv3dDisplayPlugin::NAME("Tv3dDisplayPlugin"); - -const QString & Tv3dDisplayPlugin::getName() { - return NAME; -} - - -void Tv3dDisplayPlugin::overrideOffAxisFrustum( - float& left, float& right, float& bottom, float& top, - float& nearVal, float& farVal, - glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const { - -#if 0 - if (_activeEye) { - left = _activeEye->left; - right = _activeEye->right; - bottom = _activeEye->bottom; - top = _activeEye->top; - } -#endif - -} - - -#if 0 - } else if (TV3DManager::isConnected()) { - - TV3DManager::display(_myCamera); - - } else { -#endif diff --git a/interface/src/plugins/render/Tv3dDisplayPlugin.h b/interface/src/plugins/render/Tv3dDisplayPlugin.h deleted file mode 100644 index 5c178b7260..0000000000 --- a/interface/src/plugins/render/Tv3dDisplayPlugin.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// Tv3dDisplayPlugin.h -// -// Created by Bradley Austin Davis on 2014/04/13. -// 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 "StereoDisplayPlugin.h" - -class Tv3dDisplayPlugin : public StereoDisplayPlugin { - Q_OBJECT -public: - static const QString NAME; - virtual const QString & getName(); - - virtual void overrideOffAxisFrustum( - float& left, float& right, float& bottom, float& top, - float& nearVal, float& farVal, - glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const; - -}; diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 6e59f4452f..7c6620e9e1 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -194,7 +194,7 @@ void ApplicationOverlay::renderOverlay() { Overlays& overlays = qApp->getOverlays(); glm::uvec2 size = qApp->getCanvasSize(); - if (!_framebufferObject || size == toGlm(_framebufferObject->size())) { + if (!_framebufferObject || size != toGlm(_framebufferObject->size())) { if(_framebufferObject) { delete _framebufferObject; } @@ -511,7 +511,7 @@ void ApplicationOverlay::computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origi // Intersection UI overlay space glm::vec3 worldSpaceDirection = overlayOrientation * overlaySpaceDirection; - glm::vec3 intersectionWithUi = glm::normalize(worldSpaceDirection) * _oculusUIRadius; + glm::vec3 intersectionWithUi = glm::normalize(worldSpaceDirection) * _hmdUIRadius; intersectionWithUi += overlayPosition; // Intersection in world space diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index 29f4934c82..c18cbdbe30 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -82,6 +82,8 @@ private: float _magSizeMult[NUMBER_OF_RETICLES]; quint64 _lastMouseMove; bool _magnifier; + float _hmdUIRadius{ 1.0 }; + float _alpha = 1.0f; float _trailingAudioLoudness; diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index e9d7e1509c..0537c62b38 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -294,7 +294,7 @@ unsigned int Overlays::getOverlayAtPoint(const glm::vec2& point) { if (qApp->isHMDMode()) { pointCopy = qApp->getApplicationOverlay().screenToOverlay(point); } - + QReadLocker lock(&_lock); QMapIterator i(_overlaysHUD); i.toBack(); diff --git a/libraries/render-utils/src/GlWindow.cpp b/libraries/render-utils/src/GlWindow.cpp new file mode 100644 index 0000000000..011198e7c0 --- /dev/null +++ b/libraries/render-utils/src/GlWindow.cpp @@ -0,0 +1,77 @@ +// +// Created by Bradley Austin Davis on 2015/05/21 +// 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 "GlWindow.h" + +#include +#include + +static QSurfaceFormat getDefaultFormat() { + QSurfaceFormat format; + // Qt Quick may need a depth and stencil buffer. Always make sure these are available. + format.setDepthBufferSize(16); + format.setStencilBufferSize(8); + format.setVersion(4, 1); +#ifdef DEBUG + format.setOption(QSurfaceFormat::DebugContext); +#endif + format.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile); + return format; +} + +GlWindow::GlWindow(QOpenGLContext * shareContext) : GlWindow(getDefaultFormat(), shareContext) { +} + +GlWindow::GlWindow(const QSurfaceFormat& format, QOpenGLContext * shareContext) { + setSurfaceType(QSurface::OpenGLSurface); + setFormat(format); + _context = new QOpenGLContext; + _context->setFormat(format); + if (shareContext) { + _context->setShareContext(shareContext); + } + _context->create(); +} + +static QOpenGLDebugLogger* logger{ nullptr }; + +GlWindow::~GlWindow() { + if (logger) { + makeCurrent(); + delete logger; + logger = nullptr; + } + _context->doneCurrent(); + _context->deleteLater(); + _context = nullptr; +} + + +void GlWindow::makeCurrent() { + _context->makeCurrent(this); +#ifdef DEBUG + if (!logger) { + logger = new QOpenGLDebugLogger(this); + if (logger->initialize()) { + connect(logger, &QOpenGLDebugLogger::messageLogged, [](const QOpenGLDebugMessage& message) { + qDebug() << message; + }); + logger->startLogging(QOpenGLDebugLogger::LoggingMode::SynchronousLogging); + } + } +#endif +} + +void GlWindow::doneCurrent() { + _context->doneCurrent(); +} + +void GlWindow::swapBuffers() { + _context->swapBuffers(this); +} + diff --git a/libraries/render-utils/src/GlWindow.h b/libraries/render-utils/src/GlWindow.h new file mode 100644 index 0000000000..5d391d0d7b --- /dev/null +++ b/libraries/render-utils/src/GlWindow.h @@ -0,0 +1,29 @@ +// +// Created by Bradley Austin Davis on 2015/05/21 +// 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 +// + +#pragma once +#ifndef hifi_GlWindow_h +#define hifi_GlWindow_h + +#include +#include + +class QOpenGLContext; + +class GlWindow : public QWindow { + QOpenGLContext * _context{ nullptr }; +public: + GlWindow(QOpenGLContext * shareContext = nullptr); + GlWindow(const QSurfaceFormat& format, QOpenGLContext * shareContext = nullptr); + virtual ~GlWindow(); + void makeCurrent(); + void doneCurrent(); + void swapBuffers(); +}; + +#endif \ No newline at end of file diff --git a/libraries/render-utils/src/GlowEffect.cpp b/libraries/render-utils/src/GlowEffect.cpp index 4413a3c5cc..07c2e0e9c6 100644 --- a/libraries/render-utils/src/GlowEffect.cpp +++ b/libraries/render-utils/src/GlowEffect.cpp @@ -175,11 +175,12 @@ gpu::FramebufferPointer GlowEffect::render() { _diffuseProgram->release(); } + destFBO = oldDiffusedFBO; + glBindFramebuffer(GL_FRAMEBUFFER, 0); // add diffused texture to the primary glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(newDiffusedFBO->getRenderBuffer(0))); - destFBO = oldDiffusedFBO; glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(destFBO)); glViewport(0, 0, framebufferSize.width(), framebufferSize.height()); _addSeparateProgram->bind(); diff --git a/libraries/render-utils/src/OffscreenGlCanvas.cpp b/libraries/render-utils/src/OffscreenGlCanvas.cpp index 0e5d4928d8..dc9205a246 100644 --- a/libraries/render-utils/src/OffscreenGlCanvas.cpp +++ b/libraries/render-utils/src/OffscreenGlCanvas.cpp @@ -11,6 +11,7 @@ #include "OffscreenGlCanvas.h" +#include OffscreenGlCanvas::OffscreenGlCanvas() { } @@ -27,16 +28,35 @@ void OffscreenGlCanvas::create(QOpenGLContext* sharedContext) { format.setMajorVersion(4); format.setMinorVersion(1); format.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile); +#ifdef DEBUG + format.setOption(QSurfaceFormat::DebugContext); +#endif _context.setFormat(format); } _context.create(); _offscreenSurface.setFormat(_context.format()); _offscreenSurface.create(); + } bool OffscreenGlCanvas::makeCurrent() { - return _context.makeCurrent(&_offscreenSurface); + bool result = _context.makeCurrent(&_offscreenSurface); + +#ifdef DEBUG + if (result && !_logger) { + _logger = new QOpenGLDebugLogger(this); + if (_logger->initialize()) { + connect(_logger, &QOpenGLDebugLogger::messageLogged, [](const QOpenGLDebugMessage& message) { + qDebug() << message; + }); + _logger->enableMessages(QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::AnyType, QOpenGLDebugMessage::HighSeverity); + _logger->startLogging(QOpenGLDebugLogger::LoggingMode::SynchronousLogging); + } + } +#endif + + return result; } void OffscreenGlCanvas::doneCurrent() { diff --git a/libraries/render-utils/src/OffscreenGlCanvas.h b/libraries/render-utils/src/OffscreenGlCanvas.h index 5a64a4cf10..545d2269b7 100644 --- a/libraries/render-utils/src/OffscreenGlCanvas.h +++ b/libraries/render-utils/src/OffscreenGlCanvas.h @@ -15,16 +15,22 @@ #include #include +class QOpenGLDebugLogger; + class OffscreenGlCanvas : public QObject { public: OffscreenGlCanvas(); void create(QOpenGLContext* sharedContext = nullptr); bool makeCurrent(); void doneCurrent(); + QOpenGLContext* getContext() { + return &_context; + } protected: QOpenGLContext _context; QOffscreenSurface _offscreenSurface; + QOpenGLDebugLogger * _logger{ nullptr }; }; diff --git a/libraries/render-utils/src/OffscreenGlContext.cpp b/libraries/render-utils/src/OffscreenGlContext.cpp deleted file mode 100644 index 96f0a93c3a..0000000000 --- a/libraries/render-utils/src/OffscreenGlContext.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// -// OffscreenGlCanvas.cpp -// interface/src/renderer -// -// Created by Bradley Austin Davis on 2014/04/09. -// 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 "OffscreenGlContext.h" - -OffscreenGlContext::OffscreenGlContext() { -} - -void OffscreenGlContext::create(QOpenGLContext * sharedContext) { - QSurfaceFormat format; - format.setDepthBufferSize(16); - format.setStencilBufferSize(8); - format.setMajorVersion(4); - format.setMinorVersion(1); - format.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile); - - _context.setFormat(format); - if (nullptr != sharedContext) { - _context.setShareContext(sharedContext); - } - _context.create(); - - _offscreenSurface.setFormat(_context.format()); - _offscreenSurface.create(); -} - -bool OffscreenGlContext::makeCurrent() { - return _context.makeCurrent(&_offscreenSurface); -} - -void OffscreenGlContext::doneCurrent() { - _context.doneCurrent(); -} - diff --git a/libraries/render-utils/src/OffscreenGlContext.h b/libraries/render-utils/src/OffscreenGlContext.h deleted file mode 100644 index c0d22b268f..0000000000 --- a/libraries/render-utils/src/OffscreenGlContext.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// OffscreenGlCanvas.h -// interface/src/renderer -// -// Created by Bradley Austin Davis on 2014/04/09. -// 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 -#ifndef hifi_OffscreenGlContext_h -#define hifi_OffscreenGlContext_h - -#include -#include - -class OffscreenGlContext : public QObject { -public: - OffscreenGlContext(); - void create(QOpenGLContext * sharedContext = nullptr); - bool makeCurrent(); - void doneCurrent(); - QOpenGLContext * getContext() { - return &_context; - } - -protected: - QOpenGLContext _context; - QOffscreenSurface _offscreenSurface; -}; - -#endif // hifi_OffscreenGlCanvas_h From e69362dadc064655897cfc0ddbc6d81a599c3f2a Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 22 May 2015 17:51:59 -0700 Subject: [PATCH 011/552] Working on stereo rendering --- CMakeLists.txt | 5 +- cmake/externals/boostconfig/CMakeLists.txt | 18 ++ cmake/externals/oglplus/CMakeLists.txt | 18 ++ cmake/modules/FindBoostConfig.cmake | 24 ++ cmake/modules/FindOGLPLUS.cmake | 24 ++ interface/CMakeLists.txt | 9 + interface/src/Application.cpp | 79 ++--- .../plugins/display/SimpleDisplayPlugin.cpp | 74 ++++- .../src/plugins/display/SimpleDisplayPlugin.h | 32 +- .../src/plugins/display/Tv3dDisplayPlugin.cpp | 293 ++++++++++++++---- .../src/plugins/display/Tv3dDisplayPlugin.h | 17 +- .../plugins/display/WindowDisplayPlugin.cpp | 18 -- .../src/plugins/display/WindowDisplayPlugin.h | 1 - interface/src/ui/ApplicationOverlay.cpp | 4 +- interface/src/ui/ApplicationOverlay.h | 6 + libraries/render-utils/src/GlWindow.cpp | 21 +- libraries/render-utils/src/GlWindow.h | 7 +- .../render-utils/src/OffscreenGlCanvas.cpp | 2 +- .../render-utils/src/OffscreenGlCanvas.h | 2 + 19 files changed, 477 insertions(+), 177 deletions(-) create mode 100644 cmake/externals/boostconfig/CMakeLists.txt create mode 100644 cmake/externals/oglplus/CMakeLists.txt create mode 100644 cmake/modules/FindBoostConfig.cmake create mode 100644 cmake/modules/FindOGLPLUS.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index e267ba97c3..6ce714b508 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -178,8 +178,11 @@ option(GET_SOXR "Get Soxr library automatically as external project" 1) option(GET_TBB "Get Threading Building Blocks library automatically as external project" 1) option(GET_LIBOVR "Get LibOVR library automatically as external project" 1) option(GET_OPENVR "Get OpenVR library automatically as external project" 1) -option(USE_NSIGHT "Attempt to find the nSight libraries" 1) option(GET_VHACD "Get V-HACD library automatically as external project" 1) +option(GET_BOOSTCONFIG "Get Boost-config library automatically as external project" 1) +option(GET_OGLPLUS "Get OGLplus library automatically as external project" 1) + +option(USE_NSIGHT "Attempt to find the nSight libraries" 1) if (WIN32) option(GET_GLEW "Get GLEW library automatically as external project" 1) diff --git a/cmake/externals/boostconfig/CMakeLists.txt b/cmake/externals/boostconfig/CMakeLists.txt new file mode 100644 index 0000000000..8785e0d7c7 --- /dev/null +++ b/cmake/externals/boostconfig/CMakeLists.txt @@ -0,0 +1,18 @@ +set(EXTERNAL_NAME boostconfig) +string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) + +include(ExternalProject) +ExternalProject_Add( + ${EXTERNAL_NAME} + URL https://github.com/boostorg/config/archive/boost-1.58.0.zip + URL_MD5 42fa673bae2b7645a22736445e80eb8d + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + LOG_DOWNLOAD 1 +) + +ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) + +set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include CACHE TYPE INTERNAL) + diff --git a/cmake/externals/oglplus/CMakeLists.txt b/cmake/externals/oglplus/CMakeLists.txt new file mode 100644 index 0000000000..1413edce34 --- /dev/null +++ b/cmake/externals/oglplus/CMakeLists.txt @@ -0,0 +1,18 @@ +set(EXTERNAL_NAME oglplus) +string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) + +include(ExternalProject) +ExternalProject_Add( + ${EXTERNAL_NAME} + URL http://softlayer-dal.dl.sourceforge.net/project/oglplus/oglplus-0.61.x/oglplus-0.61.0.zip + URL_MD5 bb55038c36c660d2b6c7be380414fa60 + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + LOG_DOWNLOAD 1 +) + +ExternalProject_Get_Property(${EXTERNAL_NAME} SOURCE_DIR) + +set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${SOURCE_DIR}/include ${SOURCE_DIR}/implement CACHE TYPE INTERNAL) + diff --git a/cmake/modules/FindBoostConfig.cmake b/cmake/modules/FindBoostConfig.cmake new file mode 100644 index 0000000000..90682d2425 --- /dev/null +++ b/cmake/modules/FindBoostConfig.cmake @@ -0,0 +1,24 @@ +# +# Try to find BOOSTCONFIG include path. +# Once done this will define +# +# BOOSTCONFIG_INCLUDE_DIRS +# +# Created by Bradley Austin Davis on 2015/05/22 +# 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 +# + +# setup hints for BOOSTCONFIG search +include("${MACRO_DIR}/HifiLibrarySearchHints.cmake") +hifi_library_search_hints("BOOSTCONFIG") + +# locate header +find_path(BOOSTCONFIG_INCLUDE_DIRS "boost/config.hpp" HINTS ${BOOSTCONFIG_SEARCH_DIRS}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(BOOSTCONFIG DEFAULT_MSG BOOSTCONFIG_INCLUDE_DIRS) + +mark_as_advanced(BOOSTCONFIG_INCLUDE_DIRS BOOSTCONFIG_SEARCH_DIRS) \ No newline at end of file diff --git a/cmake/modules/FindOGLPLUS.cmake b/cmake/modules/FindOGLPLUS.cmake new file mode 100644 index 0000000000..6ba883ee2c --- /dev/null +++ b/cmake/modules/FindOGLPLUS.cmake @@ -0,0 +1,24 @@ +# +# Try to find OGLPLUS include path. +# Once done this will define +# +# OGLPLUS_INCLUDE_DIRS +# +# Created by Bradley Austin Davis on 2015/05/22 +# 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 +# + +# setup hints for OGLPLUS search +include("${MACRO_DIR}/HifiLibrarySearchHints.cmake") +hifi_library_search_hints("oglplus") + +# locate header +find_path(OGLPLUS_INCLUDE_DIRS "oglplus/fwd.hpp" HINTS ${OGLPLUS_SEARCH_DIRS}) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(OGLPLUS DEFAULT_MSG OGLPLUS_INCLUDE_DIRS) + +mark_as_advanced(OGLPLUS_INCLUDE_DIRS OGLPLUS_SEARCH_DIRS) \ No newline at end of file diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 66bb02bbca..bb9960643c 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -128,6 +128,15 @@ add_dependency_external_projects(glm bullet) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PRIVATE ${GLM_INCLUDE_DIRS}) +add_dependency_external_projects(boostconfig) +find_package(BOOSTCONFIG REQUIRED) +target_include_directories(${TARGET_NAME} PUBLIC ${BOOSTCONFIG_INCLUDE_DIRS}) + +add_dependency_external_projects(oglplus) +find_package(OGLPLUS REQUIRED) +target_include_directories(${TARGET_NAME} PUBLIC ${OGLPLUS_INCLUDE_DIRS}) + + add_dependency_external_projects(LibOVR) find_package(LibOVR REQUIRED) target_include_directories(${TARGET_NAME} PRIVATE ${LIBOVR_INCLUDE_DIRS}) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index f72be6ac5b..54f6be1ceb 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1164,7 +1164,7 @@ void Application::keyPressEvent(QKeyEvent* event) { return; } - if (activeWindow() == _window) { + if (hasFocus()) { _keyboardMouseDevice.keyPressEvent(event); bool isShifted = event->modifiers().testFlag(Qt::ShiftModifier); @@ -1386,17 +1386,12 @@ void Application::keyPressEvent(QKeyEvent* event) { } -#define VR_MENU_ONLY_IN_HMD void Application::keyReleaseEvent(QKeyEvent* event) { - if (event->key() == Qt::Key_Alt && _altPressed && _window->isActiveWindow()) { -#ifdef VR_MENU_ONLY_IN_HMD - if (isHMDMode()) { -#endif + if (event->key() == Qt::Key_Alt && _altPressed && hasFocus()) { + if (getActiveDisplayPlugin()->isStereo()) { VrMenu::toggle(); -#ifdef VR_MENU_ONLY_IN_HMD } -#endif } _keysPressed.remove(event->key()); @@ -4700,52 +4695,36 @@ static void addDisplayPluginToMenu(DisplayPluginPointer displayPlugin, bool acti using DisplayPluginList = QVector; +static DisplayPlugin* PLUGIN_POOL[] = { + new LegacyDisplayPlugin(), +#ifdef DEBUG + new NullDisplayPlugin(), +#endif + new Tv3dDisplayPlugin(), + new WindowDisplayPlugin(), + nullptr +}; + // FIXME move to a plugin manager class static const DisplayPluginList & getDisplayPlugins() { static DisplayPluginList RENDER_PLUGINS; static bool init = false; if (!init) { init = true; - DisplayPluginPointer displayPlugin = DisplayPluginPointer(new LegacyDisplayPlugin()); // new WindowDisplayPlugin(); - if (displayPlugin->isSupported()) { - displayPlugin->init(); - RENDER_PLUGINS.push_back(DisplayPluginPointer(displayPlugin)); - QObject::connect(displayPlugin.data(), &DisplayPlugin::requestRender, [] { - qApp->paintGL(); - }); - QObject::connect(displayPlugin.data(), &DisplayPlugin::recommendedFramebufferSizeChanged, [](const QSize & size) { - qApp->resizeGL(); - }); - addDisplayPluginToMenu(displayPlugin, true); - } - -#ifdef DEBUG - displayPlugin = DisplayPluginPointer(new NullDisplayPlugin()); - if (displayPlugin->isSupported()) { - addDisplayPluginToMenu(displayPlugin); - displayPlugin->init(); - RENDER_PLUGINS.push_back(DisplayPluginPointer(displayPlugin)); - } -#endif - - displayPlugin = DisplayPluginPointer(new Tv3dDisplayPlugin()); - if (displayPlugin->isSupported()) { - addDisplayPluginToMenu(displayPlugin); - displayPlugin->init(); - RENDER_PLUGINS.push_back(DisplayPluginPointer(displayPlugin)); - } - - displayPlugin = DisplayPluginPointer(new WindowDisplayPlugin()); - if (displayPlugin->isSupported()) { - addDisplayPluginToMenu(displayPlugin); - displayPlugin->init(); - RENDER_PLUGINS.push_back(DisplayPluginPointer(displayPlugin)); - QObject::connect(displayPlugin.data(), &DisplayPlugin::requestRender, [] { - qApp->paintGL(); - }); - QObject::connect(displayPlugin.data(), &DisplayPlugin::recommendedFramebufferSizeChanged, [](const QSize & size) { - qApp->resizeGL(); - }); + for (int i = 0; PLUGIN_POOL[i]; ++i) { + DisplayPlugin * plugin = PLUGIN_POOL[i]; + if (plugin->isSupported()) { + plugin->init(); + QObject::connect(plugin, &DisplayPlugin::requestRender, [] { + qApp->paintGL(); + }); + QObject::connect(plugin, &DisplayPlugin::recommendedFramebufferSizeChanged, [](const QSize & size) { + qApp->resizeGL(); + }); + DisplayPluginPointer pluginPointer(plugin); + addDisplayPluginToMenu(pluginPointer, plugin == *PLUGIN_POOL); + RENDER_PLUGINS.push_back(pluginPointer); + } } } return RENDER_PLUGINS; @@ -4773,6 +4752,10 @@ void Application::updateDisplayMode() { newDisplayPlugin->deactivate(); _offscreenContext->makeCurrent(); } + + 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/plugins/display/SimpleDisplayPlugin.cpp b/interface/src/plugins/display/SimpleDisplayPlugin.cpp index af02b0e1ce..3c7ec2fb3f 100644 --- a/interface/src/plugins/display/SimpleDisplayPlugin.cpp +++ b/interface/src/plugins/display/SimpleDisplayPlugin.cpp @@ -10,12 +10,13 @@ #include "SimpleDisplayPlugin.h" #include #include +#include #include #include "DependencyManager.h" #include "TextureCache.h" #include "gpu/GLBackend.h" - +#include "OffscreenUi.h" void SimpleGlDisplayPlugin::activate() { makeCurrent(); @@ -87,3 +88,74 @@ void SimpleGlDisplayPlugin::display(GLuint sceneTexture, const glm::uvec2& scene glFinish(); } +bool GlWindowDisplayPlugin::eventFilter(QObject* object, QEvent* event) { + if (qApp->eventFilter(object, event)) { + return true; + } + + auto offscreenUi = DependencyManager::get(); + if (offscreenUi->eventFilter(object, event)) { + return true; + } + + switch (event->type()) { + case QEvent::KeyPress: + case QEvent::KeyRelease: + QCoreApplication::sendEvent(QCoreApplication::instance(), event); + break; + + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::FocusIn: + case QEvent::FocusOut: + case QEvent::Resize: + case QEvent::MouseMove: + QCoreApplication::sendEvent(QCoreApplication::instance(), event); + break; + default: + break; + } + return false; +} + + +static QSurfaceFormat getPluginFormat() { + QSurfaceFormat format; + // Qt Quick may need a depth and stencil buffer. Always make sure these are available. + format.setDepthBufferSize(16); + format.setStencilBufferSize(8); + format.setVersion(4, 1); +#ifdef DEBUG + format.setOption(QSurfaceFormat::DebugContext); +#endif + format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile); + return format; +} + + +void GlWindowDisplayPlugin::activate() { + Q_ASSERT(nullptr == _window); + _window = new GlWindow(getPluginFormat(), QOpenGLContext::currentContext()); + _window->installEventFilter(this); + DependencyManager::get()->setProxyWindow(_window); +} + +void GlWindowDisplayPlugin::deactivate() { + Q_ASSERT(nullptr != _window); + _window->hide(); + _window->destroy(); + _window->deleteLater(); + _window = nullptr; +} + +QSize GlWindowDisplayPlugin::getDeviceSize() const { + return _window->geometry().size() * _window->devicePixelRatio(); +} + +glm::ivec2 GlWindowDisplayPlugin::getCanvasSize() const { + return toGlm(_window->geometry().size()); +} + +bool GlWindowDisplayPlugin::hasFocus() const { + return _window->isActive(); +} diff --git a/interface/src/plugins/display/SimpleDisplayPlugin.h b/interface/src/plugins/display/SimpleDisplayPlugin.h index 036b50d44a..ca86d85875 100644 --- a/interface/src/plugins/display/SimpleDisplayPlugin.h +++ b/interface/src/plugins/display/SimpleDisplayPlugin.h @@ -52,31 +52,11 @@ protected: class GlWindowDisplayPlugin : public SimpleDisplayPlugin { public: - virtual void activate() { - Q_ASSERT(nullptr == _window); - _window = new GlWindow(QOpenGLContext::currentContext()); - } - - virtual void deactivate() { - Q_ASSERT(nullptr != _window); - _window->hide(); - _window->destroy(); - _window->deleteLater(); - _window = nullptr; - } - - virtual QSize getDeviceSize() const final { - return _window->geometry().size() * _window->devicePixelRatio(); - } - - virtual glm::ivec2 getCanvasSize() const final { - return toGlm(_window->geometry().size()); - } - - virtual bool hasFocus() const { - return _window->isActive(); - } - - + virtual void activate(); + virtual void deactivate(); + virtual QSize getDeviceSize() const final; + virtual glm::ivec2 getCanvasSize() const final; + virtual bool hasFocus() const; + virtual bool eventFilter(QObject* object, QEvent* event); }; diff --git a/interface/src/plugins/display/Tv3dDisplayPlugin.cpp b/interface/src/plugins/display/Tv3dDisplayPlugin.cpp index 0173a6fc33..5b35478b57 100644 --- a/interface/src/plugins/display/Tv3dDisplayPlugin.cpp +++ b/interface/src/plugins/display/Tv3dDisplayPlugin.cpp @@ -1,4 +1,3 @@ -// // Tv3dDisplayPlugin.cpp // // Created by Bradley Austin Davis on 2014/04/13. @@ -10,6 +9,44 @@ #include "Tv3dDisplayPlugin.h" #include +#include +#include + +#include "gpu/Texture.h" +#include "gpu/GLBackend.h" +#include "PathUtils.h" + +#include "Application.h" +#include "ui/ApplicationOverlay.h" + + +#include +#define OGLPLUS_LOW_PROFILE 1 +#define OGLPLUS_USE_GLEW 1 +#define OGLPLUS_USE_BOOST_CONFIG 1 +#define OGLPLUS_NO_SITE_CONFIG 1 +#define OGLPLUS_USE_GLCOREARB_H 0 +#include + +#pragma warning(disable : 4068) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Warc-performSelector-leaks" +#pragma warning( disable : 4244 4267 4065 4101) +#include +#include +#include +#include +#include +#include +#include +#pragma warning( default : 4244 4267 4065 4101) +#pragma clang diagnostic pop + +typedef std::shared_ptr ShapeWrapperPtr; +typedef std::shared_ptr BufferPtr; +typedef std::shared_ptr VertexArrayPtr; +typedef std::shared_ptr ProgramPtr; +typedef oglplus::Uniform Mat4Uniform; const QString Tv3dDisplayPlugin::NAME("Tv3dDisplayPlugin"); @@ -17,84 +54,216 @@ const QString & Tv3dDisplayPlugin::getName() { return NAME; } +Tv3dDisplayPlugin::Tv3dDisplayPlugin() { + connect(&_timer, &QTimer::timeout, this, [&] { + emit requestRender(); + }); +} + +gpu::TexturePointer _crosshairTexture; + + +void compileProgram(ProgramPtr & result, std::string vs, std::string fs) { + using namespace oglplus; + try { + result = ProgramPtr(new Program()); + // attach the shaders to the program + result->AttachShader( + VertexShader() + .Source(GLSLSource(vs)) + .Compile() + ); + result->AttachShader( + FragmentShader() + .Source(GLSLSource(fs)) + .Compile() + ); + result->Link(); + } catch (ProgramBuildError & err) { + qFatal((const char*)err.Message); + result.reset(); + } +} + + +ShapeWrapperPtr loadPlane(ProgramPtr program, float aspect) { + using namespace oglplus; + Vec3f a(1, 0, 0); + Vec3f b(0, 1, 0); + if (aspect > 1) { + b[1] /= aspect; + } else { + a[0] *= aspect; + } + return ShapeWrapperPtr( + new shapes::ShapeWrapper({ "Position", "TexCoord" }, shapes::Plane(a, b), *program) + ); +} + + +static const char * QUAD_VS = R"VS(#version 330 + +uniform mat4 Projection = mat4(1); +uniform mat4 ModelView = mat4(1); +uniform vec2 UvMultiplier = vec2(1); + +layout(location = 0) in vec3 Position; +layout(location = 1) in vec2 TexCoord; + +out vec2 vTexCoord; + +void main() { + gl_Position = Projection * ModelView * vec4(Position, 1); + vTexCoord = TexCoord * UvMultiplier; +} +)VS"; + +static const char * QUAD_FS = R"FS(#version 330 +uniform sampler2D sampler; +uniform float Alpha = 1.0; + +in vec2 vTexCoord; +out vec4 vFragColor; + +void main() { + vec4 c = texture(sampler, vTexCoord); + c.a = min(Alpha, c.a); + vFragColor = c; + //vFragColor = vec4(fract(vTexCoord), log(vTexCoord.x), 1.0); +} +)FS"; + +static ProgramPtr program; +static ShapeWrapperPtr plane; + void Tv3dDisplayPlugin::display( GLuint sceneTexture, const glm::uvec2& sceneSize, GLuint overlayTexture, const glm::uvec2& overlaySize) { + QSize size = getDeviceSize(); makeCurrent(); - glDisable(GL_LIGHTING); - glDisable(GL_DEPTH_TEST); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); + + if (!program) { + using namespace oglplus; + Context::BlendFunc(BlendFunction::SrcAlpha, BlendFunction::OneMinusSrcAlpha); + Context::Disable(Capability::Blend); + Context::Disable(Capability::DepthTest); + Context::Disable(Capability::CullFace); + + program = ProgramPtr(new oglplus::Program()); + compileProgram(program, QUAD_VS, QUAD_FS); + plane = loadPlane(program, 1.0f); + _crosshairTexture = DependencyManager::get()-> + getImageTexture(PathUtils::resourcesPath() + "images/sixense-reticle.png"); + } + + glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glEnable(GL_TEXTURE_2D); + glViewport(0, 0, size.width(), size.height()); + Mat4Uniform(*program, "ModelView").Set(mat4()); + Mat4Uniform(*program, "Projection").Set(mat4()); + glBindTexture(GL_TEXTURE_2D, sceneTexture); + plane->Draw(); - if (sceneTexture) { - glBindTexture(GL_TEXTURE_2D, sceneTexture); - glBegin(GL_QUADS); - glTexCoord2f(0, 0); - glVertex2f(-1, -1); - glTexCoord2f(1, 0); - glVertex2f(+1, -1); - glTexCoord2f(1, 1); - glVertex2f(+1, +1); - glTexCoord2f(0, 1); - glVertex2f(-1, +1); - glEnd(); + const float overlayAspect = aspect(toGlm(size)); + const GLfloat distance = 1.0f; + const GLfloat halfQuadHeight = distance * tan(DEFAULT_FIELD_OF_VIEW_DEGREES); + const GLfloat halfQuadWidth = halfQuadHeight * (float)size.width() / (float)size.height(); + const GLfloat quadWidth = halfQuadWidth * 2.0f; + const GLfloat quadHeight = halfQuadHeight * 2.0f; + + vec3 quadSize(quadWidth, quadHeight, 1.0f); + quadSize = vec3(1.0f) / quadSize; + + using namespace oglplus; + + Context::Enable(Capability::Blend); + glBindTexture(GL_TEXTURE_2D, overlayTexture); + + mat4 pr = glm::perspective(glm::radians(DEFAULT_FIELD_OF_VIEW_DEGREES), aspect(toGlm(size)), DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP); + Mat4Uniform(*program, "Projection").Set(pr); + + MatrixStack mv; + mv.translate(vec3(0, 0, -distance)).scale(vec3(0.7f, 0.7f / overlayAspect, 1.0f)); // .scale(vec3(quadWidth, quadHeight, 1.0)); + + QRect r(QPoint(0, 0), QSize(size.width() / 2, size.height())); + for (int i = 0; i < 2; ++i) { + Context::Viewport(r.x(), r.y(), r.width(), r.height()); + Mat4Uniform(*program, "ModelView").Set(mv.top()); + plane->Draw(); + r.moveLeft(r.width()); } - if (overlayTexture) { - glEnable(GL_BLEND); - glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); - glBindTexture(GL_TEXTURE_2D, overlayTexture); - - QSize size = getDeviceSize(); - QRect r(QPoint(0, 0), QSize(size.width() / 2, size.height())); - for (int i = 0; i < 2; ++i) { - glViewport(r.x(), r.y(), r.width(), r.height()); - glScissor(r.x(), r.y(), r.width(), r.height()); - - glBegin(GL_QUADS); - glTexCoord2f(0, 0); - glVertex2f(-1, -1); - glTexCoord2f(1, 0); - glVertex2f(+1, -1); - glTexCoord2f(1, 1); - glVertex2f(+1, +1); - glTexCoord2f(0, 1); - glVertex2f(-1, +1); - glEnd(); - - r.moveLeft(r.width()); - } - - glBindTexture(GL_TEXTURE_2D, 0); - glDisable(GL_BLEND); + glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_crosshairTexture)); + glm::vec2 canvasSize = qApp->getCanvasSize(); + glm::vec2 mouse = qApp->getMouse(); + mouse /= canvasSize; + mouse *= 2.0f; + mouse -= 1.0f; + mouse.y *= -1.0f; + mv.translate(mouse); + mv.scale(0.1f); + Mat4Uniform(*program, "ModelView").Set(mv.top()); + r = QRect(QPoint(0, 0), QSize(size.width() / 2, size.height())); + for (int i = 0; i < 2; ++i) { + Context::Viewport(r.x(), r.y(), r.width(), r.height()); + plane->Draw(); + r.moveLeft(r.width()); } - glDisable(GL_TEXTURE_2D); - Q_ASSERT(!glGetError()); - - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - - glEnable(GL_LIGHTING); - glEnable(GL_DEPTH_TEST); - - glFinish(); + Context::Disable(Capability::Blend); } + +void Tv3dDisplayPlugin::activate() { + GlWindowDisplayPlugin::activate(); + _window->installEventFilter(this); + _window->setFlags(Qt::FramelessWindowHint); + auto desktop = QApplication::desktop(); + _window->setGeometry(desktop->screenGeometry()); + _window->setCursor(Qt::BlankCursor); + _window->show(); + + _timer.start(8); +} + +void Tv3dDisplayPlugin::deactivate() { + makeCurrent(); + if (plane) { + plane.reset(); + program.reset(); + _crosshairTexture.reset(); + } + _timer.stop(); + GlWindowDisplayPlugin::deactivate(); +} +/* +std::function Tv3dDisplayPlugin::getMouseTranslator() { + return [=](const QPointF& point){ + QPointF result{ point }; + QSize size = getDeviceSize(); + result.rx() *= 2.0f; + if (result.x() > size.width()) { + result.rx() -= size.width(); + } + return result; + }; +} + +glm::ivec2 Tv3dDisplayPlugin::trueMouseToUiMouse(const glm::ivec2 & position) const { + ivec2 result{ position }; + uvec2 size = getCanvasSize(); + result.x *= 2; + result.x %= size.x; + return result; +} + +*/ + /* void Tv3dDisplayPlugin::activate() { GlWindowDisplayPlugin::activate(); - _window->setFlags(Qt::FramelessWindowHint); _window->setPosition(100, 100); _window->resize(512, 512); _window->setVisible(true); diff --git a/interface/src/plugins/display/Tv3dDisplayPlugin.h b/interface/src/plugins/display/Tv3dDisplayPlugin.h index 5dbfc543b8..a748870abb 100644 --- a/interface/src/plugins/display/Tv3dDisplayPlugin.h +++ b/interface/src/plugins/display/Tv3dDisplayPlugin.h @@ -11,18 +11,23 @@ #pragma once #include "SimpleDisplayPlugin.h" -#include "LegacyDisplayPlugin.h" +#include -class Tv3dDisplayPlugin : public LegacyDisplayPlugin { +class Tv3dDisplayPlugin : public GlWindowDisplayPlugin { Q_OBJECT public: static const QString NAME; virtual const QString & getName(); - + Tv3dDisplayPlugin(); virtual bool isStereo() const final { return true; } void display(GLuint sceneTexture, const glm::uvec2& sceneSize, GLuint overlayTexture, const glm::uvec2& overlaySize); - //virtual bool isMouseOnScreen() const { return true; } - //virtual bool isThrottled() const; - //virtual void preDisplay(); + virtual void activate(); + virtual void deactivate(); + + //virtual std::function getMouseTranslator(); + //virtual glm::ivec2 trueMouseToUiMouse(const glm::ivec2 & position) const; + +private: + QTimer _timer; }; diff --git a/interface/src/plugins/display/WindowDisplayPlugin.cpp b/interface/src/plugins/display/WindowDisplayPlugin.cpp index 662c527821..b904a9d141 100644 --- a/interface/src/plugins/display/WindowDisplayPlugin.cpp +++ b/interface/src/plugins/display/WindowDisplayPlugin.cpp @@ -26,7 +26,6 @@ const QString & WindowDisplayPlugin::getName() { void WindowDisplayPlugin::activate() { GlWindowDisplayPlugin::activate(); - _window->installEventFilter(this); _window->show(); _timer.start(8); } @@ -36,23 +35,6 @@ void WindowDisplayPlugin::deactivate() { GlWindowDisplayPlugin::deactivate(); } -bool WindowDisplayPlugin::eventFilter(QObject* object, QEvent* event) { - switch (event->type()) { - case QEvent::MouseButtonPress: - case QEvent::MouseButtonRelease: - case QEvent::KeyPress: - case QEvent::KeyRelease: - case QEvent::FocusIn: - case QEvent::FocusOut: - case QEvent::Resize: - case QEvent::MouseMove: - QCoreApplication::sendEvent(QCoreApplication::instance(), event); - break; - default: - break; - } - return false; -} #if 0 diff --git a/interface/src/plugins/display/WindowDisplayPlugin.h b/interface/src/plugins/display/WindowDisplayPlugin.h index 1b1d3f81b9..7bc0d5163d 100644 --- a/interface/src/plugins/display/WindowDisplayPlugin.h +++ b/interface/src/plugins/display/WindowDisplayPlugin.h @@ -25,7 +25,6 @@ public: virtual void activate(); virtual void deactivate(); - virtual bool eventFilter(QObject* object, QEvent* event); private: QTimer _timer; }; diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 7c6620e9e1..ea5f74e1c8 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -394,6 +394,7 @@ void ApplicationOverlay::displayOverlayTextureHmd(Camera& whichCamera) { glEnable(GL_LIGHTING); } glPopMatrix(); } +#endif // Draws the FBO texture for 3DTV. void ApplicationOverlay::displayOverlayTextureStereo(Camera& whichCamera, float aspectRatio, float fov) { @@ -442,7 +443,7 @@ void ApplicationOverlay::displayOverlayTextureStereo(Camera& whichCamera, float GLfloat y = -halfQuadHeight; glDisable(GL_DEPTH_TEST); - with_each_texture(_overlays.getTexture(), _newUiTexture, [&] { + with_each_texture(getOverlayTexture(), _newUiTexture, [&] { DependencyManager::get()->renderQuad(glm::vec3(x, y + quadHeight, -distance), glm::vec3(x + quadWidth, y + quadHeight, -distance), glm::vec3(x + quadWidth, y, -distance), @@ -488,7 +489,6 @@ void ApplicationOverlay::displayOverlayTextureStereo(Camera& whichCamera, float glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); glEnable(GL_LIGHTING); } -#endif void ApplicationOverlay::computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction) const { diff --git a/interface/src/ui/ApplicationOverlay.h b/interface/src/ui/ApplicationOverlay.h index c18cbdbe30..d0d50dc114 100644 --- a/interface/src/ui/ApplicationOverlay.h +++ b/interface/src/ui/ApplicationOverlay.h @@ -18,6 +18,8 @@ class Overlays; class QOpenGLFramebufferObject; class QOpenGLTexture; +class PalmData; + const float MAGNIFY_WIDTH = 220.0f; const float MAGNIFY_HEIGHT = 100.0f; const float MAGNIFY_MULT = 2.0f; @@ -42,6 +44,10 @@ public: bool hasMagnifier() const { return _magnifier; } void toggleMagnifier() { _magnifier = !_magnifier; } + // FIXME: remove + void displayOverlayTextureStereo(Camera& whichCamera, float aspectRatio, float fov); + + // Converter from one frame of reference to another. // Frame of reference: // Direction: Ray that represents the spherical values diff --git a/libraries/render-utils/src/GlWindow.cpp b/libraries/render-utils/src/GlWindow.cpp index 011198e7c0..b395140518 100644 --- a/libraries/render-utils/src/GlWindow.cpp +++ b/libraries/render-utils/src/GlWindow.cpp @@ -38,14 +38,14 @@ GlWindow::GlWindow(const QSurfaceFormat& format, QOpenGLContext * shareContext) _context->create(); } -static QOpenGLDebugLogger* logger{ nullptr }; - GlWindow::~GlWindow() { - if (logger) { +#ifdef DEBUG + if (_logger) { makeCurrent(); - delete logger; - logger = nullptr; + delete _logger; + _logger = nullptr; } +#endif _context->doneCurrent(); _context->deleteLater(); _context = nullptr; @@ -55,13 +55,14 @@ GlWindow::~GlWindow() { void GlWindow::makeCurrent() { _context->makeCurrent(this); #ifdef DEBUG - if (!logger) { - logger = new QOpenGLDebugLogger(this); - if (logger->initialize()) { - connect(logger, &QOpenGLDebugLogger::messageLogged, [](const QOpenGLDebugMessage& message) { + if (!_logger) { + _logger = new QOpenGLDebugLogger(this); + if (_logger->initialize()) { + connect(_logger, &QOpenGLDebugLogger::messageLogged, [](const QOpenGLDebugMessage& message) { qDebug() << message; }); - logger->startLogging(QOpenGLDebugLogger::LoggingMode::SynchronousLogging); + _logger->disableMessages(QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::AnyType, QOpenGLDebugMessage::NotificationSeverity); + _logger->startLogging(QOpenGLDebugLogger::LoggingMode::SynchronousLogging); } } #endif diff --git a/libraries/render-utils/src/GlWindow.h b/libraries/render-utils/src/GlWindow.h index 5d391d0d7b..69fb09932e 100644 --- a/libraries/render-utils/src/GlWindow.h +++ b/libraries/render-utils/src/GlWindow.h @@ -14,9 +14,9 @@ #include class QOpenGLContext; +class QOpenGLDebugLogger; class GlWindow : public QWindow { - QOpenGLContext * _context{ nullptr }; public: GlWindow(QOpenGLContext * shareContext = nullptr); GlWindow(const QSurfaceFormat& format, QOpenGLContext * shareContext = nullptr); @@ -24,6 +24,11 @@ public: void makeCurrent(); void doneCurrent(); void swapBuffers(); +private: + QOpenGLContext * _context{ nullptr }; +#ifdef DEBUG + QOpenGLDebugLogger * _logger{ nullptr }; +#endif }; #endif \ No newline at end of file diff --git a/libraries/render-utils/src/OffscreenGlCanvas.cpp b/libraries/render-utils/src/OffscreenGlCanvas.cpp index dc9205a246..a3025bc3f6 100644 --- a/libraries/render-utils/src/OffscreenGlCanvas.cpp +++ b/libraries/render-utils/src/OffscreenGlCanvas.cpp @@ -50,7 +50,7 @@ bool OffscreenGlCanvas::makeCurrent() { connect(_logger, &QOpenGLDebugLogger::messageLogged, [](const QOpenGLDebugMessage& message) { qDebug() << message; }); - _logger->enableMessages(QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::AnyType, QOpenGLDebugMessage::HighSeverity); + _logger->disableMessages(QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::AnyType, QOpenGLDebugMessage::NotificationSeverity); _logger->startLogging(QOpenGLDebugLogger::LoggingMode::SynchronousLogging); } } diff --git a/libraries/render-utils/src/OffscreenGlCanvas.h b/libraries/render-utils/src/OffscreenGlCanvas.h index 545d2269b7..c9578f5a7c 100644 --- a/libraries/render-utils/src/OffscreenGlCanvas.h +++ b/libraries/render-utils/src/OffscreenGlCanvas.h @@ -30,7 +30,9 @@ public: protected: QOpenGLContext _context; QOffscreenSurface _offscreenSurface; +#ifdef DEBUG QOpenGLDebugLogger * _logger{ nullptr }; +#endif }; From b5e6b737c4f3e3c05681272f14cf2050214fd5ad Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 26 May 2015 17:32:41 -0700 Subject: [PATCH 012/552] Working on display plugins --- interface/src/Application.cpp | 198 +++----- interface/src/Application.h | 24 +- interface/src/Camera.cpp | 63 ++- interface/src/Camera.h | 39 +- interface/src/Environment.cpp | 10 +- interface/src/Environment.h | 4 +- interface/src/avatar/SkeletonModel.cpp | 2 + interface/src/devices/TV3DManager.cpp | 2 +- interface/src/plugins/Plugin.h | 2 +- interface/src/plugins/display/DisplayPlugin.h | 50 ++- .../plugins/display/LegacyDisplayPlugin.cpp | 2 + .../src/plugins/display/Tv3dDisplayPlugin.cpp | 212 +-------- .../src/plugins/display/Tv3dDisplayPlugin.h | 1 + .../plugins/display/WindowDisplayPlugin.cpp | 423 +----------------- interface/src/ui/ApplicationOverlay.cpp | 12 +- .../src/ui/overlays/LocalModelsOverlay.cpp | 15 +- libraries/octree/src/ViewFrustum.cpp | 9 +- libraries/octree/src/ViewFrustum.h | 10 +- .../src/AbstractViewStateInterface.h | 4 - .../src/AmbientOcclusionEffect.cpp | 4 +- .../src/DeferredLightingEffect.cpp | 7 +- 21 files changed, 220 insertions(+), 873 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 54f6be1ceb..1ba9db8a99 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -316,7 +316,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _previousScriptLocation("LastScriptLocation"), _scriptsLocationHandle("scriptsLocation"), _fieldOfView("fieldOfView", DEFAULT_FIELD_OF_VIEW_DEGREES), - _viewTransform(), _scaleMirror(1.0f), _rotateMirror(0.0f), _raiseMirror(0.0f), @@ -878,7 +877,7 @@ void Application::paintGL() { // Sync up the View Furstum with the camera // FIXME: it's happening again in the updateSHadow and it shouldn't, this should be the place - loadViewFrustum(_myCamera, _viewFrustum); + _myCamera.loadViewFrustum(_viewFrustum); if (getShadowsEnabled()) { updateShadowMap(); @@ -891,43 +890,40 @@ void Application::paintGL() { auto finalFbo = primaryFbo; glBindFramebuffer(GL_FRAMEBUFFER, gpu::GLBackend::getFramebufferID(primaryFbo)); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glPushMatrix(); { // Viewport is assigned to the size of the framebuffer QSize size = DependencyManager::get()->getFrameBufferSize(); if (displayPlugin->isStereo()) { QRect r(QPoint(0, 0), QSize(size.width() / 2, size.height())); glEnable(GL_SCISSOR_TEST); - for (int i = 0; i < 2; ++i) { + for_each_eye([&](Eye eye){ + // FIXME we need to let the display plugin decide how the geometry works for stereo rendering + // for instance, an interleaved display should have half the vertical resolution, while a side + // by side display for a temporal interleave should have full resolution glViewport(r.x(), r.y(), r.width(), r.height()); glScissor(r.x(), r.y(), r.width(), r.height()); - glMatrixMode(GL_PROJECTION); - // FIXME Fetch the projection matrix from the plugin - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); + // Load the view frustum, used by meshes Camera eyeCamera; - eyeCamera.setRotation(_myCamera.getRotation()); - eyeCamera.setPosition(_myCamera.getPosition()); + eyeCamera.setTransform(displayPlugin->getModelview(eye, _myCamera.getTransform())); + eyeCamera.setProjection(displayPlugin->getProjection(eye, _myCamera.getProjection())); + displaySide(eyeCamera); - glPopMatrix(); + if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) { glm::vec2 mpos = getActiveDisplayPlugin()->getUiMousePosition(); _rearMirrorTools->render(true, QPoint(mpos.x, mpos.y)); } else if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { renderRearViewMirror(_mirrorViewRect); } + }, [&] { r.moveLeft(r.width()); - } + }); glDisable(GL_SCISSOR_TEST); } else { glViewport(0, 0, size.width(), size.height()); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); displaySide(_myCamera); - glPopMatrix(); if (Menu::getInstance()->isOptionChecked(MenuOption::FullscreenMirror)) { glm::vec2 mpos = getActiveDisplayPlugin()->getUiMousePosition(); _rearMirrorTools->render(true, QPoint(mpos.x, mpos.y)); @@ -938,6 +934,8 @@ void Application::paintGL() { finalFbo = DependencyManager::get()->render(); } + glPopMatrix(); + // This might not be needed *right now*. We want to ensure that the FBO rendering // has completed before we start trying to read from it in another context. However // once we have multi-threaded rendering, this will almost certainly be critical, @@ -984,19 +982,6 @@ void Application::showEditEntitiesHelp() { InfoView::show(INFO_EDIT_ENTITIES_PATH); } -void Application::resetCamerasOnResizeGL(Camera& camera, const glm::uvec2& size) { -#if 0 - if (OculusManager::isConnected()) { - OculusManager::configureCamera(camera); - } else if (TV3DManager::isConnected()) { - TV3DManager::configureCamera(camera, size.x, size.y); - } else { -#endif - camera.setProjection(glm::perspective(glm::radians(_fieldOfView.get()), (float)size.x / size.y, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)); -#if 0 - } -#endif -} void Application::resizeEvent(QResizeEvent * event) { resizeGL(); @@ -1014,12 +999,9 @@ void Application::resizeGL() { _renderResolution = toGlm(renderSize); DependencyManager::get()->setFrameBufferSize(renderSize); - resetCamerasOnResizeGL(_myCamera, _renderResolution); - glViewport(0, 0, _renderResolution.x, _renderResolution.y); // shouldn't this account for the menu??? - - updateProjectionMatrix(); - glLoadIdentity(); + _myCamera.setProjection(glm::perspective(glm::radians(_fieldOfView.get()), + aspect(getCanvasSize()), DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)); auto offscreenUi = DependencyManager::get(); offscreenUi->resize(fromGlm(getCanvasSize())); @@ -1031,24 +1013,6 @@ void Application::resizeGL() { Stats::getInstance()->resetWidth(_renderResolution.x, horizontalOffset); } -void Application::updateProjectionMatrix() { - updateProjectionMatrix(_myCamera); -} - -void Application::updateProjectionMatrix(Camera& camera, bool updateViewFrustum) { - _projectionMatrix = camera.getProjection(); - - glMatrixMode(GL_PROJECTION); - glLoadMatrixf(glm::value_ptr(_projectionMatrix)); - - // Tell our viewFrustum about this change, using the application camera - if (updateViewFrustum) { - loadViewFrustum(camera, _viewFrustum); - } - - glMatrixMode(GL_MODELVIEW); -} - void Application::controlledBroadcastToNodes(const QByteArray& packet, const NodeSet& destinationNodeTypes) { foreach(NodeType_t type, destinationNodeTypes) { // Perform the broadcast for one type @@ -2205,7 +2169,7 @@ void Application::updateMouseRay() { PerformanceWarning warn(showWarnings, "Application::updateMouseRay()"); // make sure the frustum is up-to-date - loadViewFrustum(_myCamera, _viewFrustum); + _myCamera.loadViewFrustum(_viewFrustum); PickRay pickRay = computePickRay(getTrueMouseX(), getTrueMouseY()); _mouseRayOrigin = pickRay.origin; @@ -2491,7 +2455,7 @@ void Application::update(float deltaTime) { // to the server. { PerformanceTimer perfTimer("loadViewFrustum"); - loadViewFrustum(_myCamera, _viewFrustum); + _myCamera.loadViewFrustum(_viewFrustum); } quint64 now = usecTimestampNow(); @@ -2826,24 +2790,6 @@ QRect Application::getDesirableApplicationGeometry() { return applicationGeometry; } -///////////////////////////////////////////////////////////////////////////////////// -// loadViewFrustum() -// -// Description: this will load the view frustum bounds for EITHER the head -// or the "myCamera". -// -void Application::loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum) { - // We will use these below, from either the camera or head vectors calculated above - viewFrustum.setProjection(camera.getProjection()); - - // Set the viewFrustum up with the correct position and orientation of the camera - viewFrustum.setPosition(camera.getPosition()); - viewFrustum.setOrientation(camera.getRotation()); - - // Ask the ViewFrustum class to calculate our corners - viewFrustum.calculate(); -} - glm::vec3 Application::getSunDirection() { // Sun direction is in fact just the location of the sun relative to the origin auto skyStage = DependencyManager::get()->getSkyStage(); @@ -2872,7 +2818,7 @@ void Application::updateShadowMap() { glm::vec2(0.0f, 0.5f), glm::vec2(0.5f, 0.5f) }; float frustumScale = 1.0f / (_viewFrustum.getFarClip() - _viewFrustum.getNearClip()); - loadViewFrustum(_myCamera, _viewFrustum); + _myCamera.loadViewFrustum(_viewFrustum); int matrixCount = 1; //int targetSize = fbo->width(); @@ -2944,28 +2890,18 @@ void Application::updateShadowMap() { glMatrixMode(GL_PROJECTION); glPushMatrix(); - glLoadIdentity(); - glOrtho(minima.x, maxima.x, minima.y, maxima.y, -maxima.z, -minima.z); - - glm::mat4 projAgain; - glGetFloatv(GL_PROJECTION_MATRIX, (GLfloat*)&projAgain); - + glm::mat4 proj = glm::ortho(minima.x, maxima.x, minima.y, maxima.y, -maxima.z, -minima.z); + glLoadMatrixf(glm::value_ptr(proj)); glMatrixMode(GL_MODELVIEW); glPushMatrix(); - glLoadIdentity(); - glm::vec3 axis = glm::axis(inverseRotation); - glRotatef(glm::degrees(glm::angle(inverseRotation)), axis.x, axis.y, axis.z); + glLoadMatrixf(glm::value_ptr(glm::mat4_cast(inverseRotation))); - // store view matrix without translation, which we'll use for precision-sensitive objects - updateUntranslatedViewMatrix(); - // Equivalent to what is happening with _untranslatedViewMatrix and the _viewMatrixTranslation // the viewTransofmr object is updatded with the correct values and saved, // this is what is used for rendering the Entities and avatars Transform viewTransform; viewTransform.setRotation(rotation); - // viewTransform.postTranslate(shadowFrustumCenter); setViewTransform(viewTransform); @@ -3003,7 +2939,6 @@ void Application::updateShadowMap() { glMatrixMode(GL_MODELVIEW); } -// glViewport(0, 0, _glWidget->getDeviceWidth(), _glWidget->getDeviceHeight()); activeRenderingThread = nullptr; } @@ -3118,16 +3053,23 @@ const ViewFrustum* Application::getDisplayViewFrustum() const { return &_displayViewFrustum; } -void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs::RenderSide renderSide) { +void Application::displaySide(const Camera& theCamera, bool selfAvatarOnly) { activeRenderingThread = QThread::currentThread(); PROFILE_RANGE(__FUNCTION__); PerformanceTimer perfTimer("display"); PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide()"); - // transform by eye offset // load the view frustum - loadViewFrustum(theCamera, _displayViewFrustum); + theCamera.loadViewFrustum(_displayViewFrustum); + // Load the legacy GL stacks, used by entities (for now) + glMatrixMode(GL_PROJECTION); + glLoadMatrixf(glm::value_ptr(theCamera.getProjection())); + + glMatrixMode(GL_MODELVIEW); + glLoadMatrixf(glm::value_ptr(glm::inverse(theCamera.getTransform()))); + + // FIXME just flip the texture coordinates // flip x if in mirror mode (also requires reversing winding order for backface culling) if (theCamera.getMode() == CAMERA_MODE_MIRROR) { glScalef(-1.0f, 1.0f, 1.0f); @@ -3137,17 +3079,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs glFrontFace(GL_CCW); } - // transform view according to theCamera - // could be myCamera (if in normal mode) - // or could be viewFrustumOffsetCamera if in offset mode - glm::quat rotation = theCamera.getRotation(); - glm::vec3 axis = glm::axis(rotation); - glRotatef(-glm::degrees(glm::angle(rotation)), axis.x, axis.y, axis.z); - - // store view matrix without translation, which we'll use for precision-sensitive objects - updateUntranslatedViewMatrix(-theCamera.getPosition()); - // Equivalent to what is happening with _untranslatedViewMatrix and the _viewMatrixTranslation // the viewTransofmr object is updatded with the correct values and saved, // this is what is used for rendering the Entities and avatars @@ -3157,17 +3089,8 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs if (theCamera.getMode() == CAMERA_MODE_MIRROR) { viewTransform.setScale(Transform::Vec3(-1.0f, 1.0f, 1.0f)); } - if (renderSide != RenderArgs::MONO) { - glm::mat4 invView = glm::inverse(_untranslatedViewMatrix); - - viewTransform.evalFromRawMatrix(invView); - viewTransform.preTranslate(_viewMatrixTranslation); - } - setViewTransform(viewTransform); - glTranslatef(_viewMatrixTranslation.x, _viewMatrixTranslation.y, _viewMatrixTranslation.z); - // Setup 3D lights (after the camera transform, so that they are positioned in world space) { PerformanceTimer perfTimer("lights"); @@ -3208,7 +3131,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs if (Menu::getInstance()->isOptionChecked(MenuOption::Atmosphere)) { // TODO: handle this correctly for zones - const EnvironmentData& closestData = _environment.getClosestData(theCamera.getPosition()); + const EnvironmentData& closestData = _environment.getClosestData(_displayViewFrustum.getPosition()); if (closestData.getHasStars()) { const float APPROXIMATE_DISTANCE_FROM_HORIZON = 0.1f; @@ -3216,7 +3139,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs glm::vec3 sunDirection = (getAvatarPosition() - closestData.getSunLocation()) / closestData.getAtmosphereOuterRadius(); - float height = glm::distance(theCamera.getPosition(), closestData.getAtmosphereCenter()); + float height = glm::distance(_displayViewFrustum.getPosition(), closestData.getAtmosphereCenter()); if (height < closestData.getAtmosphereInnerRadius()) { // If we're inside the atmosphere, then determine if our keyLight is below the horizon alpha = 0.0f; @@ -3255,7 +3178,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs PerformanceTimer perfTimer("atmosphere"); PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::displaySide() ... atmosphere..."); - _environment.renderAtmospheres(theCamera); + _environment.renderAtmospheres(_displayViewFrustum.getPosition()); } } @@ -3303,7 +3226,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs if (theCamera.getMode() == CAMERA_MODE_MIRROR) { renderMode = RenderArgs::MIRROR_RENDER_MODE; } - _entities.render(renderMode, renderSide, renderDebugFlags); + _entities.render(renderMode, RenderArgs::MONO, renderDebugFlags); if (!Menu::getInstance()->isOptionChecked(MenuOption::Wireframe)) { // Restaure polygon mode @@ -3327,7 +3250,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs } bool mirrorMode = (theCamera.getMode() == CAMERA_MODE_MIRROR); - + { PerformanceTimer perfTimer("avatars"); DependencyManager::get()->renderAvatars(mirrorMode ? RenderArgs::MIRROR_RENDER_MODE : RenderArgs::NORMAL_RENDER_MODE, @@ -3362,7 +3285,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs _nodeBoundsDisplay.draw(); // Render the world box - if (theCamera.getMode() != CAMERA_MODE_MIRROR && Menu::getInstance()->isOptionChecked(MenuOption::Stats)) { + if (!mirrorMode && Menu::getInstance()->isOptionChecked(MenuOption::Stats)) { PerformanceTimer perfTimer("worldBox"); renderWorldBox(); } @@ -3405,33 +3328,32 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs activeRenderingThread = nullptr; } -void Application::updateUntranslatedViewMatrix(const glm::vec3& viewMatrixTranslation) { - glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat*)&_untranslatedViewMatrix); - _viewMatrixTranslation = viewMatrixTranslation; -} - void Application::setViewTransform(const Transform& view) { _viewTransform = view; } -void Application::loadTranslatedViewMatrix(const glm::vec3& translation) { - glLoadMatrixf((const GLfloat*)&_untranslatedViewMatrix); - glTranslatef(translation.x + _viewMatrixTranslation.x, translation.y + _viewMatrixTranslation.y, - translation.z + _viewMatrixTranslation.z); -} +//void Application::updateUntranslatedViewMatrix(const glm::vec3& viewMatrixTranslation) { +// glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat*)&_untranslatedViewMatrix); +// _viewMatrixTranslation = viewMatrixTranslation; +//} +// +//void Application::loadTranslatedViewMatrix(const glm::vec3& translation) { +// glLoadMatrixf((const GLfloat*)&_untranslatedViewMatrix); +// glTranslatef(translation.x + _viewMatrixTranslation.x, translation.y + _viewMatrixTranslation.y, +// translation.z + _viewMatrixTranslation.z); +//} +// +//void Application::getModelViewMatrix(glm::dmat4* modelViewMatrix) { +// (*modelViewMatrix) =_untranslatedViewMatrix; +// (*modelViewMatrix)[3] = _untranslatedViewMatrix * glm::vec4(_viewMatrixTranslation, 1); +//} void Application::getModelViewMatrix(glm::dmat4* modelViewMatrix) { - (*modelViewMatrix) =_untranslatedViewMatrix; - (*modelViewMatrix)[3] = _untranslatedViewMatrix * glm::vec4(_viewMatrixTranslation, 1); + (*modelViewMatrix) = glm::inverse(_displayViewFrustum.getView()); } void Application::getProjectionMatrix(glm::dmat4* projectionMatrix) { - *projectionMatrix = _projectionMatrix; -} - -void Application::computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& nearVal, - float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const { - _displayViewFrustum.computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); + *projectionMatrix = _displayViewFrustum.getProjection(); } bool Application::getShadowsEnabled() { @@ -3497,8 +3419,6 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) { glViewport(x, size.height() - y - height, width, height); glScissor(x, size.height() - y - height, width, height); } - bool updateViewFrustum = false; - updateProjectionMatrix(_mirrorCamera, updateViewFrustum); glEnable(GL_SCISSOR_TEST); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -3511,11 +3431,9 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) { glm::vec2 mpos = getActiveDisplayPlugin()->getUiMousePosition(); _rearMirrorTools->render(false, QPoint(mpos.x, mpos.y)); } - // reset Viewport and projection matrix glViewport(viewport[0], viewport[1], viewport[2], viewport[3]); glDisable(GL_SCISSOR_TEST); - updateProjectionMatrix(_myCamera, updateViewFrustum); } void Application::resetSensors() { @@ -4598,11 +4516,11 @@ void Application::shutdownPlugins() { } glm::vec3 Application::getHeadPosition() const { - return getActiveDisplayPlugin()->headTranslation(); + return glm::vec3(getActiveDisplayPlugin()->getHeadPose()[3]); } glm::quat Application::getHeadOrientation() const { - return getActiveDisplayPlugin()->headOrientation(); + return glm::quat_cast(getActiveDisplayPlugin()->getHeadPose()); } glm::uvec2 Application::getCanvasSize() const { diff --git a/interface/src/Application.h b/interface/src/Application.h index 5c03df953e..a94859263a 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -249,10 +249,11 @@ public: Overlays& getOverlays() { return _overlays; } float getFps() const { return _fps; } - const glm::vec3& getViewMatrixTranslation() const { return _viewMatrixTranslation; } - void setViewMatrixTranslation(const glm::vec3& translation) { _viewMatrixTranslation = translation; } + //const glm::vec3& getViewMatrixTranslation() const { return _viewMatrixTranslation; } + //void setViewMatrixTranslation(const glm::vec3& translation) { _viewMatrixTranslation = translation; } virtual const Transform& getViewTransform() const { return _viewTransform; } + virtual Transform& getViewTransform() { return _viewTransform; } void setViewTransform(const Transform& view); float getFieldOfView() { return _fieldOfView.get(); } @@ -278,8 +279,9 @@ public: QImage renderAvatarBillboard(); - void displaySide(Camera& whichCamera, bool selfAvatarOnly = false, RenderArgs::RenderSide renderSide = RenderArgs::MONO); + void displaySide(const Camera& camera, bool selfAvatarOnly = false); +/* /// Stores the current modelview matrix as the untranslated view matrix to use for transforms and the supplied vector as /// the view matrix translation. void updateUntranslatedViewMatrix(const glm::vec3& viewMatrixTranslation = glm::vec3()); @@ -289,16 +291,11 @@ public: /// Loads a view matrix that incorporates the specified model translation without the precision issues that can /// result from matrix multiplication at high translation magnitudes. void loadTranslatedViewMatrix(const glm::vec3& translation); - +*/ void getModelViewMatrix(glm::dmat4* modelViewMatrix); void getProjectionMatrix(glm::dmat4* projectionMatrix); virtual const glm::vec3& getShadowDistances() const { return _shadowDistances; } - - /// Computes the off-axis frustum parameters for the view frustum, taking mirroring into account. - virtual void computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& nearVal, - float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const; - virtual ViewFrustum* getCurrentViewFrustum() { return getDisplayViewFrustum(); } virtual bool getShadowsEnabled(); virtual bool getCascadeShadowsEnabled(); @@ -476,10 +473,6 @@ private slots: void setCursorVisible(bool visible); private: - void resetCamerasOnResizeGL(Camera& camera, const glm::uvec2& size); - void updateProjectionMatrix(); - void updateProjectionMatrix(Camera& camera, bool updateViewFrustum = true); - void updateCursorVisibility(); void sendPingPackets(); @@ -505,7 +498,6 @@ private: void renderLookatIndicator(glm::vec3 pointOfInterest); void queryOctree(NodeType_t serverType, PacketType packetType, NodeToJurisdictionMap& jurisdictions); - void loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum); glm::vec3 getSunDirection(); @@ -579,9 +571,11 @@ private: Setting::Handle _fieldOfView; Transform _viewTransform; + glm::mat4 _projectionMatrix; +/* glm::mat4 _untranslatedViewMatrix; glm::vec3 _viewMatrixTranslation; - glm::mat4 _projectionMatrix; +*/ float _scaleMirror; float _rotateMirror; diff --git a/interface/src/Camera.cpp b/interface/src/Camera.cpp index e501b91dea..39ae70cd5b 100644 --- a/interface/src/Camera.cpp +++ b/interface/src/Camera.cpp @@ -46,13 +46,7 @@ QString modeToString(CameraMode mode) { } Camera::Camera() : - _mode(CAMERA_MODE_THIRD_PERSON), - _position(0.0f, 0.0f, 0.0f), - _projection(glm::perspective(glm::radians(DEFAULT_FIELD_OF_VIEW_DEGREES), 16.0f/9.0f, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)), - _hmdPosition(), - _hmdRotation(), - _isKeepLookingAt(false), - _lookingAt(0.0f, 0.0f, 0.0f) + _projection(glm::perspective(glm::radians(DEFAULT_FIELD_OF_VIEW_DEGREES), 16.0f/9.0f, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)) { } @@ -63,26 +57,33 @@ void Camera::update(float deltaTime) { return; } +void Camera::recompose() { + mat4 orientation = glm::mat4_cast(_rotation); + mat4 translation = glm::translate(mat4(), _position); + _transform = translation * orientation; +} + +void Camera::decompose() { + _position = vec3(_transform[3]); + _rotation = glm::quat_cast(_transform); +} + +void Camera::setTransform(const glm::mat4& transform) { + _transform = transform; + decompose(); +} + void Camera::setPosition(const glm::vec3& position) { - _position = position; + _position = position; + recompose(); + if (_isKeepLookingAt) { + lookAt(_lookingAt); + } } void Camera::setRotation(const glm::quat& rotation) { _rotation = rotation; - if (_isKeepLookingAt) { - lookAt(_lookingAt); - } -} - -void Camera::setHmdPosition(const glm::vec3& hmdPosition) { - _hmdPosition = hmdPosition; - if (_isKeepLookingAt) { - lookAt(_lookingAt); - } -} - -void Camera::setHmdRotation(const glm::quat& hmdRotation) { - _hmdRotation = hmdRotation; + recompose(); if (_isKeepLookingAt) { lookAt(_lookingAt); } @@ -143,3 +144,21 @@ void Camera::keepLookingAt(const glm::vec3& point) { _isKeepLookingAt = true; _lookingAt = point; } + +void Camera::loadViewFrustum(ViewFrustum& frustum) const { + // We will use these below, from either the camera or head vectors calculated above + frustum.setProjection(getProjection()); + + // Set the viewFrustum up with the correct position and orientation of the camera + frustum.setPosition(getPosition()); + frustum.setOrientation(getRotation()); + + // Ask the ViewFrustum class to calculate our corners + frustum.calculate(); +} + +ViewFrustum Camera::toViewFrustum() const { + ViewFrustum result; + loadViewFrustum(result); + return result; +} diff --git a/interface/src/Camera.h b/interface/src/Camera.h index fc1dbcaf00..c4ba67ec5d 100644 --- a/interface/src/Camera.h +++ b/interface/src/Camera.h @@ -43,28 +43,31 @@ public: void update( float deltaTime ); - void setRotation(const glm::quat& rotation); - void setProjection(const glm::mat4 & projection); - void setHmdPosition(const glm::vec3& hmdPosition); - void setHmdRotation(const glm::quat& hmdRotation); + CameraMode getMode() const { return _mode; } void setMode(CameraMode m); - glm::quat getRotation() const { return _rotation * _hmdRotation; } const glm::mat4& getProjection() const { return _projection; } - const glm::vec3& getHmdPosition() const { return _hmdPosition; } - const glm::quat& getHmdRotation() const { return _hmdRotation; } - CameraMode getMode() const { return _mode; } + void setProjection(const glm::mat4& projection); + + void loadViewFrustum(ViewFrustum& frustum) const; + ViewFrustum toViewFrustum() const; public slots: QString getModeString() const; void setModeString(const QString& mode); - glm::vec3 getPosition() const { return _position + _hmdPosition; } + const glm::quat getRotation() const { return _rotation; } + void setRotation(const glm::quat& rotation); + + const glm::vec3 getPosition() const { return _position; } void setPosition(const glm::vec3& position); + const glm::quat getOrientation() const { return getRotation(); } void setOrientation(const glm::quat& orientation) { setRotation(orientation); } - glm::quat getOrientation() const { return getRotation(); } - + + const glm::mat4 getTransform() const { return _transform; } + void setTransform(const glm::mat4& transform); + PickRay computePickRay(float x, float y); // These only work on independent cameras @@ -82,13 +85,17 @@ signals: void modeUpdated(const QString& newMode); private: - CameraMode _mode; + void recompose(); + void decompose(); + + CameraMode _mode{ CAMERA_MODE_THIRD_PERSON }; + glm::mat4 _transform; + glm::mat4 _projection; + + // derived glm::vec3 _position; glm::quat _rotation; - glm::mat4 _projection; - glm::vec3 _hmdPosition; - glm::quat _hmdRotation; - bool _isKeepLookingAt; + bool _isKeepLookingAt{ false }; glm::vec3 _lookingAt; }; diff --git a/interface/src/Environment.cpp b/interface/src/Environment.cpp index a2b78c2ff5..a4af31f6c7 100644 --- a/interface/src/Environment.cpp +++ b/interface/src/Environment.cpp @@ -68,17 +68,17 @@ void Environment::resetToDefault() { _data[HifiSockAddr()][0]; } -void Environment::renderAtmospheres(Camera& camera) { +void Environment::renderAtmospheres(const glm::vec3& position) { // get the lock for the duration of the call QMutexLocker locker(&_mutex); if (_environmentIsOverridden) { - renderAtmosphere(camera, _overrideData); + renderAtmosphere(position, _overrideData); } else { foreach (const ServerData& serverData, _data) { // TODO: do something about EnvironmentData foreach (const EnvironmentData& environmentData, serverData) { - renderAtmosphere(camera, environmentData); + renderAtmosphere(position, environmentData); } } } @@ -228,13 +228,13 @@ ProgramObject* Environment::createSkyProgram(const char* from, int* locations) { return program; } -void Environment::renderAtmosphere(Camera& camera, const EnvironmentData& data) { +void Environment::renderAtmosphere(const glm::vec3& position, const EnvironmentData& data) { glm::vec3 center = data.getAtmosphereCenter(); glPushMatrix(); glTranslatef(center.x, center.y, center.z); - glm::vec3 relativeCameraPos = camera.getPosition() - center; + glm::vec3 relativeCameraPos = position - center; float height = glm::length(relativeCameraPos); // use the appropriate shader depending on whether we're inside or outside diff --git a/interface/src/Environment.h b/interface/src/Environment.h index 1a46a10175..fac5aa26ca 100644 --- a/interface/src/Environment.h +++ b/interface/src/Environment.h @@ -29,7 +29,7 @@ public: void init(); void resetToDefault(); - void renderAtmospheres(Camera& camera); + void renderAtmospheres(const glm::vec3& camera); void override(const EnvironmentData& overrideData) { _overrideData = overrideData; _environmentIsOverridden = true; } void endOverride() { _environmentIsOverridden = false; } @@ -46,7 +46,7 @@ private: ProgramObject* createSkyProgram(const char* from, int* locations); - void renderAtmosphere(Camera& camera, const EnvironmentData& data); + void renderAtmosphere(const glm::vec3& position, const EnvironmentData& data); bool _initialized; ProgramObject* _skyFromAtmosphereProgram; diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 8c52c79ca0..c2c30b37f7 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -767,6 +767,7 @@ void SkeletonModel::resetShapePositionsToDefaultPose() { void SkeletonModel::renderBoundingCollisionShapes(float alpha) { const int BALL_SUBDIVISIONS = 10; +#if 0 if (_shapes.isEmpty()) { // the bounding shape has not been propery computed // so no need to render it @@ -797,6 +798,7 @@ void SkeletonModel::renderBoundingCollisionShapes(float alpha) { Avatar::renderJointConnectingCone( origin, axis, _boundingShape.getRadius(), _boundingShape.getRadius(), glm::vec4(0.6f, 0.8f, 0.6f, alpha)); glPopMatrix(); +#endif } bool SkeletonModel::hasSkeleton() { diff --git a/interface/src/devices/TV3DManager.cpp b/interface/src/devices/TV3DManager.cpp index 5ae0107a46..f2de97856e 100644 --- a/interface/src/devices/TV3DManager.cpp +++ b/interface/src/devices/TV3DManager.cpp @@ -120,7 +120,7 @@ void TV3DManager::display(Camera& whichCamera) { glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - qApp->displaySide(eyeCamera, false, RenderArgs::MONO); + qApp->displaySide(eyeCamera, false); #if 0 qApp->getApplicationOverlay().displayOverlayTextureStereo(whichCamera, _aspect, fov); #endif diff --git a/interface/src/plugins/Plugin.h b/interface/src/plugins/Plugin.h index d22fc52c3d..a49c7487b8 100644 --- a/interface/src/plugins/Plugin.h +++ b/interface/src/plugins/Plugin.h @@ -6,7 +6,7 @@ class Plugin : public QObject { public: virtual const QString & getName() = 0; - virtual bool isSupported() { return true; } + virtual bool isSupported() const { return true; } virtual void init() {} virtual void deinit() {} diff --git a/interface/src/plugins/display/DisplayPlugin.h b/interface/src/plugins/display/DisplayPlugin.h index b68edf5f6a..e620b5e04a 100644 --- a/interface/src/plugins/display/DisplayPlugin.h +++ b/interface/src/plugins/display/DisplayPlugin.h @@ -21,14 +21,34 @@ #include #include +enum class Eye { + Left, + Right, + Mono +}; + +/* + * Helper method to iterate over each eye + */ +template +void for_each_eye(F f) { + f(Left); + f(Right); +} + +/* + * Helper method to iterate over each eye, with an additional lambda to take action between the eyes + */ +template +void for_each_eye(F f, FF ff) { + f(Eye::Left); + ff(); + f(Eye::Right); +} + class DisplayPlugin : public Plugin { Q_OBJECT public: - enum class Eye { - Left, - Right, - Mono - }; virtual bool isHmd() const { return false; } virtual bool isStereo() const { return false; } virtual bool isThrottled() const { return false; } @@ -76,23 +96,24 @@ public: }; virtual bool isMouseOnScreen() const; + // Stereo specific methods - virtual glm::mat4 getProjection(Eye eye) const { - return glm::mat4(); + virtual glm::mat4 getProjection(Eye eye, const glm::mat4& baseProjection) const { + return baseProjection; + } + + virtual glm::mat4 getModelview(Eye eye, const glm::mat4& baseModelview) const { + return glm::inverse(getEyePose(eye)) * baseModelview; } // HMD specific methods // TODO move these into another class - virtual glm::mat4 headPose() const { + virtual glm::mat4 getEyePose(Eye eye) const { static const glm::mat4 pose; return pose; } - virtual glm::quat headOrientation() const { - static const glm::quat orientation; return orientation; - } - - virtual glm::vec3 headTranslation() const { - static const glm::vec3 tranlsation; return tranlsation; + virtual glm::mat4 getHeadPose() const { + static const glm::mat4 pose; return pose; } virtual void abandonCalibration() {} @@ -108,3 +129,4 @@ protected: virtual void doneCurrent() {} virtual void swapBuffers() {} }; + diff --git a/interface/src/plugins/display/LegacyDisplayPlugin.cpp b/interface/src/plugins/display/LegacyDisplayPlugin.cpp index 00d922c37a..a6b79fa5ef 100644 --- a/interface/src/plugins/display/LegacyDisplayPlugin.cpp +++ b/interface/src/plugins/display/LegacyDisplayPlugin.cpp @@ -45,6 +45,8 @@ void LegacyDisplayPlugin::activate() { _window->installEventFilter(qApp); _window->installEventFilter(DependencyManager::get().data()); + + DependencyManager::get()->setProxyWindow(_window->windowHandle()); SimpleDisplayPlugin::activate(); } diff --git a/interface/src/plugins/display/Tv3dDisplayPlugin.cpp b/interface/src/plugins/display/Tv3dDisplayPlugin.cpp index 5b35478b57..efd6c055c9 100644 --- a/interface/src/plugins/display/Tv3dDisplayPlugin.cpp +++ b/interface/src/plugins/display/Tv3dDisplayPlugin.cpp @@ -60,6 +60,11 @@ Tv3dDisplayPlugin::Tv3dDisplayPlugin() { }); } +bool Tv3dDisplayPlugin::isSupported() const { + // FIXME this should attempt to do a scan for supported 3D output + return true; +} + gpu::TexturePointer _crosshairTexture; @@ -238,210 +243,3 @@ void Tv3dDisplayPlugin::deactivate() { _timer.stop(); GlWindowDisplayPlugin::deactivate(); } -/* -std::function Tv3dDisplayPlugin::getMouseTranslator() { - return [=](const QPointF& point){ - QPointF result{ point }; - QSize size = getDeviceSize(); - result.rx() *= 2.0f; - if (result.x() > size.width()) { - result.rx() -= size.width(); - } - return result; - }; -} - -glm::ivec2 Tv3dDisplayPlugin::trueMouseToUiMouse(const glm::ivec2 & position) const { - ivec2 result{ position }; - uvec2 size = getCanvasSize(); - result.x *= 2; - result.x %= size.x; - return result; -} - -*/ - -/* -void Tv3dDisplayPlugin::activate() { - GlWindowDisplayPlugin::activate(); - _window->setPosition(100, 100); - _window->resize(512, 512); - _window->setVisible(true); - _window->show(); -} - -void Tv3dDisplayPlugin::deactivate() { - GlWindowDisplayPlugin::deactivate(); -} -*/ - -/* -glm::ivec2 LegacyDisplayPlugin::getCanvasSize() const { - return toGlm(_window->size()); -} - -bool LegacyDisplayPlugin::hasFocus() const { - return _window->hasFocus(); -} - -PickRay LegacyDisplayPlugin::computePickRay(const glm::vec2 & pos) const { - return PickRay(); -} - -bool isMouseOnScreen() { - return false; -} - -void LegacyDisplayPlugin::preDisplay() { - SimpleDisplayPlugin::preDisplay(); - auto size = toGlm(_window->size()); - glViewport(0, 0, size.x, size.y); -} - -bool LegacyDisplayPlugin::isThrottled() const { - return _window->isThrottleRendering(); - - - */ - -#if 0 - -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(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(); - 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(); - qApp->displaySide(eyeCamera, false, RenderArgs::MONO); -#if 0 - qApp->getApplicationOverlay().displayOverlayTextureStereo(whichCamera, _aspect, fov); -#endif - _activeEye = NULL; - }, [&] { - // render right side view - portalX = deviceSize.width() / 2; - }); - glPopMatrix(); - glDisable(GL_SCISSOR_TEST); - - auto finalFbo = DependencyManager::get()->render(); - 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; - } -} - -#endif diff --git a/interface/src/plugins/display/Tv3dDisplayPlugin.h b/interface/src/plugins/display/Tv3dDisplayPlugin.h index a748870abb..ad2ccc7369 100644 --- a/interface/src/plugins/display/Tv3dDisplayPlugin.h +++ b/interface/src/plugins/display/Tv3dDisplayPlugin.h @@ -20,6 +20,7 @@ public: virtual const QString & getName(); Tv3dDisplayPlugin(); virtual bool isStereo() const final { return true; } + virtual bool isSupported() const final; void display(GLuint sceneTexture, const glm::uvec2& sceneSize, GLuint overlayTexture, const glm::uvec2& overlaySize); virtual void activate(); diff --git a/interface/src/plugins/display/WindowDisplayPlugin.cpp b/interface/src/plugins/display/WindowDisplayPlugin.cpp index b904a9d141..25162e9343 100644 --- a/interface/src/plugins/display/WindowDisplayPlugin.cpp +++ b/interface/src/plugins/display/WindowDisplayPlugin.cpp @@ -9,16 +9,17 @@ // #include "WindowDisplayPlugin.h" #include "RenderUtil.h" - -#include +#include "Application.h" WindowDisplayPlugin::WindowDisplayPlugin() { connect(&_timer, &QTimer::timeout, this, [&] { - emit requestRender(); +// if (qApp->getActiveDisplayPlugin() == this) { + emit requestRender(); +// } }); } -const QString WindowDisplayPlugin::NAME("WindowDisplayPlugin"); +const QString WindowDisplayPlugin::NAME("QWindow 2D Renderer"); const QString & WindowDisplayPlugin::getName() { return NAME; @@ -35,417 +36,3 @@ void WindowDisplayPlugin::deactivate() { GlWindowDisplayPlugin::deactivate(); } - -#if 0 - -// -// MainWindow.h -// interface -// -// Created by Mohammed Nafees on 04/06/2014. -// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. -// -// 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__MainWindow__ -#define __hifi__MainWindow__ - -#include -#include - -#include - -#define MSECS_PER_FRAME_WHEN_THROTTLED 66 - -class MainWindow : public QWindow { -public: - explicit MainWindow(QWindow* parent = NULL); - - // Some helpers for compatiblity with QMainWindow - void activateWindow() { - requestActivate(); - } - - bool isMinimized() const { - return windowState() == Qt::WindowMinimized; - } - - void stopFrameTimer(); - - bool isThrottleRendering() const; - - int getDeviceWidth() const; - int getDeviceHeight() const; - QSize getDeviceSize() const { return QSize(getDeviceWidth(), getDeviceHeight()); } - - /* - - - - private slots: - void activeChanged(Qt::ApplicationState state); - void throttleRender(); - bool eventFilter(QObject*, QEvent* event); - */ - public slots: - void restoreGeometry(); - void saveGeometry(); - -signals: - void windowGeometryChanged(QRect geometry); - void windowShown(bool shown); - -protected: - virtual void moveEvent(QMoveEvent* event); - virtual void resizeEvent(QResizeEvent* event); - virtual void showEvent(QShowEvent* event); - virtual void hideEvent(QHideEvent* event); - virtual void changeEvent(QEvent* event); - virtual void windowStateChanged(Qt::WindowState windowState); - virtual void activeChanged(); - - virtual void initializeGL(); - virtual void paintGL(); - virtual void resizeGL(int width, int height); - -private: - Setting::Handle _windowGeometry; - Setting::Handle _windowState; - Qt::WindowState _lastState{ Qt::WindowNoState }; - QOpenGLContext * _context{ nullptr }; - QTimer _frameTimer; - bool _throttleRendering{ false }; - int _idleRenderInterval{ MSECS_PER_FRAME_WHEN_THROTTLED }; -}; - -#endif /* defined(__hifi__MainWindow__) */ - - - - -// -// MainWindow.cpp -// interface -// -// Created by Mohammed Nafees on 04/06/2014. -// Copyright (c) 2014 High Fidelity, Inc. All rights reserved. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Application.h" - -#include "MainWindow.h" -#include "Menu.h" -#include "Util.h" - -#include - - -MainWindow::MainWindow(QWindow * parent) : -QWindow(parent), -_windowGeometry("WindowGeometry"), -_windowState("WindowState", 0) { - setSurfaceType(QSurface::OpenGLSurface); - - QSurfaceFormat format; - // Qt Quick may need a depth and stencil buffer. Always make sure these are available. - format.setDepthBufferSize(16); - format.setStencilBufferSize(8); - format.setVersion(4, 1); - // Ugh.... - format.setProfile(QSurfaceFormat::OpenGLContextProfile::CompatibilityProfile); - setFormat(format); - - _context = new QOpenGLContext; - _context->setFormat(format); - _context->create(); - - show(); -} - -void MainWindow::restoreGeometry() { - QRect geometry = _windowGeometry.get(qApp->desktop()->availableGeometry()); - setGeometry(geometry); - - // Restore to maximized or full screen after restoring to windowed so that going windowed goes to good position and sizes. - int state = _windowState.get(Qt::WindowNoState) & ~Qt::WindowActive; - if (state != Qt::WindowNoState) { - setWindowState((Qt::WindowState)state); - } -} - -void MainWindow::saveGeometry() { - // Did not use geometry() on purpose, - // see http://doc.qt.io/qt-5/qsettings.html#restoring-the-state-of-a-gui-application - _windowState.set((int)windowState()); - - // Save position and size only if windowed so that have good values for windowed after starting maximized or full screen. - if (windowState() == Qt::WindowNoState) { - _windowGeometry.set(geometry()); - } -} - -void MainWindow::moveEvent(QMoveEvent* event) { - emit windowGeometryChanged(QRect(event->pos(), size())); - QWindow::moveEvent(event); -} - -void MainWindow::resizeEvent(QResizeEvent* event) { - emit windowGeometryChanged(QRect(QPoint(x(), y()), event->size())); - QWindow::resizeEvent(event); -} - -void MainWindow::showEvent(QShowEvent* event) { - if (event->spontaneous()) { - emit windowShown(true); - } - QWindow::showEvent(event); -} - -void MainWindow::hideEvent(QHideEvent* event) { - if (event->spontaneous()) { - emit windowShown(false); - } - QWindow::hideEvent(event); -} - -void MainWindow::windowStateChanged(Qt::WindowState windowState) { - // If we're changing from minimized to non-minimized or vice versas, emit - // a windowShown signal (i.e. don't emit the signal if we're going from - // fullscreen to nostate - if ((_lastState == Qt::WindowMinimized) ^ (windowState == Qt::WindowMinimized)) { - emit windowShown(windowState != Qt::WindowMinimized); - } - - bool fullscreen = windowState == Qt::WindowFullScreen; - if (fullscreen != Menu::getInstance()->isOptionChecked(MenuOption::Fullscreen)) { - Menu::getInstance()->setIsOptionChecked(MenuOption::Fullscreen, fullscreen); - } - - _lastState = windowState; - QWindow::windowStateChanged(windowState); -} - -void MainWindow::activeChanged() { - if (isActive()) { - emit windowShown(true); - } else { - emit windowShown(false); - } - QWindow::activeChanged(); -} - -void MainWindow::stopFrameTimer() { - _frameTimer.stop(); -} - -bool MainWindow::isThrottleRendering() const { - return _throttleRendering || isMinimized(); -} - - -int MainWindow::getDeviceWidth() const { - return width() * devicePixelRatio(); -} - -int MainWindow::getDeviceHeight() const { - return height() * devicePixelRatio(); -} - - - -void MainWindow::initializeGL() { - Application::getInstance()->initializeGL(); - // setAttribute(Qt::WA_AcceptTouchEvents); - // setAcceptDrops(true); - connect(Application::getInstance(), SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SLOT(activeChanged(Qt::ApplicationState))); - connect(&_frameTimer, SIGNAL(timeout()), this, SLOT(throttleRender())); -} - -void GLCanvas::resizeGL(int width, int height) { - Application::getInstance()->resizeGL(width, height); -} - -void GLCanvas::paintGL() { - if (!_throttleRendering && !Application::getInstance()->getWindow()->isMinimized()) { - //Need accurate frame timing for the oculus rift - if (OculusManager::isConnected()) { - OculusManager::beginFrameTiming(); - } - - Application::getInstance()->paintGL(); - - if (!OculusManager::isConnected()) { - swapBuffers(); - } else { - if (OculusManager::allowSwap()) { - swapBuffers(); - } - OculusManager::endFrameTiming(); - } - } -} - - - -/* - -GLCanvas::GLCanvas() : QGLWidget(QGL::NoDepthBuffer | QGL::NoStencilBuffer), -#ifdef Q_OS_LINUX -// Cause GLCanvas::eventFilter to be called. -// It wouldn't hurt to do this on Mac and PC too; but apparently it's only needed on linux. -qApp->installEventFilter(this); -#endif -} - -void GLCanvas::keyPressEvent(QKeyEvent* event) { -Application::getInstance()->keyPressEvent(event); -} - -void GLCanvas::keyReleaseEvent(QKeyEvent* event) { -Application::getInstance()->keyReleaseEvent(event); -} - -void GLCanvas::focusOutEvent(QFocusEvent* event) { -Application::getInstance()->focusOutEvent(event); -} - -void GLCanvas::mouseMoveEvent(QMouseEvent* event) { -Application::getInstance()->mouseMoveEvent(event); -} - -void GLCanvas::mousePressEvent(QMouseEvent* event) { -Application::getInstance()->mousePressEvent(event); -} - -void GLCanvas::mouseReleaseEvent(QMouseEvent* event) { -Application::getInstance()->mouseReleaseEvent(event); -} - -void GLCanvas::activeChanged(Qt::ApplicationState state) { -switch (state) { -case Qt::ApplicationActive: -// If we're active, stop the frame timer and the throttle. -_frameTimer.stop(); -_throttleRendering = false; -break; - -case Qt::ApplicationSuspended: -case Qt::ApplicationHidden: -// If we're hidden or are about to suspend, don't render anything. -_throttleRendering = false; -_frameTimer.stop(); -break; - -default: -// Otherwise, throttle. -if (!_throttleRendering && !Application::getInstance()->isAboutToQuit()) { -_frameTimer.start(_idleRenderInterval); -_throttleRendering = true; -} -break; -} -} - -void GLCanvas::throttleRender() { -_frameTimer.start(_idleRenderInterval); -if (!Application::getInstance()->getWindow()->isMinimized()) { -//Need accurate frame timing for the oculus rift -if (OculusManager::isConnected()) { -OculusManager::beginFrameTiming(); -} - -Application::getInstance()->paintGL(); -swapBuffers(); - -if (OculusManager::isConnected()) { -OculusManager::endFrameTiming(); -} -} -} - -int updateTime = 0; -bool GLCanvas::event(QEvent* event) { -switch (event->type()) { -case QEvent::TouchBegin: -Application::getInstance()->touchBeginEvent(static_cast(event)); -event->accept(); -return true; -case QEvent::TouchEnd: -Application::getInstance()->touchEndEvent(static_cast(event)); -return true; -case QEvent::TouchUpdate: -Application::getInstance()->touchUpdateEvent(static_cast(event)); -return true; -default: -break; -} -return QGLWidget::event(event); -} - -void GLCanvas::wheelEvent(QWheelEvent* event) { -Application::getInstance()->wheelEvent(event); -} - -void GLCanvas::dragEnterEvent(QDragEnterEvent* event) { -const QMimeData* mimeData = event->mimeData(); -foreach(QUrl url, mimeData->urls()) { -auto urlString = url.toString(); -if (Application::getInstance()->canAcceptURL(urlString)) { -event->acceptProposedAction(); -break; -} -} -} - -void GLCanvas::dropEvent(QDropEvent* event) { -Application::getInstance()->dropEvent(event); -} - -// Pressing Alt (and Meta) key alone activates the menubar because its style inherits the -// SHMenuBarAltKeyNavigation from QWindowsStyle. This makes it impossible for a scripts to -// receive keyPress events for the Alt (and Meta) key in a reliable manner. -// -// This filter catches events before QMenuBar can steal the keyboard focus. -// The idea was borrowed from -// http://www.archivum.info/qt-interest@trolltech.com/2006-09/00053/Re-(Qt4)-Alt-key-focus-QMenuBar-(solved).html - -bool GLCanvas::eventFilter(QObject*, QEvent* event) { -switch (event->type()) { -case QEvent::KeyPress: -case QEvent::KeyRelease: -case QEvent::ShortcutOverride: -{ -QKeyEvent* keyEvent = static_cast(event); -if (keyEvent->key() == Qt::Key_Alt || keyEvent->key() == Qt::Key_Meta) { -if (event->type() == QEvent::KeyPress) { -keyPressEvent(keyEvent); -} else if (event->type() == QEvent::KeyRelease) { -keyReleaseEvent(keyEvent); -} else { -QGLWidget::event(event); -} -return true; -} -} -default: -break; -} -return false; -} - -*/ -#endif diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index 7c77c72f13..7441a24ddb 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -394,7 +394,6 @@ void ApplicationOverlay::displayOverlayTextureHmd(Camera& whichCamera) { glEnable(GL_LIGHTING); } glPopMatrix(); } -#endif // Draws the FBO texture for 3DTV. void ApplicationOverlay::displayOverlayTextureStereo(Camera& whichCamera, float aspectRatio, float fov) { @@ -489,6 +488,7 @@ void ApplicationOverlay::displayOverlayTextureStereo(Camera& whichCamera, float glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE); glEnable(GL_LIGHTING); } +#endif void ApplicationOverlay::computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origin, glm::vec3& direction) const { @@ -501,13 +501,13 @@ void ApplicationOverlay::computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& origi glm::vec3 overlaySpaceDirection = glm::normalize(orientation * IDENTITY_FRONT); - const glm::vec3& hmdPosition = qApp->getCamera()->getHmdPosition(); - const glm::quat& hmdOrientation = qApp->getCamera()->getHmdRotation(); + glm::vec3 hmdPosition; // = qApp->getCamera()->getHmdPosition(); + glm::quat hmdOrientation; // = qApp->getCamera()->getHmdRotation(); - // We need the RAW camera orientation and position, because this is what the overlay is + // We need the camera orientation and position, because this is what the overlay is // rendered relative to - const glm::vec3 overlayPosition = qApp->getCamera()->getPosition() - hmdPosition; - const glm::quat overlayOrientation = qApp->getCamera()->getRotation() * glm::inverse(hmdOrientation); + const glm::vec3 overlayPosition = qApp->getCamera()->getPosition(); + const glm::quat overlayOrientation = qApp->getCamera()->getRotation(); // Intersection UI overlay space glm::vec3 worldSpaceDirection = overlayOrientation * overlaySpaceDirection; diff --git a/interface/src/ui/overlays/LocalModelsOverlay.cpp b/interface/src/ui/overlays/LocalModelsOverlay.cpp index e6fae4ff3d..7390ea4310 100644 --- a/interface/src/ui/overlays/LocalModelsOverlay.cpp +++ b/interface/src/ui/overlays/LocalModelsOverlay.cpp @@ -38,23 +38,18 @@ void LocalModelsOverlay::render(RenderArgs* args) { if (_visible) { float glowLevel = getGlowLevel(); - Glower* glower = NULL; + QSharedPointer glower; if (glowLevel > 0.0f) { - glower = new Glower(glowLevel); + glower = QSharedPointer(new Glower(glowLevel)); } glPushMatrix(); { Application* app = Application::getInstance(); - glm::vec3 oldTranslation = app->getViewMatrixTranslation(); - app->setViewMatrixTranslation(oldTranslation + _position); + Transform originalTransform = qApp->getViewTransform(); + qApp->getViewTransform().postTranslate(_position); _entityTreeRenderer->render(); - Application::getInstance()->setViewMatrixTranslation(oldTranslation); + qApp->setViewTransform(originalTransform); } glPopMatrix(); - - if (glower) { - delete glower; - } - } } diff --git a/libraries/octree/src/ViewFrustum.cpp b/libraries/octree/src/ViewFrustum.cpp index 2694314b57..80f0023970 100644 --- a/libraries/octree/src/ViewFrustum.cpp +++ b/libraries/octree/src/ViewFrustum.cpp @@ -27,14 +27,17 @@ using namespace std; -ViewFrustum::ViewFrustum() { -} - void ViewFrustum::setOrientation(const glm::quat& orientationAsQuaternion) { _orientation = orientationAsQuaternion; _right = glm::vec3(orientationAsQuaternion * glm::vec4(IDENTITY_RIGHT, 0.0f)); _up = glm::vec3(orientationAsQuaternion * glm::vec4(IDENTITY_UP, 0.0f)); _direction = glm::vec3(orientationAsQuaternion * glm::vec4(IDENTITY_FRONT, 0.0f)); + _view = glm::translate(mat4(), _position) * glm::mat4_cast(_orientation); +} + +void ViewFrustum::setPosition(const glm::vec3& position) { + _position = position; + _view = glm::translate(mat4(), _position) * glm::mat4_cast(_orientation); } // Order cooresponds to the order defined in the BoxVertex enum. diff --git a/libraries/octree/src/ViewFrustum.h b/libraries/octree/src/ViewFrustum.h index 0422120e51..43bc1d992e 100644 --- a/libraries/octree/src/ViewFrustum.h +++ b/libraries/octree/src/ViewFrustum.h @@ -36,11 +36,9 @@ const float DEFAULT_FAR_CLIP = (float)TREE_SCALE; class ViewFrustum { public: - ViewFrustum(); - // setters for camera attributes - void setPosition(const glm::vec3& p) { _position = p; } - void setOrientation(const glm::quat& orientationAsQuaternion); + void setPosition(const glm::vec3& position); + void setOrientation(const glm::quat& orientation); // getters for camera attributes const glm::vec3& getPosition() const { return _position; } @@ -54,7 +52,8 @@ public: void getFocalLength(float focalLength) { _focalLength = focalLength; } // getters for lens attributes - const glm::mat4 getProjection() const { return _projection; }; + const glm::mat4& getProjection() const { return _projection; }; + const glm::mat4& getView() const { return _view; }; float getWidth() const { return _width; } float getHeight() const { return _height; } float getFieldOfView() const { return _fieldOfView; } @@ -120,6 +119,7 @@ private: // camera location/orientation attributes glm::vec3 _position; // the position in world-frame glm::quat _orientation; + glm::mat4 _view; // Lens attributes glm::mat4 _projection; diff --git a/libraries/render-utils/src/AbstractViewStateInterface.h b/libraries/render-utils/src/AbstractViewStateInterface.h index a1447293b7..a0cd103804 100644 --- a/libraries/render-utils/src/AbstractViewStateInterface.h +++ b/libraries/render-utils/src/AbstractViewStateInterface.h @@ -30,10 +30,6 @@ public: /// Returns the shadow distances for the current view state virtual const glm::vec3& getShadowDistances() const = 0; - /// Computes the off-axis frustum parameters for the view frustum, taking mirroring into account. - virtual void computeOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& nearVal, - float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const = 0; - /// gets the current view frustum for rendering the view state virtual ViewFrustum* getCurrentViewFrustum() = 0; diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.cpp b/libraries/render-utils/src/AmbientOcclusionEffect.cpp index f58419ec6e..ee53578a9e 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.cpp +++ b/libraries/render-utils/src/AmbientOcclusionEffect.cpp @@ -18,6 +18,7 @@ #include #include +#include #include "AbstractViewStateInterface.h" #include "AmbientOcclusionEffect.h" @@ -112,7 +113,8 @@ void AmbientOcclusionEffect::render() { float left, right, bottom, top, nearVal, farVal; glm::vec4 nearClipPlane, farClipPlane; - _viewState->computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); + auto viewFrustum = _viewState->getCurrentViewFrustum(); + viewFrustum->computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); int viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 54e5388ec8..ff1c965b44 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -319,9 +319,10 @@ void DeferredLightingEffect::render() { glUniformMatrix4fv(locations->invViewMat, 1, false, reinterpret_cast< const GLfloat* >(&invViewMat)); } + auto viewFrustum = _viewState->getCurrentViewFrustum(); float left, right, bottom, top, nearVal, farVal; glm::vec4 nearClipPlane, farClipPlane; - _viewState->computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); + viewFrustum->computeOffAxisFrustum(left, right, bottom, top, nearVal, farVal, nearClipPlane, farClipPlane); program->setUniformValue(locations->nearLocation, nearVal); float depthScale = (farVal - nearVal) / farVal; program->setUniformValue(locations->depthScale, depthScale); @@ -363,8 +364,8 @@ void DeferredLightingEffect::render() { // enlarge the scales slightly to account for tesselation const float SCALE_EXPANSION = 0.05f; - const glm::vec3& eyePoint = _viewState->getCurrentViewFrustum()->getPosition(); - float nearRadius = glm::distance(eyePoint, _viewState->getCurrentViewFrustum()->getNearTopLeft()); + const glm::vec3& eyePoint = viewFrustum->getPosition(); + float nearRadius = glm::distance(eyePoint, viewFrustum->getNearTopLeft()); auto geometryCache = DependencyManager::get(); From 810db3923388b2346f9f132217e13d33a5665bfe Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 27 May 2015 12:42:05 -0700 Subject: [PATCH 013/552] Working on oculus rendering --- cmake/externals/LibOVR/CMakeLists.txt | 4 +- interface/src/plugins/display/DisplayPlugin.h | 2 +- .../display/OculusBaseDisplayPlugin.cpp | 41 ++++ .../plugins/display/OculusBaseDisplayPlugin.h | 32 +++ .../plugins/display/OculusDisplayPlugin.cpp | 96 --------- .../src/plugins/display/OculusDisplayPlugin.h | 30 --- interface/src/plugins/display/OculusHelpers.h | 75 +++++++ .../display/OculusWin32DisplayPlugin.cpp | 200 ++++++++++++++++++ .../display/OculusWin32DisplayPlugin.h | 15 ++ .../src/plugins/display/OglplusHelpers.h | 26 +++ 10 files changed, 392 insertions(+), 129 deletions(-) create mode 100644 interface/src/plugins/display/OculusBaseDisplayPlugin.cpp create mode 100644 interface/src/plugins/display/OculusBaseDisplayPlugin.h delete mode 100644 interface/src/plugins/display/OculusDisplayPlugin.cpp delete mode 100644 interface/src/plugins/display/OculusDisplayPlugin.h create mode 100644 interface/src/plugins/display/OculusHelpers.h create mode 100644 interface/src/plugins/display/OculusWin32DisplayPlugin.cpp create mode 100644 interface/src/plugins/display/OculusWin32DisplayPlugin.h create mode 100644 interface/src/plugins/display/OglplusHelpers.h diff --git a/cmake/externals/LibOVR/CMakeLists.txt b/cmake/externals/LibOVR/CMakeLists.txt index 2198ed378a..d491434b5f 100644 --- a/cmake/externals/LibOVR/CMakeLists.txt +++ b/cmake/externals/LibOVR/CMakeLists.txt @@ -9,8 +9,8 @@ if (WIN32) ExternalProject_Add( ${EXTERNAL_NAME} - URL http://static.oculus.com/sdk-downloads/ovr_sdk_win_0.5.0.1.zip - URL_MD5 d3fc4c02db9be5ff08af4ef4c97b32f9 + URL http://static.oculus.com/sdk-downloads/0.6.0.0/1431634088/ovr_sdk_win_0.6.0.0.zip + URL_MD5 a3dfdab037a854fdcf7e6033fa8d7028 CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" diff --git a/interface/src/plugins/display/DisplayPlugin.h b/interface/src/plugins/display/DisplayPlugin.h index e620b5e04a..711b53e9f4 100644 --- a/interface/src/plugins/display/DisplayPlugin.h +++ b/interface/src/plugins/display/DisplayPlugin.h @@ -21,7 +21,7 @@ #include #include -enum class Eye { +enum Eye { Left, Right, Mono diff --git a/interface/src/plugins/display/OculusBaseDisplayPlugin.cpp b/interface/src/plugins/display/OculusBaseDisplayPlugin.cpp new file mode 100644 index 0000000000..50e1583548 --- /dev/null +++ b/interface/src/plugins/display/OculusBaseDisplayPlugin.cpp @@ -0,0 +1,41 @@ +// +// OculusBaseDisplayPlugin.cpp +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "OculusBaseDisplayPlugin.h" + +#include + +#include "OculusHelpers.h" + + +void OculusBaseDisplayPlugin::activate() { + ovr_for_each_eye([&](ovrEyeType eye) { + ovrEyeRenderDesc erd = ovrHmd_GetRenderDesc(_hmd, eye, _hmd->MaxEyeFov[eye]); + ovrMatrix4f ovrPerspectiveProjection = + ovrMatrix4f_Projection(erd.Fov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_RightHanded); + _eyeProjections[eye] = toGlm(ovrPerspectiveProjection); + _eyeOffsets[eye] = erd.HmdToEyeViewOffset; + }); +} + +void OculusBaseDisplayPlugin::deactivate() { +} + +void OculusBaseDisplayPlugin::preRender() { + ovrHmd_GetEyePoses(_hmd, _frameIndex, _eyeOffsets, _eyePoses, nullptr); +} + +glm::mat4 OculusBaseDisplayPlugin::getProjection(Eye eye, const glm::mat4& baseProjection) const { + return _eyeProjections[eye]; +} + +glm::mat4 OculusBaseDisplayPlugin::getModelview(Eye eye, const glm::mat4& baseModelview) const { + return toGlm(_eyePoses[eye]); +} + diff --git a/interface/src/plugins/display/OculusBaseDisplayPlugin.h b/interface/src/plugins/display/OculusBaseDisplayPlugin.h new file mode 100644 index 0000000000..94f73522b5 --- /dev/null +++ b/interface/src/plugins/display/OculusBaseDisplayPlugin.h @@ -0,0 +1,32 @@ +// +// OculusBaseDisplayPlugin.h +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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" + +#include + +class OculusBaseDisplayPlugin : public HmdDisplayPlugin { +public: + // Stereo specific methods + virtual glm::mat4 getProjection(Eye eye, const glm::mat4& baseProjection) const; + virtual glm::mat4 getModelview(Eye eye, const glm::mat4& baseModelview) const; + virtual void activate(); + virtual void deactivate(); + virtual void preRender(); + virtual void configureRendering() = 0; +protected: + ovrHmd _hmd; + unsigned int _frameIndex{ 0 }; + + ovrPosef _eyePoses[2]; + ovrVector3f _eyeOffsets[2]; + glm::mat4 _eyeProjections[2]; +}; diff --git a/interface/src/plugins/display/OculusDisplayPlugin.cpp b/interface/src/plugins/display/OculusDisplayPlugin.cpp deleted file mode 100644 index d32af59ebf..0000000000 --- a/interface/src/plugins/display/OculusDisplayPlugin.cpp +++ /dev/null @@ -1,96 +0,0 @@ -// -// OculusDisplayPlugin.cpp -// -// Created by Bradley Austin Davis on 2014/04/13. -// 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 "OculusDisplayPlugin.h" - -#include - -bool OculusDisplayPlugin::isSupported() { - ovr_Initialize(); - bool result = false; - if (ovrHmd_Detect() != 0) { - result = true; - } - ovr_Shutdown(); - return result; -} - -void OculusDisplayPlugin::activate() { -} - -void OculusDisplayPlugin::deactivate() { -} - -void OculusDisplayPlugin::init() { -} - -void OculusDisplayPlugin::deinit() { -} - - -void OculusDisplayPlugin::overrideOffAxisFrustum( - float& left, float& right, float& bottom, float& top, - float& nearVal, float& farVal, - glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const { - -} - - - -#if 0 -// Set the desired FBO texture size. If it hasn't changed, this does nothing. -// Otherwise, it must rebuild the FBOs -if (OculusManager::isConnected()) { - DependencyManager::get()->setFrameBufferSize(OculusManager::getRenderTargetSize()); -} else { -#endif - -#if 0 - // Update camera position - if (!OculusManager::isConnected()) { - _myCamera.update(1.0f / _fps); - } -#endif - -#if 0 - if (OculusManager::isConnected()) { - //When in mirror mode, use camera rotation. Otherwise, use body rotation - if (_myCamera.getMode() == CAMERA_MODE_MIRROR) { - OculusManager::display(_myCamera.getRotation(), _myCamera.getPosition(), _myCamera); - } else { - OculusManager::display(_myAvatar->getWorldAlignedOrientation(), _myAvatar->getDefaultEyePosition(), _myCamera); - } - _myCamera.update(1.0f / _fps); - -#endif - -#if 0 - OculusManager::abandonCalibration(); -#endif - -#if 0 - if (OculusManager::isConnected()) { - return getMouseX() >= 0 && getMouseX() <= _glWidget->getDeviceWidth() && - getMouseY() >= 0 && getMouseY() <= _glWidget->getDeviceHeight(); - } -#endif - -#if 0 - if (OculusManager::isConnected()) { - glm::vec2 pos = _applicationOverlay.screenToOverlay(glm::vec2(getTrueMouseX(), getTrueMouseY())); - return pos.x; - } -#endif -#if 0 - if (OculusManager::isConnected()) { - glm::vec2 pos = _applicationOverlay.screenToOverlay(glm::vec2(getTrueMouseX(), getTrueMouseY())); - return pos.y; - } -#endif - diff --git a/interface/src/plugins/display/OculusDisplayPlugin.h b/interface/src/plugins/display/OculusDisplayPlugin.h deleted file mode 100644 index 7b846ae569..0000000000 --- a/interface/src/plugins/display/OculusDisplayPlugin.h +++ /dev/null @@ -1,30 +0,0 @@ -// -// OculusBaseDisplayPlugin.h -// -// Created by Bradley Austin Davis on 2014/04/13. -// 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" -#include - -class OculusDisplayPlugin : public HmdDisplayPlugin { -public: - virtual bool isSupported(); - - virtual void init(); - virtual void deinit(); - - virtual void activate(); - virtual void deactivate(); - - virtual void overrideOffAxisFrustum( - float& left, float& right, float& bottom, float& top, - float& nearVal, float& farVal, - glm::vec4& nearClipPlane, glm::vec4& farClipPlane) const; - -}; diff --git a/interface/src/plugins/display/OculusHelpers.h b/interface/src/plugins/display/OculusHelpers.h new file mode 100644 index 0000000000..553a1671e5 --- /dev/null +++ b/interface/src/plugins/display/OculusHelpers.h @@ -0,0 +1,75 @@ +// +// Created by Bradley Austin Davis on 2015/05/26. +// 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 + +// Convenience method for looping over each eye with a lambda +template +inline void ovr_for_each_eye(Function function) { + for (ovrEyeType eye = ovrEyeType::ovrEye_Left; + eye < ovrEyeType::ovrEye_Count; + eye = static_cast(eye + 1)) { + function(eye); + } +} + +inline glm::mat4 toGlm(const ovrMatrix4f & om) { + return glm::transpose(glm::make_mat4(&om.M[0][0])); +} + +inline glm::mat4 toGlm(const ovrFovPort & fovport, float nearPlane = 0.01f, float farPlane = 10000.0f) { + return toGlm(ovrMatrix4f_Projection(fovport, nearPlane, farPlane, true)); +} + +inline glm::vec3 toGlm(const ovrVector3f & ov) { + return glm::make_vec3(&ov.x); +} + +inline glm::vec2 toGlm(const ovrVector2f & ov) { + return glm::make_vec2(&ov.x); +} + +inline glm::uvec2 toGlm(const ovrSizei & ov) { + return glm::uvec2(ov.w, ov.h); +} + +inline glm::quat toGlm(const ovrQuatf & oq) { + return glm::make_quat(&oq.x); +} + +inline glm::mat4 toGlm(const ovrPosef & op) { + glm::mat4 orientation = glm::mat4_cast(toGlm(op.Orientation)); + glm::mat4 translation = glm::translate(glm::mat4(), toGlm(op.Position)); + return translation * orientation; +} + +inline ovrMatrix4f ovrFromGlm(const glm::mat4 & m) { + ovrMatrix4f result; + glm::mat4 transposed(glm::transpose(m)); + memcpy(result.M, &(transposed[0][0]), sizeof(float) * 16); + return result; +} + +inline ovrVector3f ovrFromGlm(const glm::vec3 & v) { + return{ v.x, v.y, v.z }; +} + +inline ovrVector2f ovrFromGlm(const glm::vec2 & v) { + return{ v.x, v.y }; +} + +inline ovrSizei ovrFromGlm(const glm::uvec2 & v) { + return{ (int)v.x, (int)v.y }; +} + +inline ovrQuatf ovrFromGlm(const glm::quat & q) { + return{ q.x, q.y, q.z, q.w }; +} diff --git a/interface/src/plugins/display/OculusWin32DisplayPlugin.cpp b/interface/src/plugins/display/OculusWin32DisplayPlugin.cpp new file mode 100644 index 0000000000..f7414cc551 --- /dev/null +++ b/interface/src/plugins/display/OculusWin32DisplayPlugin.cpp @@ -0,0 +1,200 @@ +// +// Created by Bradley Austin Davis on 2014/04/13. +// 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 "OculusWin32DisplayPlugin.h" + + +#include + +bool OculusWin32DisplayPlugin::isSupported() { + ovr_Initialize(); + bool result = false; + if (ovrHmd_Detect() != 0) { + result = true; + } + ovr_Shutdown(); + return result; +} + +// A basic wrapper for constructing a framebuffer with a renderbuffer +// for the depth attachment and an undefined type for the color attachement +// This allows us to reuse the basic framebuffer code for both the Mirror +// FBO as well as the Oculus swap textures we will use to render the scene +// Though we don't really need depth at all for the mirror FBO, or even an +// FBO, but using one means I can just use a glBlitFramebuffer to get it onto +// the screen. +template +struct FramebufferWrapper { + glm::uvec2 size; + oglplus::Framebuffer fbo; + C color{ 0 }; + GLuint depth{ 0 }; + + virtual ~FramebufferWrapper() { + } + + FramebufferWrapper() {} + + virtual void Init(const uvec2 & size) { + this->size = size; + if (!fbo) { + glGenFramebuffers(1, &fbo); + } + initColor(); + initDepth(); + initDone(); + } + + template + void Bound(F f) { + Bound(GL_FRAMEBUFFER, f); + } + + template + void Bound(GLenum target, F f) { + glBindFramebuffer(target, fbo); + onBind(target); + f(); + onUnbind(target); + glBindFramebuffer(target, 0); + } + + void Viewport() { + glViewport(0, 0, size.x, size.y); + } + +private: + virtual void onBind(GLenum target) {} + virtual void onUnbind(GLenum target) {} + + + virtual void initDepth() { + glGenRenderbuffers(1, &depth); + assert(depth); + glBindRenderbuffer(GL_RENDERBUFFER, depth); + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, size.x, size.y); + glBindRenderbuffer(GL_RENDERBUFFER, 0); + } + + virtual void initColor() = 0; + virtual void initDone() = 0; +}; + + + +// A base class for FBO wrappers that need to use the Oculus C +// API to manage textures via ovrHmd_CreateSwapTextureSetGL, +// ovrHmd_CreateMirrorTextureGL, etc +template +struct RiftFramebufferWrapper : public FramebufferWrapper { + ovrHmd hmd; + RiftFramebufferWrapper(const ovrHmd & hmd) : hmd(hmd) {}; +}; + +// A wrapper for constructing and using a swap texture set, +// where each frame you draw to a texture via the FBO, +// then submit it and increment to the next texture. +// The Oculus SDK manages the creation and destruction of +// the textures +struct SwapTextureFramebufferWrapper : public RiftFramebufferWrapper{ + SwapTextureFramebufferWrapper(const ovrHmd & hmd) + : RiftFramebufferWrapper(hmd) {} + ~SwapTextureFramebufferWrapper() { + if (color) { + ovrHmd_DestroySwapTextureSet(hmd, color); + color = nullptr; + } + } + + void Increment() { + ++color->CurrentIndex; + color->CurrentIndex %= color->TextureCount; + } + +protected: + virtual void initColor() { + if (color) { + ovrHmd_DestroySwapTextureSet(hmd, color); + color = nullptr; + } + + if (!OVR_SUCCESS(ovrHmd_CreateSwapTextureSetGL(hmd, GL_RGBA, size.x, size.y, &color))) { + FAIL("Unable to create swap textures"); + } + + for (int i = 0; i < color->TextureCount; ++i) { + ovrGLTexture& ovrTex = (ovrGLTexture&)color->Textures[i]; + glBindTexture(GL_TEXTURE_2D, ovrTex.OGL.TexId); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + } + glBindTexture(GL_TEXTURE_2D, 0); + } + + virtual void initDone() { + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + } + + virtual void onBind(GLenum target) { + ovrGLTexture& tex = (ovrGLTexture&)(color->Textures[color->CurrentIndex]); + glFramebufferTexture2D(target, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex.OGL.TexId, 0); + } + + virtual void onUnbind(GLenum target) { + glFramebufferTexture2D(target, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); + } +}; + +using SwapTexFboPtr = std::shared_ptr; + +// We use a FBO to wrap the mirror texture because it makes it easier to +// render to the screen via glBlitFramebuffer +struct MirrorFramebufferWrapper : public RiftFramebufferWrapper{ + float targetAspect; + MirrorFramebufferWrapper(const ovrHmd & hmd) + : RiftFramebufferWrapper(hmd) {} + ~MirrorFramebufferWrapper() { + if (color) { + ovrHmd_DestroyMirrorTexture(hmd, (ovrTexture*)color); + color = nullptr; + } + } + + void Resize(const uvec2 & size) { + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + this->size = size; + initColor(); + initDone(); + } +private: + virtual void initDepth() { + } + + void initColor() { + if (color) { + ovrHmd_DestroyMirrorTexture(hmd, (ovrTexture*)color); + color = nullptr; + } + ovrResult result = ovrHmd_CreateMirrorTextureGL(hmd, GL_RGBA, size.x, size.y, (ovrTexture**)&color); + assert(OVR_SUCCESS(result)); + } + + void initDone() { + glBindFramebuffer(GL_FRAMEBUFFER, fbo); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color->OGL.TexId, 0); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + } + +}; + +using MirrorFboPtr = std::shared_ptr; diff --git a/interface/src/plugins/display/OculusWin32DisplayPlugin.h b/interface/src/plugins/display/OculusWin32DisplayPlugin.h new file mode 100644 index 0000000000..436efb5742 --- /dev/null +++ b/interface/src/plugins/display/OculusWin32DisplayPlugin.h @@ -0,0 +1,15 @@ +// +// Created by Bradley Austin Davis on 2015/05/26. +// 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 "OculusBaseDisplayPlugin.h" + +class OculusWin32DisplayPlugin : public OculusBaseDisplayPlugin { +public: + virtual bool isSupported(); +}; diff --git a/interface/src/plugins/display/OglplusHelpers.h b/interface/src/plugins/display/OglplusHelpers.h new file mode 100644 index 0000000000..b74362a617 --- /dev/null +++ b/interface/src/plugins/display/OglplusHelpers.h @@ -0,0 +1,26 @@ +// +// Created by Bradley Austin Davis on 2015/05/26. +// 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 + +#define OGLPLUS_USE_GLEW 1 +#define OGLPLUS_USE_GLCOREARB_H 0 +#define OGLPLUS_USE_BOOST_CONFIG 1 +#define OGLPLUS_NO_SITE_CONFIG 1 +#define OGLPLUS_LOW_PROFILE 1 +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +typedef std::shared_ptr FramebufferPtr; From a94f25738172c4c42a280b8a638b3eeb6edc31b6 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 29 May 2015 09:03:44 -0700 Subject: [PATCH 014/552] Working on plugin library --- interface/src/plugins/Plugin.h | 6 +++++- libraries/plugins/CMakeLists.txt | 12 ++++++++++++ libraries/plugins/src/Plugin.h | 20 ++++++++++++++++++++ libraries/plugins/src/PluginContainer.h | 7 +++++++ 4 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 libraries/plugins/CMakeLists.txt create mode 100644 libraries/plugins/src/Plugin.h create mode 100644 libraries/plugins/src/PluginContainer.h diff --git a/interface/src/plugins/Plugin.h b/interface/src/plugins/Plugin.h index a49c7487b8..ff91a6e1e2 100644 --- a/interface/src/plugins/Plugin.h +++ b/interface/src/plugins/Plugin.h @@ -3,6 +3,10 @@ #include #include +class PluginContainer { + virtual void addMenuItem(const QString& path, std::function onClicked, bool checkable = false, bool checked = false, const QString& groupName = "") = 0; +}; + class Plugin : public QObject { public: virtual const QString & getName() = 0; @@ -11,7 +15,7 @@ public: virtual void init() {} virtual void deinit() {} - virtual void activate() {} + virtual void activate(PluginContainer * container) {} virtual void deactivate() {} virtual void idle() {} diff --git a/libraries/plugins/CMakeLists.txt b/libraries/plugins/CMakeLists.txt new file mode 100644 index 0000000000..9401f73174 --- /dev/null +++ b/libraries/plugins/CMakeLists.txt @@ -0,0 +1,12 @@ +set(TARGET_NAME plugins) + +# use setup_hifi_library macro to setup our project and link appropriate Qt modules +setup_hifi_library(OpenGL Network Qml Quick Script XmlPatterns) + +link_hifi_libraries(shared) + +add_dependency_external_projects(glm) +find_package(GLM REQUIRED) +target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) + + diff --git a/libraries/plugins/src/Plugin.h b/libraries/plugins/src/Plugin.h new file mode 100644 index 0000000000..db01aa74ca --- /dev/null +++ b/libraries/plugins/src/Plugin.h @@ -0,0 +1,20 @@ +#pragma once + +#include +#include + +class PluginContainer; + +class Plugin : public QObject { +public: + virtual const QString& getName() = 0; + virtual bool isSupported() const { return true; } + + virtual void init() {} + virtual void deinit() {} + + virtual void activate(PluginContainer * container) {} + virtual void deactivate() {} + + virtual void idle() {} +}; diff --git a/libraries/plugins/src/PluginContainer.h b/libraries/plugins/src/PluginContainer.h new file mode 100644 index 0000000000..d0a21f0cdd --- /dev/null +++ b/libraries/plugins/src/PluginContainer.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +class PluginContainer { + virtual void addMenuItem(const QString& path, std::function onClicked, bool checkable = false, bool checked = false, const QString& groupName = "") = 0; +}; From 912c003d58e7932ff59b717169ee977000216883 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 29 May 2015 16:49:11 -0700 Subject: [PATCH 015/552] Making (most) plugins into a library --- cmake/macros/SetupHifiOpenGL.cmake | 43 +++ interface/CMakeLists.txt | 21 +- interface/src/Application.cpp | 28 +- interface/src/Application.h | 5 +- .../display => }/LegacyDisplayPlugin.cpp | 62 +++-- .../display => }/LegacyDisplayPlugin.h | 20 +- interface/src/avatar/MyAvatar.cpp | 1 - interface/src/plugins/Plugin.cpp | 1 - interface/src/plugins/Plugin.h | 22 -- .../src/plugins/display/HmdDisplayPlugin.cpp | 11 - .../src/plugins/display/HmdDisplayPlugin.h | 15 -- .../plugins/display/SimpleDisplayPlugin.cpp | 161 ------------ .../src/plugins/display/SimpleDisplayPlugin.h | 62 ----- .../plugins/display/StereoDisplayPlugin.cpp | 10 - .../src/plugins/display/StereoDisplayPlugin.h | 17 -- .../src/plugins/display/Tv3dDisplayPlugin.cpp | 245 ------------------ .../plugins/display/WindowDisplayPlugin.cpp | 38 --- libraries/display-plugins/CMakeLists.txt | 30 +++ .../display-plugins/src}/OculusHelpers.h | 2 +- .../display-plugins/src/OglplusHelpers.cpp | 122 +++++++++ .../display-plugins/src}/OglplusHelpers.h | 16 +- .../src/display-plugins}/DisplayPlugin.cpp | 6 +- .../src/display-plugins}/DisplayPlugin.h | 50 ++-- .../display-plugins/GlWindowDisplayPlugin.cpp | 127 +++++++++ .../display-plugins/GlWindowDisplayPlugin.h | 41 +++ .../display-plugins}/NullDisplayPlugin.cpp | 13 + .../src/display-plugins}/NullDisplayPlugin.h | 14 +- .../OculusBaseDisplayPlugin.cpp | 9 +- .../OculusBaseDisplayPlugin.h | 11 +- .../OculusWin32DisplayPlugin.cpp | 10 +- .../OculusWin32DisplayPlugin.h | 2 +- .../display-plugins/OpenGlDisplayPlugin.cpp | 88 +++++++ .../src/display-plugins/OpenGlDisplayPlugin.h | 24 ++ .../src/display-plugins/Tv3dDisplayPlugin.cpp | 176 +++++++++++++ .../src/display-plugins}/Tv3dDisplayPlugin.h | 19 +- .../display-plugins/WindowDisplayPlugin.cpp | 18 ++ .../display-plugins}/WindowDisplayPlugin.h | 13 +- libraries/plugins/CMakeLists.txt | 2 +- libraries/plugins/src/Plugin.h | 20 -- libraries/plugins/src/plugins/Plugin.cpp | 9 + libraries/plugins/src/plugins/Plugin.h | 29 +++ .../src/{ => plugins}/PluginContainer.h | 0 .../plugins}/src/plugins/PluginManager.cpp | 0 .../plugins}/src/plugins/PluginManager.h | 4 +- 44 files changed, 889 insertions(+), 728 deletions(-) create mode 100644 cmake/macros/SetupHifiOpenGL.cmake rename interface/src/{plugins/display => }/LegacyDisplayPlugin.cpp (73%) rename interface/src/{plugins/display => }/LegacyDisplayPlugin.h (60%) delete mode 100644 interface/src/plugins/Plugin.cpp delete mode 100644 interface/src/plugins/Plugin.h delete mode 100644 interface/src/plugins/display/HmdDisplayPlugin.cpp delete mode 100644 interface/src/plugins/display/HmdDisplayPlugin.h delete mode 100644 interface/src/plugins/display/SimpleDisplayPlugin.cpp delete mode 100644 interface/src/plugins/display/SimpleDisplayPlugin.h delete mode 100644 interface/src/plugins/display/StereoDisplayPlugin.cpp delete mode 100644 interface/src/plugins/display/StereoDisplayPlugin.h delete mode 100644 interface/src/plugins/display/Tv3dDisplayPlugin.cpp delete mode 100644 interface/src/plugins/display/WindowDisplayPlugin.cpp create mode 100644 libraries/display-plugins/CMakeLists.txt rename {interface/src/plugins/display => libraries/display-plugins/src}/OculusHelpers.h (97%) create mode 100644 libraries/display-plugins/src/OglplusHelpers.cpp rename {interface/src/plugins/display => libraries/display-plugins/src}/OglplusHelpers.h (55%) rename {interface/src/plugins/display => libraries/display-plugins/src/display-plugins}/DisplayPlugin.cpp (86%) rename {interface/src/plugins/display => libraries/display-plugins/src/display-plugins}/DisplayPlugin.h (72%) create mode 100644 libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.cpp create mode 100644 libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.h rename {interface/src/plugins/display => libraries/display-plugins/src/display-plugins}/NullDisplayPlugin.cpp (69%) rename {interface/src/plugins/display => libraries/display-plugins/src/display-plugins}/NullDisplayPlugin.h (72%) rename {interface/src/plugins/display => libraries/display-plugins/src/display-plugins}/OculusBaseDisplayPlugin.cpp (87%) rename {interface/src/plugins/display => libraries/display-plugins/src/display-plugins}/OculusBaseDisplayPlugin.h (74%) rename {interface/src/plugins/display => libraries/display-plugins/src/display-plugins}/OculusWin32DisplayPlugin.cpp (97%) rename {interface/src/plugins/display => libraries/display-plugins/src/display-plugins}/OculusWin32DisplayPlugin.h (87%) create mode 100644 libraries/display-plugins/src/display-plugins/OpenGlDisplayPlugin.cpp create mode 100644 libraries/display-plugins/src/display-plugins/OpenGlDisplayPlugin.h create mode 100644 libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.cpp rename {interface/src/plugins/display => libraries/display-plugins/src/display-plugins}/Tv3dDisplayPlugin.h (67%) create mode 100644 libraries/display-plugins/src/display-plugins/WindowDisplayPlugin.cpp rename {interface/src/plugins/display => libraries/display-plugins/src/display-plugins}/WindowDisplayPlugin.h (62%) delete mode 100644 libraries/plugins/src/Plugin.h create mode 100644 libraries/plugins/src/plugins/Plugin.cpp create mode 100644 libraries/plugins/src/plugins/Plugin.h rename libraries/plugins/src/{ => plugins}/PluginContainer.h (100%) rename {interface => libraries/plugins}/src/plugins/PluginManager.cpp (100%) rename {interface => libraries/plugins}/src/plugins/PluginManager.h (51%) diff --git a/cmake/macros/SetupHifiOpenGL.cmake b/cmake/macros/SetupHifiOpenGL.cmake new file mode 100644 index 0000000000..c62e43c27e --- /dev/null +++ b/cmake/macros/SetupHifiOpenGL.cmake @@ -0,0 +1,43 @@ + + +macro(SETUP_HIFI_OPENGL) + + if (APPLE) + + # link in required OS X frameworks and include the right GL headers + find_library(OpenGL OpenGL) + target_link_libraries(${TARGET_NAME} ${OpenGL}) + + elseif (WIN32) + + add_dependency_external_projects(glew) + find_package(GLEW REQUIRED) + target_include_directories(${TARGET_NAME} PUBLIC ${GLEW_INCLUDE_DIRS}) + target_link_libraries(${TARGET_NAME} ${GLEW_LIBRARIES} opengl32.lib) + + if (USE_NSIGHT) + # try to find the Nsight package and add it to the build if we find it + find_package(NSIGHT) + if (NSIGHT_FOUND) + include_directories(${NSIGHT_INCLUDE_DIRS}) + add_definitions(-DNSIGHT_FOUND) + target_link_libraries(${TARGET_NAME} "${NSIGHT_LIBRARIES}") + endif() + endif() + + elseif(ANDROID) + + target_link_libraries(${TARGET_NAME} "-lGLESv3" "-lEGL") + + else() + + find_package(OpenGL REQUIRED) + if (${OPENGL_INCLUDE_DIR}) + include_directories(SYSTEM "${OPENGL_INCLUDE_DIR}") + endif() + target_link_libraries(${TARGET_NAME} "${OPENGL_LIBRARY}") + target_include_directories(${TARGET_NAME} PUBLIC ${OPENGL_INCLUDE_DIR}) + + endif() + +endmacro() diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index bb9960643c..458b6a7d7c 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -128,25 +128,6 @@ add_dependency_external_projects(glm bullet) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PRIVATE ${GLM_INCLUDE_DIRS}) -add_dependency_external_projects(boostconfig) -find_package(BOOSTCONFIG REQUIRED) -target_include_directories(${TARGET_NAME} PUBLIC ${BOOSTCONFIG_INCLUDE_DIRS}) - -add_dependency_external_projects(oglplus) -find_package(OGLPLUS REQUIRED) -target_include_directories(${TARGET_NAME} PUBLIC ${OGLPLUS_INCLUDE_DIRS}) - - -add_dependency_external_projects(LibOVR) -find_package(LibOVR REQUIRED) -target_include_directories(${TARGET_NAME} PRIVATE ${LIBOVR_INCLUDE_DIRS}) -target_link_libraries(${TARGET_NAME} ${LIBOVR_LIBRARIES}) - -add_dependency_external_projects(OpenVR) -find_package(OpenVR REQUIRED) -target_include_directories(${TARGET_NAME} PRIVATE ${OPENVR_INCLUDE_DIRS}) -target_link_libraries(${TARGET_NAME} ${OPENVR_LIBRARIES}) - find_package(Bullet REQUIRED) target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${BULLET_INCLUDE_DIRS}) target_link_libraries(${TARGET_NAME} ${BULLET_LIBRARIES}) @@ -154,7 +135,7 @@ target_link_libraries(${TARGET_NAME} ${BULLET_LIBRARIES}) # link required hifi libraries link_hifi_libraries(shared octree environment gpu model fbx networking entities avatars audio audio-client animation script-engine physics - render-utils entities-renderer ui) + render-utils entities-renderer ui plugins display-plugins) add_dependency_external_projects(sdl2) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 90730e8c82..f42d86d8eb 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -116,7 +116,7 @@ #include "gpu/Batch.h" #include "gpu/GLBackend.h" -#include "plugins/display/DisplayPlugin.h" +#include #include "scripting/AccountScriptingInterface.h" #include "scripting/AudioDeviceScriptingInterface.h" @@ -4582,12 +4582,11 @@ qreal Application::getDevicePixelRatio() { using DisplayPluginPointer = QSharedPointer; -#include "plugins/display/NullDisplayPlugin.h" -#include "plugins/display/WindowDisplayPlugin.h" -#include "plugins/display/LegacyDisplayPlugin.h" -#include "plugins/display/OculusDisplayPlugin.h" -#include "plugins/display/Tv3dDisplayPlugin.h" -#include "plugins/display/WindowDisplayPlugin.h" +#include +#include "LegacyDisplayPlugin.h" +//#include +#include +//#include static DisplayPluginPointer _displayPlugin{ nullptr }; @@ -4631,7 +4630,7 @@ static DisplayPlugin* PLUGIN_POOL[] = { new NullDisplayPlugin(), #endif new Tv3dDisplayPlugin(), - new WindowDisplayPlugin(), +// new WindowDisplayPlugin(), nullptr }; @@ -4674,9 +4673,17 @@ void Application::updateDisplayMode() { if (_displayPlugin != newDisplayPlugin) { if (newDisplayPlugin) { _offscreenContext->makeCurrent(); - newDisplayPlugin->activate(); + newDisplayPlugin->activate(this); + QWindow* pluginWindow = newDisplayPlugin->getWindow(); + if (pluginWindow) { + // Event filter queue is 'last in, first used' + pluginWindow->installEventFilter(DependencyManager::get().data()); + pluginWindow->installEventFilter(qApp); + DependencyManager::get()->setProxyWindow(pluginWindow); + } _offscreenContext->makeCurrent(); } + std::swap(newDisplayPlugin, _displayPlugin); if (newDisplayPlugin) { newDisplayPlugin->deactivate(); @@ -4694,3 +4701,6 @@ glm::ivec2 Application::getMouse() const { return getActiveDisplayPlugin()->getUiMousePosition(); } +void Application::addMenuItem(const QString& path, std::function onClicked, bool checkable, bool checked, const QString& groupName) { + +} diff --git a/interface/src/Application.h b/interface/src/Application.h index a94859263a..a91e5f77f2 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -40,6 +40,7 @@ #include #include #include +#include #include "AudioClient.h" #include "Bookmarks.h" @@ -136,7 +137,7 @@ class Application; typedef bool (Application::* AcceptURLMethod)(const QString &); -class Application : public QApplication, public AbstractViewStateInterface, AbstractScriptingServicesInterface { +class Application : public QApplication, public AbstractViewStateInterface, AbstractScriptingServicesInterface, PluginContainer { Q_OBJECT friend class OctreePacketProcessor; @@ -280,6 +281,8 @@ public: QImage renderAvatarBillboard(); void displaySide(const Camera& camera, bool selfAvatarOnly = false); + + virtual void addMenuItem(const QString& path, std::function onClicked, bool checkable, bool checked, const QString& groupName); /* /// Stores the current modelview matrix as the untranslated view matrix to use for transforms and the supplied vector as diff --git a/interface/src/plugins/display/LegacyDisplayPlugin.cpp b/interface/src/LegacyDisplayPlugin.cpp similarity index 73% rename from interface/src/plugins/display/LegacyDisplayPlugin.cpp rename to interface/src/LegacyDisplayPlugin.cpp index a6b79fa5ef..4fbb02e454 100644 --- a/interface/src/plugins/display/LegacyDisplayPlugin.cpp +++ b/interface/src/LegacyDisplayPlugin.cpp @@ -19,38 +19,46 @@ const QString & LegacyDisplayPlugin::getName() { return NAME; } +LegacyDisplayPlugin::LegacyDisplayPlugin() { + connect(&_timer, &QTimer::timeout, this, [&] { + emit requestRender(); + }); +} + static QWidget * oldWidget = nullptr; -void LegacyDisplayPlugin::activate() { +void LegacyDisplayPlugin::activate(PluginContainer * container) { _window = new GLCanvas(); QOpenGLContext * sourceContext = QOpenGLContext::currentContext(); - QSurfaceFormat format; - format.setOption(QSurfaceFormat::DebugContext); QOpenGLContext * newContext = new QOpenGLContext(); - newContext->setFormat(format); + + { + QSurfaceFormat format; + format.setOption(QSurfaceFormat::DebugContext); + newContext->setFormat(format); + } + _window->setContext( QGLContext::fromOpenGLContext(newContext), QGLContext::fromOpenGLContext(sourceContext)); - _window->makeCurrent(); - oldWidget = qApp->getWindow()->centralWidget(); + + // FIXME necessary? + makeCurrent(); qApp->getWindow()->setCentralWidget(_window); - _window->doneCurrent(); + doneCurrent(); _window->setFocusPolicy(Qt::StrongFocus); _window->setFocus(); _window->setMouseTracking(true); - - _window->installEventFilter(qApp); - _window->installEventFilter(DependencyManager::get().data()); - - DependencyManager::get()->setProxyWindow(_window->windowHandle()); - SimpleDisplayPlugin::activate(); + _timer.start(8); } + void LegacyDisplayPlugin::deactivate() { + _timer.stop(); _window->removeEventFilter(DependencyManager::get().data()); _window->removeEventFilter(qApp); // FIXME, during shutdown, this causes an NPE. Need to deactivate the plugin before the main window is destroyed. @@ -84,16 +92,32 @@ PickRay LegacyDisplayPlugin::computePickRay(const glm::vec2 & pos) const { return PickRay(); } -bool isMouseOnScreen() { - return false; -} - void LegacyDisplayPlugin::preDisplay() { - SimpleDisplayPlugin::preDisplay(); + OpenGlDisplayPlugin::preDisplay(); auto size = toGlm(_window->size()); glViewport(0, 0, size.x, size.y); } bool LegacyDisplayPlugin::isThrottled() const { return _window->isThrottleRendering(); -} \ No newline at end of file +} + +void LegacyDisplayPlugin::makeCurrent() { + _window->makeCurrent(); +} + +void LegacyDisplayPlugin::doneCurrent() { + _window->doneCurrent(); +} + +void LegacyDisplayPlugin::swapBuffers() { + _window->swapBuffers(); +} + +ivec2 LegacyDisplayPlugin::getTrueMousePosition() const { + return toGlm(_window->mapFromGlobal(QCursor::pos())); +} + +QWindow* LegacyDisplayPlugin::getWindow() const { + return _window->windowHandle(); +} diff --git a/interface/src/plugins/display/LegacyDisplayPlugin.h b/interface/src/LegacyDisplayPlugin.h similarity index 60% rename from interface/src/plugins/display/LegacyDisplayPlugin.h rename to interface/src/LegacyDisplayPlugin.h index 33ea6187c3..223f4d9e01 100644 --- a/interface/src/plugins/display/LegacyDisplayPlugin.h +++ b/interface/src/LegacyDisplayPlugin.h @@ -9,26 +9,36 @@ // #pragma once -#include "SimpleDisplayPlugin.h" +#include #include "GLCanvas.h" -class LegacyDisplayPlugin : public SimpleDisplayPlugin { +class LegacyDisplayPlugin : public OpenGlDisplayPlugin { Q_OBJECT public: + LegacyDisplayPlugin(); static const QString NAME; virtual const QString & getName(); - virtual void activate(); + virtual void activate(PluginContainer * container); virtual void deactivate(); virtual QSize getDeviceSize() const; - virtual glm::ivec2 getCanvasSize() const; + virtual ivec2 getCanvasSize() const; virtual bool hasFocus() const; virtual PickRay computePickRay(const glm::vec2 & pos) const; virtual bool isMouseOnScreen() const { return true; } virtual bool isThrottled() const; virtual void preDisplay(); + virtual void idle(); + virtual ivec2 getTrueMousePosition() const; + virtual QWindow* getWindow() const; protected: - virtual void idle(); + virtual void makeCurrent() final; + virtual void doneCurrent() final; + virtual void swapBuffers() final; + +private: + GLCanvas * _window; + QTimer _timer; }; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 0ba4d1637b..e573110157 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -34,7 +34,6 @@ #include #include "Application.h" -#include "plugins/display/DisplayPlugin.h" #include "AvatarManager.h" #include "Environment.h" #include "Menu.h" diff --git a/interface/src/plugins/Plugin.cpp b/interface/src/plugins/Plugin.cpp deleted file mode 100644 index d882c538b4..0000000000 --- a/interface/src/plugins/Plugin.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "Plugin.h" diff --git a/interface/src/plugins/Plugin.h b/interface/src/plugins/Plugin.h deleted file mode 100644 index ff91a6e1e2..0000000000 --- a/interface/src/plugins/Plugin.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include -#include - -class PluginContainer { - virtual void addMenuItem(const QString& path, std::function onClicked, bool checkable = false, bool checked = false, const QString& groupName = "") = 0; -}; - -class Plugin : public QObject { -public: - virtual const QString & getName() = 0; - virtual bool isSupported() const { return true; } - - virtual void init() {} - virtual void deinit() {} - - virtual void activate(PluginContainer * container) {} - virtual void deactivate() {} - - virtual void idle() {} -}; diff --git a/interface/src/plugins/display/HmdDisplayPlugin.cpp b/interface/src/plugins/display/HmdDisplayPlugin.cpp deleted file mode 100644 index bfe4a088fa..0000000000 --- a/interface/src/plugins/display/HmdDisplayPlugin.cpp +++ /dev/null @@ -1,11 +0,0 @@ -// -// HmdDisplayPlugin.cpp -// -// Created by Bradley Austin Davis on 2014/04/13. -// 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 "HmdDisplayPlugin.h" diff --git a/interface/src/plugins/display/HmdDisplayPlugin.h b/interface/src/plugins/display/HmdDisplayPlugin.h deleted file mode 100644 index 1156bafcda..0000000000 --- a/interface/src/plugins/display/HmdDisplayPlugin.h +++ /dev/null @@ -1,15 +0,0 @@ -// -// HmdDisplayPlugin.h -// -// Created by Bradley Austin Davis on 2014/04/13. -// 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 "StereoDisplayPlugin.h" - -class HmdDisplayPlugin : public StereoDisplayPlugin { - virtual bool isHmd() const final { return true; } -}; diff --git a/interface/src/plugins/display/SimpleDisplayPlugin.cpp b/interface/src/plugins/display/SimpleDisplayPlugin.cpp deleted file mode 100644 index 3c7ec2fb3f..0000000000 --- a/interface/src/plugins/display/SimpleDisplayPlugin.cpp +++ /dev/null @@ -1,161 +0,0 @@ -// -// SimpleDisplayPlugin.cpp -// -// Created by Bradley Austin Davis on 2014/04/13. -// 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 "SimpleDisplayPlugin.h" -#include -#include -#include - -#include -#include "DependencyManager.h" -#include "TextureCache.h" -#include "gpu/GLBackend.h" -#include "OffscreenUi.h" - -void SimpleGlDisplayPlugin::activate() { - makeCurrent(); - doneCurrent(); -} - -void SimpleGlDisplayPlugin::display(GLuint sceneTexture, const glm::uvec2& sceneSize, - GLuint overlayTexture, const glm::uvec2& overlaySize) { - makeCurrent(); - glDisable(GL_LIGHTING); - glDisable(GL_DEPTH_TEST); - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - - glClearColor(0, 0, 1, 1); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glEnable(GL_TEXTURE_2D); - - glViewport(0, 0, getDeviceSize().width(), getDeviceSize().height()); - if (sceneTexture) { - glBindTexture(GL_TEXTURE_2D, sceneTexture); - glBegin(GL_QUADS); - glTexCoord2f(0, 0); - glVertex2f(-1, -1); - glTexCoord2f(1, 0); - glVertex2f(+1, -1); - glTexCoord2f(1, 1); - glVertex2f(+1, +1); - glTexCoord2f(0, 1); - glVertex2f(-1, +1); - glEnd(); - } - - if (overlayTexture) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glBindTexture(GL_TEXTURE_2D, overlayTexture); - glBegin(GL_QUADS); - glTexCoord2f(0, 0); - glVertex2f(-1, -1); - glTexCoord2f(1, 0); - glVertex2f(+1, -1); - glTexCoord2f(1, 1); - glVertex2f(+1, +1); - glTexCoord2f(0, 1); - glVertex2f(-1, +1); - glEnd(); - } - - - glDisable(GL_BLEND); - - glBindTexture(GL_TEXTURE_2D, 0); - glDisable(GL_TEXTURE_2D); - //Q_ASSERT(!glGetError()); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - - glEnable(GL_LIGHTING); - glEnable(GL_DEPTH_TEST); - - glFinish(); -} - -bool GlWindowDisplayPlugin::eventFilter(QObject* object, QEvent* event) { - if (qApp->eventFilter(object, event)) { - return true; - } - - auto offscreenUi = DependencyManager::get(); - if (offscreenUi->eventFilter(object, event)) { - return true; - } - - switch (event->type()) { - case QEvent::KeyPress: - case QEvent::KeyRelease: - QCoreApplication::sendEvent(QCoreApplication::instance(), event); - break; - - case QEvent::MouseButtonPress: - case QEvent::MouseButtonRelease: - case QEvent::FocusIn: - case QEvent::FocusOut: - case QEvent::Resize: - case QEvent::MouseMove: - QCoreApplication::sendEvent(QCoreApplication::instance(), event); - break; - default: - break; - } - return false; -} - - -static QSurfaceFormat getPluginFormat() { - QSurfaceFormat format; - // Qt Quick may need a depth and stencil buffer. Always make sure these are available. - format.setDepthBufferSize(16); - format.setStencilBufferSize(8); - format.setVersion(4, 1); -#ifdef DEBUG - format.setOption(QSurfaceFormat::DebugContext); -#endif - format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile); - return format; -} - - -void GlWindowDisplayPlugin::activate() { - Q_ASSERT(nullptr == _window); - _window = new GlWindow(getPluginFormat(), QOpenGLContext::currentContext()); - _window->installEventFilter(this); - DependencyManager::get()->setProxyWindow(_window); -} - -void GlWindowDisplayPlugin::deactivate() { - Q_ASSERT(nullptr != _window); - _window->hide(); - _window->destroy(); - _window->deleteLater(); - _window = nullptr; -} - -QSize GlWindowDisplayPlugin::getDeviceSize() const { - return _window->geometry().size() * _window->devicePixelRatio(); -} - -glm::ivec2 GlWindowDisplayPlugin::getCanvasSize() const { - return toGlm(_window->geometry().size()); -} - -bool GlWindowDisplayPlugin::hasFocus() const { - return _window->isActive(); -} diff --git a/interface/src/plugins/display/SimpleDisplayPlugin.h b/interface/src/plugins/display/SimpleDisplayPlugin.h deleted file mode 100644 index ca86d85875..0000000000 --- a/interface/src/plugins/display/SimpleDisplayPlugin.h +++ /dev/null @@ -1,62 +0,0 @@ -// -// SimpleDisplayPlugin.h -// -// Created by Bradley Austin Davis on 2014/04/13. -// 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 "DisplayPlugin.h" - -#include - -#include -#include -#include -#include - -class SimpleGlDisplayPlugin : public DisplayPlugin { -public: - virtual void activate(); - virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize, - GLuint overlayTexture, const glm::uvec2& overlaySize); -}; - -template -class SimpleDisplayPlugin : public SimpleGlDisplayPlugin { -public: - virtual glm::ivec2 getTrueMousePosition() const { - return toGlm(_window->mapFromGlobal(QCursor::pos())); - } - -protected: - void makeCurrent() final { - _window->makeCurrent(); - } - - void doneCurrent() final { - _window->doneCurrent(); - } - - void swapBuffers() final { - _window->swapBuffers(); - } - -protected: - T * _window{ nullptr }; -}; - - -class GlWindowDisplayPlugin : public SimpleDisplayPlugin { -public: - virtual void activate(); - virtual void deactivate(); - virtual QSize getDeviceSize() const final; - virtual glm::ivec2 getCanvasSize() const final; - virtual bool hasFocus() const; - virtual bool eventFilter(QObject* object, QEvent* event); -}; - diff --git a/interface/src/plugins/display/StereoDisplayPlugin.cpp b/interface/src/plugins/display/StereoDisplayPlugin.cpp deleted file mode 100644 index 25070a4967..0000000000 --- a/interface/src/plugins/display/StereoDisplayPlugin.cpp +++ /dev/null @@ -1,10 +0,0 @@ -// -// StereoDisplayPlugin.cpp -// -// Created by Bradley Austin Davis on 2014/04/13. -// 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 "StereoDisplayPlugin.h" diff --git a/interface/src/plugins/display/StereoDisplayPlugin.h b/interface/src/plugins/display/StereoDisplayPlugin.h deleted file mode 100644 index e3944ff878..0000000000 --- a/interface/src/plugins/display/StereoDisplayPlugin.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// StereoDisplayPlugin.h -// -// Created by Bradley Austin Davis on 2014/04/13. -// 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 "DisplayPlugin.h" - -class StereoDisplayPlugin : public DisplayPlugin { - virtual bool isStereo() const final { return true; } -}; - diff --git a/interface/src/plugins/display/Tv3dDisplayPlugin.cpp b/interface/src/plugins/display/Tv3dDisplayPlugin.cpp deleted file mode 100644 index efd6c055c9..0000000000 --- a/interface/src/plugins/display/Tv3dDisplayPlugin.cpp +++ /dev/null @@ -1,245 +0,0 @@ -// Tv3dDisplayPlugin.cpp -// -// Created by Bradley Austin Davis on 2014/04/13. -// 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 "Tv3dDisplayPlugin.h" -#include -#include -#include - -#include "gpu/Texture.h" -#include "gpu/GLBackend.h" -#include "PathUtils.h" - -#include "Application.h" -#include "ui/ApplicationOverlay.h" - - -#include -#define OGLPLUS_LOW_PROFILE 1 -#define OGLPLUS_USE_GLEW 1 -#define OGLPLUS_USE_BOOST_CONFIG 1 -#define OGLPLUS_NO_SITE_CONFIG 1 -#define OGLPLUS_USE_GLCOREARB_H 0 -#include - -#pragma warning(disable : 4068) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Warc-performSelector-leaks" -#pragma warning( disable : 4244 4267 4065 4101) -#include -#include -#include -#include -#include -#include -#include -#pragma warning( default : 4244 4267 4065 4101) -#pragma clang diagnostic pop - -typedef std::shared_ptr ShapeWrapperPtr; -typedef std::shared_ptr BufferPtr; -typedef std::shared_ptr VertexArrayPtr; -typedef std::shared_ptr ProgramPtr; -typedef oglplus::Uniform Mat4Uniform; - -const QString Tv3dDisplayPlugin::NAME("Tv3dDisplayPlugin"); - -const QString & Tv3dDisplayPlugin::getName() { - return NAME; -} - -Tv3dDisplayPlugin::Tv3dDisplayPlugin() { - connect(&_timer, &QTimer::timeout, this, [&] { - emit requestRender(); - }); -} - -bool Tv3dDisplayPlugin::isSupported() const { - // FIXME this should attempt to do a scan for supported 3D output - return true; -} - -gpu::TexturePointer _crosshairTexture; - - -void compileProgram(ProgramPtr & result, std::string vs, std::string fs) { - using namespace oglplus; - try { - result = ProgramPtr(new Program()); - // attach the shaders to the program - result->AttachShader( - VertexShader() - .Source(GLSLSource(vs)) - .Compile() - ); - result->AttachShader( - FragmentShader() - .Source(GLSLSource(fs)) - .Compile() - ); - result->Link(); - } catch (ProgramBuildError & err) { - qFatal((const char*)err.Message); - result.reset(); - } -} - - -ShapeWrapperPtr loadPlane(ProgramPtr program, float aspect) { - using namespace oglplus; - Vec3f a(1, 0, 0); - Vec3f b(0, 1, 0); - if (aspect > 1) { - b[1] /= aspect; - } else { - a[0] *= aspect; - } - return ShapeWrapperPtr( - new shapes::ShapeWrapper({ "Position", "TexCoord" }, shapes::Plane(a, b), *program) - ); -} - - -static const char * QUAD_VS = R"VS(#version 330 - -uniform mat4 Projection = mat4(1); -uniform mat4 ModelView = mat4(1); -uniform vec2 UvMultiplier = vec2(1); - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec2 TexCoord; - -out vec2 vTexCoord; - -void main() { - gl_Position = Projection * ModelView * vec4(Position, 1); - vTexCoord = TexCoord * UvMultiplier; -} -)VS"; - -static const char * QUAD_FS = R"FS(#version 330 -uniform sampler2D sampler; -uniform float Alpha = 1.0; - -in vec2 vTexCoord; -out vec4 vFragColor; - -void main() { - vec4 c = texture(sampler, vTexCoord); - c.a = min(Alpha, c.a); - vFragColor = c; - //vFragColor = vec4(fract(vTexCoord), log(vTexCoord.x), 1.0); -} -)FS"; - -static ProgramPtr program; -static ShapeWrapperPtr plane; - -void Tv3dDisplayPlugin::display( - GLuint sceneTexture, const glm::uvec2& sceneSize, - GLuint overlayTexture, const glm::uvec2& overlaySize) { - QSize size = getDeviceSize(); - makeCurrent(); - - - if (!program) { - using namespace oglplus; - Context::BlendFunc(BlendFunction::SrcAlpha, BlendFunction::OneMinusSrcAlpha); - Context::Disable(Capability::Blend); - Context::Disable(Capability::DepthTest); - Context::Disable(Capability::CullFace); - - program = ProgramPtr(new oglplus::Program()); - compileProgram(program, QUAD_VS, QUAD_FS); - plane = loadPlane(program, 1.0f); - _crosshairTexture = DependencyManager::get()-> - getImageTexture(PathUtils::resourcesPath() + "images/sixense-reticle.png"); - } - - - - glClearColor(0, 0, 0, 1); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glViewport(0, 0, size.width(), size.height()); - Mat4Uniform(*program, "ModelView").Set(mat4()); - Mat4Uniform(*program, "Projection").Set(mat4()); - glBindTexture(GL_TEXTURE_2D, sceneTexture); - plane->Draw(); - - const float overlayAspect = aspect(toGlm(size)); - const GLfloat distance = 1.0f; - const GLfloat halfQuadHeight = distance * tan(DEFAULT_FIELD_OF_VIEW_DEGREES); - const GLfloat halfQuadWidth = halfQuadHeight * (float)size.width() / (float)size.height(); - const GLfloat quadWidth = halfQuadWidth * 2.0f; - const GLfloat quadHeight = halfQuadHeight * 2.0f; - - vec3 quadSize(quadWidth, quadHeight, 1.0f); - quadSize = vec3(1.0f) / quadSize; - - using namespace oglplus; - - Context::Enable(Capability::Blend); - glBindTexture(GL_TEXTURE_2D, overlayTexture); - - mat4 pr = glm::perspective(glm::radians(DEFAULT_FIELD_OF_VIEW_DEGREES), aspect(toGlm(size)), DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP); - Mat4Uniform(*program, "Projection").Set(pr); - - MatrixStack mv; - mv.translate(vec3(0, 0, -distance)).scale(vec3(0.7f, 0.7f / overlayAspect, 1.0f)); // .scale(vec3(quadWidth, quadHeight, 1.0)); - - QRect r(QPoint(0, 0), QSize(size.width() / 2, size.height())); - for (int i = 0; i < 2; ++i) { - Context::Viewport(r.x(), r.y(), r.width(), r.height()); - Mat4Uniform(*program, "ModelView").Set(mv.top()); - plane->Draw(); - r.moveLeft(r.width()); - } - - glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_crosshairTexture)); - glm::vec2 canvasSize = qApp->getCanvasSize(); - glm::vec2 mouse = qApp->getMouse(); - mouse /= canvasSize; - mouse *= 2.0f; - mouse -= 1.0f; - mouse.y *= -1.0f; - mv.translate(mouse); - mv.scale(0.1f); - Mat4Uniform(*program, "ModelView").Set(mv.top()); - r = QRect(QPoint(0, 0), QSize(size.width() / 2, size.height())); - for (int i = 0; i < 2; ++i) { - Context::Viewport(r.x(), r.y(), r.width(), r.height()); - plane->Draw(); - r.moveLeft(r.width()); - } - Context::Disable(Capability::Blend); -} - - -void Tv3dDisplayPlugin::activate() { - GlWindowDisplayPlugin::activate(); - _window->installEventFilter(this); - _window->setFlags(Qt::FramelessWindowHint); - auto desktop = QApplication::desktop(); - _window->setGeometry(desktop->screenGeometry()); - _window->setCursor(Qt::BlankCursor); - _window->show(); - - _timer.start(8); -} - -void Tv3dDisplayPlugin::deactivate() { - makeCurrent(); - if (plane) { - plane.reset(); - program.reset(); - _crosshairTexture.reset(); - } - _timer.stop(); - GlWindowDisplayPlugin::deactivate(); -} diff --git a/interface/src/plugins/display/WindowDisplayPlugin.cpp b/interface/src/plugins/display/WindowDisplayPlugin.cpp deleted file mode 100644 index 25162e9343..0000000000 --- a/interface/src/plugins/display/WindowDisplayPlugin.cpp +++ /dev/null @@ -1,38 +0,0 @@ -// -// WindowDisplayPlugin.cpp -// -// Created by Bradley Austin Davis on 2014/04/13. -// 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 "WindowDisplayPlugin.h" -#include "RenderUtil.h" -#include "Application.h" - -WindowDisplayPlugin::WindowDisplayPlugin() { - connect(&_timer, &QTimer::timeout, this, [&] { -// if (qApp->getActiveDisplayPlugin() == this) { - emit requestRender(); -// } - }); -} - -const QString WindowDisplayPlugin::NAME("QWindow 2D Renderer"); - -const QString & WindowDisplayPlugin::getName() { - return NAME; -} - -void WindowDisplayPlugin::activate() { - GlWindowDisplayPlugin::activate(); - _window->show(); - _timer.start(8); -} - -void WindowDisplayPlugin::deactivate() { - _timer.stop(); - GlWindowDisplayPlugin::deactivate(); -} - diff --git a/libraries/display-plugins/CMakeLists.txt b/libraries/display-plugins/CMakeLists.txt new file mode 100644 index 0000000000..cbfecfb0da --- /dev/null +++ b/libraries/display-plugins/CMakeLists.txt @@ -0,0 +1,30 @@ +set(TARGET_NAME display-plugins) + +# use setup_hifi_library macro to setup our project and link appropriate Qt modules +setup_hifi_library(OpenGL) + +setup_hifi_opengl() + +link_hifi_libraries(shared plugins ) + +add_dependency_external_projects(glm) +find_package(GLM REQUIRED) +target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) + +add_dependency_external_projects(boostconfig) +find_package(BOOSTCONFIG REQUIRED) +target_include_directories(${TARGET_NAME} PUBLIC ${BOOSTCONFIG_INCLUDE_DIRS}) + +add_dependency_external_projects(oglplus) +find_package(OGLPLUS REQUIRED) +target_include_directories(${TARGET_NAME} PUBLIC ${OGLPLUS_INCLUDE_DIRS}) + +add_dependency_external_projects(LibOVR) +find_package(LibOVR REQUIRED) +target_include_directories(${TARGET_NAME} PRIVATE ${LIBOVR_INCLUDE_DIRS}) +target_link_libraries(${TARGET_NAME} ${LIBOVR_LIBRARIES}) + +add_dependency_external_projects(OpenVR) +find_package(OpenVR REQUIRED) +target_include_directories(${TARGET_NAME} PRIVATE ${OPENVR_INCLUDE_DIRS}) +target_link_libraries(${TARGET_NAME} ${OPENVR_LIBRARIES}) diff --git a/interface/src/plugins/display/OculusHelpers.h b/libraries/display-plugins/src/OculusHelpers.h similarity index 97% rename from interface/src/plugins/display/OculusHelpers.h rename to libraries/display-plugins/src/OculusHelpers.h index 553a1671e5..acd02e1af9 100644 --- a/interface/src/plugins/display/OculusHelpers.h +++ b/libraries/display-plugins/src/OculusHelpers.h @@ -1,5 +1,5 @@ // -// Created by Bradley Austin Davis on 2015/05/26. +// Created by Bradley Austin Davis on 2015/05/26 // Copyright 2015 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. diff --git a/libraries/display-plugins/src/OglplusHelpers.cpp b/libraries/display-plugins/src/OglplusHelpers.cpp new file mode 100644 index 0000000000..fd9d9500f1 --- /dev/null +++ b/libraries/display-plugins/src/OglplusHelpers.cpp @@ -0,0 +1,122 @@ +// +// Created by Bradley Austin Davis on 2015/05/29 +// 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 "OglplusHelpers.h" + + +static const char * SIMPLE_TEXTURED_VS = R"VS(#version 410 core +#pragma line __LINE__ + +uniform mat4 Projection = mat4(1); +uniform mat4 ModelView = mat4(1); + +layout(location = 0) in vec3 Position; +layout(location = 1) in vec2 TexCoord; + +out vec2 vTexCoord; + +void main() { + gl_Position = Projection * ModelView * vec4(Position, 1); + vTexCoord = TexCoord; +} + +)VS"; + +static const char * SIMPLE_TEXTURED_FS = R"FS(#version 410 core +#pragma line __LINE__ + +uniform sampler2D sampler; +uniform float Alpha = 1.0; + +in vec2 vTexCoord; +out vec4 vFragColor; + +void main() { + vec4 c = texture(sampler, vTexCoord); + c.a = min(Alpha, c.a); + vFragColor = c; +} + +)FS"; + + +ProgramPtr loadDefaultShader() { + ProgramPtr result; + compileProgram(result, SIMPLE_TEXTURED_VS, SIMPLE_TEXTURED_FS); + return result; +} + +void compileProgram(ProgramPtr & result, const std::string& vs, const std::string& fs) { + using namespace oglplus; + try { + result = ProgramPtr(new Program()); + // attach the shaders to the program + result->AttachShader( + VertexShader() + .Source(GLSLSource(vs)) + .Compile() + ); + result->AttachShader( + FragmentShader() + .Source(GLSLSource(fs)) + .Compile() + ); + result->Link(); + } catch (ProgramBuildError & err) { + Q_UNUSED(err); + Q_ASSERT_X(false, "compileProgram", "Failed to build shader program"); + qFatal((const char*)err.Message); + result.reset(); + } +} + + +ShapeWrapperPtr loadPlane(ProgramPtr program, float aspect) { + using namespace oglplus; + Vec3f a(1, 0, 0); + Vec3f b(0, 1, 0); + if (aspect > 1) { + b[1] /= aspect; + } else { + a[0] *= aspect; + } + return ShapeWrapperPtr( + new shapes::ShapeWrapper({ "Position", "TexCoord" }, shapes::Plane(a, b), *program) + ); +} + + +static const char * QUAD_VS = R"VS(#version 330 + +uniform mat4 Projection = mat4(1); +uniform mat4 ModelView = mat4(1); +uniform vec2 UvMultiplier = vec2(1); + +layout(location = 0) in vec3 Position; +layout(location = 1) in vec2 TexCoord; + +out vec2 vTexCoord; + +void main() { + gl_Position = Projection * ModelView * vec4(Position, 1); + vTexCoord = TexCoord * UvMultiplier; +} +)VS"; + +static const char * QUAD_FS = R"FS(#version 330 +uniform sampler2D sampler; +uniform float Alpha = 1.0; + +in vec2 vTexCoord; +out vec4 vFragColor; + +void main() { + vec4 c = texture(sampler, vTexCoord); + c.a = min(Alpha, c.a); + vFragColor = c; +} +)FS"; diff --git a/interface/src/plugins/display/OglplusHelpers.h b/libraries/display-plugins/src/OglplusHelpers.h similarity index 55% rename from interface/src/plugins/display/OglplusHelpers.h rename to libraries/display-plugins/src/OglplusHelpers.h index b74362a617..ddeff20506 100644 --- a/interface/src/plugins/display/OglplusHelpers.h +++ b/libraries/display-plugins/src/OglplusHelpers.h @@ -1,5 +1,5 @@ // -// Created by Bradley Austin Davis on 2015/05/26. +// Created by Bradley Austin Davis on 2015/05/26 // Copyright 2015 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. @@ -7,6 +7,10 @@ // #pragma once +#include + +#pragma warning(disable : 4068) + #define OGLPLUS_USE_GLEW 1 #define OGLPLUS_USE_GLCOREARB_H 0 #define OGLPLUS_USE_BOOST_CONFIG 1 @@ -24,3 +28,13 @@ #include typedef std::shared_ptr FramebufferPtr; +typedef std::shared_ptr ShapeWrapperPtr; +typedef std::shared_ptr BufferPtr; +typedef std::shared_ptr VertexArrayPtr; +typedef std::shared_ptr ProgramPtr; +typedef oglplus::Uniform Mat4Uniform; + +ProgramPtr loadDefaultShader(); +void compileProgram(ProgramPtr & result, const std::string& vs, const std::string& fs); +ShapeWrapperPtr loadPlane(ProgramPtr program, float aspect = 1.0f); + diff --git a/interface/src/plugins/display/DisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/DisplayPlugin.cpp similarity index 86% rename from interface/src/plugins/display/DisplayPlugin.cpp rename to libraries/display-plugins/src/display-plugins/DisplayPlugin.cpp index d9d649019f..55e4dbd8ae 100644 --- a/interface/src/plugins/display/DisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/DisplayPlugin.cpp @@ -1,7 +1,5 @@ // -// DisplayPlugin.cpp -// -// Created by Bradley Austin Davis on 2014/04/13. +// Created by Bradley Austin Davis on 2015/05/29 // Copyright 2015 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. @@ -13,4 +11,4 @@ bool DisplayPlugin::isMouseOnScreen() const { glm::ivec2 mousePosition = getTrueMousePosition(); return (glm::all(glm::greaterThanEqual(mousePosition, glm::ivec2(0))) && glm::all(glm::lessThanEqual(mousePosition, glm::ivec2(getCanvasSize())))); -} \ No newline at end of file +} diff --git a/interface/src/plugins/display/DisplayPlugin.h b/libraries/display-plugins/src/display-plugins/DisplayPlugin.h similarity index 72% rename from interface/src/plugins/display/DisplayPlugin.h rename to libraries/display-plugins/src/display-plugins/DisplayPlugin.h index 711b53e9f4..b2726288cf 100644 --- a/interface/src/plugins/display/DisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/DisplayPlugin.h @@ -1,7 +1,5 @@ // -// DisplayPlugin.h -// -// Created by Bradley Austin Davis on 2014/04/13. +// Created by Bradley Austin Davis on 2015/05/29 // Copyright 2015 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. @@ -46,28 +44,43 @@ void for_each_eye(F f, FF ff) { f(Eye::Right); } +class QWindow; + class DisplayPlugin : public Plugin { Q_OBJECT public: virtual bool isHmd() const { return false; } - virtual bool isStereo() const { return false; } + /// By default, all HMDs are stereo + virtual bool isStereo() const { return isHmd(); } virtual bool isThrottled() const { return false; } // Rendering support - virtual void preRender() {}; - - virtual void preDisplay() { - makeCurrent(); - }; + /** + * Called by the application before the frame rendering. Can be used for + * render timing related calls (for instance, the Oculus begin frame timing + * call) + */ + virtual void preRender() = 0; + /** + * Called by the application immediately before calling the display function. + * For OpenGL based plugins, this is the best place to put activate the output + * OpenGL context + */ + virtual void preDisplay() = 0; + /** + * Sends the scene texture and the overlay texture to the display plugin. + * The plugin is responsible for compositing these and adding rendering of + * additional elements like mouse and hydra pointers as required + */ virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize, GLuint overlayTexture, const glm::uvec2& overlaySize) = 0; + /** + * Called by the application immeidately after display. For OpenGL based + * displays, this is the best place to put the buffer swap + */ + virtual void finishFrame() = 0; - virtual void finishFrame() { - swapBuffers(); - doneCurrent(); - }; - // Does the rendering surface have current focus? virtual bool hasFocus() const = 0; // The size of the rendering surface @@ -76,13 +89,15 @@ public: virtual QSize getRecommendedFramebufferSize() const { return getDeviceSize(); }; // The size of the window (differs from the framebuffers size in instances like Retina macs) virtual glm::ivec2 getCanvasSize() const = 0; + // The window for the surface, used for event interception. May be null. + virtual QWindow* getWindow() const = 0; // The mouse position relative to the window (or proxy window) surface virtual glm::ivec2 getTrueMousePosition() const = 0; // The mouse position relative to the UI elements virtual glm::ivec2 getUiMousePosition() const { - return trueMouseToUiMouse(getTrueMousePosition()); + return trueMouseToUiMouse(getTrueMousePosition()); } virtual std::function getMouseTranslator() { return [](const QPointF& p) { return p; }; }; @@ -123,10 +138,5 @@ public: signals: void recommendedFramebufferSizeChanged(const QSize & size); void requestRender(); - -protected: - virtual void makeCurrent() {} - virtual void doneCurrent() {} - virtual void swapBuffers() {} }; diff --git a/libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.cpp new file mode 100644 index 0000000000..a456bf667b --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.cpp @@ -0,0 +1,127 @@ +// +// Created by Bradley Austin Davis on 2015/05/29 +// 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 "GlWindowDisplayPlugin.h" + +#include +#include +#include +#include + +#include +#include + +GlWindowDisplayPlugin::GlWindowDisplayPlugin() : _timer(new QTimer()) { + connect(_timer, &QTimer::timeout, this, [&] { + // if (qApp->getActiveDisplayPlugin() == this) { + emit requestRender(); + // } + }); +} + +GlWindowDisplayPlugin::~GlWindowDisplayPlugin() { + delete _timer; +} + +void GlWindowDisplayPlugin::makeCurrent() { + _window->makeCurrent(); +} + +void GlWindowDisplayPlugin::doneCurrent() { + _window->doneCurrent(); +} + +void GlWindowDisplayPlugin::swapBuffers() { + _window->swapBuffers(); +} + +glm::ivec2 GlWindowDisplayPlugin::getTrueMousePosition() const { + return toGlm(_window->mapFromGlobal(QCursor::pos())); +} + +QWindow* GlWindowDisplayPlugin::getWindow() const { + return _window; +} + +bool GlWindowDisplayPlugin::eventFilter(QObject* object, QEvent* event) { + if (qApp->eventFilter(object, event)) { + return true; + } + + // FIXME + /* + auto offscreenUi = DependencyManager::get(); + if (offscreenUi->eventFilter(object, event)) { + return true; + } + */ + + // distinct calls for easier debugging with breakpoints + switch (event->type()) { + case QEvent::KeyPress: + QCoreApplication::sendEvent(QCoreApplication::instance(), event); + break; + case QEvent::KeyRelease: + QCoreApplication::sendEvent(QCoreApplication::instance(), event); + break; + case QEvent::MouseButtonPress: + QCoreApplication::sendEvent(QCoreApplication::instance(), event); + break; + case QEvent::MouseButtonRelease: + QCoreApplication::sendEvent(QCoreApplication::instance(), event); + break; + case QEvent::FocusIn: + QCoreApplication::sendEvent(QCoreApplication::instance(), event); + break; + case QEvent::FocusOut: + QCoreApplication::sendEvent(QCoreApplication::instance(), event); + break; + case QEvent::Resize: + QCoreApplication::sendEvent(QCoreApplication::instance(), event); + break; + case QEvent::MouseMove: + QCoreApplication::sendEvent(QCoreApplication::instance(), event); + break; + default: + break; + } + return false; +} + +void GlWindowDisplayPlugin::activate(PluginContainer * container) { + Q_ASSERT(nullptr == _window); + _window = new GlWindow(QOpenGLContext::currentContext()); + _window->installEventFilter(this); + customizeWindow(); + _window->show(); + _timer->start(8); + makeCurrent(); + customizeContext(); + // FIXME + //DependencyManager::get()->setProxyWindow(_window); +} + +void GlWindowDisplayPlugin::deactivate() { + _timer->stop(); + Q_ASSERT(nullptr != _window); + _window->hide(); + _window->destroy(); + _window->deleteLater(); + _window = nullptr; +} + +QSize GlWindowDisplayPlugin::getDeviceSize() const { + return _window->geometry().size() * _window->devicePixelRatio(); +} + +glm::ivec2 GlWindowDisplayPlugin::getCanvasSize() const { + return toGlm(_window->geometry().size()); +} + +bool GlWindowDisplayPlugin::hasFocus() const { + return _window->isActive(); +} diff --git a/libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.h new file mode 100644 index 0000000000..1833ab3a84 --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.h @@ -0,0 +1,41 @@ +// +// Created by Bradley Austin Davis on 2015/05/29 +// 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 "OpenGlDisplayPlugin.h" + +class GlWindow; +class QTimer; + +class GlWindowDisplayPlugin : public OpenGlDisplayPlugin { +public: + GlWindowDisplayPlugin(); + virtual ~GlWindowDisplayPlugin(); + virtual void activate(PluginContainer * container); + virtual void deactivate(); + virtual QSize getDeviceSize() const final; + virtual glm::ivec2 getCanvasSize() const final; + virtual bool hasFocus() const; + virtual bool eventFilter(QObject* object, QEvent* event); + + virtual glm::ivec2 getTrueMousePosition() const; + virtual QWindow* getWindow() const; + +protected: + virtual void makeCurrent() final; + virtual void doneCurrent() final; + virtual void swapBuffers() final; + virtual void customizeWindow() = 0; + virtual void customizeContext() = 0; + +private: + QTimer* _timer{ nullptr }; +protected: + GlWindow* _window{ nullptr }; +}; + diff --git a/interface/src/plugins/display/NullDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp similarity index 69% rename from interface/src/plugins/display/NullDisplayPlugin.cpp rename to libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp index 9b5ab8ed0a..2204c0499c 100644 --- a/interface/src/plugins/display/NullDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.cpp @@ -42,3 +42,16 @@ PickRay NullDisplayPlugin::computePickRay(const glm::vec2 & pos) const { bool NullDisplayPlugin::isMouseOnScreen() const { return false; } + +QWindow* NullDisplayPlugin::getWindow() const { + return nullptr; +} + +void NullDisplayPlugin::preRender() {} +void NullDisplayPlugin::preDisplay() {} +void NullDisplayPlugin::display(GLuint sceneTexture, const glm::uvec2& sceneSize, + GLuint overlayTexture, const glm::uvec2& overlaySize) {} +void NullDisplayPlugin::finishFrame() {} + +void NullDisplayPlugin::activate(PluginContainer * container) {} +void NullDisplayPlugin::deactivate() {} diff --git a/interface/src/plugins/display/NullDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h similarity index 72% rename from interface/src/plugins/display/NullDisplayPlugin.h rename to libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h index 8a06febb7b..0fedf872b1 100644 --- a/interface/src/plugins/display/NullDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h @@ -1,7 +1,5 @@ // -// NullDisplayPlugin.h -// -// Created by Bradley Austin Davis on 2014/04/13. +// Created by Bradley Austin Davis on 2015/05/29 // Copyright 2015 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. @@ -18,6 +16,9 @@ public: virtual ~NullDisplayPlugin() final {} virtual const QString & getName(); + void activate(PluginContainer * container); + void deactivate(); + virtual QSize getDeviceSize() const; virtual glm::ivec2 getCanvasSize() const; virtual bool hasFocus() const; @@ -25,8 +26,11 @@ public: 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, - GLuint overlayTexture, const glm::uvec2& overlaySize) {}; + GLuint overlayTexture, const glm::uvec2& overlaySize); + virtual void finishFrame(); }; diff --git a/interface/src/plugins/display/OculusBaseDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OculusBaseDisplayPlugin.cpp similarity index 87% rename from interface/src/plugins/display/OculusBaseDisplayPlugin.cpp rename to libraries/display-plugins/src/display-plugins/OculusBaseDisplayPlugin.cpp index 50e1583548..7648be1d25 100644 --- a/interface/src/plugins/display/OculusBaseDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OculusBaseDisplayPlugin.cpp @@ -1,7 +1,5 @@ // -// OculusBaseDisplayPlugin.cpp -// -// Created by Bradley Austin Davis on 2014/04/13. +// Created by Bradley Austin Davis on 2015/05/29 // Copyright 2015 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. @@ -11,10 +9,9 @@ #include -#include "OculusHelpers.h" +#include "../OculusHelpers.h" - -void OculusBaseDisplayPlugin::activate() { +void OculusBaseDisplayPlugin::activate(PluginContainer * container) { ovr_for_each_eye([&](ovrEyeType eye) { ovrEyeRenderDesc erd = ovrHmd_GetRenderDesc(_hmd, eye, _hmd->MaxEyeFov[eye]); ovrMatrix4f ovrPerspectiveProjection = diff --git a/interface/src/plugins/display/OculusBaseDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OculusBaseDisplayPlugin.h similarity index 74% rename from interface/src/plugins/display/OculusBaseDisplayPlugin.h rename to libraries/display-plugins/src/display-plugins/OculusBaseDisplayPlugin.h index 94f73522b5..0462f00321 100644 --- a/interface/src/plugins/display/OculusBaseDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OculusBaseDisplayPlugin.h @@ -1,7 +1,5 @@ // -// OculusBaseDisplayPlugin.h -// -// Created by Bradley Austin Davis on 2014/04/13. +// Created by Bradley Austin Davis on 2015/05/29 // Copyright 2015 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. @@ -9,16 +7,17 @@ // #pragma once -#include "HmdDisplayPlugin.h" +#include "DisplayPlugin.h" #include -class OculusBaseDisplayPlugin : public HmdDisplayPlugin { +class OculusBaseDisplayPlugin : public DisplayPlugin { public: // Stereo specific methods + virtual bool isHmd() const { return true; } virtual glm::mat4 getProjection(Eye eye, const glm::mat4& baseProjection) const; virtual glm::mat4 getModelview(Eye eye, const glm::mat4& baseModelview) const; - virtual void activate(); + virtual void activate(PluginContainer * container); virtual void deactivate(); virtual void preRender(); virtual void configureRendering() = 0; diff --git a/interface/src/plugins/display/OculusWin32DisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.cpp similarity index 97% rename from interface/src/plugins/display/OculusWin32DisplayPlugin.cpp rename to libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.cpp index f7414cc551..a15550a20b 100644 --- a/interface/src/plugins/display/OculusWin32DisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.cpp @@ -7,11 +7,16 @@ // #include "OculusWin32DisplayPlugin.h" +#include +#include #include +#include "../OglplusHelpers.h" + +#if 0 bool OculusWin32DisplayPlugin::isSupported() { - ovr_Initialize(); + ovr_Initialize(nullptr); bool result = false; if (ovrHmd_Detect() != 0) { result = true; @@ -29,7 +34,7 @@ bool OculusWin32DisplayPlugin::isSupported() { // the screen. template struct FramebufferWrapper { - glm::uvec2 size; + uvec2 size; oglplus::Framebuffer fbo; C color{ 0 }; GLuint depth{ 0 }; @@ -198,3 +203,4 @@ private: }; using MirrorFboPtr = std::shared_ptr; +#endif \ No newline at end of file diff --git a/interface/src/plugins/display/OculusWin32DisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.h similarity index 87% rename from interface/src/plugins/display/OculusWin32DisplayPlugin.h rename to libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.h index 436efb5742..6866f096fc 100644 --- a/interface/src/plugins/display/OculusWin32DisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.h @@ -1,5 +1,5 @@ // -// Created by Bradley Austin Davis on 2015/05/26. +// Created by Bradley Austin Davis on 2015/05/29 // Copyright 2015 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. diff --git a/libraries/display-plugins/src/display-plugins/OpenGlDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGlDisplayPlugin.cpp new file mode 100644 index 0000000000..f2bd328915 --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/OpenGlDisplayPlugin.cpp @@ -0,0 +1,88 @@ +// +// Created by Bradley Austin Davis on 2015/05/29 +// 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 "OpenGlDisplayPlugin.h" + +#include + +void OpenGlDisplayPlugin::preDisplay() { + makeCurrent(); +}; + +void OpenGlDisplayPlugin::preRender() { + // NOOP +} + +void OpenGlDisplayPlugin::finishFrame() { + swapBuffers(); + doneCurrent(); +}; + +void OpenGlDisplayPlugin::display(GLuint sceneTexture, const glm::uvec2& sceneSize, + GLuint overlayTexture, const glm::uvec2& overlaySize) { + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + + glClearColor(0, 0, 1, 1); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glEnable(GL_TEXTURE_2D); + + glViewport(0, 0, getDeviceSize().width(), getDeviceSize().height()); + if (sceneTexture) { + glBindTexture(GL_TEXTURE_2D, sceneTexture); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); + glVertex2f(-1, -1); + glTexCoord2f(1, 0); + glVertex2f(+1, -1); + glTexCoord2f(1, 1); + glVertex2f(+1, +1); + glTexCoord2f(0, 1); + glVertex2f(-1, +1); + glEnd(); + } + + if (overlayTexture) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBindTexture(GL_TEXTURE_2D, overlayTexture); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); + glVertex2f(-1, -1); + glTexCoord2f(1, 0); + glVertex2f(+1, -1); + glTexCoord2f(1, 1); + glVertex2f(+1, +1); + glTexCoord2f(0, 1); + glVertex2f(-1, +1); + glEnd(); + } + + + glDisable(GL_BLEND); + + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_TEXTURE_2D); + //Q_ASSERT(!glGetError()); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + glEnable(GL_LIGHTING); + glEnable(GL_DEPTH_TEST); + + glFinish(); +} + diff --git a/libraries/display-plugins/src/display-plugins/OpenGlDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGlDisplayPlugin.h new file mode 100644 index 0000000000..19587b997e --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/OpenGlDisplayPlugin.h @@ -0,0 +1,24 @@ +// +// Created by Bradley Austin Davis on 2015/05/29 +// 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 "DisplayPlugin.h" + +class OpenGlDisplayPlugin : public DisplayPlugin { +public: + virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize, + GLuint overlayTexture, const glm::uvec2& overlaySize); + virtual void preRender(); + virtual void preDisplay(); + virtual void finishFrame(); + +protected: + virtual void makeCurrent() = 0; + virtual void doneCurrent() = 0; + virtual void swapBuffers() = 0; +}; diff --git a/libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.cpp new file mode 100644 index 0000000000..b6607e5518 --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.cpp @@ -0,0 +1,176 @@ +// +// Created by Bradley Austin Davis on 2015/05/29 +// 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 "Tv3dDisplayPlugin.h" + +#include +#include + +#include +#include +#include +#include + + +#include "../OglplusHelpers.h" + +const QString Tv3dDisplayPlugin::NAME("Tv3dDisplayPlugin"); + +const QString & Tv3dDisplayPlugin::getName() { + return NAME; +} + +Tv3dDisplayPlugin::Tv3dDisplayPlugin() { +} + +bool Tv3dDisplayPlugin::isSupported() const { + // FIXME this should attempt to do a scan for supported 3D output + return true; +} + +static ProgramPtr program; +static ShapeWrapperPtr plane; + +void Tv3dDisplayPlugin::customizeWindow() { + _window->setFlags(Qt::FramelessWindowHint); + auto desktop = QApplication::desktop(); + QRect primaryGeometry = desktop->screenGeometry(); + for (int i = 0; i < desktop->screenCount(); ++i) { + QRect geometry = desktop->screen(i)->geometry(); + if (geometry.topLeft() == primaryGeometry.topLeft()) { + continue; + } + float aspect = (float)geometry.width() / (float)geometry.height(); + if (aspect < 1.0f) { + continue; + } + _window->setGeometry(geometry); + break; + } + _window->setCursor(Qt::BlankCursor); +} + +void Tv3dDisplayPlugin::customizeContext() { + using namespace oglplus; + Context::BlendFunc(BlendFunction::SrcAlpha, BlendFunction::OneMinusSrcAlpha); + Context::Disable(Capability::Blend); + Context::Disable(Capability::DepthTest); + Context::Disable(Capability::CullFace); + program = loadDefaultShader(); + plane = loadPlane(program); + Context::ClearColor(0, 0, 0, 1); + // _crosshairTexture = DependencyManager::get()-> + // getImageTexture(PathUtils::resourcesPath() + "images/sixense-reticle.png"); +} + + +const float DEFAULT_IPD = 0.064f; +const float HALF_DEFAULT_IPD = DEFAULT_IPD / 2.0f; + +glm::mat4 Tv3dDisplayPlugin::getProjection(Eye eye, const glm::mat4& baseProjection) const { + float nearZ = DEFAULT_NEAR_CLIP; // near clipping plane + float screenZ = 0.25f; // screen projection plane + // FIXME verify this is the right calculation + float frustumshift = HALF_DEFAULT_IPD * nearZ / screenZ; + if (eye == Right) { + frustumshift = -frustumshift; + } + return glm::translate(baseProjection, vec3(frustumshift, 0, 0)); +} + +glm::mat4 Tv3dDisplayPlugin::getModelview(Eye eye, const glm::mat4& baseModelview) const { + float modelviewShift = HALF_DEFAULT_IPD; + if (eye == Left) { + modelviewShift = -modelviewShift; + } + return baseModelview * glm::translate(mat4(), vec3(modelviewShift, 0, 0)); +} + + + +void Tv3dDisplayPlugin::display( + GLuint sceneTexture, const glm::uvec2& sceneSize, + GLuint overlayTexture, const glm::uvec2& overlaySize) { + + QSize size = getDeviceSize(); + using namespace oglplus; + Context::Viewport(size.width(), size.height()); + Context::Clear().ColorBuffer().DepthBuffer(); + + Mat4Uniform(*program, "ModelView").Set(mat4()); + Mat4Uniform(*program, "Projection").Set(mat4()); + + glBindTexture(GL_TEXTURE_2D, sceneTexture); + + plane->Draw(); + + const float overlayAspect = aspect(toGlm(size)); + const GLfloat distance = 1.0f; + const GLfloat halfQuadHeight = distance * tan(DEFAULT_FIELD_OF_VIEW_DEGREES); + const GLfloat halfQuadWidth = halfQuadHeight * (float)size.width() / (float)size.height(); + const GLfloat quadWidth = halfQuadWidth * 2.0f; + const GLfloat quadHeight = halfQuadHeight * 2.0f; + + vec3 quadSize(quadWidth, quadHeight, 1.0f); + quadSize = vec3(1.0f) / quadSize; + + using namespace oglplus; + Context::Enable(Capability::Blend); + glBindTexture(GL_TEXTURE_2D, overlayTexture); + + mat4 pr = glm::perspective(glm::radians(DEFAULT_FIELD_OF_VIEW_DEGREES), aspect(toGlm(size)), DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP); + Mat4Uniform(*program, "Projection").Set(pr); + + MatrixStack mv; + mv.translate(vec3(0, 0, -distance)).scale(vec3(0.7f, 0.7f / overlayAspect, 1.0f)); // .scale(vec3(quadWidth, quadHeight, 1.0)); + + QRect r(QPoint(0, 0), QSize(size.width() / 2, size.height())); + for (int i = 0; i < 2; ++i) { + Context::Viewport(r.x(), r.y(), r.width(), r.height()); + Mat4Uniform(*program, "ModelView").Set(mv.top()); + plane->Draw(); + r.moveLeft(r.width()); + } + +#if 0 + glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_crosshairTexture)); + glm::vec2 canvasSize = qApp->getCanvasSize(); + glm::vec2 mouse = qApp->getMouse(); + mouse /= canvasSize; + mouse *= 2.0f; + mouse -= 1.0f; + mouse.y *= -1.0f; + mv.translate(mouse); + mv.scale(0.1f); + Mat4Uniform(*program, "ModelView").Set(mv.top()); + r = QRect(QPoint(0, 0), QSize(size.width() / 2, size.height())); + for (int i = 0; i < 2; ++i) { + Context::Viewport(r.x(), r.y(), r.width(), r.height()); + plane->Draw(); + r.moveLeft(r.width()); + } +#endif + Context::Disable(Capability::Blend); +} + + +void Tv3dDisplayPlugin::activate(PluginContainer * container) { + GlWindowDisplayPlugin::activate(container); + _window->show(); +} + +void Tv3dDisplayPlugin::deactivate() { + makeCurrent(); + if (plane) { + plane.reset(); + program.reset(); +// _crosshairTexture.reset(); + } + doneCurrent(); + GlWindowDisplayPlugin::deactivate(); +} diff --git a/interface/src/plugins/display/Tv3dDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.h similarity index 67% rename from interface/src/plugins/display/Tv3dDisplayPlugin.h rename to libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.h index ad2ccc7369..9baa9261ef 100644 --- a/interface/src/plugins/display/Tv3dDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.h @@ -1,17 +1,13 @@ // -// Tv3dDisplayPlugin.h -// -// Created by Bradley Austin Davis on 2014/04/13. +// Created by Bradley Austin Davis on 2015/05/29 // 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 "SimpleDisplayPlugin.h" -#include +#include "GlWindowDisplayPlugin.h" class Tv3dDisplayPlugin : public GlWindowDisplayPlugin { Q_OBJECT @@ -23,12 +19,15 @@ public: virtual bool isSupported() const final; void display(GLuint sceneTexture, const glm::uvec2& sceneSize, GLuint overlayTexture, const glm::uvec2& overlaySize); - virtual void activate(); + virtual void activate(PluginContainer * container); virtual void deactivate(); + virtual glm::mat4 getProjection(Eye eye, const glm::mat4& baseProjection) const; + virtual glm::mat4 getModelview(Eye eye, const glm::mat4& baseModelview) const; + +protected: + virtual void customizeWindow(); + virtual void customizeContext(); //virtual std::function getMouseTranslator(); //virtual glm::ivec2 trueMouseToUiMouse(const glm::ivec2 & position) const; - -private: - QTimer _timer; }; diff --git a/libraries/display-plugins/src/display-plugins/WindowDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/WindowDisplayPlugin.cpp new file mode 100644 index 0000000000..0298d6b823 --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/WindowDisplayPlugin.cpp @@ -0,0 +1,18 @@ +// +// Created by Bradley Austin Davis on 2015/05/29 +// 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 "WindowDisplayPlugin.h" + +WindowDisplayPlugin::WindowDisplayPlugin() { +} + +const QString WindowDisplayPlugin::NAME("QWindow 2D Renderer"); + +const QString & WindowDisplayPlugin::getName() { + return NAME; +} + diff --git a/interface/src/plugins/display/WindowDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/WindowDisplayPlugin.h similarity index 62% rename from interface/src/plugins/display/WindowDisplayPlugin.h rename to libraries/display-plugins/src/display-plugins/WindowDisplayPlugin.h index 7bc0d5163d..208dc26975 100644 --- a/interface/src/plugins/display/WindowDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/WindowDisplayPlugin.h @@ -1,7 +1,5 @@ // -// WindowDisplayPlugin.h -// -// Created by Bradley Austin Davis on 2014/04/13. +// Created by Bradley Austin Davis on 2015/05/29 // Copyright 2015 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. @@ -9,10 +7,7 @@ // #pragma once -#include "SimpleDisplayPlugin.h" - -#include -#include +#include "GlWindowDisplayPlugin.h" class WindowDisplayPlugin : public GlWindowDisplayPlugin { Q_OBJECT @@ -22,9 +17,5 @@ public: WindowDisplayPlugin(); virtual const QString & getName(); - - virtual void activate(); - virtual void deactivate(); private: - QTimer _timer; }; diff --git a/libraries/plugins/CMakeLists.txt b/libraries/plugins/CMakeLists.txt index 9401f73174..28b136ccf4 100644 --- a/libraries/plugins/CMakeLists.txt +++ b/libraries/plugins/CMakeLists.txt @@ -1,7 +1,7 @@ set(TARGET_NAME plugins) # use setup_hifi_library macro to setup our project and link appropriate Qt modules -setup_hifi_library(OpenGL Network Qml Quick Script XmlPatterns) +setup_hifi_library(OpenGL) link_hifi_libraries(shared) diff --git a/libraries/plugins/src/Plugin.h b/libraries/plugins/src/Plugin.h deleted file mode 100644 index db01aa74ca..0000000000 --- a/libraries/plugins/src/Plugin.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#include -#include - -class PluginContainer; - -class Plugin : public QObject { -public: - virtual const QString& getName() = 0; - virtual bool isSupported() const { return true; } - - virtual void init() {} - virtual void deinit() {} - - virtual void activate(PluginContainer * container) {} - virtual void deactivate() {} - - virtual void idle() {} -}; diff --git a/libraries/plugins/src/plugins/Plugin.cpp b/libraries/plugins/src/plugins/Plugin.cpp new file mode 100644 index 0000000000..1910b525c2 --- /dev/null +++ b/libraries/plugins/src/plugins/Plugin.cpp @@ -0,0 +1,9 @@ +#include "Plugin.h" + +bool Plugin::isSupported() const { return true; } + +void Plugin::init() {} + +void Plugin::deinit() {} + +void Plugin::idle() {} diff --git a/libraries/plugins/src/plugins/Plugin.h b/libraries/plugins/src/plugins/Plugin.h new file mode 100644 index 0000000000..6f55cb2b1d --- /dev/null +++ b/libraries/plugins/src/plugins/Plugin.h @@ -0,0 +1,29 @@ +#pragma once + +#include +#include + +class PluginContainer; + +class Plugin : public QObject { +public: + virtual const QString& getName() = 0; + virtual bool isSupported() const; + + /// Called when plugin is initially loaded, typically at application start + virtual void init(); + /// Called when application is shutting down + virtual void deinit(); + + /// Called when a plugin is being activated for use. May be called multiple times. + virtual void activate(PluginContainer * container) = 0; + /// Called when a plugin is no longer being used. May be called multiple times. + virtual void deactivate() = 0; + + /** + * Called by the application during it's idle phase. If the plugin needs to do + * CPU intensive work, it should launch a thread for that, rather than trying to + * do long operations in the idle call + */ + virtual void idle(); +}; diff --git a/libraries/plugins/src/PluginContainer.h b/libraries/plugins/src/plugins/PluginContainer.h similarity index 100% rename from libraries/plugins/src/PluginContainer.h rename to libraries/plugins/src/plugins/PluginContainer.h diff --git a/interface/src/plugins/PluginManager.cpp b/libraries/plugins/src/plugins/PluginManager.cpp similarity index 100% rename from interface/src/plugins/PluginManager.cpp rename to libraries/plugins/src/plugins/PluginManager.cpp diff --git a/interface/src/plugins/PluginManager.h b/libraries/plugins/src/plugins/PluginManager.h similarity index 51% rename from interface/src/plugins/PluginManager.h rename to libraries/plugins/src/plugins/PluginManager.h index 2526490eea..653c7a616a 100644 --- a/interface/src/plugins/PluginManager.h +++ b/libraries/plugins/src/plugins/PluginManager.h @@ -1,12 +1,10 @@ #pragma once -#include "plugins/Plugin.h" -#include "plugins/display/DisplayPlugin.h" +#include "Plugin.h" #include #include class PluginManager : public QObject { public: static PluginManager * getInstance(); - const QList> getDisplayPlugins(); }; From fec214c552231c4f05b42f8d3e3f65b5e01c5067 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Sat, 30 May 2015 02:01:11 -0700 Subject: [PATCH 016/552] Working on consistent input response --- interface/src/Application.cpp | 25 +++--- interface/src/GLCanvas.cpp | 11 +-- interface/src/LegacyDisplayPlugin.cpp | 15 ++-- interface/src/LegacyDisplayPlugin.h | 3 + libraries/display-plugins/CMakeLists.txt | 2 +- .../src/display-plugins/DisplayPlugin.h | 3 + .../display-plugins/GlWindowDisplayPlugin.cpp | 80 +++++++---------- .../display-plugins/GlWindowDisplayPlugin.h | 9 +- .../src/display-plugins/NullDisplayPlugin.h | 1 - .../OculusWin32DisplayPlugin.cpp | 2 +- .../OculusWin32DisplayPlugin.h | 4 + .../src/display-plugins/Tv3dDisplayPlugin.cpp | 88 +++++++++++-------- 12 files changed, 130 insertions(+), 113 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 9839794127..071ca30c10 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1102,9 +1102,9 @@ bool Application::event(QEvent* event) { } bool Application::eventFilter(QObject* object, QEvent* event) { - if (event->type() == QEvent::ShortcutOverride) { - if (DependencyManager::get()->shouldSwallowShortcut(event)) { + auto offscreenUi = DependencyManager::get(); + if (offscreenUi->shouldSwallowShortcut(event)) { event->accept(); return true; } @@ -1115,7 +1115,6 @@ bool Application::eventFilter(QObject* object, QEvent* event) { return true; } } - return false; } @@ -1459,7 +1458,7 @@ void Application::mousePressEvent(QMouseEvent* event, unsigned int deviceID) { } - if (activeWindow() == _window) { + if (hasFocus()) { _keyboardMouseDevice.mousePressEvent(event); if (event->button() == Qt::LeftButton) { @@ -1500,7 +1499,7 @@ void Application::mouseDoublePressEvent(QMouseEvent* event, unsigned int deviceI return; } - if (activeWindow() == _window) { + if (hasFocus()) { if (event->button() == Qt::LeftButton) { if (mouseOnScreen()) { if (DependencyManager::get()->mouseDoublePressEvent(getMouseX(), getMouseY())) { @@ -1525,7 +1524,7 @@ void Application::mouseReleaseEvent(QMouseEvent* event, unsigned int deviceID) { return; } - if (activeWindow() == _window) { + if (hasFocus()) { _keyboardMouseDevice.mouseReleaseEvent(event); if (event->button() == Qt::LeftButton) { @@ -1563,7 +1562,7 @@ void Application::touchUpdateEvent(QTouchEvent* event) { _keyboardMouseDevice.touchUpdateEvent(event); bool validTouch = false; - if (activeWindow() == _window) { + if (hasFocus()) { const QList& tPoints = event->touchPoints(); _touchAvg = glm::vec2(0); int numTouches = tPoints.count(); @@ -4675,21 +4674,23 @@ void Application::updateDisplayMode() { } } if (_displayPlugin != newDisplayPlugin) { + DependencyManager::get()->setProxyWindow(nullptr); + if (newDisplayPlugin) { _offscreenContext->makeCurrent(); newDisplayPlugin->activate(this); + newDisplayPlugin->installEventFilter(DependencyManager::get().data()); + newDisplayPlugin->installEventFilter(qApp); QWindow* pluginWindow = newDisplayPlugin->getWindow(); if (pluginWindow) { - // Event filter queue is 'last in, first used' - pluginWindow->installEventFilter(DependencyManager::get().data()); - pluginWindow->installEventFilter(qApp); DependencyManager::get()->setProxyWindow(pluginWindow); - } + } _offscreenContext->makeCurrent(); - } + } std::swap(newDisplayPlugin, _displayPlugin); if (newDisplayPlugin) { + newDisplayPlugin->removeEventFilter(DependencyManager::get().data()); newDisplayPlugin->deactivate(); _offscreenContext->makeCurrent(); } diff --git a/interface/src/GLCanvas.cpp b/interface/src/GLCanvas.cpp index 066ae97ebf..6fb2a742f3 100644 --- a/interface/src/GLCanvas.cpp +++ b/interface/src/GLCanvas.cpp @@ -9,13 +9,10 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#include -#include -#include #include "Application.h" #include "GLCanvas.h" -#include "MainWindow.h" + const int MSECS_PER_FRAME_WHEN_THROTTLED = 66; @@ -35,7 +32,7 @@ void GLCanvas::stopFrameTimer() { } bool GLCanvas::isThrottleRendering() const { - return _throttleRendering || Application::getInstance()->getWindow()->isMinimized(); + return _throttleRendering || parentWidget()->isMinimized(); } int GLCanvas::getDeviceWidth() const { @@ -57,7 +54,7 @@ void GLCanvas::initializeGL() { } void GLCanvas::paintGL() { - if (!_throttleRendering && !Application::getInstance()->getWindow()->isMinimized()) { + if (!isThrottleRendering()) { Application::getInstance()->paintGL(); } } @@ -93,7 +90,7 @@ void GLCanvas::activeChanged(Qt::ApplicationState state) { void GLCanvas::throttleRender() { _frameTimer.start(_idleRenderInterval); - if (!Application::getInstance()->getWindow()->isMinimized()) { + if (!parentWidget()->isMinimized()) { Application::getInstance()->paintGL(); } } diff --git a/interface/src/LegacyDisplayPlugin.cpp b/interface/src/LegacyDisplayPlugin.cpp index 4fbb02e454..76629e896e 100644 --- a/interface/src/LegacyDisplayPlugin.cpp +++ b/interface/src/LegacyDisplayPlugin.cpp @@ -29,12 +29,8 @@ static QWidget * oldWidget = nullptr; void LegacyDisplayPlugin::activate(PluginContainer * container) { _window = new GLCanvas(); - QOpenGLContext * sourceContext = QOpenGLContext::currentContext(); - - QOpenGLContext * newContext = new QOpenGLContext(); - { QSurfaceFormat format; format.setOption(QSurfaceFormat::DebugContext); @@ -56,11 +52,8 @@ void LegacyDisplayPlugin::activate(PluginContainer * container) { _timer.start(8); } - void LegacyDisplayPlugin::deactivate() { _timer.stop(); - _window->removeEventFilter(DependencyManager::get().data()); - _window->removeEventFilter(qApp); // FIXME, during shutdown, this causes an NPE. Need to deactivate the plugin before the main window is destroyed. // if (qApp->getWindow()) { // qApp->getWindow()->setCentralWidget(oldWidget); @@ -121,3 +114,11 @@ ivec2 LegacyDisplayPlugin::getTrueMousePosition() const { QWindow* LegacyDisplayPlugin::getWindow() const { return _window->windowHandle(); } + +void LegacyDisplayPlugin::installEventFilter(QObject* filter) { + _window->installEventFilter(filter); +} + +void LegacyDisplayPlugin::removeEventFilter(QObject* filter) { + _window->removeEventFilter(filter); +} \ No newline at end of file diff --git a/interface/src/LegacyDisplayPlugin.h b/interface/src/LegacyDisplayPlugin.h index 223f4d9e01..d41dc25090 100644 --- a/interface/src/LegacyDisplayPlugin.h +++ b/interface/src/LegacyDisplayPlugin.h @@ -31,7 +31,10 @@ public: virtual void preDisplay(); virtual void idle(); virtual ivec2 getTrueMousePosition() const; + virtual QWindow* getWindow() const; + virtual void installEventFilter(QObject* filter); + virtual void removeEventFilter(QObject* filter); protected: virtual void makeCurrent() final; diff --git a/libraries/display-plugins/CMakeLists.txt b/libraries/display-plugins/CMakeLists.txt index cbfecfb0da..98d15a7804 100644 --- a/libraries/display-plugins/CMakeLists.txt +++ b/libraries/display-plugins/CMakeLists.txt @@ -5,7 +5,7 @@ setup_hifi_library(OpenGL) setup_hifi_opengl() -link_hifi_libraries(shared plugins ) +link_hifi_libraries(shared plugins gpu render-utils) add_dependency_external_projects(glm) find_package(GLM REQUIRED) diff --git a/libraries/display-plugins/src/display-plugins/DisplayPlugin.h b/libraries/display-plugins/src/display-plugins/DisplayPlugin.h index b2726288cf..f8563f4e20 100644 --- a/libraries/display-plugins/src/display-plugins/DisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/DisplayPlugin.h @@ -92,6 +92,9 @@ public: // The window for the surface, used for event interception. May be null. virtual QWindow* getWindow() const = 0; + virtual void installEventFilter(QObject* filter) {} + virtual void removeEventFilter(QObject* filter) {} + // The mouse position relative to the window (or proxy window) surface virtual glm::ivec2 getTrueMousePosition() const = 0; diff --git a/libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.cpp index a456bf667b..fe3347a185 100644 --- a/libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.cpp @@ -47,51 +47,6 @@ QWindow* GlWindowDisplayPlugin::getWindow() const { return _window; } -bool GlWindowDisplayPlugin::eventFilter(QObject* object, QEvent* event) { - if (qApp->eventFilter(object, event)) { - return true; - } - - // FIXME - /* - auto offscreenUi = DependencyManager::get(); - if (offscreenUi->eventFilter(object, event)) { - return true; - } - */ - - // distinct calls for easier debugging with breakpoints - switch (event->type()) { - case QEvent::KeyPress: - QCoreApplication::sendEvent(QCoreApplication::instance(), event); - break; - case QEvent::KeyRelease: - QCoreApplication::sendEvent(QCoreApplication::instance(), event); - break; - case QEvent::MouseButtonPress: - QCoreApplication::sendEvent(QCoreApplication::instance(), event); - break; - case QEvent::MouseButtonRelease: - QCoreApplication::sendEvent(QCoreApplication::instance(), event); - break; - case QEvent::FocusIn: - QCoreApplication::sendEvent(QCoreApplication::instance(), event); - break; - case QEvent::FocusOut: - QCoreApplication::sendEvent(QCoreApplication::instance(), event); - break; - case QEvent::Resize: - QCoreApplication::sendEvent(QCoreApplication::instance(), event); - break; - case QEvent::MouseMove: - QCoreApplication::sendEvent(QCoreApplication::instance(), event); - break; - default: - break; - } - return false; -} - void GlWindowDisplayPlugin::activate(PluginContainer * container) { Q_ASSERT(nullptr == _window); _window = new GlWindow(QOpenGLContext::currentContext()); @@ -101,8 +56,6 @@ void GlWindowDisplayPlugin::activate(PluginContainer * container) { _timer->start(8); makeCurrent(); customizeContext(); - // FIXME - //DependencyManager::get()->setProxyWindow(_window); } void GlWindowDisplayPlugin::deactivate() { @@ -125,3 +78,36 @@ glm::ivec2 GlWindowDisplayPlugin::getCanvasSize() const { bool GlWindowDisplayPlugin::hasFocus() const { return _window->isActive(); } + +void GlWindowDisplayPlugin::installEventFilter(QObject* filter) { + _window->installEventFilter(filter); +} + +void GlWindowDisplayPlugin::removeEventFilter(QObject* filter) { + _window->removeEventFilter(filter); +} + +bool GlWindowDisplayPlugin::eventFilter(QObject* receiver, QEvent* event) { + switch (event->type()) { + case QEvent::MouseMove: + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseButtonDblClick: + case QEvent::KeyPress: + case QEvent::KeyRelease: + case QEvent::FocusIn: + case QEvent::FocusOut: + case QEvent::Resize: + case QEvent::TouchBegin: + case QEvent::TouchEnd: + case QEvent::TouchUpdate: + case QEvent::Wheel: + case QEvent::DragEnter: + case QEvent::Drop: + if (QCoreApplication::sendEvent(QCoreApplication::instance(), event)) { + return true; + } + break; + } + return false; +} \ No newline at end of file diff --git a/libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.h index 1833ab3a84..9a7c284ff9 100644 --- a/libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.h @@ -21,16 +21,23 @@ public: virtual QSize getDeviceSize() const final; virtual glm::ivec2 getCanvasSize() const final; virtual bool hasFocus() const; - virtual bool eventFilter(QObject* object, QEvent* event); virtual glm::ivec2 getTrueMousePosition() const; virtual QWindow* getWindow() const; + virtual bool eventFilter(QObject* receiver, QEvent* event); + virtual void installEventFilter(QObject* filter); + virtual void removeEventFilter(QObject* filter); protected: virtual void makeCurrent() final; virtual void doneCurrent() final; virtual void swapBuffers() final; + + // Called by the activate method to specify the initial window geometry + // flags, etc virtual void customizeWindow() = 0; + // Called by the activate method after the GL context has been created to + // initialize OpenGL context settings needed by the plugin virtual void customizeContext() = 0; private: diff --git a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h index 0fedf872b1..123bf55d33 100644 --- a/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/NullDisplayPlugin.h @@ -32,5 +32,4 @@ public: virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize, GLuint overlayTexture, const glm::uvec2& overlaySize); virtual void finishFrame(); - }; diff --git a/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.cpp index a15550a20b..ee6f2dc4a4 100644 --- a/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.cpp @@ -14,7 +14,6 @@ #include "../OglplusHelpers.h" -#if 0 bool OculusWin32DisplayPlugin::isSupported() { ovr_Initialize(nullptr); bool result = false; @@ -25,6 +24,7 @@ bool OculusWin32DisplayPlugin::isSupported() { return result; } +#if 0 // A basic wrapper for constructing a framebuffer with a renderbuffer // for the depth attachment and an undefined type for the color attachement // This allows us to reuse the basic framebuffer code for both the Mirror diff --git a/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.h index 6866f096fc..d1203bde77 100644 --- a/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.h @@ -9,7 +9,11 @@ #include "OculusBaseDisplayPlugin.h" +class OffscreenGlCanvas; class OculusWin32DisplayPlugin : public OculusBaseDisplayPlugin { public: virtual bool isSupported(); + +private: + OffscreenGlCanvas* _canvas; }; diff --git a/libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.cpp index b6607e5518..db5e1422cf 100644 --- a/libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.cpp @@ -16,6 +16,8 @@ #include #include +#include +#include #include "../OglplusHelpers.h" @@ -35,6 +37,7 @@ bool Tv3dDisplayPlugin::isSupported() const { static ProgramPtr program; static ShapeWrapperPtr plane; +static gpu::TexturePointer crosshairTexture; void Tv3dDisplayPlugin::customizeWindow() { _window->setFlags(Qt::FramelessWindowHint); @@ -64,15 +67,19 @@ void Tv3dDisplayPlugin::customizeContext() { program = loadDefaultShader(); plane = loadPlane(program); Context::ClearColor(0, 0, 0, 1); - // _crosshairTexture = DependencyManager::get()-> - // getImageTexture(PathUtils::resourcesPath() + "images/sixense-reticle.png"); + crosshairTexture = DependencyManager::get()-> + getImageTexture(PathUtils::resourcesPath() + "images/sixense-reticle.png"); } +// FIXME make this into a setting that can be adjusted const float DEFAULT_IPD = 0.064f; const float HALF_DEFAULT_IPD = DEFAULT_IPD / 2.0f; glm::mat4 Tv3dDisplayPlugin::getProjection(Eye eye, const glm::mat4& baseProjection) const { + // Refer to http://www.nvidia.com/content/gtc-2010/pdfs/2010_gtc2010.pdf on creating + // stereo projection matrices. Do NOT use "toe-in", use translation. + float nearZ = DEFAULT_NEAR_CLIP; // near clipping plane float screenZ = 0.25f; // screen projection plane // FIXME verify this is the right calculation @@ -91,15 +98,24 @@ glm::mat4 Tv3dDisplayPlugin::getModelview(Eye eye, const glm::mat4& baseModelvie return baseModelview * glm::translate(mat4(), vec3(modelviewShift, 0, 0)); } - +template +void sbs_for_each_eye(const uvec2& size, F f) { + QRect r(QPoint(0, 0), QSize(size.x / 2, size.y)); + for_each_eye([&](Eye eye) { + oglplus::Context::Viewport(r.x(), r.y(), r.width(), r.height()); + f(eye); + }, [&] { + r.moveLeft(r.width()); + }); +} void Tv3dDisplayPlugin::display( GLuint sceneTexture, const glm::uvec2& sceneSize, GLuint overlayTexture, const glm::uvec2& overlaySize) { - QSize size = getDeviceSize(); + uvec2 size = toGlm(getDeviceSize()); using namespace oglplus; - Context::Viewport(size.width(), size.height()); + Context::Viewport(size.x, size.y); Context::Clear().ColorBuffer().DepthBuffer(); Mat4Uniform(*program, "ModelView").Set(mat4()); @@ -109,10 +125,11 @@ void Tv3dDisplayPlugin::display( plane->Draw(); - const float overlayAspect = aspect(toGlm(size)); + // FIXME the + const float screenAspect = aspect(size); const GLfloat distance = 1.0f; const GLfloat halfQuadHeight = distance * tan(DEFAULT_FIELD_OF_VIEW_DEGREES); - const GLfloat halfQuadWidth = halfQuadHeight * (float)size.width() / (float)size.height(); + const GLfloat halfQuadWidth = halfQuadHeight * screenAspect; const GLfloat quadWidth = halfQuadWidth * 2.0f; const GLfloat quadHeight = halfQuadHeight * 2.0f; @@ -123,38 +140,39 @@ void Tv3dDisplayPlugin::display( Context::Enable(Capability::Blend); glBindTexture(GL_TEXTURE_2D, overlayTexture); - mat4 pr = glm::perspective(glm::radians(DEFAULT_FIELD_OF_VIEW_DEGREES), aspect(toGlm(size)), DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP); + mat4 pr = glm::perspective(glm::radians(DEFAULT_FIELD_OF_VIEW_DEGREES), screenAspect, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP); Mat4Uniform(*program, "Projection").Set(pr); + // Position the camera relative to the overlay texture MatrixStack mv; - mv.translate(vec3(0, 0, -distance)).scale(vec3(0.7f, 0.7f / overlayAspect, 1.0f)); // .scale(vec3(quadWidth, quadHeight, 1.0)); + mv.translate(vec3(0, 0, -distance)).scale(vec3(0.7f, 0.7f / screenAspect, 1.0f)); // .scale(vec3(quadWidth, quadHeight, 1.0)); + sbs_for_each_eye(size, [&](Eye eye) { + mv.withPush([&] { + // translate + mv.top() = getModelview(eye, mv.top()); + Mat4Uniform(*program, "ModelView").Set(mv.top()); + plane->Draw(); + }); + }); - QRect r(QPoint(0, 0), QSize(size.width() / 2, size.height())); - for (int i = 0; i < 2; ++i) { - Context::Viewport(r.x(), r.y(), r.width(), r.height()); - Mat4Uniform(*program, "ModelView").Set(mv.top()); - plane->Draw(); - r.moveLeft(r.width()); - } - -#if 0 - glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_crosshairTexture)); - glm::vec2 canvasSize = qApp->getCanvasSize(); - glm::vec2 mouse = qApp->getMouse(); + glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(crosshairTexture)); + glm::vec2 canvasSize = getCanvasSize(); + glm::vec2 mouse = toGlm(_window->mapFromGlobal(QCursor::pos())); mouse /= canvasSize; mouse *= 2.0f; mouse -= 1.0f; mouse.y *= -1.0f; - mv.translate(mouse); - mv.scale(0.1f); - Mat4Uniform(*program, "ModelView").Set(mv.top()); - r = QRect(QPoint(0, 0), QSize(size.width() / 2, size.height())); - for (int i = 0; i < 2; ++i) { - Context::Viewport(r.x(), r.y(), r.width(), r.height()); - plane->Draw(); - r.moveLeft(r.width()); - } -#endif + sbs_for_each_eye(size, [&](Eye eye) { + mv.withPush([&] { + // translate + mv.top() = getModelview(eye, mv.top()); + mv.translate(mouse); + //mv.scale(0.05f); + mv.scale(vec3(0.025f, 0.05f, 1.0f)); + Mat4Uniform(*program, "ModelView").Set(mv.top()); + plane->Draw(); + }); + }); Context::Disable(Capability::Blend); } @@ -166,11 +184,9 @@ void Tv3dDisplayPlugin::activate(PluginContainer * container) { void Tv3dDisplayPlugin::deactivate() { makeCurrent(); - if (plane) { - plane.reset(); - program.reset(); -// _crosshairTexture.reset(); - } + plane.reset(); + program.reset(); + crosshairTexture.reset(); doneCurrent(); GlWindowDisplayPlugin::deactivate(); } From 23d6725a6a3b08ad89690cc79968f12e4ffa9512 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Sun, 31 May 2015 00:24:19 -0700 Subject: [PATCH 017/552] Consolidating GL display plugins --- interface/CMakeLists.txt | 8 +- interface/src/Application.cpp | 73 +------ interface/src/Application.h | 20 +- interface/src/DisplayPlugins.cpp | 77 +++++++ interface/src/DisplayPlugins.h | 18 ++ interface/src/GLCanvas.cpp | 3 +- interface/src/GLCanvas.h | 2 + interface/src/LegacyDisplayPlugin.cpp | 124 ----------- interface/src/LegacyDisplayPlugin.h | 47 ---- interface/src/avatar/Head.cpp | 1 - interface/src/ui/ApplicationOverlay.cpp | 5 + .../display-plugins/GlWindowDisplayPlugin.cpp | 113 ---------- .../display-plugins/GlWindowDisplayPlugin.h | 48 ----- .../OculusBaseDisplayPlugin.cpp | 10 +- .../display-plugins/OculusBaseDisplayPlugin.h | 9 +- .../OculusWin32DisplayPlugin.cpp | 51 ++++- .../OculusWin32DisplayPlugin.h | 16 +- .../display-plugins/OpenGlDisplayPlugin.cpp | 200 ++++++++++++------ .../src/display-plugins/OpenGlDisplayPlugin.h | 47 +++- .../src/display-plugins/Tv3dDisplayPlugin.cpp | 44 +--- .../src/display-plugins/Tv3dDisplayPlugin.h | 18 +- .../display-plugins/WindowDisplayPlugin.cpp | 76 +++++++ .../src/display-plugins/WindowDisplayPlugin.h | 13 +- .../plugins/src/plugins/PluginContainer.h | 4 + libraries/render-utils/src/GlWindow.cpp | 3 + .../render-utils/src/OffscreenGlCanvas.cpp | 3 + 26 files changed, 496 insertions(+), 537 deletions(-) create mode 100644 interface/src/DisplayPlugins.cpp create mode 100644 interface/src/DisplayPlugins.h delete mode 100644 interface/src/LegacyDisplayPlugin.cpp delete mode 100644 interface/src/LegacyDisplayPlugin.h delete mode 100644 libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.cpp delete mode 100644 libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.h diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index 458b6a7d7c..f68e9dcab2 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -123,8 +123,9 @@ else() add_executable(${TARGET_NAME} ${INTERFACE_SRCS} ${QM}) endif() +add_dependency_external_projects(glm bullet LibOVR) + # set up the external glm library -add_dependency_external_projects(glm bullet) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PRIVATE ${GLM_INCLUDE_DIRS}) @@ -132,6 +133,11 @@ find_package(Bullet REQUIRED) target_include_directories(${TARGET_NAME} SYSTEM PRIVATE ${BULLET_INCLUDE_DIRS}) target_link_libraries(${TARGET_NAME} ${BULLET_LIBRARIES}) +find_package(LibOVR REQUIRED) +target_include_directories(${TARGET_NAME} PRIVATE ${LIBOVR_INCLUDE_DIRS}) +#target_link_libraries(${TARGET_NAME} ${LIBOVR_LIBRARIES}) + + # link required hifi libraries link_hifi_libraries(shared octree environment gpu model fbx networking entities avatars audio audio-client animation script-engine physics diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 071ca30c10..44a39d302d 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4581,18 +4581,6 @@ qreal Application::getDevicePixelRatio() { return _window ? _window->windowHandle()->devicePixelRatio() : 1.0; } - - -using DisplayPluginPointer = QSharedPointer; - -#include -#include "LegacyDisplayPlugin.h" -//#include -#include -//#include - -static DisplayPluginPointer _displayPlugin{ nullptr }; - DisplayPlugin * Application::getActiveDisplayPlugin() { if (nullptr == _displayPlugin) { updateDisplayMode(); @@ -4605,63 +4593,6 @@ const DisplayPlugin * Application::getActiveDisplayPlugin() const { return ((Application*)this)->getActiveDisplayPlugin(); } -static void addDisplayPluginToMenu(DisplayPluginPointer displayPlugin, bool active = false) { - auto menu = Menu::getInstance(); - QString name = displayPlugin->getName(); - Q_ASSERT(!menu->menuItemExists(MenuOption::OutputMenu, name)); - - static QActionGroup* displayPluginGroup = nullptr; - if (!displayPluginGroup) { - displayPluginGroup = new QActionGroup(menu); - displayPluginGroup->setExclusive(true); - } - auto parent = menu->getMenu(MenuOption::OutputMenu); - auto action = menu->addActionToQMenuAndActionHash(parent, - name, 0, qApp, - SLOT(updateDisplayMode())); - action->setCheckable(true); - action->setChecked(active); - displayPluginGroup->addAction(action); - Q_ASSERT(menu->menuItemExists(MenuOption::OutputMenu, name)); -} - -using DisplayPluginList = QVector; - -static DisplayPlugin* PLUGIN_POOL[] = { - new LegacyDisplayPlugin(), -#ifdef DEBUG - new NullDisplayPlugin(), -#endif - new Tv3dDisplayPlugin(), -// new WindowDisplayPlugin(), - nullptr -}; - -// FIXME move to a plugin manager class -static const DisplayPluginList & getDisplayPlugins() { - static DisplayPluginList RENDER_PLUGINS; - static bool init = false; - if (!init) { - init = true; - for (int i = 0; PLUGIN_POOL[i]; ++i) { - DisplayPlugin * plugin = PLUGIN_POOL[i]; - if (plugin->isSupported()) { - plugin->init(); - QObject::connect(plugin, &DisplayPlugin::requestRender, [] { - qApp->paintGL(); - }); - QObject::connect(plugin, &DisplayPlugin::recommendedFramebufferSizeChanged, [](const QSize & size) { - qApp->resizeGL(); - }); - DisplayPluginPointer pluginPointer(plugin); - addDisplayPluginToMenu(pluginPointer, plugin == *PLUGIN_POOL); - RENDER_PLUGINS.push_back(pluginPointer); - } - } - } - return RENDER_PLUGINS; -} - void Application::updateDisplayMode() { auto menu = Menu::getInstance(); DisplayPluginPointer newDisplayPlugin; @@ -4709,3 +4640,7 @@ glm::ivec2 Application::getMouse() const { void Application::addMenuItem(const QString& path, std::function onClicked, bool checkable, bool checked, const QString& groupName) { } + +QMainWindow* Application::getAppMainWindow() { + return _window; +} diff --git a/interface/src/Application.h b/interface/src/Application.h index a91e5f77f2..40c71ad6dc 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -76,8 +76,8 @@ #include "octree/OctreeFade.h" #include "octree/OctreePacketProcessor.h" #include "UndoStackScriptingInterface.h" +#include "DisplayPlugins.h" -class DisplayPlugin; class QGLWidget; class QKeyEvent; class QMouseEvent; @@ -282,19 +282,6 @@ public: void displaySide(const Camera& camera, bool selfAvatarOnly = false); - virtual void addMenuItem(const QString& path, std::function onClicked, bool checkable, bool checked, const QString& groupName); - -/* - /// Stores the current modelview matrix as the untranslated view matrix to use for transforms and the supplied vector as - /// the view matrix translation. - void updateUntranslatedViewMatrix(const glm::vec3& viewMatrixTranslation = glm::vec3()); - - const glm::mat4& getUntranslatedViewMatrix() const { return _untranslatedViewMatrix; } - - /// Loads a view matrix that incorporates the specified model translation without the precision issues that can - /// result from matrix multiplication at high translation magnitudes. - void loadTranslatedViewMatrix(const glm::vec3& translation); -*/ void getModelViewMatrix(glm::dmat4* modelViewMatrix); void getProjectionMatrix(glm::dmat4* projectionMatrix); @@ -311,6 +298,10 @@ public: virtual void endOverrideEnvironmentData() { _environment.endOverride(); } virtual qreal getDevicePixelRatio(); + // Plugin container support + virtual void addMenuItem(const QString& path, std::function onClicked, bool checkable, bool checked, const QString& groupName); + virtual QMainWindow* getAppMainWindow(); + private: DisplayPlugin * getActiveDisplayPlugin(); const DisplayPlugin * getActiveDisplayPlugin() const; @@ -516,6 +507,7 @@ private: bool _dependencyManagerIsSetup; OffscreenGlCanvas* _offscreenContext; + DisplayPluginPointer _displayPlugin; MainWindow* _window; diff --git a/interface/src/DisplayPlugins.cpp b/interface/src/DisplayPlugins.cpp new file mode 100644 index 0000000000..006ca1523d --- /dev/null +++ b/interface/src/DisplayPlugins.cpp @@ -0,0 +1,77 @@ +// +// Created by Bradley Austin Davis on 2015/05/30 +// 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 "DisplayPlugins.h" + +#include "Application.h" + +#include +#include +#include +#include + +#ifdef Q_OS_WIN +#include +#else +#endif + + +static void addDisplayPluginToMenu(DisplayPluginPointer displayPlugin, bool active = false) { + auto menu = Menu::getInstance(); + QString name = displayPlugin->getName(); + Q_ASSERT(!menu->menuItemExists(MenuOption::OutputMenu, name)); + + static QActionGroup* displayPluginGroup = nullptr; + if (!displayPluginGroup) { + displayPluginGroup = new QActionGroup(menu); + displayPluginGroup->setExclusive(true); + } + auto parent = menu->getMenu(MenuOption::OutputMenu); + auto action = menu->addActionToQMenuAndActionHash(parent, + name, 0, qApp, + SLOT(updateDisplayMode())); + action->setCheckable(true); + action->setChecked(active); + displayPluginGroup->addAction(action); + Q_ASSERT(menu->menuItemExists(MenuOption::OutputMenu, name)); +} + +// FIXME move to a plugin manager class +const DisplayPluginList& getDisplayPlugins() { + static DisplayPluginList RENDER_PLUGINS; + static bool init = false; + if (!init) { + init = true; + + DisplayPlugin* PLUGIN_POOL[] = { + new WindowDisplayPlugin(), +#ifdef DEBUG + new NullDisplayPlugin(), +#endif + new Tv3dDisplayPlugin(), + new OculusWin32DisplayPlugin(), + nullptr + }; + for (int i = 0; PLUGIN_POOL[i]; ++i) { + DisplayPlugin * plugin = PLUGIN_POOL[i]; + if (plugin->isSupported()) { + plugin->init(); + QObject::connect(plugin, &DisplayPlugin::requestRender, [] { + qApp->paintGL(); + }); + QObject::connect(plugin, &DisplayPlugin::recommendedFramebufferSizeChanged, [](const QSize & size) { + qApp->resizeGL(); + }); + DisplayPluginPointer pluginPointer(plugin); + addDisplayPluginToMenu(pluginPointer, plugin == *PLUGIN_POOL); + RENDER_PLUGINS.push_back(pluginPointer); + } + } + } + return RENDER_PLUGINS; +} diff --git a/interface/src/DisplayPlugins.h b/interface/src/DisplayPlugins.h new file mode 100644 index 0000000000..f40b8d049f --- /dev/null +++ b/interface/src/DisplayPlugins.h @@ -0,0 +1,18 @@ +// +// Created by Bradley Austin Davis on 2015/05/30 +// 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 + +class DisplayPlugin; + +#include +#include + +using DisplayPluginPointer = QSharedPointer; +using DisplayPluginList = QVector; + +const DisplayPluginList& getDisplayPlugins(); \ No newline at end of file diff --git a/interface/src/GLCanvas.cpp b/interface/src/GLCanvas.cpp index 6fb2a742f3..c5fa536842 100644 --- a/interface/src/GLCanvas.cpp +++ b/interface/src/GLCanvas.cpp @@ -9,7 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // - +#if 0 #include "Application.h" #include "GLCanvas.h" @@ -162,3 +162,4 @@ bool GLCanvas::eventFilter(QObject*, QEvent* event) { } return false; } +#endif diff --git a/interface/src/GLCanvas.h b/interface/src/GLCanvas.h index 6c53a17e04..5a69af3d3a 100644 --- a/interface/src/GLCanvas.h +++ b/interface/src/GLCanvas.h @@ -9,6 +9,7 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#if 0 #ifndef hifi_GLCanvas_h #define hifi_GLCanvas_h @@ -51,3 +52,4 @@ private slots: #endif // hifi_GLCanvas_h +#endif diff --git a/interface/src/LegacyDisplayPlugin.cpp b/interface/src/LegacyDisplayPlugin.cpp deleted file mode 100644 index 76629e896e..0000000000 --- a/interface/src/LegacyDisplayPlugin.cpp +++ /dev/null @@ -1,124 +0,0 @@ -// -// LegacyDisplayPlugin.cpp -// -// Created by Bradley Austin Davis on 2014/04/13. -// 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 "Application.h" -#include "LegacyDisplayPlugin.h" -#include "MainWindow.h" -#include -#include - -const QString LegacyDisplayPlugin::NAME("2D Monitor (GL Windgets)"); - -const QString & LegacyDisplayPlugin::getName() { - return NAME; -} - -LegacyDisplayPlugin::LegacyDisplayPlugin() { - connect(&_timer, &QTimer::timeout, this, [&] { - emit requestRender(); - }); -} - -static QWidget * oldWidget = nullptr; - -void LegacyDisplayPlugin::activate(PluginContainer * container) { - _window = new GLCanvas(); - QOpenGLContext * sourceContext = QOpenGLContext::currentContext(); - QOpenGLContext * newContext = new QOpenGLContext(); - { - QSurfaceFormat format; - format.setOption(QSurfaceFormat::DebugContext); - newContext->setFormat(format); - } - - _window->setContext( - QGLContext::fromOpenGLContext(newContext), - QGLContext::fromOpenGLContext(sourceContext)); - oldWidget = qApp->getWindow()->centralWidget(); - - // FIXME necessary? - makeCurrent(); - qApp->getWindow()->setCentralWidget(_window); - doneCurrent(); - _window->setFocusPolicy(Qt::StrongFocus); - _window->setFocus(); - _window->setMouseTracking(true); - _timer.start(8); -} - -void LegacyDisplayPlugin::deactivate() { - _timer.stop(); - // FIXME, during shutdown, this causes an NPE. Need to deactivate the plugin before the main window is destroyed. -// if (qApp->getWindow()) { -// qApp->getWindow()->setCentralWidget(oldWidget); -// } - // stop the glWidget frame timer so it doesn't call paintGL - _window->stopFrameTimer(); - _window->doneCurrent(); - _window->deleteLater(); - _window = nullptr; -} - -QSize LegacyDisplayPlugin::getDeviceSize() const { - return _window->getDeviceSize(); -} - -void LegacyDisplayPlugin::idle() { - _window->updateGL(); -} - -glm::ivec2 LegacyDisplayPlugin::getCanvasSize() const { - return toGlm(_window->size()); -} - -bool LegacyDisplayPlugin::hasFocus() const { - return _window->hasFocus(); -} - -PickRay LegacyDisplayPlugin::computePickRay(const glm::vec2 & pos) const { - return PickRay(); -} - -void LegacyDisplayPlugin::preDisplay() { - OpenGlDisplayPlugin::preDisplay(); - auto size = toGlm(_window->size()); - glViewport(0, 0, size.x, size.y); -} - -bool LegacyDisplayPlugin::isThrottled() const { - return _window->isThrottleRendering(); -} - -void LegacyDisplayPlugin::makeCurrent() { - _window->makeCurrent(); -} - -void LegacyDisplayPlugin::doneCurrent() { - _window->doneCurrent(); -} - -void LegacyDisplayPlugin::swapBuffers() { - _window->swapBuffers(); -} - -ivec2 LegacyDisplayPlugin::getTrueMousePosition() const { - return toGlm(_window->mapFromGlobal(QCursor::pos())); -} - -QWindow* LegacyDisplayPlugin::getWindow() const { - return _window->windowHandle(); -} - -void LegacyDisplayPlugin::installEventFilter(QObject* filter) { - _window->installEventFilter(filter); -} - -void LegacyDisplayPlugin::removeEventFilter(QObject* filter) { - _window->removeEventFilter(filter); -} \ No newline at end of file diff --git a/interface/src/LegacyDisplayPlugin.h b/interface/src/LegacyDisplayPlugin.h deleted file mode 100644 index d41dc25090..0000000000 --- a/interface/src/LegacyDisplayPlugin.h +++ /dev/null @@ -1,47 +0,0 @@ -// -// LegacyDisplayPlugin.h -// -// Created by Bradley Austin Davis on 2014/04/13. -// 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 "GLCanvas.h" - -class LegacyDisplayPlugin : public OpenGlDisplayPlugin { - Q_OBJECT -public: - LegacyDisplayPlugin(); - static const QString NAME; - virtual const QString & getName(); - - virtual void activate(PluginContainer * container); - virtual void deactivate(); - - virtual QSize getDeviceSize() const; - virtual ivec2 getCanvasSize() const; - virtual bool hasFocus() const; - virtual PickRay computePickRay(const glm::vec2 & pos) const; - virtual bool isMouseOnScreen() const { return true; } - virtual bool isThrottled() const; - virtual void preDisplay(); - virtual void idle(); - virtual ivec2 getTrueMousePosition() const; - - virtual QWindow* getWindow() const; - virtual void installEventFilter(QObject* filter); - virtual void removeEventFilter(QObject* filter); - -protected: - virtual void makeCurrent() final; - virtual void doneCurrent() final; - virtual void swapBuffers() final; - -private: - GLCanvas * _window; - QTimer _timer; -}; diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index 688227c75f..e0cdef109e 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -311,7 +311,6 @@ glm::quat Head::getCameraOrientation() const { if (qApp->isHMDMode()) { return getOrientation(); } - Avatar* owningAvatar = static_cast(_owningAvatar); return owningAvatar->getWorldAlignedOrientation() * glm::quat(glm::radians(glm::vec3(_basePitch, 0.0f, 0.0f))); } diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index c20928f05a..b2d2239255 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -194,6 +194,11 @@ void ApplicationOverlay::renderOverlay() { Overlays& overlays = qApp->getOverlays(); glm::uvec2 size = qApp->getCanvasSize(); + if (size == uvec2(0)) { + qDebug() << "Bad size from display plugin"; + glm::uvec2 size = qApp->getCanvasSize(); + } + if (!_framebufferObject || size != toGlm(_framebufferObject->size())) { if(_framebufferObject) { delete _framebufferObject; diff --git a/libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.cpp deleted file mode 100644 index fe3347a185..0000000000 --- a/libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.cpp +++ /dev/null @@ -1,113 +0,0 @@ -// -// Created by Bradley Austin Davis on 2015/05/29 -// 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 "GlWindowDisplayPlugin.h" - -#include -#include -#include -#include - -#include -#include - -GlWindowDisplayPlugin::GlWindowDisplayPlugin() : _timer(new QTimer()) { - connect(_timer, &QTimer::timeout, this, [&] { - // if (qApp->getActiveDisplayPlugin() == this) { - emit requestRender(); - // } - }); -} - -GlWindowDisplayPlugin::~GlWindowDisplayPlugin() { - delete _timer; -} - -void GlWindowDisplayPlugin::makeCurrent() { - _window->makeCurrent(); -} - -void GlWindowDisplayPlugin::doneCurrent() { - _window->doneCurrent(); -} - -void GlWindowDisplayPlugin::swapBuffers() { - _window->swapBuffers(); -} - -glm::ivec2 GlWindowDisplayPlugin::getTrueMousePosition() const { - return toGlm(_window->mapFromGlobal(QCursor::pos())); -} - -QWindow* GlWindowDisplayPlugin::getWindow() const { - return _window; -} - -void GlWindowDisplayPlugin::activate(PluginContainer * container) { - Q_ASSERT(nullptr == _window); - _window = new GlWindow(QOpenGLContext::currentContext()); - _window->installEventFilter(this); - customizeWindow(); - _window->show(); - _timer->start(8); - makeCurrent(); - customizeContext(); -} - -void GlWindowDisplayPlugin::deactivate() { - _timer->stop(); - Q_ASSERT(nullptr != _window); - _window->hide(); - _window->destroy(); - _window->deleteLater(); - _window = nullptr; -} - -QSize GlWindowDisplayPlugin::getDeviceSize() const { - return _window->geometry().size() * _window->devicePixelRatio(); -} - -glm::ivec2 GlWindowDisplayPlugin::getCanvasSize() const { - return toGlm(_window->geometry().size()); -} - -bool GlWindowDisplayPlugin::hasFocus() const { - return _window->isActive(); -} - -void GlWindowDisplayPlugin::installEventFilter(QObject* filter) { - _window->installEventFilter(filter); -} - -void GlWindowDisplayPlugin::removeEventFilter(QObject* filter) { - _window->removeEventFilter(filter); -} - -bool GlWindowDisplayPlugin::eventFilter(QObject* receiver, QEvent* event) { - switch (event->type()) { - case QEvent::MouseMove: - case QEvent::MouseButtonPress: - case QEvent::MouseButtonRelease: - case QEvent::MouseButtonDblClick: - case QEvent::KeyPress: - case QEvent::KeyRelease: - case QEvent::FocusIn: - case QEvent::FocusOut: - case QEvent::Resize: - case QEvent::TouchBegin: - case QEvent::TouchEnd: - case QEvent::TouchUpdate: - case QEvent::Wheel: - case QEvent::DragEnter: - case QEvent::Drop: - if (QCoreApplication::sendEvent(QCoreApplication::instance(), event)) { - return true; - } - break; - } - return false; -} \ No newline at end of file diff --git a/libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.h deleted file mode 100644 index 9a7c284ff9..0000000000 --- a/libraries/display-plugins/src/display-plugins/GlWindowDisplayPlugin.h +++ /dev/null @@ -1,48 +0,0 @@ -// -// Created by Bradley Austin Davis on 2015/05/29 -// 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 "OpenGlDisplayPlugin.h" - -class GlWindow; -class QTimer; - -class GlWindowDisplayPlugin : public OpenGlDisplayPlugin { -public: - GlWindowDisplayPlugin(); - virtual ~GlWindowDisplayPlugin(); - virtual void activate(PluginContainer * container); - virtual void deactivate(); - virtual QSize getDeviceSize() const final; - virtual glm::ivec2 getCanvasSize() const final; - virtual bool hasFocus() const; - - virtual glm::ivec2 getTrueMousePosition() const; - virtual QWindow* getWindow() const; - virtual bool eventFilter(QObject* receiver, QEvent* event); - virtual void installEventFilter(QObject* filter); - virtual void removeEventFilter(QObject* filter); - -protected: - virtual void makeCurrent() final; - virtual void doneCurrent() final; - virtual void swapBuffers() final; - - // Called by the activate method to specify the initial window geometry - // flags, etc - virtual void customizeWindow() = 0; - // Called by the activate method after the GL context has been created to - // initialize OpenGL context settings needed by the plugin - virtual void customizeContext() = 0; - -private: - QTimer* _timer{ nullptr }; -protected: - GlWindow* _window{ nullptr }; -}; - diff --git a/libraries/display-plugins/src/display-plugins/OculusBaseDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OculusBaseDisplayPlugin.cpp index 7648be1d25..a92c9ccbe5 100644 --- a/libraries/display-plugins/src/display-plugins/OculusBaseDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OculusBaseDisplayPlugin.cpp @@ -12,16 +12,23 @@ #include "../OculusHelpers.h" void OculusBaseDisplayPlugin::activate(PluginContainer * container) { + OpenGlDisplayPlugin::activate(container); + glm::uvec2 eyeSizes[2]; ovr_for_each_eye([&](ovrEyeType eye) { ovrEyeRenderDesc erd = ovrHmd_GetRenderDesc(_hmd, eye, _hmd->MaxEyeFov[eye]); ovrMatrix4f ovrPerspectiveProjection = ovrMatrix4f_Projection(erd.Fov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_RightHanded); _eyeProjections[eye] = toGlm(ovrPerspectiveProjection); _eyeOffsets[eye] = erd.HmdToEyeViewOffset; + eyeSizes[eye] = toGlm(ovrHmd_GetFovTextureSize(_hmd, eye, erd.Fov, 1.0f)); }); + _desiredFramebufferSize = QSize( + eyeSizes[0].x + eyeSizes[1].x, + std::max(eyeSizes[0].y, eyeSizes[1].y)); } -void OculusBaseDisplayPlugin::deactivate() { +QSize OculusBaseDisplayPlugin::getRecommendedFramebufferSize() const { + return _desiredFramebufferSize; } void OculusBaseDisplayPlugin::preRender() { @@ -35,4 +42,3 @@ glm::mat4 OculusBaseDisplayPlugin::getProjection(Eye eye, const glm::mat4& baseP glm::mat4 OculusBaseDisplayPlugin::getModelview(Eye eye, const glm::mat4& baseModelview) const { return toGlm(_eyePoses[eye]); } - diff --git a/libraries/display-plugins/src/display-plugins/OculusBaseDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OculusBaseDisplayPlugin.h index 0462f00321..76612cbaa1 100644 --- a/libraries/display-plugins/src/display-plugins/OculusBaseDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OculusBaseDisplayPlugin.h @@ -7,20 +7,20 @@ // #pragma once -#include "DisplayPlugin.h" +#include "OpenGlDisplayPlugin.h" #include -class OculusBaseDisplayPlugin : public DisplayPlugin { +class OculusBaseDisplayPlugin : public OpenGlDisplayPlugin { public: // Stereo specific methods virtual bool isHmd() const { return true; } virtual glm::mat4 getProjection(Eye eye, const glm::mat4& baseProjection) const; virtual glm::mat4 getModelview(Eye eye, const glm::mat4& baseModelview) const; virtual void activate(PluginContainer * container); - virtual void deactivate(); virtual void preRender(); - virtual void configureRendering() = 0; + virtual QSize getRecommendedFramebufferSize() const; + protected: ovrHmd _hmd; unsigned int _frameIndex{ 0 }; @@ -28,4 +28,5 @@ protected: ovrPosef _eyePoses[2]; ovrVector3f _eyeOffsets[2]; glm::mat4 _eyeProjections[2]; + QSize _desiredFramebufferSize; }; diff --git a/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.cpp index ee6f2dc4a4..5c27dc6407 100644 --- a/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.cpp @@ -8,22 +8,69 @@ #include "OculusWin32DisplayPlugin.h" #include + +#include + #include +#include #include +#include "plugins/PluginContainer.h" + #include "../OglplusHelpers.h" +const QString OculusWin32DisplayPlugin::NAME("Oculus Rift"); + +const QString & OculusWin32DisplayPlugin::getName() { + return NAME; +} + bool OculusWin32DisplayPlugin::isSupported() { - ovr_Initialize(nullptr); + if (!OVR_SUCCESS(ovr_Initialize(nullptr))) { + return false; + } bool result = false; - if (ovrHmd_Detect() != 0) { + if (ovrHmd_Detect() > 0) { result = true; } ovr_Shutdown(); return result; } +void OculusWin32DisplayPlugin::activate(PluginContainer * container) { + if (!OVR_SUCCESS(ovr_Initialize(nullptr))) { + Q_ASSERT(false); + qFatal("Failed to Initialize SDK"); + } + if (!OVR_SUCCESS(ovrHmd_Create(0, &_hmd))) { + Q_ASSERT(false); + qFatal("Failed to acquire HMD"); + } + // Parent class relies on our _hmd intialization, so it must come after that. + OculusBaseDisplayPlugin::activate(container); +} + +void OculusWin32DisplayPlugin::customizeWindow(PluginContainer * container) { + container->getAppMainWindow()->setCentralWidget(QWidget::createWindowContainer(_window)); +} + +void OculusWin32DisplayPlugin::customizeContext(PluginContainer * container) { +} + +void OculusWin32DisplayPlugin::deactivate() { + ovrHmd_Destroy(_hmd); + _hmd = nullptr; + ovr_Shutdown(); +} + +void OculusWin32DisplayPlugin::display( + GLuint sceneTexture, const glm::uvec2& sceneSize, + GLuint overlayTexture, const glm::uvec2& overlaySize) { + glClearColor(0, 1, 0, 1); + glClear(GL_COLOR_BUFFER_BIT); +} + #if 0 // A basic wrapper for constructing a framebuffer with a renderbuffer // for the depth attachment and an undefined type for the color attachement diff --git a/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.h index d1203bde77..e0ed684daf 100644 --- a/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.h @@ -8,12 +8,26 @@ #pragma once #include "OculusBaseDisplayPlugin.h" +#include class OffscreenGlCanvas; class OculusWin32DisplayPlugin : public OculusBaseDisplayPlugin { public: virtual bool isSupported(); + virtual const QString & getName(); + + virtual void activate(PluginContainer * container); + virtual void deactivate(); +// virtual QSize getDeviceSize() const final; +// virtual glm::ivec2 getCanvasSize() const final; + + void display(GLuint sceneTexture, const glm::uvec2& sceneSize, + GLuint overlayTexture, const glm::uvec2& overlaySize); + +protected: + virtual void customizeWindow(PluginContainer * container); + virtual void customizeContext(PluginContainer * container); private: - OffscreenGlCanvas* _canvas; + static const QString NAME; }; diff --git a/libraries/display-plugins/src/display-plugins/OpenGlDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGlDisplayPlugin.cpp index f2bd328915..762f4ece8d 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGlDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGlDisplayPlugin.cpp @@ -8,6 +8,59 @@ #include "OpenGlDisplayPlugin.h" #include +#include +#include + +#include +#include +#include + +#include +#include + + +OpenGlDisplayPlugin::OpenGlDisplayPlugin() { + connect(&_timer, &QTimer::timeout, this, [&] { + if (_window) { + emit requestRender(); + } + }); +} + +OpenGlDisplayPlugin::~OpenGlDisplayPlugin() { +} + +QWindow* OpenGlDisplayPlugin::getWindow() const { + return _window; +} + +glm::ivec2 OpenGlDisplayPlugin::getTrueMousePosition() const { + return toGlm(_window->mapFromGlobal(QCursor::pos())); +} + +QSize OpenGlDisplayPlugin::getDeviceSize() const { + return _window->geometry().size() * _window->devicePixelRatio(); +} + +glm::ivec2 OpenGlDisplayPlugin::getCanvasSize() const { + return toGlm(_window->geometry().size()); +} + +bool OpenGlDisplayPlugin::hasFocus() const { + return _window->isActive(); +} + +void OpenGlDisplayPlugin::makeCurrent() { + _window->makeCurrent(); +} + +void OpenGlDisplayPlugin::doneCurrent() { + _window->doneCurrent(); +} + +void OpenGlDisplayPlugin::swapBuffers() { + _window->swapBuffers(); +} void OpenGlDisplayPlugin::preDisplay() { makeCurrent(); @@ -22,67 +75,96 @@ void OpenGlDisplayPlugin::finishFrame() { doneCurrent(); }; -void OpenGlDisplayPlugin::display(GLuint sceneTexture, const glm::uvec2& sceneSize, - GLuint overlayTexture, const glm::uvec2& overlaySize) { - glDisable(GL_LIGHTING); - glDisable(GL_DEPTH_TEST); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); +void OpenGlDisplayPlugin::activate(PluginContainer * container) { + Q_ASSERT(nullptr == _window); + _window = new GlWindow(QOpenGLContext::currentContext()); + _window->installEventFilter(this); + customizeWindow(container); +// _window->show(); - glClearColor(0, 0, 1, 1); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glEnable(GL_TEXTURE_2D); - - glViewport(0, 0, getDeviceSize().width(), getDeviceSize().height()); - if (sceneTexture) { - glBindTexture(GL_TEXTURE_2D, sceneTexture); - glBegin(GL_QUADS); - glTexCoord2f(0, 0); - glVertex2f(-1, -1); - glTexCoord2f(1, 0); - glVertex2f(+1, -1); - glTexCoord2f(1, 1); - glVertex2f(+1, +1); - glTexCoord2f(0, 1); - glVertex2f(-1, +1); - glEnd(); - } + makeCurrent(); + customizeContext(container); - if (overlayTexture) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glBindTexture(GL_TEXTURE_2D, overlayTexture); - glBegin(GL_QUADS); - glTexCoord2f(0, 0); - glVertex2f(-1, -1); - glTexCoord2f(1, 0); - glVertex2f(+1, -1); - glTexCoord2f(1, 1); - glVertex2f(+1, +1); - glTexCoord2f(0, 1); - glVertex2f(-1, +1); - glEnd(); - } - - - glDisable(GL_BLEND); - - glBindTexture(GL_TEXTURE_2D, 0); - glDisable(GL_TEXTURE_2D); - //Q_ASSERT(!glGetError()); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - - glEnable(GL_LIGHTING); - glEnable(GL_DEPTH_TEST); - - glFinish(); + _timer.start(1); +} + +void OpenGlDisplayPlugin::customizeContext(PluginContainer * container) { + using namespace oglplus; + Context::BlendFunc(BlendFunction::SrcAlpha, BlendFunction::OneMinusSrcAlpha); + Context::Disable(Capability::Blend); + Context::Disable(Capability::DepthTest); + Context::Disable(Capability::CullFace); + program = loadDefaultShader(); + plane = loadPlane(program); + Context::ClearColor(0, 0, 0, 1); + crosshairTexture = DependencyManager::get()-> + getImageTexture(PathUtils::resourcesPath() + "images/sixense-reticle.png"); +} + +void OpenGlDisplayPlugin::deactivate() { + _timer.stop(); + + makeCurrent(); + plane.reset(); + program.reset(); + crosshairTexture.reset(); + doneCurrent(); + + Q_ASSERT(nullptr != _window); + _window->hide(); + _window->destroy(); + _window->deleteLater(); + _window = nullptr; +} + +void OpenGlDisplayPlugin::installEventFilter(QObject* filter) { + _window->installEventFilter(filter); +} + +void OpenGlDisplayPlugin::removeEventFilter(QObject* filter) { + _window->removeEventFilter(filter); +} + + + +// Pressing Alt (and Meta) key alone activates the menubar because its style inherits the +// SHMenuBarAltKeyNavigation from QWindowsStyle. This makes it impossible for a scripts to +// receive keyPress events for the Alt (and Meta) key in a reliable manner. +// +// This filter catches events before QMenuBar can steal the keyboard focus. +// The idea was borrowed from +// http://www.archivum.info/qt-interest@trolltech.com/2006-09/00053/Re-(Qt4)-Alt-key-focus-QMenuBar-(solved).html + +// Pass input events on to the application +bool OpenGlDisplayPlugin::eventFilter(QObject* receiver, QEvent* event) { + switch (event->type()) { + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseButtonDblClick: + case QEvent::MouseMove: + case QEvent::Wheel: + + case QEvent::TouchBegin: + case QEvent::TouchEnd: + case QEvent::TouchUpdate: + + case QEvent::FocusIn: + case QEvent::FocusOut: + + case QEvent::KeyPress: + case QEvent::KeyRelease: + case QEvent::ShortcutOverride: + + case QEvent::DragEnter: + case QEvent::Drop: + + case QEvent::Resize: + if (QCoreApplication::sendEvent(QCoreApplication::instance(), event)) { + return true; + } + break; + } + return false; } diff --git a/libraries/display-plugins/src/display-plugins/OpenGlDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGlDisplayPlugin.h index 19587b997e..6e284b08bf 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGlDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/OpenGlDisplayPlugin.h @@ -7,18 +7,55 @@ // #pragma once +#include + +#include + #include "DisplayPlugin.h" +#include "../OglplusHelpers.h" + +class GlWindow; class OpenGlDisplayPlugin : public DisplayPlugin { public: - virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize, - GLuint overlayTexture, const glm::uvec2& overlaySize); + OpenGlDisplayPlugin(); + virtual ~OpenGlDisplayPlugin(); virtual void preRender(); virtual void preDisplay(); virtual void finishFrame(); + virtual void activate(PluginContainer * container); + virtual void deactivate(); + + virtual QSize getDeviceSize() const; + virtual glm::ivec2 getCanvasSize() const; + virtual bool hasFocus() const; + + virtual glm::ivec2 getTrueMousePosition() const; + virtual QWindow* getWindow() const; + virtual bool eventFilter(QObject* receiver, QEvent* event); + virtual void installEventFilter(QObject* filter); + virtual void removeEventFilter(QObject* filter); + + protected: - virtual void makeCurrent() = 0; - virtual void doneCurrent() = 0; - virtual void swapBuffers() = 0; + // Called by the activate method to specify the initial + // window geometry flags, etc + virtual void customizeWindow(PluginContainer * container) = 0; + + // Needs to be called by the activate method after the GL context has been created to + // initialize OpenGL context settings needed by the plugin + virtual void customizeContext(PluginContainer * container); + + virtual void makeCurrent() final; + virtual void doneCurrent() final; + virtual void swapBuffers() final; + + GlWindow* _window{ nullptr }; + QTimer _timer; + ProgramPtr program; + ShapeWrapperPtr plane; + gpu::TexturePointer crosshairTexture; }; + + diff --git a/libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.cpp index db5e1422cf..240306e736 100644 --- a/libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.cpp @@ -14,13 +14,9 @@ #include #include #include -#include -#include #include -#include "../OglplusHelpers.h" - const QString Tv3dDisplayPlugin::NAME("Tv3dDisplayPlugin"); const QString & Tv3dDisplayPlugin::getName() { @@ -35,11 +31,7 @@ bool Tv3dDisplayPlugin::isSupported() const { return true; } -static ProgramPtr program; -static ShapeWrapperPtr plane; -static gpu::TexturePointer crosshairTexture; - -void Tv3dDisplayPlugin::customizeWindow() { +void Tv3dDisplayPlugin::customizeWindow(PluginContainer * container) { _window->setFlags(Qt::FramelessWindowHint); auto desktop = QApplication::desktop(); QRect primaryGeometry = desktop->screenGeometry(); @@ -56,22 +48,9 @@ void Tv3dDisplayPlugin::customizeWindow() { break; } _window->setCursor(Qt::BlankCursor); + _window->show(); } -void Tv3dDisplayPlugin::customizeContext() { - using namespace oglplus; - Context::BlendFunc(BlendFunction::SrcAlpha, BlendFunction::OneMinusSrcAlpha); - Context::Disable(Capability::Blend); - Context::Disable(Capability::DepthTest); - Context::Disable(Capability::CullFace); - program = loadDefaultShader(); - plane = loadPlane(program); - Context::ClearColor(0, 0, 0, 1); - crosshairTexture = DependencyManager::get()-> - getImageTexture(PathUtils::resourcesPath() + "images/sixense-reticle.png"); -} - - // FIXME make this into a setting that can be adjusted const float DEFAULT_IPD = 0.064f; const float HALF_DEFAULT_IPD = DEFAULT_IPD / 2.0f; @@ -112,10 +91,14 @@ void sbs_for_each_eye(const uvec2& size, F f) { void Tv3dDisplayPlugin::display( GLuint sceneTexture, const glm::uvec2& sceneSize, GLuint overlayTexture, const glm::uvec2& overlaySize) { - + makeCurrent(); + GLenum err = glGetError(); uvec2 size = toGlm(getDeviceSize()); + err = glGetError(); using namespace oglplus; + err = glGetError(); Context::Viewport(size.x, size.y); + err = glGetError(); Context::Clear().ColorBuffer().DepthBuffer(); Mat4Uniform(*program, "ModelView").Set(mat4()); @@ -178,15 +161,6 @@ void Tv3dDisplayPlugin::display( void Tv3dDisplayPlugin::activate(PluginContainer * container) { - GlWindowDisplayPlugin::activate(container); - _window->show(); -} - -void Tv3dDisplayPlugin::deactivate() { - makeCurrent(); - plane.reset(); - program.reset(); - crosshairTexture.reset(); - doneCurrent(); - GlWindowDisplayPlugin::deactivate(); + OpenGlDisplayPlugin::activate(container); + // FIXME Add menu items } diff --git a/libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.h index 9baa9261ef..7541b19f23 100644 --- a/libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.h @@ -7,27 +7,29 @@ // #pragma once -#include "GlWindowDisplayPlugin.h" +#include "OpenGlDisplayPlugin.h" -class Tv3dDisplayPlugin : public GlWindowDisplayPlugin { +class Tv3dDisplayPlugin : public OpenGlDisplayPlugin { Q_OBJECT public: - static const QString NAME; - virtual const QString & getName(); Tv3dDisplayPlugin(); + virtual const QString & getName(); virtual bool isStereo() const final { return true; } virtual bool isSupported() const final; + + virtual void activate(PluginContainer * container); + void display(GLuint sceneTexture, const glm::uvec2& sceneSize, GLuint overlayTexture, const glm::uvec2& overlaySize); - virtual void activate(PluginContainer * container); - virtual void deactivate(); + virtual glm::mat4 getProjection(Eye eye, const glm::mat4& baseProjection) const; virtual glm::mat4 getModelview(Eye eye, const glm::mat4& baseModelview) const; protected: - virtual void customizeWindow(); - virtual void customizeContext(); + virtual void customizeWindow(PluginContainer * container); //virtual std::function getMouseTranslator(); //virtual glm::ivec2 trueMouseToUiMouse(const glm::ivec2 & position) const; +private: + static const QString NAME; }; diff --git a/libraries/display-plugins/src/display-plugins/WindowDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/WindowDisplayPlugin.cpp index 0298d6b823..0b3c1a8a41 100644 --- a/libraries/display-plugins/src/display-plugins/WindowDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/WindowDisplayPlugin.cpp @@ -7,6 +7,12 @@ // #include "WindowDisplayPlugin.h" +#include + +#include + +#include "plugins/PluginContainer.h" + WindowDisplayPlugin::WindowDisplayPlugin() { } @@ -16,3 +22,73 @@ const QString & WindowDisplayPlugin::getName() { return NAME; } +void WindowDisplayPlugin::customizeWindow(PluginContainer * container) { + QMainWindow* mainWindow = container->getAppMainWindow(); + QWidget* widget = QWidget::createWindowContainer(_window); + mainWindow->setCentralWidget(widget); +} + +void WindowDisplayPlugin::display( + GLuint sceneTexture, const glm::uvec2& sceneSize, + GLuint overlayTexture, const glm::uvec2& overlaySize) { + glDisable(GL_LIGHTING); + glDisable(GL_DEPTH_TEST); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glLoadIdentity(); + + glClearColor(0, 0, 1, 1); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + glEnable(GL_TEXTURE_2D); + + glViewport(0, 0, getDeviceSize().width(), getDeviceSize().height()); + if (sceneTexture) { + glBindTexture(GL_TEXTURE_2D, sceneTexture); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); + glVertex2f(-1, -1); + glTexCoord2f(1, 0); + glVertex2f(+1, -1); + glTexCoord2f(1, 1); + glVertex2f(+1, +1); + glTexCoord2f(0, 1); + glVertex2f(-1, +1); + glEnd(); + } + + if (overlayTexture) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glBindTexture(GL_TEXTURE_2D, overlayTexture); + glBegin(GL_QUADS); + glTexCoord2f(0, 0); + glVertex2f(-1, -1); + glTexCoord2f(1, 0); + glVertex2f(+1, -1); + glTexCoord2f(1, 1); + glVertex2f(+1, +1); + glTexCoord2f(0, 1); + glVertex2f(-1, +1); + glEnd(); + } + + + glDisable(GL_BLEND); + + glBindTexture(GL_TEXTURE_2D, 0); + glDisable(GL_TEXTURE_2D); + //Q_ASSERT(!glGetError()); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + glEnable(GL_LIGHTING); + glEnable(GL_DEPTH_TEST); + + glFinish(); +} diff --git a/libraries/display-plugins/src/display-plugins/WindowDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/WindowDisplayPlugin.h index 208dc26975..1f4915c7f3 100644 --- a/libraries/display-plugins/src/display-plugins/WindowDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/WindowDisplayPlugin.h @@ -7,9 +7,9 @@ // #pragma once -#include "GlWindowDisplayPlugin.h" +#include "OpenGlDisplayPlugin.h" -class WindowDisplayPlugin : public GlWindowDisplayPlugin { +class WindowDisplayPlugin : public OpenGlDisplayPlugin { Q_OBJECT public: static const QString NAME; @@ -17,5 +17,12 @@ public: WindowDisplayPlugin(); virtual const QString & getName(); -private: + + void display(GLuint sceneTexture, const glm::uvec2& sceneSize, + GLuint overlayTexture, const glm::uvec2& overlaySize); + +protected: + // Called by the activate method to specify the initial + // window geometry flags, etc + virtual void customizeWindow(PluginContainer * container); }; diff --git a/libraries/plugins/src/plugins/PluginContainer.h b/libraries/plugins/src/plugins/PluginContainer.h index d0a21f0cdd..c6463e949f 100644 --- a/libraries/plugins/src/plugins/PluginContainer.h +++ b/libraries/plugins/src/plugins/PluginContainer.h @@ -2,6 +2,10 @@ #include +class QMainWindow; + class PluginContainer { +public: virtual void addMenuItem(const QString& path, std::function onClicked, bool checkable = false, bool checked = false, const QString& groupName = "") = 0; + virtual QMainWindow* getAppMainWindow() = 0; }; diff --git a/libraries/render-utils/src/GlWindow.cpp b/libraries/render-utils/src/GlWindow.cpp index ec294dca5e..406d34318f 100644 --- a/libraries/render-utils/src/GlWindow.cpp +++ b/libraries/render-utils/src/GlWindow.cpp @@ -47,6 +47,9 @@ void GlWindow::makeCurrent() { _logger = new QOpenGLDebugLogger(this); if (_logger->initialize()) { connect(_logger, &QOpenGLDebugLogger::messageLogged, [](const QOpenGLDebugMessage& message) { + if (message.type() == QOpenGLDebugMessage::Type::ErrorType) { + qDebug() << "Error"; + } qDebug() << message; }); _logger->disableMessages(QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::AnyType, QOpenGLDebugMessage::NotificationSeverity); diff --git a/libraries/render-utils/src/OffscreenGlCanvas.cpp b/libraries/render-utils/src/OffscreenGlCanvas.cpp index a3025bc3f6..db4d864e51 100644 --- a/libraries/render-utils/src/OffscreenGlCanvas.cpp +++ b/libraries/render-utils/src/OffscreenGlCanvas.cpp @@ -48,6 +48,9 @@ bool OffscreenGlCanvas::makeCurrent() { _logger = new QOpenGLDebugLogger(this); if (_logger->initialize()) { connect(_logger, &QOpenGLDebugLogger::messageLogged, [](const QOpenGLDebugMessage& message) { + if (message.type() == QOpenGLDebugMessage::Type::ErrorType) { + qDebug() << "Error"; + } qDebug() << message; }); _logger->disableMessages(QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::AnyType, QOpenGLDebugMessage::NotificationSeverity); From a483dd27ba944cf5acd4c3afdd9f7e1a6320f0d7 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 1 Jun 2015 17:31:18 -0700 Subject: [PATCH 018/552] Trying to get widgets / windows working --- cmake/macros/GroupSources.cmake | 16 ++ interface/CMakeLists.txt | 13 - interface/src/Application.cpp | 3 + interface/src/DisplayPlugins.cpp | 12 +- interface/src/ui/ApplicationOverlay.cpp | 2 +- libraries/display-plugins/CMakeLists.txt | 2 + .../OculusWin32DisplayPlugin.h | 33 --- .../{ => display-plugins}/OglplusHelpers.cpp | 0 .../{ => display-plugins}/OglplusHelpers.h | 0 ...playPlugin.cpp => OpenGLDisplayPlugin.cpp} | 125 +++------ .../src/display-plugins/OpenGLDisplayPlugin.h | 52 ++++ .../src/display-plugins/OpenGlDisplayPlugin.h | 61 ----- .../src/display-plugins/Tv3dDisplayPlugin.cpp | 166 ----------- .../src/display-plugins/Tv3dDisplayPlugin.h | 35 --- .../WidgetOpenGLDisplayPlugin.cpp | 108 ++++++++ .../WidgetOpenGLDisplayPlugin.h | 40 +++ .../display-plugins/WindowDisplayPlugin.cpp | 94 ------- .../src/display-plugins/WindowDisplayPlugin.h | 28 -- .../WindowOpenGLDisplayPlugin.cpp | 87 ++++++ .../WindowOpenGLDisplayPlugin.h | 38 +++ .../{ => oculus}/OculusBaseDisplayPlugin.cpp | 20 +- .../{ => oculus}/OculusBaseDisplayPlugin.h | 19 +- .../oculus}/OculusHelpers.h | 1 + .../{ => oculus}/OculusWin32DisplayPlugin.cpp | 259 ++++++++++++------ .../oculus/OculusWin32DisplayPlugin.h | 43 +++ .../stereo/InterleavedStereoDisplayPlugin.cpp | 38 +++ .../stereo/InterleavedStereoDisplayPlugin.h | 26 ++ .../stereo/SideBySideStereoDisplayPlugin.cpp | 108 ++++++++ .../stereo/SideBySideStereoDisplayPlugin.h | 22 ++ .../stereo/StereoDisplayPlugin.cpp | 77 ++++++ .../stereo/StereoDisplayPlugin.h | 26 ++ libraries/render-utils/src/GlWindow.cpp | 10 +- libraries/render-utils/src/GlWindow.h | 5 +- 33 files changed, 954 insertions(+), 615 deletions(-) create mode 100644 cmake/macros/GroupSources.cmake delete mode 100644 libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.h rename libraries/display-plugins/src/{ => display-plugins}/OglplusHelpers.cpp (100%) rename libraries/display-plugins/src/{ => display-plugins}/OglplusHelpers.h (100%) rename libraries/display-plugins/src/display-plugins/{OpenGlDisplayPlugin.cpp => OpenGLDisplayPlugin.cpp} (52%) create mode 100644 libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h delete mode 100644 libraries/display-plugins/src/display-plugins/OpenGlDisplayPlugin.h delete mode 100644 libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.cpp delete mode 100644 libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.h create mode 100644 libraries/display-plugins/src/display-plugins/WidgetOpenGLDisplayPlugin.cpp create mode 100644 libraries/display-plugins/src/display-plugins/WidgetOpenGLDisplayPlugin.h delete mode 100644 libraries/display-plugins/src/display-plugins/WindowDisplayPlugin.cpp delete mode 100644 libraries/display-plugins/src/display-plugins/WindowDisplayPlugin.h create mode 100644 libraries/display-plugins/src/display-plugins/WindowOpenGLDisplayPlugin.cpp create mode 100644 libraries/display-plugins/src/display-plugins/WindowOpenGLDisplayPlugin.h rename libraries/display-plugins/src/display-plugins/{ => oculus}/OculusBaseDisplayPlugin.cpp (70%) rename libraries/display-plugins/src/display-plugins/{ => oculus}/OculusBaseDisplayPlugin.h (57%) rename libraries/display-plugins/src/{ => display-plugins/oculus}/OculusHelpers.h (98%) rename libraries/display-plugins/src/display-plugins/{ => oculus}/OculusWin32DisplayPlugin.cpp (53%) create mode 100644 libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.h create mode 100644 libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.cpp create mode 100644 libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.h create mode 100644 libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.cpp create mode 100644 libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.h create mode 100644 libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.cpp create mode 100644 libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.h diff --git a/cmake/macros/GroupSources.cmake b/cmake/macros/GroupSources.cmake new file mode 100644 index 0000000000..07e46afc94 --- /dev/null +++ b/cmake/macros/GroupSources.cmake @@ -0,0 +1,16 @@ +# +# Distributed under the Apache License, Version 2.0. +# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +# + +macro(GroupSources curdir) + file(GLOB children RELATIVE ${PROJECT_SOURCE_DIR}/${curdir} ${PROJECT_SOURCE_DIR}/${curdir}/*) + foreach(child ${children}) + if(IS_DIRECTORY ${PROJECT_SOURCE_DIR}/${curdir}/${child}) + GroupSources(${curdir}/${child}) + else() + string(REPLACE "/" "\\" groupname ${curdir}) + source_group(${groupname} FILES ${PROJECT_SOURCE_DIR}/${curdir}/${child}) + endif() + endforeach() +endmacro() diff --git a/interface/CMakeLists.txt b/interface/CMakeLists.txt index f68e9dcab2..2f91cf6a68 100644 --- a/interface/CMakeLists.txt +++ b/interface/CMakeLists.txt @@ -36,19 +36,6 @@ endif () configure_file(InterfaceConfig.h.in "${PROJECT_BINARY_DIR}/includes/InterfaceConfig.h") configure_file(InterfaceVersion.h.in "${PROJECT_BINARY_DIR}/includes/InterfaceVersion.h") - -macro(GroupSources curdir) - file(GLOB children RELATIVE ${PROJECT_SOURCE_DIR}/${curdir} ${PROJECT_SOURCE_DIR}/${curdir}/*) - foreach(child ${children}) - if(IS_DIRECTORY ${PROJECT_SOURCE_DIR}/${curdir}/${child}) - GroupSources(${curdir}/${child}) - else() - string(REPLACE "/" "\\" groupname ${curdir}) - source_group(${groupname} FILES ${PROJECT_SOURCE_DIR}/${curdir}/${child}) - endif() - endforeach() -endmacro() - # grab the implementation and header files from src dirs file(GLOB_RECURSE INTERFACE_SRCS "src/*.cpp" "src/*.h") GroupSources("src") diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 44a39d302d..630e3347c9 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -821,6 +821,9 @@ void Application::initializeUi() { } void Application::paintGL() { + if (getCanvasSize() == uvec2(0)) { + return; + } PROFILE_RANGE(__FUNCTION__); auto displayPlugin = getActiveDisplayPlugin(); displayPlugin->preRender(); diff --git a/interface/src/DisplayPlugins.cpp b/interface/src/DisplayPlugins.cpp index 006ca1523d..b1fbca5d6c 100644 --- a/interface/src/DisplayPlugins.cpp +++ b/interface/src/DisplayPlugins.cpp @@ -12,11 +12,12 @@ #include #include -#include -#include +#include +#include +#include #ifdef Q_OS_WIN -#include +#include #else #endif @@ -49,11 +50,12 @@ const DisplayPluginList& getDisplayPlugins() { init = true; DisplayPlugin* PLUGIN_POOL[] = { - new WindowDisplayPlugin(), + new WidgetOpenGLDisplayPlugin(), #ifdef DEBUG new NullDisplayPlugin(), #endif - new Tv3dDisplayPlugin(), + new SideBySideStereoDisplayPlugin(), + new InterleavedStereoDisplayPlugin(), new OculusWin32DisplayPlugin(), nullptr }; diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index b2d2239255..f70e8a10e5 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -196,7 +196,7 @@ void ApplicationOverlay::renderOverlay() { glm::uvec2 size = qApp->getCanvasSize(); if (size == uvec2(0)) { qDebug() << "Bad size from display plugin"; - glm::uvec2 size = qApp->getCanvasSize(); + size = qApp->getCanvasSize(); } if (!_framebufferObject || size != toGlm(_framebufferObject->size())) { diff --git a/libraries/display-plugins/CMakeLists.txt b/libraries/display-plugins/CMakeLists.txt index 98d15a7804..709dd27dc0 100644 --- a/libraries/display-plugins/CMakeLists.txt +++ b/libraries/display-plugins/CMakeLists.txt @@ -7,6 +7,8 @@ setup_hifi_opengl() link_hifi_libraries(shared plugins gpu render-utils) +GroupSources("src/display-plugins") + add_dependency_external_projects(glm) find_package(GLM REQUIRED) target_include_directories(${TARGET_NAME} PUBLIC ${GLM_INCLUDE_DIRS}) diff --git a/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.h deleted file mode 100644 index e0ed684daf..0000000000 --- a/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.h +++ /dev/null @@ -1,33 +0,0 @@ -// -// Created by Bradley Austin Davis on 2015/05/29 -// 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 "OculusBaseDisplayPlugin.h" -#include - -class OffscreenGlCanvas; -class OculusWin32DisplayPlugin : public OculusBaseDisplayPlugin { -public: - virtual bool isSupported(); - virtual const QString & getName(); - - virtual void activate(PluginContainer * container); - virtual void deactivate(); -// virtual QSize getDeviceSize() const final; -// virtual glm::ivec2 getCanvasSize() const final; - - void display(GLuint sceneTexture, const glm::uvec2& sceneSize, - GLuint overlayTexture, const glm::uvec2& overlaySize); - -protected: - virtual void customizeWindow(PluginContainer * container); - virtual void customizeContext(PluginContainer * container); - -private: - static const QString NAME; -}; diff --git a/libraries/display-plugins/src/OglplusHelpers.cpp b/libraries/display-plugins/src/display-plugins/OglplusHelpers.cpp similarity index 100% rename from libraries/display-plugins/src/OglplusHelpers.cpp rename to libraries/display-plugins/src/display-plugins/OglplusHelpers.cpp diff --git a/libraries/display-plugins/src/OglplusHelpers.h b/libraries/display-plugins/src/display-plugins/OglplusHelpers.h similarity index 100% rename from libraries/display-plugins/src/OglplusHelpers.h rename to libraries/display-plugins/src/display-plugins/OglplusHelpers.h diff --git a/libraries/display-plugins/src/display-plugins/OpenGlDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp similarity index 52% rename from libraries/display-plugins/src/display-plugins/OpenGlDisplayPlugin.cpp rename to libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp index 762f4ece8d..15fccf5941 100644 --- a/libraries/display-plugins/src/display-plugins/OpenGlDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.cpp @@ -5,7 +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 "OpenGlDisplayPlugin.h" +#include "OpenGLDisplayPlugin.h" #include #include @@ -19,115 +19,55 @@ #include -OpenGlDisplayPlugin::OpenGlDisplayPlugin() { +OpenGLDisplayPlugin::OpenGLDisplayPlugin() { connect(&_timer, &QTimer::timeout, this, [&] { - if (_window) { - emit requestRender(); - } + emit requestRender(); }); } -OpenGlDisplayPlugin::~OpenGlDisplayPlugin() { +OpenGLDisplayPlugin::~OpenGLDisplayPlugin() { } -QWindow* OpenGlDisplayPlugin::getWindow() const { - return _window; -} - -glm::ivec2 OpenGlDisplayPlugin::getTrueMousePosition() const { - return toGlm(_window->mapFromGlobal(QCursor::pos())); -} - -QSize OpenGlDisplayPlugin::getDeviceSize() const { - return _window->geometry().size() * _window->devicePixelRatio(); -} - -glm::ivec2 OpenGlDisplayPlugin::getCanvasSize() const { - return toGlm(_window->geometry().size()); -} - -bool OpenGlDisplayPlugin::hasFocus() const { - return _window->isActive(); -} - -void OpenGlDisplayPlugin::makeCurrent() { - _window->makeCurrent(); -} - -void OpenGlDisplayPlugin::doneCurrent() { - _window->doneCurrent(); -} - -void OpenGlDisplayPlugin::swapBuffers() { - _window->swapBuffers(); -} - -void OpenGlDisplayPlugin::preDisplay() { +void OpenGLDisplayPlugin::preDisplay() { makeCurrent(); }; -void OpenGlDisplayPlugin::preRender() { +void OpenGLDisplayPlugin::preRender() { // NOOP } -void OpenGlDisplayPlugin::finishFrame() { +void OpenGLDisplayPlugin::finishFrame() { swapBuffers(); doneCurrent(); }; - -void OpenGlDisplayPlugin::activate(PluginContainer * container) { - Q_ASSERT(nullptr == _window); - _window = new GlWindow(QOpenGLContext::currentContext()); - _window->installEventFilter(this); - customizeWindow(container); -// _window->show(); - - makeCurrent(); - customizeContext(container); - - _timer.start(1); -} - -void OpenGlDisplayPlugin::customizeContext(PluginContainer * container) { +void OpenGLDisplayPlugin::customizeContext(PluginContainer * container) { using namespace oglplus; Context::BlendFunc(BlendFunction::SrcAlpha, BlendFunction::OneMinusSrcAlpha); Context::Disable(Capability::Blend); Context::Disable(Capability::DepthTest); Context::Disable(Capability::CullFace); - program = loadDefaultShader(); - plane = loadPlane(program); + _program = loadDefaultShader(); + _plane = loadPlane(_program); Context::ClearColor(0, 0, 0, 1); - crosshairTexture = DependencyManager::get()-> + _crosshairTexture = DependencyManager::get()-> getImageTexture(PathUtils::resourcesPath() + "images/sixense-reticle.png"); } -void OpenGlDisplayPlugin::deactivate() { +void OpenGLDisplayPlugin::activate(PluginContainer * container) { + _timer.start(1); +} + +void OpenGLDisplayPlugin::deactivate() { _timer.stop(); - makeCurrent(); - plane.reset(); - program.reset(); - crosshairTexture.reset(); + Q_ASSERT(0 == glGetError()); + _plane.reset(); + _program.reset(); + _crosshairTexture.reset(); doneCurrent(); - - Q_ASSERT(nullptr != _window); - _window->hide(); - _window->destroy(); - _window->deleteLater(); - _window = nullptr; } -void OpenGlDisplayPlugin::installEventFilter(QObject* filter) { - _window->installEventFilter(filter); -} - -void OpenGlDisplayPlugin::removeEventFilter(QObject* filter) { - _window->removeEventFilter(filter); -} - - - // Pressing Alt (and Meta) key alone activates the menubar because its style inherits the // SHMenuBarAltKeyNavigation from QWindowsStyle. This makes it impossible for a scripts to // receive keyPress events for the Alt (and Meta) key in a reliable manner. @@ -137,7 +77,7 @@ void OpenGlDisplayPlugin::removeEventFilter(QObject* filter) { // http://www.archivum.info/qt-interest@trolltech.com/2006-09/00053/Re-(Qt4)-Alt-key-focus-QMenuBar-(solved).html // Pass input events on to the application -bool OpenGlDisplayPlugin::eventFilter(QObject* receiver, QEvent* event) { +bool OpenGLDisplayPlugin::eventFilter(QObject* receiver, QEvent* event) { switch (event->type()) { case QEvent::MouseButtonPress: case QEvent::MouseButtonRelease: @@ -168,3 +108,26 @@ bool OpenGlDisplayPlugin::eventFilter(QObject* receiver, QEvent* event) { return false; } +void OpenGLDisplayPlugin::display( + GLuint sceneTexture, const glm::uvec2& sceneSize, + GLuint overlayTexture, const glm::uvec2& overlaySize) { + makeCurrent(); + Q_ASSERT(0 == glGetError()); + uvec2 size = toGlm(getDeviceSize()); + using namespace oglplus; + Context::Viewport(size.x, size.y); + glClearColor(0, 1, 1, 1); + Context::Clear().ColorBuffer().DepthBuffer(); + _program->Bind(); + Mat4Uniform(*_program, "ModelView").Set(mat4()); + Mat4Uniform(*_program, "Projection").Set(mat4()); + glBindTexture(GL_TEXTURE_2D, sceneTexture); + _plane->Use(); + _plane->Draw(); + Context::Enable(Capability::Blend); + glBindTexture(GL_TEXTURE_2D, overlayTexture); + _plane->Draw(); + Context::Disable(Capability::Blend); + glBindTexture(GL_TEXTURE_2D, 0); + Q_ASSERT(0 == glGetError()); +} diff --git a/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h new file mode 100644 index 0000000000..e4f709b852 --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/OpenGLDisplayPlugin.h @@ -0,0 +1,52 @@ +// +// Created by Bradley Austin Davis on 2015/05/29 +// 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 "DisplayPlugin.h" +#include "OglplusHelpers.h" + +class GlWindow; +class QOpenGLContext; +class OpenGLDisplayPlugin : public DisplayPlugin { +public: + OpenGLDisplayPlugin(); + virtual ~OpenGLDisplayPlugin(); + virtual void preRender() override; + virtual void preDisplay() override; + virtual void finishFrame() override; + + virtual void activate(PluginContainer * container) override; + virtual void deactivate() override; + + virtual bool eventFilter(QObject* receiver, QEvent* event) override; + + void display( + GLuint sceneTexture, const glm::uvec2& sceneSize, + GLuint overlayTexture, const glm::uvec2& overlaySize) override; + +protected: + + // Needs to be called by the activate method after the GL context has been created to + // initialize OpenGL context settings needed by the plugin + virtual void customizeContext(PluginContainer * container); + + virtual void makeCurrent() = 0; + virtual void doneCurrent() = 0; + virtual void swapBuffers() = 0; + + QTimer _timer; + ProgramPtr _program; + ShapeWrapperPtr _plane; + gpu::TexturePointer _crosshairTexture; +}; + + diff --git a/libraries/display-plugins/src/display-plugins/OpenGlDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/OpenGlDisplayPlugin.h deleted file mode 100644 index 6e284b08bf..0000000000 --- a/libraries/display-plugins/src/display-plugins/OpenGlDisplayPlugin.h +++ /dev/null @@ -1,61 +0,0 @@ -// -// Created by Bradley Austin Davis on 2015/05/29 -// 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 "DisplayPlugin.h" -#include "../OglplusHelpers.h" - -class GlWindow; - -class OpenGlDisplayPlugin : public DisplayPlugin { -public: - OpenGlDisplayPlugin(); - virtual ~OpenGlDisplayPlugin(); - virtual void preRender(); - virtual void preDisplay(); - virtual void finishFrame(); - - virtual void activate(PluginContainer * container); - virtual void deactivate(); - - virtual QSize getDeviceSize() const; - virtual glm::ivec2 getCanvasSize() const; - virtual bool hasFocus() const; - - virtual glm::ivec2 getTrueMousePosition() const; - virtual QWindow* getWindow() const; - virtual bool eventFilter(QObject* receiver, QEvent* event); - virtual void installEventFilter(QObject* filter); - virtual void removeEventFilter(QObject* filter); - - -protected: - // Called by the activate method to specify the initial - // window geometry flags, etc - virtual void customizeWindow(PluginContainer * container) = 0; - - // Needs to be called by the activate method after the GL context has been created to - // initialize OpenGL context settings needed by the plugin - virtual void customizeContext(PluginContainer * container); - - virtual void makeCurrent() final; - virtual void doneCurrent() final; - virtual void swapBuffers() final; - - GlWindow* _window{ nullptr }; - QTimer _timer; - ProgramPtr program; - ShapeWrapperPtr plane; - gpu::TexturePointer crosshairTexture; -}; - - diff --git a/libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.cpp deleted file mode 100644 index 240306e736..0000000000 --- a/libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.cpp +++ /dev/null @@ -1,166 +0,0 @@ -// -// Created by Bradley Austin Davis on 2015/05/29 -// 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 "Tv3dDisplayPlugin.h" - -#include -#include - -#include -#include -#include - -#include - -const QString Tv3dDisplayPlugin::NAME("Tv3dDisplayPlugin"); - -const QString & Tv3dDisplayPlugin::getName() { - return NAME; -} - -Tv3dDisplayPlugin::Tv3dDisplayPlugin() { -} - -bool Tv3dDisplayPlugin::isSupported() const { - // FIXME this should attempt to do a scan for supported 3D output - return true; -} - -void Tv3dDisplayPlugin::customizeWindow(PluginContainer * container) { - _window->setFlags(Qt::FramelessWindowHint); - auto desktop = QApplication::desktop(); - QRect primaryGeometry = desktop->screenGeometry(); - for (int i = 0; i < desktop->screenCount(); ++i) { - QRect geometry = desktop->screen(i)->geometry(); - if (geometry.topLeft() == primaryGeometry.topLeft()) { - continue; - } - float aspect = (float)geometry.width() / (float)geometry.height(); - if (aspect < 1.0f) { - continue; - } - _window->setGeometry(geometry); - break; - } - _window->setCursor(Qt::BlankCursor); - _window->show(); -} - -// FIXME make this into a setting that can be adjusted -const float DEFAULT_IPD = 0.064f; -const float HALF_DEFAULT_IPD = DEFAULT_IPD / 2.0f; - -glm::mat4 Tv3dDisplayPlugin::getProjection(Eye eye, const glm::mat4& baseProjection) const { - // Refer to http://www.nvidia.com/content/gtc-2010/pdfs/2010_gtc2010.pdf on creating - // stereo projection matrices. Do NOT use "toe-in", use translation. - - float nearZ = DEFAULT_NEAR_CLIP; // near clipping plane - float screenZ = 0.25f; // screen projection plane - // FIXME verify this is the right calculation - float frustumshift = HALF_DEFAULT_IPD * nearZ / screenZ; - if (eye == Right) { - frustumshift = -frustumshift; - } - return glm::translate(baseProjection, vec3(frustumshift, 0, 0)); -} - -glm::mat4 Tv3dDisplayPlugin::getModelview(Eye eye, const glm::mat4& baseModelview) const { - float modelviewShift = HALF_DEFAULT_IPD; - if (eye == Left) { - modelviewShift = -modelviewShift; - } - return baseModelview * glm::translate(mat4(), vec3(modelviewShift, 0, 0)); -} - -template -void sbs_for_each_eye(const uvec2& size, F f) { - QRect r(QPoint(0, 0), QSize(size.x / 2, size.y)); - for_each_eye([&](Eye eye) { - oglplus::Context::Viewport(r.x(), r.y(), r.width(), r.height()); - f(eye); - }, [&] { - r.moveLeft(r.width()); - }); -} - -void Tv3dDisplayPlugin::display( - GLuint sceneTexture, const glm::uvec2& sceneSize, - GLuint overlayTexture, const glm::uvec2& overlaySize) { - makeCurrent(); - GLenum err = glGetError(); - uvec2 size = toGlm(getDeviceSize()); - err = glGetError(); - using namespace oglplus; - err = glGetError(); - Context::Viewport(size.x, size.y); - err = glGetError(); - Context::Clear().ColorBuffer().DepthBuffer(); - - Mat4Uniform(*program, "ModelView").Set(mat4()); - Mat4Uniform(*program, "Projection").Set(mat4()); - - glBindTexture(GL_TEXTURE_2D, sceneTexture); - - plane->Draw(); - - // FIXME the - const float screenAspect = aspect(size); - const GLfloat distance = 1.0f; - const GLfloat halfQuadHeight = distance * tan(DEFAULT_FIELD_OF_VIEW_DEGREES); - const GLfloat halfQuadWidth = halfQuadHeight * screenAspect; - const GLfloat quadWidth = halfQuadWidth * 2.0f; - const GLfloat quadHeight = halfQuadHeight * 2.0f; - - vec3 quadSize(quadWidth, quadHeight, 1.0f); - quadSize = vec3(1.0f) / quadSize; - - using namespace oglplus; - Context::Enable(Capability::Blend); - glBindTexture(GL_TEXTURE_2D, overlayTexture); - - mat4 pr = glm::perspective(glm::radians(DEFAULT_FIELD_OF_VIEW_DEGREES), screenAspect, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP); - Mat4Uniform(*program, "Projection").Set(pr); - - // Position the camera relative to the overlay texture - MatrixStack mv; - mv.translate(vec3(0, 0, -distance)).scale(vec3(0.7f, 0.7f / screenAspect, 1.0f)); // .scale(vec3(quadWidth, quadHeight, 1.0)); - sbs_for_each_eye(size, [&](Eye eye) { - mv.withPush([&] { - // translate - mv.top() = getModelview(eye, mv.top()); - Mat4Uniform(*program, "ModelView").Set(mv.top()); - plane->Draw(); - }); - }); - - glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(crosshairTexture)); - glm::vec2 canvasSize = getCanvasSize(); - glm::vec2 mouse = toGlm(_window->mapFromGlobal(QCursor::pos())); - mouse /= canvasSize; - mouse *= 2.0f; - mouse -= 1.0f; - mouse.y *= -1.0f; - sbs_for_each_eye(size, [&](Eye eye) { - mv.withPush([&] { - // translate - mv.top() = getModelview(eye, mv.top()); - mv.translate(mouse); - //mv.scale(0.05f); - mv.scale(vec3(0.025f, 0.05f, 1.0f)); - Mat4Uniform(*program, "ModelView").Set(mv.top()); - plane->Draw(); - }); - }); - Context::Disable(Capability::Blend); -} - - -void Tv3dDisplayPlugin::activate(PluginContainer * container) { - OpenGlDisplayPlugin::activate(container); - // FIXME Add menu items -} diff --git a/libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.h deleted file mode 100644 index 7541b19f23..0000000000 --- a/libraries/display-plugins/src/display-plugins/Tv3dDisplayPlugin.h +++ /dev/null @@ -1,35 +0,0 @@ -// -// Created by Bradley Austin Davis on 2015/05/29 -// 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 "OpenGlDisplayPlugin.h" - -class Tv3dDisplayPlugin : public OpenGlDisplayPlugin { - Q_OBJECT -public: - Tv3dDisplayPlugin(); - virtual const QString & getName(); - virtual bool isStereo() const final { return true; } - virtual bool isSupported() const final; - - virtual void activate(PluginContainer * container); - - void display(GLuint sceneTexture, const glm::uvec2& sceneSize, - GLuint overlayTexture, const glm::uvec2& overlaySize); - - virtual glm::mat4 getProjection(Eye eye, const glm::mat4& baseProjection) const; - virtual glm::mat4 getModelview(Eye eye, const glm::mat4& baseModelview) const; - -protected: - virtual void customizeWindow(PluginContainer * container); - - //virtual std::function getMouseTranslator(); - //virtual glm::ivec2 trueMouseToUiMouse(const glm::ivec2 & position) const; -private: - static const QString NAME; -}; diff --git a/libraries/display-plugins/src/display-plugins/WidgetOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/WidgetOpenGLDisplayPlugin.cpp new file mode 100644 index 0000000000..70627372dc --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/WidgetOpenGLDisplayPlugin.cpp @@ -0,0 +1,108 @@ +// +// Created by Bradley Austin Davis on 2015/05/29 +// 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 "WidgetOpenGLDisplayPlugin.h" + +#include + +#include + +#include +#include +#include +#include +#include +#include "plugins/PluginContainer.h" + +WidgetOpenGLDisplayPlugin::WidgetOpenGLDisplayPlugin() { +} + +const QString WidgetOpenGLDisplayPlugin::NAME("QWindow 2D Renderer"); + +const QString & WidgetOpenGLDisplayPlugin::getName() { + return NAME; +} + +class CustomOpenGLWidget : public QGLWidget { +public: + explicit CustomOpenGLWidget(const QGLFormat& format, QWidget* parent = 0, + const QGLWidget* shareWidget = 0, Qt::WindowFlags f = 0) : QGLWidget(format, parent, shareWidget, f) { + setAutoBufferSwap(false); + } +protected: + + void paintGL() { } + void resizeGL() {} + void initializeGL() {} +}; + +void WidgetOpenGLDisplayPlugin::activate(PluginContainer * container) { + OpenGLDisplayPlugin::activate(container); + + Q_ASSERT(nullptr == _widget); + _widget = new CustomOpenGLWidget(QGL::NoDepthBuffer | QGL::NoStencilBuffer); + QOpenGLContext * sourceContext = QOpenGLContext::currentContext(); + QOpenGLContext * newContext = new QOpenGLContext(); + _widget->setContext( + QGLContext::fromOpenGLContext(newContext), + QGLContext::fromOpenGLContext(sourceContext)); + + QMainWindow* mainWindow = container->getAppMainWindow(); + mainWindow->setCentralWidget(_widget); + + makeCurrent(); + customizeContext(container); + + _widget->installEventFilter(this); +} + +void WidgetOpenGLDisplayPlugin::deactivate() { + OpenGLDisplayPlugin::deactivate(); + _widget->deleteLater(); + _widget = nullptr; +} + +void WidgetOpenGLDisplayPlugin::makeCurrent() { + _widget->makeCurrent(); + +} + +void WidgetOpenGLDisplayPlugin::doneCurrent() { + _widget->doneCurrent(); +} + +void WidgetOpenGLDisplayPlugin::swapBuffers() { + _widget->swapBuffers(); +} + +glm::ivec2 WidgetOpenGLDisplayPlugin::getTrueMousePosition() const { + return toGlm(_widget->mapFromGlobal(QCursor::pos())); +} + +QSize WidgetOpenGLDisplayPlugin::getDeviceSize() const { + return _widget->geometry().size() * _widget->devicePixelRatio(); +} + +glm::ivec2 WidgetOpenGLDisplayPlugin::getCanvasSize() const { + return toGlm(_widget->geometry().size()); +} + +bool WidgetOpenGLDisplayPlugin::hasFocus() const { + return _widget->hasFocus(); +} + +void WidgetOpenGLDisplayPlugin::installEventFilter(QObject* filter) { + _widget->installEventFilter(filter); +} + +void WidgetOpenGLDisplayPlugin::removeEventFilter(QObject* filter) { + _widget->removeEventFilter(filter); +} + +QWindow* WidgetOpenGLDisplayPlugin::getWindow() const { + return _widget->windowHandle(); +} \ No newline at end of file diff --git a/libraries/display-plugins/src/display-plugins/WidgetOpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/WidgetOpenGLDisplayPlugin.h new file mode 100644 index 0000000000..94242cf042 --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/WidgetOpenGLDisplayPlugin.h @@ -0,0 +1,40 @@ +// +// Created by Bradley Austin Davis on 2015/05/29 +// 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 "OpenGLDisplayPlugin.h" + +class QGLWidget; +class QOpenGLDebugLogger; +class WidgetOpenGLDisplayPlugin : public OpenGLDisplayPlugin { + Q_OBJECT +public: + static const QString NAME; + + WidgetOpenGLDisplayPlugin(); + + virtual const QString & getName() override; + virtual glm::ivec2 getTrueMousePosition() const override; + virtual QSize getDeviceSize() const override; + virtual glm::ivec2 getCanvasSize() const override; + virtual bool hasFocus() const override; + virtual QWindow* getWindow() const override; + + virtual void activate(PluginContainer * container) override; + virtual void deactivate() override; + + virtual void installEventFilter(QObject* filter) override; + virtual void removeEventFilter(QObject* filter) override; + +protected: + virtual void makeCurrent() override; + virtual void doneCurrent() override; + virtual void swapBuffers() override; + + QGLWidget* _widget{ nullptr }; +}; diff --git a/libraries/display-plugins/src/display-plugins/WindowDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/WindowDisplayPlugin.cpp deleted file mode 100644 index 0b3c1a8a41..0000000000 --- a/libraries/display-plugins/src/display-plugins/WindowDisplayPlugin.cpp +++ /dev/null @@ -1,94 +0,0 @@ -// -// Created by Bradley Austin Davis on 2015/05/29 -// 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 "WindowDisplayPlugin.h" - -#include - -#include - -#include "plugins/PluginContainer.h" - -WindowDisplayPlugin::WindowDisplayPlugin() { -} - -const QString WindowDisplayPlugin::NAME("QWindow 2D Renderer"); - -const QString & WindowDisplayPlugin::getName() { - return NAME; -} - -void WindowDisplayPlugin::customizeWindow(PluginContainer * container) { - QMainWindow* mainWindow = container->getAppMainWindow(); - QWidget* widget = QWidget::createWindowContainer(_window); - mainWindow->setCentralWidget(widget); -} - -void WindowDisplayPlugin::display( - GLuint sceneTexture, const glm::uvec2& sceneSize, - GLuint overlayTexture, const glm::uvec2& overlaySize) { - glDisable(GL_LIGHTING); - glDisable(GL_DEPTH_TEST); - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - - glClearColor(0, 0, 1, 1); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glEnable(GL_TEXTURE_2D); - - glViewport(0, 0, getDeviceSize().width(), getDeviceSize().height()); - if (sceneTexture) { - glBindTexture(GL_TEXTURE_2D, sceneTexture); - glBegin(GL_QUADS); - glTexCoord2f(0, 0); - glVertex2f(-1, -1); - glTexCoord2f(1, 0); - glVertex2f(+1, -1); - glTexCoord2f(1, 1); - glVertex2f(+1, +1); - glTexCoord2f(0, 1); - glVertex2f(-1, +1); - glEnd(); - } - - if (overlayTexture) { - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glBindTexture(GL_TEXTURE_2D, overlayTexture); - glBegin(GL_QUADS); - glTexCoord2f(0, 0); - glVertex2f(-1, -1); - glTexCoord2f(1, 0); - glVertex2f(+1, -1); - glTexCoord2f(1, 1); - glVertex2f(+1, +1); - glTexCoord2f(0, 1); - glVertex2f(-1, +1); - glEnd(); - } - - - glDisable(GL_BLEND); - - glBindTexture(GL_TEXTURE_2D, 0); - glDisable(GL_TEXTURE_2D); - //Q_ASSERT(!glGetError()); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - - glEnable(GL_LIGHTING); - glEnable(GL_DEPTH_TEST); - - glFinish(); -} diff --git a/libraries/display-plugins/src/display-plugins/WindowDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/WindowDisplayPlugin.h deleted file mode 100644 index 1f4915c7f3..0000000000 --- a/libraries/display-plugins/src/display-plugins/WindowDisplayPlugin.h +++ /dev/null @@ -1,28 +0,0 @@ -// -// Created by Bradley Austin Davis on 2015/05/29 -// 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 "OpenGlDisplayPlugin.h" - -class WindowDisplayPlugin : public OpenGlDisplayPlugin { - Q_OBJECT -public: - static const QString NAME; - - WindowDisplayPlugin(); - - virtual const QString & getName(); - - void display(GLuint sceneTexture, const glm::uvec2& sceneSize, - GLuint overlayTexture, const glm::uvec2& overlaySize); - -protected: - // Called by the activate method to specify the initial - // window geometry flags, etc - virtual void customizeWindow(PluginContainer * container); -}; diff --git a/libraries/display-plugins/src/display-plugins/WindowOpenGLDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/WindowOpenGLDisplayPlugin.cpp new file mode 100644 index 0000000000..7c70c67069 --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/WindowOpenGLDisplayPlugin.cpp @@ -0,0 +1,87 @@ +// +// Created by Bradley Austin Davis on 2015/05/29 +// 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 "WindowOpenGLDisplayPlugin.h" + +#include +#include + +WindowOpenGLDisplayPlugin::WindowOpenGLDisplayPlugin() { +} + +glm::ivec2 WindowOpenGLDisplayPlugin::getTrueMousePosition() const { + return toGlm(_window->mapFromGlobal(QCursor::pos())); +} + +QSize WindowOpenGLDisplayPlugin::getDeviceSize() const { + return _window->geometry().size() * _window->devicePixelRatio(); +} + +glm::ivec2 WindowOpenGLDisplayPlugin::getCanvasSize() const { + return toGlm(_window->geometry().size()); +} + +bool WindowOpenGLDisplayPlugin::hasFocus() const { + return _window->isActive(); +} + +void WindowOpenGLDisplayPlugin::initSurfaceFormat(QSurfaceFormat& format) { + // Qt Quick may need a depth and stencil buffer. Always make sure these are available. + format.setDepthBufferSize(0); + format.setStencilBufferSize(0); + format.setVersion(4, 1); +#ifdef DEBUG + format.setOption(QSurfaceFormat::DebugContext); +#endif + format.setProfile(QSurfaceFormat::OpenGLContextProfile::CoreProfile); +} + +void WindowOpenGLDisplayPlugin::activate(PluginContainer * container) { + OpenGLDisplayPlugin::activate(container); + _window = new GlWindow(QOpenGLContext::currentContext()); + + QSurfaceFormat format; + initSurfaceFormat(format); + _window->setFormat(format); + _window->create(); + _window->installEventFilter(this); + customizeWindow(container); + + makeCurrent(); + customizeContext(container); +} + +void WindowOpenGLDisplayPlugin::deactivate() { + OpenGLDisplayPlugin::deactivate(); + _window->deleteLater(); + _window = nullptr; +} + + +void WindowOpenGLDisplayPlugin::makeCurrent() { + _window->makeCurrent(); +} + +void WindowOpenGLDisplayPlugin::doneCurrent() { + _window->doneCurrent(); +} + +void WindowOpenGLDisplayPlugin::swapBuffers() { + _window->swapBuffers(); +} + +void WindowOpenGLDisplayPlugin::installEventFilter(QObject* filter) { + _window->installEventFilter(filter); +} + +void WindowOpenGLDisplayPlugin::removeEventFilter(QObject* filter) { + _window->removeEventFilter(filter); +} + +QWindow* WindowOpenGLDisplayPlugin::getWindow() const { + return _window; +} \ No newline at end of file diff --git a/libraries/display-plugins/src/display-plugins/WindowOpenGLDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/WindowOpenGLDisplayPlugin.h new file mode 100644 index 0000000000..44d5501d59 --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/WindowOpenGLDisplayPlugin.h @@ -0,0 +1,38 @@ +// +// Created by Bradley Austin Davis on 2015/05/29 +// 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 "OpenGLDisplayPlugin.h" + +class GlWindow; +class QSurfaceFormat; + +class WindowOpenGLDisplayPlugin : public OpenGLDisplayPlugin { + Q_OBJECT +public: + WindowOpenGLDisplayPlugin(); + + virtual glm::ivec2 getTrueMousePosition() const override; + virtual QSize getDeviceSize() const override; + virtual glm::ivec2 getCanvasSize() const override; + virtual bool hasFocus() const override; + virtual QWindow* getWindow() const override; + virtual void activate(PluginContainer * container) override; + virtual void deactivate() override; + virtual void installEventFilter(QObject* filter) override; + virtual void removeEventFilter(QObject* filter) override; + +protected: + virtual void makeCurrent() override; + virtual void doneCurrent() override; + virtual void swapBuffers() override; + virtual void customizeWindow(PluginContainer * container) = 0; + virtual void initSurfaceFormat(QSurfaceFormat& format); + + GlWindow* _window{ nullptr }; +}; diff --git a/libraries/display-plugins/src/display-plugins/OculusBaseDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.cpp similarity index 70% rename from libraries/display-plugins/src/display-plugins/OculusBaseDisplayPlugin.cpp rename to libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.cpp index a92c9ccbe5..91fca03bc8 100644 --- a/libraries/display-plugins/src/display-plugins/OculusBaseDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.cpp @@ -9,13 +9,12 @@ #include -#include "../OculusHelpers.h" +#include "OculusHelpers.h" void OculusBaseDisplayPlugin::activate(PluginContainer * container) { - OpenGlDisplayPlugin::activate(container); glm::uvec2 eyeSizes[2]; ovr_for_each_eye([&](ovrEyeType eye) { - ovrEyeRenderDesc erd = ovrHmd_GetRenderDesc(_hmd, eye, _hmd->MaxEyeFov[eye]); + ovrEyeRenderDesc& erd = _eyeRenderDescs[eye] = ovrHmd_GetRenderDesc(_hmd, eye, _hmd->MaxEyeFov[eye]); ovrMatrix4f ovrPerspectiveProjection = ovrMatrix4f_Projection(erd.Fov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_RightHanded); _eyeProjections[eye] = toGlm(ovrPerspectiveProjection); @@ -23,8 +22,15 @@ void OculusBaseDisplayPlugin::activate(PluginContainer * container) { eyeSizes[eye] = toGlm(ovrHmd_GetFovTextureSize(_hmd, eye, erd.Fov, 1.0f)); }); _desiredFramebufferSize = QSize( - eyeSizes[0].x + eyeSizes[1].x, + eyeSizes[0].x + eyeSizes[1].x, std::max(eyeSizes[0].y, eyeSizes[1].y)); + + if (!OVR_SUCCESS(ovrHmd_ConfigureTracking(_hmd, + ovrTrackingCap_Orientation | ovrTrackingCap_Position | ovrTrackingCap_MagYawCorrection, 0))) { + qFatal("Could not attach to sensor device"); + } + + WidgetOpenGLDisplayPlugin::activate(container); } QSize OculusBaseDisplayPlugin::getRecommendedFramebufferSize() const { @@ -40,5 +46,9 @@ glm::mat4 OculusBaseDisplayPlugin::getProjection(Eye eye, const glm::mat4& baseP } glm::mat4 OculusBaseDisplayPlugin::getModelview(Eye eye, const glm::mat4& baseModelview) const { - return toGlm(_eyePoses[eye]); + return baseModelview * toGlm(_eyePoses[eye]); } + +void OculusBaseDisplayPlugin::resetSensors() { + ovrHmd_RecenterPose(_hmd); +} \ No newline at end of file diff --git a/libraries/display-plugins/src/display-plugins/OculusBaseDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.h similarity index 57% rename from libraries/display-plugins/src/display-plugins/OculusBaseDisplayPlugin.h rename to libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.h index 76612cbaa1..4c299ee729 100644 --- a/libraries/display-plugins/src/display-plugins/OculusBaseDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.h @@ -7,24 +7,25 @@ // #pragma once -#include "OpenGlDisplayPlugin.h" +#include "../WidgetOpenGLDisplayPlugin.h" #include -class OculusBaseDisplayPlugin : public OpenGlDisplayPlugin { +class OculusBaseDisplayPlugin : public WidgetOpenGLDisplayPlugin { public: // Stereo specific methods - virtual bool isHmd() const { return true; } - virtual glm::mat4 getProjection(Eye eye, const glm::mat4& baseProjection) const; - virtual glm::mat4 getModelview(Eye eye, const glm::mat4& baseModelview) const; - virtual void activate(PluginContainer * container); - virtual void preRender(); - virtual QSize getRecommendedFramebufferSize() const; - + 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 activate(PluginContainer * container) override; + virtual void preRender() override; + virtual QSize getRecommendedFramebufferSize() const override; + virtual void resetSensors() override; protected: ovrHmd _hmd; unsigned int _frameIndex{ 0 }; + ovrEyeRenderDesc _eyeRenderDescs[2]; ovrPosef _eyePoses[2]; ovrVector3f _eyeOffsets[2]; glm::mat4 _eyeProjections[2]; diff --git a/libraries/display-plugins/src/OculusHelpers.h b/libraries/display-plugins/src/display-plugins/oculus/OculusHelpers.h similarity index 98% rename from libraries/display-plugins/src/OculusHelpers.h rename to libraries/display-plugins/src/display-plugins/oculus/OculusHelpers.h index acd02e1af9..08c65cc399 100644 --- a/libraries/display-plugins/src/OculusHelpers.h +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusHelpers.h @@ -10,6 +10,7 @@ #include #include #include +#include // Convenience method for looping over each eye with a lambda template diff --git a/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.cpp similarity index 53% rename from libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.cpp rename to libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.cpp index 5c27dc6407..4df454b361 100644 --- a/libraries/display-plugins/src/display-plugins/OculusWin32DisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.cpp @@ -10,68 +10,23 @@ #include #include - +#include #include #include +#include +#include #include #include "plugins/PluginContainer.h" +#include "OculusHelpers.h" + #include "../OglplusHelpers.h" -const QString OculusWin32DisplayPlugin::NAME("Oculus Rift"); +using oglplus::Framebuffer; +using oglplus::DefaultFramebuffer; -const QString & OculusWin32DisplayPlugin::getName() { - return NAME; -} - -bool OculusWin32DisplayPlugin::isSupported() { - if (!OVR_SUCCESS(ovr_Initialize(nullptr))) { - return false; - } - bool result = false; - if (ovrHmd_Detect() > 0) { - result = true; - } - ovr_Shutdown(); - return result; -} - -void OculusWin32DisplayPlugin::activate(PluginContainer * container) { - if (!OVR_SUCCESS(ovr_Initialize(nullptr))) { - Q_ASSERT(false); - qFatal("Failed to Initialize SDK"); - } - if (!OVR_SUCCESS(ovrHmd_Create(0, &_hmd))) { - Q_ASSERT(false); - qFatal("Failed to acquire HMD"); - } - // Parent class relies on our _hmd intialization, so it must come after that. - OculusBaseDisplayPlugin::activate(container); -} - -void OculusWin32DisplayPlugin::customizeWindow(PluginContainer * container) { - container->getAppMainWindow()->setCentralWidget(QWidget::createWindowContainer(_window)); -} - -void OculusWin32DisplayPlugin::customizeContext(PluginContainer * container) { -} - -void OculusWin32DisplayPlugin::deactivate() { - ovrHmd_Destroy(_hmd); - _hmd = nullptr; - ovr_Shutdown(); -} - -void OculusWin32DisplayPlugin::display( - GLuint sceneTexture, const glm::uvec2& sceneSize, - GLuint overlayTexture, const glm::uvec2& overlaySize) { - glClearColor(0, 1, 0, 1); - glClear(GL_COLOR_BUFFER_BIT); -} - -#if 0 // A basic wrapper for constructing a framebuffer with a renderbuffer // for the depth attachment and an undefined type for the color attachement // This allows us to reuse the basic framebuffer code for both the Mirror @@ -81,10 +36,10 @@ void OculusWin32DisplayPlugin::display( // the screen. template struct FramebufferWrapper { - uvec2 size; - oglplus::Framebuffer fbo; + uvec2 size; + Framebuffer fbo; C color{ 0 }; - GLuint depth{ 0 }; + D depth{ 0 }; virtual ~FramebufferWrapper() { } @@ -93,9 +48,6 @@ struct FramebufferWrapper { virtual void Init(const uvec2 & size) { this->size = size; - if (!fbo) { - glGenFramebuffers(1, &fbo); - } initColor(); initDepth(); initDone(); @@ -108,7 +60,7 @@ struct FramebufferWrapper { template void Bound(GLenum target, F f) { - glBindFramebuffer(target, fbo); + glBindFramebuffer(target, oglplus::GetName(fbo)); onBind(target); f(); onUnbind(target); @@ -152,10 +104,11 @@ struct RiftFramebufferWrapper : public FramebufferWrapper { // then submit it and increment to the next texture. // The Oculus SDK manages the creation and destruction of // the textures -struct SwapTextureFramebufferWrapper : public RiftFramebufferWrapper{ - SwapTextureFramebufferWrapper(const ovrHmd & hmd) - : RiftFramebufferWrapper(hmd) {} - ~SwapTextureFramebufferWrapper() { +struct SwapFramebufferWrapper : public RiftFramebufferWrapper { + SwapFramebufferWrapper(const ovrHmd & hmd) + : RiftFramebufferWrapper(hmd) { + } + ~SwapFramebufferWrapper() { if (color) { ovrHmd_DestroySwapTextureSet(hmd, color); color = nullptr; @@ -175,7 +128,7 @@ protected: } if (!OVR_SUCCESS(ovrHmd_CreateSwapTextureSetGL(hmd, GL_RGBA, size.x, size.y, &color))) { - FAIL("Unable to create swap textures"); + qFatal("Unable to create swap textures"); } for (int i = 0; i < color->TextureCount; ++i) { @@ -190,9 +143,9 @@ protected: } virtual void initDone() { - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, oglplus::GetName(fbo)); + glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); } virtual void onBind(GLenum target) { @@ -205,14 +158,14 @@ protected: } }; -using SwapTexFboPtr = std::shared_ptr; // We use a FBO to wrap the mirror texture because it makes it easier to // render to the screen via glBlitFramebuffer -struct MirrorFramebufferWrapper : public RiftFramebufferWrapper{ +struct MirrorFramebufferWrapper : public RiftFramebufferWrapper { float targetAspect; MirrorFramebufferWrapper(const ovrHmd & hmd) - : RiftFramebufferWrapper(hmd) {} + : RiftFramebufferWrapper(hmd) { + } ~MirrorFramebufferWrapper() { if (color) { ovrHmd_DestroyMirrorTexture(hmd, (ovrTexture*)color); @@ -221,13 +174,14 @@ struct MirrorFramebufferWrapper : public RiftFramebufferWrapper{ } void Resize(const uvec2 & size) { - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, oglplus::GetName(fbo)); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); this->size = size; initColor(); initDone(); } + private: virtual void initDepth() { } @@ -238,16 +192,163 @@ private: color = nullptr; } ovrResult result = ovrHmd_CreateMirrorTextureGL(hmd, GL_RGBA, size.x, size.y, (ovrTexture**)&color); - assert(OVR_SUCCESS(result)); + Q_ASSERT(OVR_SUCCESS(result)); } void initDone() { - glBindFramebuffer(GL_FRAMEBUFFER, fbo); - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color->OGL.TexId, 0); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, oglplus::GetName(fbo)); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color->OGL.TexId, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); } }; -using MirrorFboPtr = std::shared_ptr; -#endif \ No newline at end of file +const QString OculusWin32DisplayPlugin::NAME("Oculus Rift"); + +const QString & OculusWin32DisplayPlugin::getName() { + return NAME; +} + +bool OculusWin32DisplayPlugin::isSupported() { + if (!OVR_SUCCESS(ovr_Initialize(nullptr))) { + return false; + } + bool result = false; + if (ovrHmd_Detect() > 0) { + result = true; + } + ovr_Shutdown(); + return result; +} + +void OculusWin32DisplayPlugin::activate(PluginContainer * container) { + if (!OVR_SUCCESS(ovr_Initialize(nullptr))) { + Q_ASSERT(false); + qFatal("Failed to Initialize SDK"); + } + if (!OVR_SUCCESS(ovrHmd_Create(0, &_hmd))) { + Q_ASSERT(false); + qFatal("Failed to acquire HMD"); + } + // Parent class relies on our _hmd intialization, so it must come after that. + OculusBaseDisplayPlugin::activate(container); + _layer.Header.Type = ovrLayerType_EyeFov; + _layer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft; + ovr_for_each_eye([&](ovrEyeType eye) { + ovrFovPort & fov = _layer.Fov[eye] = _eyeRenderDescs[eye].Fov; + ovrSizei & size = _layer.Viewport[eye].Size = ovrHmd_GetFovTextureSize(_hmd, eye, fov, 1.0f); + _layer.Viewport[eye].Pos = { eye == ovrEye_Left ? 0 : size.w, 0 }; + }); +} + +void OculusWin32DisplayPlugin::customizeContext(PluginContainer * container) { + OculusBaseDisplayPlugin::customizeContext(container); + wglSwapIntervalEXT(0); + uvec2 mirrorSize = toGlm(_widget->geometry().size()); + _mirrorFbo = MirrorFboPtr(new MirrorFramebufferWrapper(_hmd)); + _mirrorFbo->Init(mirrorSize); + _swapFbo = SwapFboPtr(new SwapFramebufferWrapper(_hmd)); + uvec2 swapSize = toGlm(getRecommendedFramebufferSize()); + _swapFbo->Init(swapSize); +} + +void OculusWin32DisplayPlugin::deactivate() { + makeCurrent(); + _swapFbo.reset(); + _mirrorFbo.reset(); +// doneCurrent(); + OculusBaseDisplayPlugin::deactivate(); + ovrHmd_Destroy(_hmd); + _hmd = nullptr; + ovr_Shutdown(); +} + +void OculusWin32DisplayPlugin::display( + GLuint sceneTexture, const glm::uvec2& sceneSize, + GLuint overlayTexture, const glm::uvec2& overlaySize) { + using namespace oglplus; + + //Context::Viewport(_mirrorFbo->size.x, _mirrorFbo->size.y); + //glClearColor(0, 0, 1, 1); + //Context::Clear().ColorBuffer().DepthBuffer(); + //_program->Bind(); + //Mat4Uniform(*_program, "ModelView").Set(mat4()); + //Mat4Uniform(*_program, "Projection").Set(mat4()); + //glBindTexture(GL_TEXTURE_2D, sceneTexture); + //_plane->Use(); + //_plane->Draw(); + + _swapFbo->Bound([&] { + Q_ASSERT(0 == glGetError()); + using namespace oglplus; + Context::Viewport(_swapFbo->size.x, _swapFbo->size.y); + glClearColor(0, 0, 1, 1); + Context::Clear().ColorBuffer().DepthBuffer(); + + _program->Bind(); + Mat4Uniform(*_program, "ModelView").Set(mat4()); + Mat4Uniform(*_program, "Projection").Set(mat4()); + glBindTexture(GL_TEXTURE_2D, sceneTexture); + _plane->Use(); + _plane->Draw(); + /* + Context::Enable(Capability::Blend); + glBindTexture(GL_TEXTURE_2D, overlayTexture); + _plane->Draw(); + Context::Disable(Capability::Blend); + */ + glBindTexture(GL_TEXTURE_2D, 0); + Q_ASSERT(0 == glGetError()); + }); + _swapFbo->Bound(GL_READ_FRAMEBUFFER, [&] { + glBlitFramebuffer( + 0, 0, _swapFbo->size.x, _swapFbo->size.y, + 0, 0, _mirrorFbo->size.x, _mirrorFbo->size.y, + GL_COLOR_BUFFER_BIT, GL_NEAREST); + }); + + ovr_for_each_eye([&](ovrEyeType eye){ + _layer.RenderPose[eye] = _eyePoses[eye]; + }); + + _layer.ColorTexture[0] = _swapFbo->color; + _layer.ColorTexture[1] = nullptr; + ovrLayerHeader* layers = &_layer.Header; + ovrResult result = ovrHmd_SubmitFrame(_hmd, _frameIndex, nullptr, &layers, 1); + _swapFbo->Increment(); + wglSwapIntervalEXT(0); + + auto mirrorSize = toGlm(getDeviceSize()); + Context::Viewport(mirrorSize.x, mirrorSize.y); + _mirrorFbo->Bound(GL_READ_FRAMEBUFFER, [&] { + glBlitFramebuffer( + 0, _mirrorFbo->size.y, _mirrorFbo->size.x, 0, + 0, 0, _mirrorFbo->size.x, _mirrorFbo->size.y, + GL_COLOR_BUFFER_BIT, GL_NEAREST); + }); +} + + +// Pressing Alt (and Meta) key alone activates the menubar because its style inherits the +// SHMenuBarAltKeyNavigation from QWindowsStyle. This makes it impossible for a scripts to +// receive keyPress events for the Alt (and Meta) key in a reliable manner. +// +// This filter catches events before QMenuBar can steal the keyboard focus. +// The idea was borrowed from +// http://www.archivum.info/qt-interest@trolltech.com/2006-09/00053/Re-(Qt4)-Alt-key-focus-QMenuBar-(solved).html + +// Pass input events on to the application +bool OculusWin32DisplayPlugin::eventFilter(QObject* receiver, QEvent* event) { + if (event->type() == QEvent::Resize) { + QResizeEvent* resizeEvent = static_cast(event); + qDebug() << resizeEvent->size().width() << " x " << resizeEvent->size().height(); + auto newSize = toGlm(resizeEvent->size()); + makeCurrent(); + _mirrorFbo->Resize(newSize); + doneCurrent(); + } + return OculusBaseDisplayPlugin::eventFilter(receiver, event); +} + +void OculusWin32DisplayPlugin::swapBuffers() { +} \ No newline at end of file diff --git a/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.h b/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.h new file mode 100644 index 0000000000..e86c93af56 --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.h @@ -0,0 +1,43 @@ +// +// Created by Bradley Austin Davis on 2015/05/29 +// 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 "OculusBaseDisplayPlugin.h" + +#include + +class OffscreenGlCanvas; +class MirrorFramebufferWrapper; +class SwapFramebufferWrapper; + +using SwapFboPtr = QSharedPointer; +using MirrorFboPtr = QSharedPointer; + +class OculusWin32DisplayPlugin : public OculusBaseDisplayPlugin { +public: + virtual bool isSupported(); + virtual const QString & getName(); + + virtual void activate(PluginContainer * container) override; + virtual void deactivate() override; + + virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize, + GLuint overlayTexture, const glm::uvec2& overlaySize) override; + + virtual bool eventFilter(QObject* receiver, QEvent* event) override; + +protected: + virtual void customizeContext(PluginContainer * container) override; + virtual void swapBuffers() override; + +private: + static const QString NAME; + SwapFboPtr _swapFbo; + MirrorFboPtr _mirrorFbo; + ovrLayerEyeFov _layer; +}; diff --git a/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.cpp new file mode 100644 index 0000000000..20cfa19e50 --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.cpp @@ -0,0 +1,38 @@ +// +// Created by Bradley Austin Davis on 2015/05/29 +// 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 "InterleavedStereoDisplayPlugin.h" + +#include +#include + +#include +#include +#include + +#include + +const QString InterleavedStereoDisplayPlugin::NAME("Interleaved Stereo Display"); + +const QString & InterleavedStereoDisplayPlugin::getName() { + return NAME; +} + +InterleavedStereoDisplayPlugin::InterleavedStereoDisplayPlugin() { +} + +void InterleavedStereoDisplayPlugin::display( + GLuint sceneTexture, const glm::uvec2& sceneSize, + GLuint overlayTexture, const glm::uvec2& overlaySize) { +} + +void InterleavedStereoDisplayPlugin::customizeContext(PluginContainer * container) { + StereoDisplayPlugin::customizeContext(container); + // Set up the stencil buffers + +} diff --git a/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.h new file mode 100644 index 0000000000..ba7f5f264b --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/stereo/InterleavedStereoDisplayPlugin.h @@ -0,0 +1,26 @@ +// +// Created by Bradley Austin Davis on 2015/05/29 +// 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 "StereoDisplayPlugin.h" + +class InterleavedStereoDisplayPlugin : public StereoDisplayPlugin { + Q_OBJECT +public: + InterleavedStereoDisplayPlugin(); + virtual const QString & getName() override; + + virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize, + GLuint overlayTexture, const glm::uvec2& overlaySize) override; + + // initialize OpenGL context settings needed by the plugin + virtual void customizeContext(PluginContainer * container) override; + +private: + static const QString NAME; +}; diff --git a/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.cpp new file mode 100644 index 0000000000..63ce594df4 --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.cpp @@ -0,0 +1,108 @@ +// +// Created by Bradley Austin Davis on 2015/05/29 +// 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 "SideBySideStereoDisplayPlugin.h" + +#include +#include + +#include +#include +#include + +#include + +const QString SideBySideStereoDisplayPlugin::NAME("SBS Stereo Display"); + +const QString & SideBySideStereoDisplayPlugin::getName() { + return NAME; +} + +SideBySideStereoDisplayPlugin::SideBySideStereoDisplayPlugin() { +} + +template +void sbs_for_each_eye(const uvec2& size, F f) { + QRect r(QPoint(0, 0), QSize(size.x / 2, size.y)); + for_each_eye([&](Eye eye) { + oglplus::Context::Viewport(r.x(), r.y(), r.width(), r.height()); + f(eye); + }, [&] { + r.moveLeft(r.width()); + }); +} + +void SideBySideStereoDisplayPlugin::display( + GLuint sceneTexture, const glm::uvec2& sceneSize, + GLuint overlayTexture, const glm::uvec2& overlaySize) { + makeCurrent(); + Q_ASSERT(0 == glGetError()); + uvec2 size = toGlm(getDeviceSize()); + using namespace oglplus; + Context::Viewport(size.x, size.y); + Context::Clear().ColorBuffer(); + + _program->Bind(); + Mat4Uniform(*_program, "ModelView").Set(mat4()); + Mat4Uniform(*_program, "Projection").Set(mat4()); + + glBindTexture(GL_TEXTURE_2D, sceneTexture); + + _plane->Use(); + _plane->Draw(); + + // FIXME the + const float screenAspect = aspect(size); + const GLfloat distance = 1.0f; + const GLfloat halfQuadHeight = distance * tan(DEFAULT_FIELD_OF_VIEW_DEGREES); + const GLfloat halfQuadWidth = halfQuadHeight * screenAspect; + const GLfloat quadWidth = halfQuadWidth * 2.0f; + const GLfloat quadHeight = halfQuadHeight * 2.0f; + + vec3 quadSize(quadWidth, quadHeight, 1.0f); + quadSize = vec3(1.0f) / quadSize; + + using namespace oglplus; + Context::Enable(Capability::Blend); + glBindTexture(GL_TEXTURE_2D, overlayTexture); + + mat4 pr = glm::perspective(glm::radians(DEFAULT_FIELD_OF_VIEW_DEGREES), screenAspect, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP); + Mat4Uniform(*_program, "Projection").Set(pr); + + // Position the camera relative to the overlay texture + MatrixStack mv; + mv.translate(vec3(0, 0, -distance)).scale(vec3(0.7f, 0.7f / screenAspect, 1.0f)); // .scale(vec3(quadWidth, quadHeight, 1.0)); + sbs_for_each_eye(size, [&](Eye eye) { + mv.withPush([&] { + // translate + mv.top() = getModelview(eye, mv.top()); + Mat4Uniform(*_program, "ModelView").Set(mv.top()); + _plane->Draw(); + }); + }); + + glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_crosshairTexture)); + glm::vec2 canvasSize = getCanvasSize(); + glm::vec2 mouse = toGlm(_window->mapFromGlobal(QCursor::pos())); + mouse /= canvasSize; + mouse *= 2.0f; + mouse -= 1.0f; + mouse.y *= -1.0f; + sbs_for_each_eye(size, [&](Eye eye) { + mv.withPush([&] { + // translate + mv.top() = getModelview(eye, mv.top()); + mv.translate(mouse); + //mv.scale(0.05f); + mv.scale(vec3(0.025f, 0.05f, 1.0f)); + Mat4Uniform(*_program, "ModelView").Set(mv.top()); + _plane->Draw(); + }); + }); + Context::Disable(Capability::Blend); +} diff --git a/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.h new file mode 100644 index 0000000000..4487079387 --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/stereo/SideBySideStereoDisplayPlugin.h @@ -0,0 +1,22 @@ +// +// Created by Bradley Austin Davis on 2015/05/29 +// 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 "StereoDisplayPlugin.h" + +class SideBySideStereoDisplayPlugin : public StereoDisplayPlugin { + Q_OBJECT +public: + SideBySideStereoDisplayPlugin(); + virtual const QString & getName() override; + + void display(GLuint sceneTexture, const glm::uvec2& sceneSize, + GLuint overlayTexture, const glm::uvec2& overlaySize) override; +private: + static const QString NAME; +}; diff --git a/libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.cpp new file mode 100644 index 0000000000..a9faed6a70 --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.cpp @@ -0,0 +1,77 @@ +// +// Created by Bradley Austin Davis on 2015/05/29 +// 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 "StereoDisplayPlugin.h" + +#include +#include + +#include +#include +#include + +#include + +StereoDisplayPlugin::StereoDisplayPlugin() { +} + +bool StereoDisplayPlugin::isSupported() const { + // FIXME this should attempt to do a scan for supported 3D output + return true; +} + +void StereoDisplayPlugin::customizeWindow(PluginContainer * container) { + _window->setFlags(Qt::FramelessWindowHint); + auto desktop = QApplication::desktop(); + QRect primaryGeometry = desktop->screenGeometry(); + for (int i = 0; i < desktop->screenCount(); ++i) { + QRect geometry = desktop->screen(i)->geometry(); + if (geometry.topLeft() == primaryGeometry.topLeft()) { + continue; + } + float aspect = (float)geometry.width() / (float)geometry.height(); + if (aspect < 1.0f) { + continue; + } + _window->setGeometry(geometry); + break; + } + _window->setCursor(Qt::BlankCursor); + _window->show(); +} + +// FIXME make this into a setting that can be adjusted +const float DEFAULT_IPD = 0.064f; +const float HALF_DEFAULT_IPD = DEFAULT_IPD / 2.0f; + +glm::mat4 StereoDisplayPlugin::getProjection(Eye eye, const glm::mat4& baseProjection) const { + // Refer to http://www.nvidia.com/content/gtc-2010/pdfs/2010_gtc2010.pdf on creating + // stereo projection matrices. Do NOT use "toe-in", use translation. + + float nearZ = DEFAULT_NEAR_CLIP; // near clipping plane + float screenZ = 0.25f; // screen projection plane + // FIXME verify this is the right calculation + float frustumshift = HALF_DEFAULT_IPD * nearZ / screenZ; + if (eye == Right) { + frustumshift = -frustumshift; + } + return glm::translate(baseProjection, vec3(frustumshift, 0, 0)); +} + +glm::mat4 StereoDisplayPlugin::getModelview(Eye eye, const glm::mat4& baseModelview) const { + float modelviewShift = HALF_DEFAULT_IPD; + if (eye == Left) { + modelviewShift = -modelviewShift; + } + return baseModelview * glm::translate(mat4(), vec3(modelviewShift, 0, 0)); +} + +void StereoDisplayPlugin::activate(PluginContainer * container) { + WindowOpenGLDisplayPlugin::activate(container); + // FIXME Add menu items +} diff --git a/libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.h new file mode 100644 index 0000000000..b3229eb9f9 --- /dev/null +++ b/libraries/display-plugins/src/display-plugins/stereo/StereoDisplayPlugin.h @@ -0,0 +1,26 @@ +// +// Created by Bradley Austin Davis on 2015/05/29 +// 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 "../WindowOpenGLDisplayPlugin.h" + +class StereoDisplayPlugin : public WindowOpenGLDisplayPlugin { + Q_OBJECT +public: + StereoDisplayPlugin(); + virtual bool isStereo() const override final { return true; } + virtual bool isSupported() const override final; + + virtual void activate(PluginContainer * container) override; + + virtual glm::mat4 getProjection(Eye eye, const glm::mat4& baseProjection) const override; + virtual glm::mat4 getModelview(Eye eye, const glm::mat4& baseModelview) const override; + +protected: + virtual void customizeWindow(PluginContainer * container) override; +}; diff --git a/libraries/render-utils/src/GlWindow.cpp b/libraries/render-utils/src/GlWindow.cpp index 406d34318f..dcba05545f 100644 --- a/libraries/render-utils/src/GlWindow.cpp +++ b/libraries/render-utils/src/GlWindow.cpp @@ -40,8 +40,11 @@ GlWindow::~GlWindow() { } -void GlWindow::makeCurrent() { - _context->makeCurrent(this); +bool GlWindow::makeCurrent() { + bool makeCurrentResult = _context->makeCurrent(this); + Q_ASSERT(makeCurrentResult); + QOpenGLContext * currentContext = QOpenGLContext::currentContext(); + Q_ASSERT(_context == currentContext); #ifdef DEBUG if (!_logger) { _logger = new QOpenGLDebugLogger(this); @@ -52,11 +55,12 @@ void GlWindow::makeCurrent() { } qDebug() << message; }); - _logger->disableMessages(QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::AnyType, QOpenGLDebugMessage::NotificationSeverity); + //_logger->disableMessages(QOpenGLDebugMessage::AnySource, QOpenGLDebugMessage::AnyType, QOpenGLDebugMessage::NotificationSeverity); _logger->startLogging(QOpenGLDebugLogger::LoggingMode::SynchronousLogging); } } #endif + return makeCurrentResult; } void GlWindow::doneCurrent() { diff --git a/libraries/render-utils/src/GlWindow.h b/libraries/render-utils/src/GlWindow.h index 57108c6e37..1272191637 100644 --- a/libraries/render-utils/src/GlWindow.h +++ b/libraries/render-utils/src/GlWindow.h @@ -20,11 +20,12 @@ public: GlWindow(QOpenGLContext* shareContext = nullptr); GlWindow(const QSurfaceFormat& format, QOpenGLContext* shareContext = nullptr); virtual ~GlWindow(); - void makeCurrent(); + bool makeCurrent(); void doneCurrent(); void swapBuffers(); -private: + QOpenGLContext* _context{ nullptr }; +private: #ifdef DEBUG QOpenGLDebugLogger* _logger{ nullptr }; #endif From 5fdf032a65e258d15472a1c5c7e903b41ee9c260 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Mon, 1 Jun 2015 22:59:24 -0700 Subject: [PATCH 019/552] Working on oculus --- .../oculus/OculusWin32DisplayPlugin.cpp | 10 +++++++--- .../display-plugins/oculus/OculusWin32DisplayPlugin.h | 2 ++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.cpp index 4df454b361..ffb3fcb210 100644 --- a/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.cpp @@ -316,8 +316,7 @@ void OculusWin32DisplayPlugin::display( ovrLayerHeader* layers = &_layer.Header; ovrResult result = ovrHmd_SubmitFrame(_hmd, _frameIndex, nullptr, &layers, 1); _swapFbo->Increment(); - wglSwapIntervalEXT(0); - + /* auto mirrorSize = toGlm(getDeviceSize()); Context::Viewport(mirrorSize.x, mirrorSize.y); _mirrorFbo->Bound(GL_READ_FRAMEBUFFER, [&] { @@ -326,6 +325,7 @@ void OculusWin32DisplayPlugin::display( 0, 0, _mirrorFbo->size.x, _mirrorFbo->size.y, GL_COLOR_BUFFER_BIT, GL_NEAREST); }); + */ } @@ -351,4 +351,8 @@ bool OculusWin32DisplayPlugin::eventFilter(QObject* receiver, QEvent* event) { } void OculusWin32DisplayPlugin::swapBuffers() { -} \ No newline at end of file +} + +void OculusWin32DisplayPlugin::finishFrame() { + doneCurrent(); +}; diff --git a/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.h b/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.h index e86c93af56..5cf977f41a 100644 --- a/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.h @@ -34,6 +34,8 @@ public: protected: virtual void customizeContext(PluginContainer * container) override; virtual void swapBuffers() override; + virtual void finishFrame() override; + private: static const QString NAME; From 9d5a462a6371ca1f5e6935748014c7aed2f0f2aa Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 2 Jun 2015 12:18:00 -0700 Subject: [PATCH 020/552] Working on UI in oculus --- interface/src/Application.cpp | 32 ++-- interface/src/ui/ApplicationOverlay.cpp | 172 +----------------- .../src/display-plugins/DisplayPlugin.h | 4 +- .../oculus/OculusBaseDisplayPlugin.cpp | 11 +- .../oculus/OculusBaseDisplayPlugin.h | 4 + .../oculus/OculusWin32DisplayPlugin.cpp | 155 ++++++++++------ .../oculus/OculusWin32DisplayPlugin.h | 13 +- 7 files changed, 148 insertions(+), 243 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6d5f1db30e..8283952fa2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -997,29 +997,33 @@ void Application::resizeEvent(QResizeEvent * event) { } void Application::resizeGL() { + + auto displayPlugin = getActiveDisplayPlugin(); + // Set the desired FBO texture size. If it hasn't changed, this does nothing. // Otherwise, it must rebuild the FBOs QSize framebufferSize = getActiveDisplayPlugin()->getRecommendedFramebufferSize(); QSize renderSize = framebufferSize * getRenderResolutionScale(); + if (_renderResolution != toGlm(renderSize)) { + _renderResolution = toGlm(renderSize); + DependencyManager::get()->setFrameBufferSize(renderSize); - if (_renderResolution == toGlm(renderSize)) { - return; + // Possible change in aspect ratio + _myCamera.setProjection(glm::perspective(glm::radians(_fieldOfView.get()), + aspect(getCanvasSize()), DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)); } - _renderResolution = toGlm(renderSize); - DependencyManager::get()->setFrameBufferSize(renderSize); - - _myCamera.setProjection(glm::perspective(glm::radians(_fieldOfView.get()), - aspect(getCanvasSize()), DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)); - auto offscreenUi = DependencyManager::get(); - offscreenUi->resize(fromGlm(getCanvasSize())); - _offscreenContext->makeCurrent(); + auto uiSize = displayPlugin->getCanvasSize(); + if (offscreenUi->getWindow()->geometry().size() != fromGlm(uiSize)) { + offscreenUi->resize(fromGlm(uiSize)); + _offscreenContext->makeCurrent(); + // update Stats width + // let's set horizontal offset to give stats some margin to mirror + int horizontalOffset = MIRROR_VIEW_WIDTH + MIRROR_VIEW_LEFT_PADDING * 2; + Stats::getInstance()->resetWidth(uiSize.x, horizontalOffset); + } - // update Stats width - // let's set horizontal offset to give stats some margin to mirror - int horizontalOffset = MIRROR_VIEW_WIDTH + MIRROR_VIEW_LEFT_PADDING * 2; - Stats::getInstance()->resetWidth(_renderResolution.x, horizontalOffset); } void Application::controlledBroadcastToNodes(const QByteArray& packet, const NodeSet& destinationNodeTypes) { diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index f70e8a10e5..621c2a5dd7 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -193,12 +193,8 @@ void ApplicationOverlay::renderOverlay() { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "ApplicationOverlay::displayOverlay()"); Overlays& overlays = qApp->getOverlays(); - glm::uvec2 size = qApp->getCanvasSize(); - if (size == uvec2(0)) { - qDebug() << "Bad size from display plugin"; - size = qApp->getCanvasSize(); - } - + uvec2 size = qApp->getCanvasSize(); + Q_ASSERT(size != uvec2(0)); if (!_framebufferObject || size != toGlm(_framebufferObject->size())) { if(_framebufferObject) { delete _framebufferObject; @@ -1074,170 +1070,6 @@ void ApplicationOverlay::renderDomainConnectionStatusBorder() { geometryCache->renderVertices(gpu::LINE_STRIP, _domainStatusBorder); } } -#if 0 -ApplicationOverlay::TexturedHemisphere::TexturedHemisphere() : - _vertices(0), - _indices(0), - _framebufferObject(NULL), - _vbo(0, 0) { -} - -ApplicationOverlay::TexturedHemisphere::~TexturedHemisphere() { - cleanupVBO(); - if (_framebufferObject != NULL) { - delete _framebufferObject; - } -} - -void ApplicationOverlay::TexturedHemisphere::bind() { - _framebufferObject->bind(); -} - -void ApplicationOverlay::TexturedHemisphere::release() { - _framebufferObject->release(); -} - -void ApplicationOverlay::TexturedHemisphere::buildVBO(const float fov, - const float aspectRatio, - const int slices, - const int stacks) { - if (fov >= PI) { - qDebug() << "TexturedHemisphere::buildVBO(): FOV greater or equal than Pi will create issues"; - } - // Cleanup old VBO if necessary - cleanupVBO(); - - //UV mapping source: http://www.mvps.org/directx/articles/spheremap.htm - - // Compute number of vertices needed - _vertices = slices * stacks; - - // Compute vertices positions and texture UV coordinate - TextureVertex* vertexData = new TextureVertex[_vertices]; - TextureVertex* vertexPtr = &vertexData[0]; - for (int i = 0; i < stacks; i++) { - float stacksRatio = (float)i / (float)(stacks - 1); // First stack is 0.0f, last stack is 1.0f - // abs(theta) <= fov / 2.0f - float pitch = -fov * (stacksRatio - 0.5f); - - for (int j = 0; j < slices; j++) { - float slicesRatio = (float)j / (float)(slices - 1); // First slice is 0.0f, last slice is 1.0f - // abs(phi) <= fov * aspectRatio / 2.0f - float yaw = -fov * aspectRatio * (slicesRatio - 0.5f); - - vertexPtr->position = getPoint(yaw, pitch); - vertexPtr->uv.x = slicesRatio; - vertexPtr->uv.y = stacksRatio; - vertexPtr++; - } - } - // Create and write to buffer - glGenBuffers(1, &_vbo.first); - glBindBuffer(GL_ARRAY_BUFFER, _vbo.first); - static const int BYTES_PER_VERTEX = sizeof(TextureVertex); - glBufferData(GL_ARRAY_BUFFER, _vertices * BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW); - delete[] vertexData; - - - // Compute number of indices needed - static const int VERTEX_PER_TRANGLE = 3; - static const int TRIANGLE_PER_RECTANGLE = 2; - int numberOfRectangles = (slices - 1) * (stacks - 1); - _indices = numberOfRectangles * TRIANGLE_PER_RECTANGLE * VERTEX_PER_TRANGLE; - - // Compute indices order - GLushort* indexData = new GLushort[_indices]; - GLushort* indexPtr = indexData; - for (int i = 0; i < stacks - 1; i++) { - for (int j = 0; j < slices - 1; j++) { - GLushort bottomLeftIndex = i * slices + j; - GLushort bottomRightIndex = bottomLeftIndex + 1; - GLushort topLeftIndex = bottomLeftIndex + slices; - GLushort topRightIndex = topLeftIndex + 1; - - *(indexPtr++) = topLeftIndex; - *(indexPtr++) = bottomLeftIndex; - *(indexPtr++) = topRightIndex; - - *(indexPtr++) = topRightIndex; - *(indexPtr++) = bottomLeftIndex; - *(indexPtr++) = bottomRightIndex; - } - } - // Create and write to buffer - glGenBuffers(1, &_vbo.second); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vbo.second); - static const int BYTES_PER_INDEX = sizeof(GLushort); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, _indices * BYTES_PER_INDEX, indexData, GL_STATIC_DRAW); - delete[] indexData; -} - -void ApplicationOverlay::TexturedHemisphere::cleanupVBO() { - if (_vbo.first != 0) { - glDeleteBuffers(1, &_vbo.first); - _vbo.first = 0; - } - if (_vbo.second != 0) { - glDeleteBuffers(1, &_vbo.second); - _vbo.second = 0; - } -} - -void ApplicationOverlay::TexturedHemisphere::buildFramebufferObject() { - auto canvasSize = qApp->getCanvasSize(); - QSize fboSize = QSize(canvasSize.x, canvasSize.y); - if (_framebufferObject != NULL && fboSize == _framebufferObject->size()) { - // Already build - return; - } - - if (_framebufferObject != NULL) { - delete _framebufferObject; - } - - _framebufferObject = new QOpenGLFramebufferObject(fboSize, QOpenGLFramebufferObject::Depth); - glBindTexture(GL_TEXTURE_2D, getTexture()); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER); - GLfloat borderColor[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; - glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor); - glBindTexture(GL_TEXTURE_2D, 0); -} - -//Renders a hemisphere with texture coordinates. -void ApplicationOverlay::TexturedHemisphere::render() { - if (_framebufferObject == NULL || _vbo.first == 0 || _vbo.second == 0) { - qDebug() << "TexturedHemisphere::render(): Incorrect initialisation"; - return; - } - - glBindBuffer(GL_ARRAY_BUFFER, _vbo.first); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _vbo.second); - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - - static const int STRIDE = sizeof(TextureVertex); - static const void* VERTEX_POINTER = 0; - static const void* TEX_COORD_POINTER = (void*)sizeof(glm::vec3); - glVertexPointer(3, GL_FLOAT, STRIDE, VERTEX_POINTER); - glTexCoordPointer(2, GL_FLOAT, STRIDE, TEX_COORD_POINTER); - - glDrawRangeElements(GL_TRIANGLES, 0, _vertices - 1, _indices, GL_UNSIGNED_SHORT, 0); - - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); -} - -GLuint ApplicationOverlay::TexturedHemisphere::getTexture() { - return _framebufferObject->texture(); -} -#endif glm::vec2 ApplicationOverlay::directionToSpherical(const glm::vec3& direction) { glm::vec2 result; diff --git a/libraries/display-plugins/src/display-plugins/DisplayPlugin.h b/libraries/display-plugins/src/display-plugins/DisplayPlugin.h index f8563f4e20..e9a5d4a383 100644 --- a/libraries/display-plugins/src/display-plugins/DisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/DisplayPlugin.h @@ -86,9 +86,11 @@ public: // The size of the rendering surface virtual QSize getDeviceSize() const = 0; // The size of the rendering target (may be larger than the device size due to distortion) - virtual QSize getRecommendedFramebufferSize() const { return getDeviceSize(); }; + virtual QSize getRecommendedFramebufferSize() const { return getDeviceSize(); } + // The size of the window (differs from the framebuffers size in instances like Retina macs) virtual glm::ivec2 getCanvasSize() const = 0; + // The window for the surface, used for event interception. May be null. virtual QWindow* getWindow() const = 0; diff --git a/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.cpp index 91fca03bc8..e7d5055457 100644 --- a/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.cpp @@ -51,4 +51,13 @@ glm::mat4 OculusBaseDisplayPlugin::getModelview(Eye eye, const glm::mat4& baseMo void OculusBaseDisplayPlugin::resetSensors() { ovrHmd_RecenterPose(_hmd); -} \ No newline at end of file +} + +glm::mat4 OculusBaseDisplayPlugin::getEyePose(Eye eye) const { + return toGlm(_eyePoses[eye]); +} + +glm::mat4 OculusBaseDisplayPlugin::getHeadPose() const { + ovrTrackingState state = ovrHmd_GetTrackingState(_hmd, 0.0f); + return toGlm(state.HeadPose.ThePose); +} diff --git a/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.h b/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.h index 4c299ee729..a5b6799f24 100644 --- a/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.h @@ -21,6 +21,10 @@ public: 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: ovrHmd _hmd; unsigned int _frameIndex{ 0 }; diff --git a/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.cpp index ffb3fcb210..16bcc67260 100644 --- a/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.cpp @@ -71,7 +71,7 @@ struct FramebufferWrapper { glViewport(0, 0, size.x, size.y); } -private: +protected: virtual void onBind(GLenum target) {} virtual void onUnbind(GLenum target) {} @@ -97,6 +97,19 @@ template struct RiftFramebufferWrapper : public FramebufferWrapper { ovrHmd hmd; RiftFramebufferWrapper(const ovrHmd & hmd) : hmd(hmd) {}; + + void Resize(const uvec2 & size) { + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, oglplus::GetName(fbo)); + glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + this->size = size; + initColor(); + initDone(); + } + +protected: + virtual void initDepth() override { + } }; // A wrapper for constructing and using a swap texture set, @@ -121,7 +134,7 @@ struct SwapFramebufferWrapper : public RiftFramebufferWrapper { } } - void Resize(const uvec2 & size) { - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, oglplus::GetName(fbo)); - glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - this->size = size; - initColor(); - initDone(); - } - private: - virtual void initDepth() { - } - - void initColor() { + void initColor() override { if (color) { ovrHmd_DestroyMirrorTexture(hmd, (ovrTexture*)color); color = nullptr; @@ -195,7 +193,7 @@ private: Q_ASSERT(OVR_SUCCESS(result)); } - void initDone() { + void initDone() override { glBindFramebuffer(GL_DRAW_FRAMEBUFFER, oglplus::GetName(fbo)); glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color->OGL.TexId, 0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); @@ -221,6 +219,15 @@ bool OculusWin32DisplayPlugin::isSupported() { return result; } +ovrLayerEyeFov& OculusWin32DisplayPlugin::getSceneLayer() { + return _layers[0]->EyeFov; +} + +ovrLayerQuad& OculusWin32DisplayPlugin::getUiLayer() { + return _layers[1]->Quad; +} + + void OculusWin32DisplayPlugin::activate(PluginContainer * container) { if (!OVR_SUCCESS(ovr_Initialize(nullptr))) { Q_ASSERT(false); @@ -231,14 +238,27 @@ void OculusWin32DisplayPlugin::activate(PluginContainer * container) { qFatal("Failed to acquire HMD"); } // Parent class relies on our _hmd intialization, so it must come after that. - OculusBaseDisplayPlugin::activate(container); - _layer.Header.Type = ovrLayerType_EyeFov; - _layer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft; + _layers.push_back(new ovrLayer_Union()); + _layers.push_back(new ovrLayer_Union()); + + ovrLayerEyeFov& sceneLayer = getSceneLayer(); + memset(&sceneLayer, 0, sizeof(ovrLayerEyeFov)); + sceneLayer.Header.Type = ovrLayerType_EyeFov; + sceneLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft; ovr_for_each_eye([&](ovrEyeType eye) { - ovrFovPort & fov = _layer.Fov[eye] = _eyeRenderDescs[eye].Fov; - ovrSizei & size = _layer.Viewport[eye].Size = ovrHmd_GetFovTextureSize(_hmd, eye, fov, 1.0f); - _layer.Viewport[eye].Pos = { eye == ovrEye_Left ? 0 : size.w, 0 }; + ovrFovPort & fov = sceneLayer.Fov[eye] = _eyeRenderDescs[eye].Fov; + ovrSizei & size = sceneLayer.Viewport[eye].Size = ovrHmd_GetFovTextureSize(_hmd, eye, fov, 1.0f); + sceneLayer.Viewport[eye].Pos = { eye == ovrEye_Left ? 0 : size.w, 0 }; }); + + ovrLayerQuad& uiLayer = getUiLayer(); + memset(&uiLayer, 0, sizeof(ovrLayerQuad)); + uiLayer.Header.Type = ovrLayerType_QuadInWorld; + uiLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft | ovrLayerFlag_HighQuality; + uiLayer.QuadPoseCenter.Orientation = { 0, 0, 0, 1 }; + uiLayer.QuadPoseCenter.Position = { 0, 0, -1 }; + + OculusBaseDisplayPlugin::activate(container); } void OculusWin32DisplayPlugin::customizeContext(PluginContainer * container) { @@ -247,14 +267,22 @@ void OculusWin32DisplayPlugin::customizeContext(PluginContainer * container) { uvec2 mirrorSize = toGlm(_widget->geometry().size()); _mirrorFbo = MirrorFboPtr(new MirrorFramebufferWrapper(_hmd)); _mirrorFbo->Init(mirrorSize); - _swapFbo = SwapFboPtr(new SwapFramebufferWrapper(_hmd)); + _sceneFbo = SwapFboPtr(new SwapFramebufferWrapper(_hmd)); uvec2 swapSize = toGlm(getRecommendedFramebufferSize()); - _swapFbo->Init(swapSize); + _sceneFbo->Init(swapSize); + + ovrLayerEyeFov& sceneLayer = getSceneLayer(); + sceneLayer.ColorTexture[0] = _sceneFbo->color; + sceneLayer.ColorTexture[1] = nullptr; + + _uiFbo = SwapFboPtr(new SwapFramebufferWrapper(_hmd)); + _uiFbo->Init(getCanvasSize()); } void OculusWin32DisplayPlugin::deactivate() { makeCurrent(); - _swapFbo.reset(); + _sceneFbo.reset(); + _uiFbo.reset(); _mirrorFbo.reset(); // doneCurrent(); OculusBaseDisplayPlugin::deactivate(); @@ -278,45 +306,66 @@ void OculusWin32DisplayPlugin::display( //_plane->Use(); //_plane->Draw(); - _swapFbo->Bound([&] { + _sceneFbo->Bound([&] { Q_ASSERT(0 == glGetError()); using namespace oglplus; - Context::Viewport(_swapFbo->size.x, _swapFbo->size.y); + Context::Viewport(_sceneFbo->size.x, _sceneFbo->size.y); glClearColor(0, 0, 1, 1); - Context::Clear().ColorBuffer().DepthBuffer(); + Context::Clear().ColorBuffer(); _program->Bind(); - Mat4Uniform(*_program, "ModelView").Set(mat4()); - Mat4Uniform(*_program, "Projection").Set(mat4()); glBindTexture(GL_TEXTURE_2D, sceneTexture); _plane->Use(); _plane->Draw(); - /* - Context::Enable(Capability::Blend); - glBindTexture(GL_TEXTURE_2D, overlayTexture); - _plane->Draw(); - Context::Disable(Capability::Blend); - */ - glBindTexture(GL_TEXTURE_2D, 0); Q_ASSERT(0 == glGetError()); }); - _swapFbo->Bound(GL_READ_FRAMEBUFFER, [&] { - glBlitFramebuffer( - 0, 0, _swapFbo->size.x, _swapFbo->size.y, - 0, 0, _mirrorFbo->size.x, _mirrorFbo->size.y, - GL_COLOR_BUFFER_BIT, GL_NEAREST); + + ovrLayerQuad& uiLayer = _layers[1]->Quad; + if (nullptr == uiLayer.ColorTexture || overlaySize != _uiFbo->size) { + _uiFbo->Resize(overlaySize); + uiLayer.ColorTexture = _uiFbo->color; + uiLayer.Viewport.Size.w = overlaySize.x; + uiLayer.Viewport.Size.h = overlaySize.y; + float overlayAspect = aspect(overlaySize); + uiLayer.QuadSize.x = 1.0f; + uiLayer.QuadSize.y = 1.0f / overlayAspect; + } + + _uiFbo->Bound([&] { + Q_ASSERT(0 == glGetError()); + using namespace oglplus; + Context::Viewport(_uiFbo->size.x, _uiFbo->size.y); + glClearColor(0, 0, 0, 0); + Context::Clear().ColorBuffer(); + + _program->Bind(); + glBindTexture(GL_TEXTURE_2D, overlayTexture); + _plane->Use(); + _plane->Draw(); + Q_ASSERT(0 == glGetError()); }); - ovr_for_each_eye([&](ovrEyeType eye){ - _layer.RenderPose[eye] = _eyePoses[eye]; + ovrLayerEyeFov& sceneLayer = _layers[0]->EyeFov; + ovr_for_each_eye([&](ovrEyeType eye) { + sceneLayer.RenderPose[eye] = _eyePoses[eye]; }); - _layer.ColorTexture[0] = _swapFbo->color; - _layer.ColorTexture[1] = nullptr; - ovrLayerHeader* layers = &_layer.Header; - ovrResult result = ovrHmd_SubmitFrame(_hmd, _frameIndex, nullptr, &layers, 1); - _swapFbo->Increment(); + ovrLayerHeader* layers[2]; + layers[0] = &_layers[0]->Header; + layers[1] = &_layers[1]->Header; + + ovrResult result = ovrHmd_SubmitFrame(_hmd, _frameIndex, nullptr, layers, 2); + _sceneFbo->Increment(); + _uiFbo->Increment(); /* + _swapFbo->Bound(GL_READ_FRAMEBUFFER, [&] { + glBlitFramebuffer( + 0, 0, _swapFbo->size.x, _swapFbo->size.y, + 0, 0, _mirrorFbo->size.x, _mirrorFbo->size.y, + GL_COLOR_BUFFER_BIT, GL_NEAREST); + }); + + auto mirrorSize = toGlm(getDeviceSize()); Context::Viewport(mirrorSize.x, mirrorSize.y); _mirrorFbo->Bound(GL_READ_FRAMEBUFFER, [&] { diff --git a/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.h b/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.h index 5cf977f41a..96845574d5 100644 --- a/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.h @@ -12,8 +12,8 @@ #include class OffscreenGlCanvas; -class MirrorFramebufferWrapper; -class SwapFramebufferWrapper; +struct MirrorFramebufferWrapper; +struct SwapFramebufferWrapper; using SwapFboPtr = QSharedPointer; using MirrorFboPtr = QSharedPointer; @@ -38,8 +38,13 @@ protected: private: + ovrLayerEyeFov& getSceneLayer(); + ovrLayerQuad& getUiLayer(); + static const QString NAME; - SwapFboPtr _swapFbo; + SwapFboPtr _sceneFbo; + SwapFboPtr _uiFbo; MirrorFboPtr _mirrorFbo; - ovrLayerEyeFov _layer; + std::vector _layers; + //ovrLayerEyeFov _layer; }; From 3d5c9151fd61cc5db48a215b2b05d987acf4f6b4 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 3 Jun 2015 00:17:45 -0700 Subject: [PATCH 021/552] Working on oculus overlay --- interface/resources/qml/AddressBarDialog.qml | 10 +- .../src/display-plugins/OglplusHelpers.cpp | 254 ++++++++++++++++-- .../src/display-plugins/OglplusHelpers.h | 5 +- .../oculus/OculusBaseDisplayPlugin.cpp | 4 +- .../oculus/OculusWin32DisplayPlugin.cpp | 168 +++++++----- .../oculus/OculusWin32DisplayPlugin.h | 15 +- 6 files changed, 352 insertions(+), 104 deletions(-) diff --git a/interface/resources/qml/AddressBarDialog.qml b/interface/resources/qml/AddressBarDialog.qml index 3893c26f3c..e03a4b6a80 100644 --- a/interface/resources/qml/AddressBarDialog.qml +++ b/interface/resources/qml/AddressBarDialog.qml @@ -112,6 +112,13 @@ Item { addressLine.forceActiveFocus(); } } + + onParentChanged: { + if (enabled && visible) { + addressLine.forceActiveFocus(); + } + } + Behavior on opacity { // Animate opacity. @@ -134,8 +141,9 @@ Item { if (destroyOnInvisible) { destroy() } + } else { + addressLine.forceActiveFocus(); } - } function reset() { diff --git a/libraries/display-plugins/src/display-plugins/OglplusHelpers.cpp b/libraries/display-plugins/src/display-plugins/OglplusHelpers.cpp index fd9d9500f1..bf5d5f6b8a 100644 --- a/libraries/display-plugins/src/display-plugins/OglplusHelpers.cpp +++ b/libraries/display-plugins/src/display-plugins/OglplusHelpers.cpp @@ -7,6 +7,10 @@ // #include "OglplusHelpers.h" +#include + +using namespace oglplus; +using namespace oglplus::shapes; static const char * SIMPLE_TEXTURED_VS = R"VS(#version 410 core #pragma line __LINE__ @@ -89,34 +93,232 @@ ShapeWrapperPtr loadPlane(ProgramPtr program, float aspect) { ); } - -static const char * QUAD_VS = R"VS(#version 330 - -uniform mat4 Projection = mat4(1); -uniform mat4 ModelView = mat4(1); -uniform vec2 UvMultiplier = vec2(1); - -layout(location = 0) in vec3 Position; -layout(location = 1) in vec2 TexCoord; - -out vec2 vTexCoord; - -void main() { - gl_Position = Projection * ModelView * vec4(Position, 1); - vTexCoord = TexCoord * UvMultiplier; +// Return a point's cartesian coordinates on a sphere from pitch and yaw +static glm::vec3 getPoint(float yaw, float pitch) { + return glm::vec3(glm::cos(-pitch) * (-glm::sin(yaw)), + glm::sin(-pitch), + glm::cos(-pitch) * (-glm::cos(yaw))); } -)VS"; -static const char * QUAD_FS = R"FS(#version 330 -uniform sampler2D sampler; -uniform float Alpha = 1.0; -in vec2 vTexCoord; -out vec4 vFragColor; +class SphereSection : public DrawingInstructionWriter, public DrawMode { +public: + using IndexArray = std::vector; + using PosArray = std::vector; + using TexArray = std::vector; + /// The type of the index container returned by Indices() + // vertex positions + PosArray _pos_data; + // vertex tex coords + TexArray _tex_data; + IndexArray _idx_data; + unsigned int _prim_count{ 0 }; -void main() { - vec4 c = texture(sampler, vTexCoord); - c.a = min(Alpha, c.a); - vFragColor = c; +public: + SphereSection( + const float fov, + const float aspectRatio, + const int slices_, + const int stacks_) { + //UV mapping source: http://www.mvps.org/directx/articles/spheremap.htm + if (fov >= PI) { + qDebug() << "TexturedHemisphere::buildVBO(): FOV greater or equal than Pi will create issues"; + } + + int gridSize = std::max(slices_, stacks_); + int gridSizeLog2 = 1; + while (1 << gridSizeLog2 < gridSize) { + ++gridSizeLog2; + } + gridSize = (1 << gridSizeLog2) + 1; + // Compute number of vertices needed + int vertices = gridSize * gridSize; + _pos_data.resize(vertices * 3); + _tex_data.resize(vertices * 2); + + // Compute vertices positions and texture UV coordinate + for (int y = 0; y <= gridSize; ++y) { + for (int x = 0; x <= gridSize; ++x) { + + } + } + for (int i = 0; i < gridSize; i++) { + float stacksRatio = (float)i / (float)(gridSize - 1); // First stack is 0.0f, last stack is 1.0f + // abs(theta) <= fov / 2.0f + float pitch = -fov * (stacksRatio - 0.5f); + for (int j = 0; j < gridSize; j++) { + float slicesRatio = (float)j / (float)(gridSize - 1); // First slice is 0.0f, last slice is 1.0f + // abs(phi) <= fov * aspectRatio / 2.0f + float yaw = -fov * aspectRatio * (slicesRatio - 0.5f); + int vertex = i * gridSize + j; + int posOffset = vertex * 3; + int texOffset = vertex * 2; + vec3 pos = getPoint(yaw, pitch); + _pos_data[posOffset] = pos.x; + _pos_data[posOffset + 1] = pos.y; + _pos_data[posOffset + 2] = pos.z; + _tex_data[texOffset] = slicesRatio; + _tex_data[texOffset + 1] = stacksRatio; + } + } // done with vertices + + int rowLen = gridSize; + + // gridsize now refers to the triangles, not the vertices, so reduce by one + // or die by fencepost error http://en.wikipedia.org/wiki/Off-by-one_error + --gridSize; + int quads = gridSize * gridSize; + for (int t = 0; t < quads; ++t) { + int x = + ((t & 0x0001) >> 0) | + ((t & 0x0004) >> 1) | + ((t & 0x0010) >> 2) | + ((t & 0x0040) >> 3) | + ((t & 0x0100) >> 4) | + ((t & 0x0400) >> 5) | + ((t & 0x1000) >> 6) | + ((t & 0x4000) >> 7); + int y = + ((t & 0x0002) >> 1) | + ((t & 0x0008) >> 2) | + ((t & 0x0020) >> 3) | + ((t & 0x0080) >> 4) | + ((t & 0x0200) >> 5) | + ((t & 0x0800) >> 6) | + ((t & 0x2000) >> 7) | + ((t & 0x8000) >> 8); + int i = x * (rowLen) + y; + + _idx_data.push_back(i); + _idx_data.push_back(i + 1); + _idx_data.push_back(i + rowLen + 1); + + _idx_data.push_back(i + rowLen + 1); + _idx_data.push_back(i + rowLen); + _idx_data.push_back(i); + } + _prim_count = quads * 2; + } + + /// Returns the winding direction of faces + FaceOrientation FaceWinding(void) const { + return FaceOrientation::CCW; + } + + typedef GLuint(SphereSection::*VertexAttribFunc)(std::vector&) const; + + /// Makes the vertex positions and returns the number of values per vertex + template + GLuint Positions(std::vector& dest) const { + dest.clear(); + dest.insert(dest.begin(), _pos_data.begin(), _pos_data.end()); + return 3; + } + + /// Makes the vertex normals and returns the number of values per vertex + template + GLuint Normals(std::vector& dest) const { + dest.clear(); + return 3; + } + + /// Makes the vertex tangents and returns the number of values per vertex + template + GLuint Tangents(std::vector& dest) const { + dest.clear(); + return 3; + } + + /// Makes the vertex bi-tangents and returns the number of values per vertex + template + GLuint Bitangents(std::vector& dest) const { + dest.clear(); + return 3; + } + + /// Makes the texture coordinates returns the number of values per vertex + template + GLuint TexCoordinates(std::vector& dest) const { + dest.clear(); + dest.insert(dest.begin(), _tex_data.begin(), _tex_data.end()); + return 2; + } + + typedef VertexAttribsInfo< + SphereSection, + std::tuple< + VertexPositionsTag, + VertexNormalsTag, + VertexTangentsTag, + VertexBitangentsTag, + VertexTexCoordinatesTag + > + > VertexAttribs; + + Spheref MakeBoundingSphere(void) const { + GLfloat min_x = _pos_data[3], max_x = _pos_data[3]; + GLfloat min_y = _pos_data[4], max_y = _pos_data[4]; + GLfloat min_z = _pos_data[5], max_z = _pos_data[5]; + for (std::size_t v = 0, vn = _pos_data.size() / 3; v != vn; ++v) { + GLfloat x = _pos_data[v * 3 + 0]; + GLfloat y = _pos_data[v * 3 + 1]; + GLfloat z = _pos_data[v * 3 + 2]; + + if (min_x > x) min_x = x; + if (min_y > y) min_y = y; + if (min_z > z) min_z = z; + if (max_x < x) max_x = x; + if (max_y < y) max_y = y; + if (max_z < z) max_z = z; + } + + Vec3f c( + (min_x + max_x) * 0.5f, + (min_y + max_y) * 0.5f, + (min_z + max_z) * 0.5f + ); + + return Spheref( + c.x(), c.y(), c.z(), + Distance(c, Vec3f(min_x, min_y, min_z)) + ); + } + + /// Queries the bounding sphere coordinates and dimensions + template + void BoundingSphere(oglplus::Sphere& bounding_sphere) const { + bounding_sphere = oglplus::Sphere(MakeBoundingSphere()); + } + + + /// Returns element indices that are used with the drawing instructions + const IndexArray & Indices(Default = Default()) const { + return _idx_data; + } + + /// Returns the instructions for rendering of faces + DrawingInstructions Instructions(PrimitiveType primitive) const { + DrawingInstructions instr = this->MakeInstructions(); + DrawOperation operation; + operation.method = DrawOperation::Method::DrawElements; + operation.mode = primitive; + operation.first = 0; + operation.count = _prim_count * 3; + operation.restart_index = DrawOperation::NoRestartIndex(); + operation.phase = 0; + this->AddInstruction(instr, operation); + return std::move(instr); + } + + /// Returns the instructions for rendering of faces + DrawingInstructions Instructions(Default = Default()) const { + return Instructions(PrimitiveType::Triangles); + } +}; + +ShapeWrapperPtr loadSphereSection(ProgramPtr program, float fov, float aspect, int slices, int stacks) { + using namespace oglplus; + return ShapeWrapperPtr( + new shapes::ShapeWrapper({ "Position", "TexCoord" }, SphereSection(fov, aspect, slices, stacks), *program) + ); } -)FS"; diff --git a/libraries/display-plugins/src/display-plugins/OglplusHelpers.h b/libraries/display-plugins/src/display-plugins/OglplusHelpers.h index ddeff20506..2525280f34 100644 --- a/libraries/display-plugins/src/display-plugins/OglplusHelpers.h +++ b/libraries/display-plugins/src/display-plugins/OglplusHelpers.h @@ -27,6 +27,8 @@ #include #include +#include + typedef std::shared_ptr FramebufferPtr; typedef std::shared_ptr ShapeWrapperPtr; typedef std::shared_ptr BufferPtr; @@ -37,4 +39,5 @@ typedef oglplus::Uniform Mat4Uniform; ProgramPtr loadDefaultShader(); void compileProgram(ProgramPtr & result, const std::string& vs, const std::string& fs); ShapeWrapperPtr loadPlane(ProgramPtr program, float aspect = 1.0f); - +ShapeWrapperPtr loadSphereSection(ProgramPtr program, float fov = PI / 3.0f * 2.0f, float aspect = 16.0f / 9.0f, int slices = 80, int stacks = 80); + diff --git a/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.cpp index e7d5055457..7caa9ecf22 100644 --- a/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusBaseDisplayPlugin.cpp @@ -16,7 +16,7 @@ void OculusBaseDisplayPlugin::activate(PluginContainer * container) { ovr_for_each_eye([&](ovrEyeType eye) { ovrEyeRenderDesc& erd = _eyeRenderDescs[eye] = ovrHmd_GetRenderDesc(_hmd, eye, _hmd->MaxEyeFov[eye]); ovrMatrix4f ovrPerspectiveProjection = - ovrMatrix4f_Projection(erd.Fov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_RightHanded); + ovrMatrix4f_Projection(erd.Fov, 0.1f, DEFAULT_FAR_CLIP, ovrProjection_RightHanded); _eyeProjections[eye] = toGlm(ovrPerspectiveProjection); _eyeOffsets[eye] = erd.HmdToEyeViewOffset; eyeSizes[eye] = toGlm(ovrHmd_GetFovTextureSize(_hmd, eye, erd.Fov, 1.0f)); @@ -29,7 +29,7 @@ void OculusBaseDisplayPlugin::activate(PluginContainer * container) { ovrTrackingCap_Orientation | ovrTrackingCap_Position | ovrTrackingCap_MagYawCorrection, 0))) { qFatal("Could not attach to sensor device"); } - + _frameIndex = 0; WidgetOpenGLDisplayPlugin::activate(container); } diff --git a/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.cpp b/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.cpp index 16bcc67260..e3b162434c 100644 --- a/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.cpp +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.cpp @@ -18,12 +18,20 @@ #include +#include + #include "plugins/PluginContainer.h" #include "OculusHelpers.h" +#include +#include +#include +#include #include "../OglplusHelpers.h" +#define DEFAULT_HMD_UI_ANGULAR_SIZE 72.0f + using oglplus::Framebuffer; using oglplus::DefaultFramebuffer; @@ -220,13 +228,10 @@ bool OculusWin32DisplayPlugin::isSupported() { } ovrLayerEyeFov& OculusWin32DisplayPlugin::getSceneLayer() { - return _layers[0]->EyeFov; -} - -ovrLayerQuad& OculusWin32DisplayPlugin::getUiLayer() { - return _layers[1]->Quad; + return _sceneLayer; } +//static gpu::TexturePointer _texture; void OculusWin32DisplayPlugin::activate(PluginContainer * container) { if (!OVR_SUCCESS(ovr_Initialize(nullptr))) { @@ -238,9 +243,6 @@ void OculusWin32DisplayPlugin::activate(PluginContainer * container) { qFatal("Failed to acquire HMD"); } // Parent class relies on our _hmd intialization, so it must come after that. - _layers.push_back(new ovrLayer_Union()); - _layers.push_back(new ovrLayer_Union()); - ovrLayerEyeFov& sceneLayer = getSceneLayer(); memset(&sceneLayer, 0, sizeof(ovrLayerEyeFov)); sceneLayer.Header.Type = ovrLayerType_EyeFov; @@ -251,41 +253,50 @@ void OculusWin32DisplayPlugin::activate(PluginContainer * container) { sceneLayer.Viewport[eye].Pos = { eye == ovrEye_Left ? 0 : size.w, 0 }; }); - ovrLayerQuad& uiLayer = getUiLayer(); - memset(&uiLayer, 0, sizeof(ovrLayerQuad)); - uiLayer.Header.Type = ovrLayerType_QuadInWorld; - uiLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft | ovrLayerFlag_HighQuality; - uiLayer.QuadPoseCenter.Orientation = { 0, 0, 0, 1 }; - uiLayer.QuadPoseCenter.Position = { 0, 0, -1 }; + //ovrLayerQuad& uiLayer = getUiLayer(); + //memset(&uiLayer, 0, sizeof(ovrLayerQuad)); + //uiLayer.Header.Type = ovrLayerType_QuadInWorld; + //uiLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft | ovrLayerFlag_HighQuality; + //uiLayer.QuadPoseCenter.Orientation = { 0, 0, 0, 1 }; + //uiLayer.QuadPoseCenter.Position = { 0, 0, -1 }; OculusBaseDisplayPlugin::activate(container); } void OculusWin32DisplayPlugin::customizeContext(PluginContainer * container) { OculusBaseDisplayPlugin::customizeContext(container); - wglSwapIntervalEXT(0); + + //_texture = DependencyManager::get()-> + // getImageTexture(PathUtils::resourcesPath() + "/images/cube_texture.png"); + + _uiSurface = loadSphereSection(_program, glm::radians(DEFAULT_HMD_UI_ANGULAR_SIZE), aspect(getCanvasSize())); + uvec2 mirrorSize = toGlm(_widget->geometry().size()); _mirrorFbo = MirrorFboPtr(new MirrorFramebufferWrapper(_hmd)); _mirrorFbo->Init(mirrorSize); - _sceneFbo = SwapFboPtr(new SwapFramebufferWrapper(_hmd)); + + uvec2 swapSize = toGlm(getRecommendedFramebufferSize()); + _sceneFbo = SwapFboPtr(new SwapFramebufferWrapper(_hmd)); _sceneFbo->Init(swapSize); + // We're rendering both eyes to the same texture, so only one of the + // pointers is populated ovrLayerEyeFov& sceneLayer = getSceneLayer(); sceneLayer.ColorTexture[0] = _sceneFbo->color; + // not needed since the structure was zeroed on init, but explicit sceneLayer.ColorTexture[1] = nullptr; - - _uiFbo = SwapFboPtr(new SwapFramebufferWrapper(_hmd)); - _uiFbo->Init(getCanvasSize()); } void OculusWin32DisplayPlugin::deactivate() { makeCurrent(); _sceneFbo.reset(); - _uiFbo.reset(); _mirrorFbo.reset(); -// doneCurrent(); + _uiSurface.reset(); + doneCurrent(); + OculusBaseDisplayPlugin::deactivate(); + ovrHmd_Destroy(_hmd); _hmd = nullptr; ovr_Shutdown(); @@ -295,32 +306,45 @@ void OculusWin32DisplayPlugin::display( GLuint sceneTexture, const glm::uvec2& sceneSize, GLuint overlayTexture, const glm::uvec2& overlaySize) { using namespace oglplus; + bool wasActive = PerformanceTimer::isActive(); + PerformanceTimer::setActive(true); + PerformanceTimer("OculusDisplayAndSwap"); + + wglSwapIntervalEXT(0); - //Context::Viewport(_mirrorFbo->size.x, _mirrorFbo->size.y); - //glClearColor(0, 0, 1, 1); - //Context::Clear().ColorBuffer().DepthBuffer(); - //_program->Bind(); - //Mat4Uniform(*_program, "ModelView").Set(mat4()); - //Mat4Uniform(*_program, "Projection").Set(mat4()); - //glBindTexture(GL_TEXTURE_2D, sceneTexture); - //_plane->Use(); - //_plane->Draw(); + { + } _sceneFbo->Bound([&] { - Q_ASSERT(0 == glGetError()); - using namespace oglplus; - Context::Viewport(_sceneFbo->size.x, _sceneFbo->size.y); - glClearColor(0, 0, 1, 1); + auto size = _sceneFbo->size; + Context::Viewport(size.x, size.y); + + glClearColor(0, 0, 0, 0); Context::Clear().ColorBuffer(); _program->Bind(); + Mat4Uniform(*_program, "Projection").Set(mat4()); + Mat4Uniform(*_program, "ModelView").Set(mat4()); glBindTexture(GL_TEXTURE_2D, sceneTexture); _plane->Use(); _plane->Draw(); - Q_ASSERT(0 == glGetError()); + + + Context::Enable(Capability::Blend); + glBindTexture(GL_TEXTURE_2D, overlayTexture); + //glBindTexture(GL_TEXTURE_2D, gpu::GLBackend::getTextureID(_texture)); + for_each_eye([&](Eye eye) { + Context::Viewport(eye == Left ? 0 : size.x / 2, 0, size.x / 2, size.y); + Mat4Uniform(*_program, "Projection").Set(getProjection(eye, mat4())); + Mat4Uniform(*_program, "ModelView").Set(glm::scale(glm::inverse(getModelview(eye, mat4())), vec3(1))); + _uiSurface->Use(); + _uiSurface->Draw(); + }); + Context::Disable(Capability::Blend); }); - ovrLayerQuad& uiLayer = _layers[1]->Quad; + /* + ovrLayerQuad& uiLayer = getUiLayer(); if (nullptr == uiLayer.ColorTexture || overlaySize != _uiFbo->size) { _uiFbo->Resize(overlaySize); uiLayer.ColorTexture = _uiFbo->color; @@ -344,48 +368,62 @@ void OculusWin32DisplayPlugin::display( _plane->Draw(); Q_ASSERT(0 == glGetError()); }); + */ - ovrLayerEyeFov& sceneLayer = _layers[0]->EyeFov; + ovrLayerEyeFov& sceneLayer = getSceneLayer(); ovr_for_each_eye([&](ovrEyeType eye) { sceneLayer.RenderPose[eye] = _eyePoses[eye]; }); - ovrLayerHeader* layers[2]; - layers[0] = &_layers[0]->Header; - layers[1] = &_layers[1]->Header; - ovrResult result = ovrHmd_SubmitFrame(_hmd, _frameIndex, nullptr, layers, 2); + auto windowSize = toGlm(getDeviceSize()); + + /* + Two alternatives for mirroring to the screen, the first is to copy our own composited + scene to the window framebuffer, before distortion. Note this only works if we're doing + ui compositing ourselves, and not relying on the Oculus SDK compositor (or we don't want + the UI visible in the output window (unlikely). This should be done before + */ + // _sceneFbo->Increment or we're be using the wrong texture + //_sceneFbo->Bound(GL_READ_FRAMEBUFFER, [&] { + // glBlitFramebuffer( + // 0, 0, _sceneFbo->size.x, _sceneFbo->size.y, + // 0, 0, windowSize.x, _mirrorFbo.y, + // GL_COLOR_BUFFER_BIT, GL_NEAREST); + //}); + + { + PerformanceTimer("OculusSubmit"); + ovrLayerHeader* layers = &sceneLayer.Header; + ovrResult result = ovrHmd_SubmitFrame(_hmd, _frameIndex, nullptr, &layers, 1); + } _sceneFbo->Increment(); - _uiFbo->Increment(); - /* - _swapFbo->Bound(GL_READ_FRAMEBUFFER, [&] { - glBlitFramebuffer( - 0, 0, _swapFbo->size.x, _swapFbo->size.y, - 0, 0, _mirrorFbo->size.x, _mirrorFbo->size.y, - GL_COLOR_BUFFER_BIT, GL_NEAREST); - }); - - auto mirrorSize = toGlm(getDeviceSize()); - Context::Viewport(mirrorSize.x, mirrorSize.y); + /* + The other alternative for mirroring is to use the Oculus mirror texture support, which + will contain the post-distorted and fully composited scene regardless of how many layers + we send. + */ + auto mirrorSize = _mirrorFbo->size; _mirrorFbo->Bound(GL_READ_FRAMEBUFFER, [&] { glBlitFramebuffer( - 0, _mirrorFbo->size.y, _mirrorFbo->size.x, 0, - 0, 0, _mirrorFbo->size.x, _mirrorFbo->size.y, + 0, mirrorSize.y, mirrorSize.x, 0, + 0, 0, windowSize.x, windowSize.y, GL_COLOR_BUFFER_BIT, GL_NEAREST); }); - */ + + ++_frameIndex; +// swapBuffers(); + PerformanceTimer::setActive(wasActive); + if (0 == (_frameIndex % (75 * 5))) { + auto record1 = PerformanceTimer::getTimerRecord("OculusDisplayAndSwap"); + auto record2 = PerformanceTimer::getTimerRecord("OculusSubmit"); + qDebug() << "Average display and submit: " << record1.getAverage(); + qDebug() << "Average submit: " << record2.getAverage(); + qDebug() << "Diff " << record1.getAverage() - record2.getAverage(); + } } - -// Pressing Alt (and Meta) key alone activates the menubar because its style inherits the -// SHMenuBarAltKeyNavigation from QWindowsStyle. This makes it impossible for a scripts to -// receive keyPress events for the Alt (and Meta) key in a reliable manner. -// -// This filter catches events before QMenuBar can steal the keyboard focus. -// The idea was borrowed from -// http://www.archivum.info/qt-interest@trolltech.com/2006-09/00053/Re-(Qt4)-Alt-key-focus-QMenuBar-(solved).html - // Pass input events on to the application bool OculusWin32DisplayPlugin::eventFilter(QObject* receiver, QEvent* event) { if (event->type() == QEvent::Resize) { @@ -399,8 +437,6 @@ bool OculusWin32DisplayPlugin::eventFilter(QObject* receiver, QEvent* event) { return OculusBaseDisplayPlugin::eventFilter(receiver, event); } -void OculusWin32DisplayPlugin::swapBuffers() { -} void OculusWin32DisplayPlugin::finishFrame() { doneCurrent(); diff --git a/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.h b/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.h index 96845574d5..7e8b16e0b5 100644 --- a/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.h +++ b/libraries/display-plugins/src/display-plugins/oculus/OculusWin32DisplayPlugin.h @@ -12,8 +12,8 @@ #include class OffscreenGlCanvas; -struct MirrorFramebufferWrapper; struct SwapFramebufferWrapper; +struct MirrorFramebufferWrapper; using SwapFboPtr = QSharedPointer; using MirrorFboPtr = QSharedPointer; @@ -33,18 +33,17 @@ public: protected: virtual void customizeContext(PluginContainer * container) override; - virtual void swapBuffers() override; + // Do not perform swap in finish virtual void finishFrame() override; - private: - ovrLayerEyeFov& getSceneLayer(); - ovrLayerQuad& getUiLayer(); static const QString NAME; + + ovrLayerEyeFov& getSceneLayer(); + SwapFboPtr _sceneFbo; - SwapFboPtr _uiFbo; MirrorFboPtr _mirrorFbo; - std::vector _layers; - //ovrLayerEyeFov _layer; + ovrLayerEyeFov _sceneLayer; + ShapeWrapperPtr _uiSurface; }; From 17ebcdd1be91291b3871c2a9a8a0e5995adffc4d Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 3 Jun 2015 17:15:00 -0700 Subject: [PATCH 022/552] Working on display plugins --- interface/resources/images/cube_texture.png | Bin 0 -> 2986055 bytes interface/src/DisplayPlugins.cpp | 4 +- interface/src/ui/ApplicationOverlay.cpp | 2 +- .../Basic2DWindowOpenGLDisplayPlugin.cpp | 14 ++ .../Basic2DWindowOpenGLDisplayPlugin.h | 20 +++ .../src/display-plugins/HmdHelper.cpp | 0 .../src/display-plugins/HmdHelper.h | 0 .../MainWindowOpenGLDisplayPlugin.cpp | 38 +++++ .../MainWindowOpenGLDisplayPlugin.h | 25 ++++ .../src/display-plugins/OglplusHelpers.h | 108 ++++++++++++++- .../WidgetOpenGLDisplayPlugin.cpp | 2 +- .../WindowOpenGLDisplayPlugin.cpp | 5 +- .../oculus/OculusBaseDisplayPlugin.cpp | 9 +- .../oculus/OculusBaseDisplayPlugin.h | 7 +- .../oculus/OculusWin32DisplayPlugin.cpp | 131 +++++------------- .../stereo/InterleavedStereoDisplayPlugin.cpp | 2 +- 16 files changed, 259 insertions(+), 108 deletions(-) create mode 100644 interface/resources/images/cube_texture.png create mode 100644 libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.cpp create mode 100644 libraries/display-plugins/src/display-plugins/Basic2DWindowOpenGLDisplayPlugin.h create mode 100644 libraries/display-plugins/src/display-plugins/HmdHelper.cpp create mode 100644 libraries/display-plugins/src/display-plugins/HmdHelper.h create mode 100644 libraries/display-plugins/src/display-plugins/MainWindowOpenGLDisplayPlugin.cpp create mode 100644 libraries/display-plugins/src/display-plugins/MainWindowOpenGLDisplayPlugin.h diff --git a/interface/resources/images/cube_texture.png b/interface/resources/images/cube_texture.png new file mode 100644 index 0000000000000000000000000000000000000000..ed65d8d6cbefc98bc89319eb4879bb183c14e133 GIT binary patch literal 2986055 zcmd42WmFv9w)fjWaCZyA-62SVySqzhTmpnZaBDocYp|d}5}X8StZ_+jcXw!98t6No zeGboi&%5_I`;7bPeyCBSXH~79^S5TLvDUxliqce9z{a4!0002kN{X`D000``uLBJc z004;f%Gv<{0Q8TFMxOuxoSwf9gfw;>N&oaL_Fhq{7ELCQ_u9qq3650jjsyOf8! zy^9;5ylO-d003b9Wswk`*}%f>gTn_qKquwS=V#Y+Ts+*YYyemA(8K53WL%t`Z9cdIu1C^40002W zUytfKxI5VZ%1$Pj0RRMmlB|@jH^R}Q!_Obf>C-pJECW(B7HAyg*|H232)!SPP5BMF z1iq4N8S{9>otGo8AUiz{?`Qf;MS3;C`wqAarpX{RN&bmk7zFu|IG<%MGI{OeRt=|mRZ9Set{GGZ%(%no$mmq)c>~Kzy4Z+2GI)v zibQgy{q}!oI2O3L^vvRK2Tl;zeE)a;AmBG)22t0PWla2U!u?1Jm__ zz(bH+Tk5}M@|V}GfTmY}d;dQ@5h(draHt#yCGP*+J6b4g)6Xpax%-xoJFouP`Y*Zy zibVI36d+-)#a;4my7NC=<^oiq{!c#teT^C~xD{}V5aY{A_3skvFN$6WAI1I`IrtIn zA?UB*a1Eza_Ww>o=d)OwXBPj*gMW&r2{Y*MpRNC@D^O+ExB!8jg=WhCs|0ulFva~B zZ2vi)|6Q8@?a}|2)W&^t6Yy5I2llHU(mKvvo_=@SwRPOwJk?5E z_dnfI!#CldPltCp9=PGd@QsdJ?x#KK$0GP0=qVq*F7fagzDE5J3R=T`K(Oq1I_!9A z1>O9rjD-L7U`GJBXW^Lz{09EC`m_jAc?3RIg08rqdOL1+;Sc%nQTPS?LE=#ZJ_(1x z?y2GZ@H1-oCg?%qX;9*flk*zhlYdJHI){D1WZ+gi!6#eHThJpAJ}U>) zfbUEEUX!?QfBGv5EETEv*azy4>XB#?imwAS!FZVh>$OZaBy)GDe?^E3?}pO^tSLe} z?yH|F;rAU+)nepC1yJwQhW;RX8eJt-(N1CdDtrD{ zJEMpS@N?jk%6{TEF3cAAGU#TtmR__A4s7QpvEC{wOXc=38Zf9W2B4lzK7s;)A^6Nc zByM(}US3H&euKY0?ZtgjwOMAXu%*_a|C;W zVDq;xP!O~p8#}INb=BHUH4zXWq(~7z!e-(3z+GuN)5M!gGYt4K2)3FoPOAJ}9#6+~ z5}WHh!w)&!iEqV39~l>;p}%P91b4KG&qxSgxK@##uLt$T^ijBD|Zq9UGXydt;im8{!%=O8ZKwxG_}vX2#bveJn7B6L2q z#zPpz7}{&n255uY$T}$0te2JPH&Xd#x48Wm}54!diQAug3s3*$7mNYTvX$_ygJL^ytzh=o> z05;9LH;DE8FN7;>vuIcqqi6nb1tKp=h%v>tEM%cs=)i?Vw;g-Dt)=RyKii>^O4{Lj zJ(|?;FUb#H77!Wkub{mo?8c#I7L1D>1tCZI;~S}0Pe8PEP6YnLHh|%6CFrU;`flc5kE~E6dT6~V zz+C=;;dIwi!W%{od-wJ747nj;{4y};*Byoz$wY2r8M!E=)o_pAB3rdLl*SZ#RE__g z#W9a1RLoU%4%>48#KCQs@49+F;7w~2%-W!ZiER-VOy>|)5U2Vh*7~!W3sgU=P?73l zS~}H`ES-$ek`tx=jiVNAUSu|TK_#6%O_NVwP)$VUAyWiTXs^ER_8ucS*7y|udzxr1 zZF^v&t%4}AJGl))zk-(E+7y%<%M&{^JZeblGLa*83@34Futw8MD}(*?-QzQhNEAZA z`@!=ciHhe>2hq{j?T=8T!- zm^DsuVJHte^GkWU|Ahl<>&Pe+Ivk9x2f|ZERoEOE`aryRt04}16eFfJthwm{^h)0w zeOwAJ&c#=wKIESz>~h!h*VpTWVRph2&@P^aI&?<0&@MT+*-|vTdGu-Kq{-|Z&N8EU zq%}O)QkZp!$NA-qUvAUE24}Gh^T=`8?{+Dit?RCZ7GItH}|}duEYC zZ(ObXNh(9~8v;Try%vY*+?;bc8{UHHC9aoCz}^ zq2wnGYag=6>%F?2*B>(tT_+#ZGbR~XruN@Db5Kk1UO~+2h%FC(KiS(WQ~~^lxsAb% zYa(GlOp9rs-bPTK;T|^20Ra}R-0}nov}Td zjcxj(3YwxZ^KW`)?&MwL^-MM2%f}b7l<8~Uvq|y#GYrs_<^`;>VbF))Ea;x3sZx?< zRrERKK72`YVdZzE_eQ9pkv9JI_ayGWPNAqNgY(Td5tTEZSuDbDn2)}>ORU58sdQ>Y zg0ikcyUPn<89w)+0xv24 zCowDeqx!7exnK5PBPv_D8MmZPDp*cSWr-WT^7tgh%<>V9?&MKjQBU=xdEc!7^sz^F z^_unjjKLvN-n2S&FT{>(%~jhP%x6}>b7$jzf#Zx;Cz|G+3FyhBbWGPjM1nR7OhSyH z#N^+}-(lfn^z}vez}KFlX)&)udZ^{_`&!4(V{)u6Ew2Zm5WoG4yhC?-46)g)Wtm7R z53&S8P(ciUSdddg9sLu9Be?*sVRV<-vHu7?G3Kf)Ulx4}>NATpNgZYHgJ_4eO)h|w zcND`_*e5pS^3nyr0cazJZwCSMXpB6cTAX~))EnOVc1ERP9XdIIH1L!$-FKF8PjtI{ zaMqBV&c%;<(BmwtFP|CehxTOd3Iq17tS`lnVO~N0s=sbd?|5px>Sc<48(Ej+2oS9cYZ0~z2DSeCtfF>U|$8Z zbCH`FyE{ZVvrWHVXs9Y;L2+JE)mm~VGGx0lQLP-uW4K!oe`_vxk z@mro;Ylf+Rb7un};wR6_xZ26O)rO}6MjSaR(GzesRI~qlk-6V^;=B3 zPK)$!EB{|IlA`Wb(DFs@c}x8!Wl;~~KT4I|sClgbZzMc$r&*YYRZNbr?9U~ee(tBY zGf&u?;U~=9kr)Z6863-zS7%pjhQw2HqF2NW9s|mn@>!7CVNBBoGM{;P?g*8zO~3iO z3Q*@_!H_iiwcq`EZ9=F#imH#%f1C$QXfp(bch7uYP(Pybd;g`qn{P^QlHM1l$s%0VJ76VDe9-+1I%(a8Fbk zEW>q6C@Zz;x``Ue9COf)47%Jy@1qZ2$Vjv`GvOlH4??CXxd9ahab-nEt?&1UV^+Ls zkQg|@HJ-OelGHqre-L%#G)lw#`k=G zk<>e>-A==%t5I558?9EWU49Ys(Rez(k?d_WZ?CQ{&@Ljvj)NZ<(lA%fD9Whak+fUl zPLwqNa@vX`!|lwvgHOc7FZC1=e|TajeX~bpRbG~- z1c2a-!E=EV#+;=tnNbJHH zs&CqhDRYAjq?2wl@!f;scJ*H~-gi=*-E;v+7+~C=MMUUdcp;e6E28xB1djFf&os%U z9|wfvS~6ELL~xnm_IFXlBdHLi96AKxMI!e#RoA>pvafB!b6l6jqdUTrT=m~Zolo72 zRi#>{2fU1ngN)WGJhKP~K*$^Uhy`SLzbf||So3^fDc+MHDcmxgs|F+>6ysowPVLiu zxNm!>ir0H1fe4KVzg1rObj*sZ*rzh#%o=vf&ig`{;ohmK#Bd}=ZLT&^kfUcOMXQuJ z-pjmBzf-We$X-gE!T`U~)MGa_T{ug5T*0z=K*b|pxqLe&ozXm5@45|O?-{0G6Xd@O z?|A%-IqlvM__}Rh^M+43{OtWuxOjuRE<|mtvaVwMD$lTT(0BVnJLLuP-9o$1l55gq zwN<;+&%2hDPend(Vo$!SoENJ(7yRT7}M-0W8k&{ z6I-J)vFc$s&J^~+nyLLW3%?hYfr)aHKa`wS=EIa|dvn;T((A$BKU1=_3u~)2qh)rP z@~pfuf4N6cwkvk$+vry8ED!r467!bx6BSHCPE+yVsyDD`b`HbPDHp|^^Vu(0cPGw+i|qtB}6}G|+UYu?;=~m9gchrqPJr4ROEg=kTC)RcjM~ zw6*xFk=Jm@#@FNV{~^7q!t1N|^1rJnFo|26u^9HVkez3LL45Fd5Ay6GNiNZ8mMMZr z6?tb`_Ome@pIvd$I=&4SKy>kRq2w_%hcN~q5C&p<8lA6blwB<{Sgd5d8N)b#Tn05O zCJIb}ZZM3u|1qo9W#s`pvq1dZc}j!`p9R7i;r*wn)fX2k__yymuJa$nR)B0?zz202 z=pv}@)(bLycbkUxFmu|{e47S%{1b2of;9qR9q>OsA{s!v+t!Zj-KU4@$6W5}(_T0T z?^XjI@&sQY3tYhr%H-QZ#)078(XYuq5`3aolI8C;2=o^aD zotNO#+djPNDe2ZV%R)pkE5p5?bT2TotBToy12nVy1Sye0+aGud0?5(1{v2dms<(PWi+iouO7cmGjs zto+M_3O5*uNjk}ZFNNK|F$$`5T3I=l>5OB&sgMa_1a5^71wsZDCN&se3s*Q>j)l>N ze;LZd6#IVD`6|eAGcw&~bCC<+iJAxw_SKu9I}H$9lJypJAJkxcDcZJ*C!m>k`ew}3 z<=)mgJ3(gCYJ$|xQId29h_`PyW5t$EHnc+@k(i}*K93Pl?aaBN!pk@HwqC#eMQ^t=V3JtMT zBF8vSy4?}OSV6G#upDql*DsBb_C(IALPE_17iZsd;WlyUFs_9#bjTf!)wKB0$n&1G zugSgA2kQKh?h(VB^E`{uoP%A#an=3zNh4md1gzBK!Kz=-N!`$naJpPMztBm?0|Cz<#BIAD!^?~~RXt4z`+}*;mW`N7>qx;+7bHkcI2>dqv9>(N| zmT`ka^Nm`=*ecTSX$@9L<@#dt=_ou-ArhhZTnagzzJ8o5Z=exPwncx-Sfl5&nzhh5 zop$4Ij{Zkt&l!vz5sO=AIYi$Lk-|6Lv3O28A>;8z^*3qewg~!Xp}ga6?zueCJc#kR zEI(!=tMORqpIG{YNu#Qblg6!*>S%NM)9&3O=dK=7G%^~8`seaVRT#e||;!HiD%ueK#322mKww-rV9 zOR$sYmws#q`c-?d#;I3c0|@uCSI4JK<~W9V=*f#3^k2RX<9{5alxrB>_!v*-P5rtR zrIIxWg3Lb`yL6~6+z1e#n-Zb;Kz@J!cH?qqe+E&cwUO}oJsCu3_&IhzU5jl#Ati2X zSB_z|s-PVx>p|nq&s}Z}lrU-04RQ3&#^nqqo<6~f<&?`h@jRw_fD}y^D8$r671_9Q z;$O_&U-PhfJhK>re4FFQ)MrB(tFvpCF`sI-H%c*AC)O&9Tls*KqXm|UtqMI1O*k1V zvqoN;S7dAf1L3In9>t%CngM}wTO34hFsG6>1&3tA?+xeyvsf+|D!>i?2~Na0pHq^q zi^F#VP=iBX`UiDCNoVn7%bo16V?aRT3zZ|9kAZuHGG92gWuP zs+u_wm)xLw1xNu?4jhmmBxYP-sX z!>{cm=d?s@1H!j0zVWy{mabLaia5(Nl8Aeb@?&m9jaO>Rtt`ukir130-O9?pz%yZ! z{;EZET{+i_%&Fu}Wk%jcif+q5qQsOZn>&un*GYek2 zbA3phQaAAjuwjGf-7?V}!;&nlqD-3R670iVd**Z>KxMA653xt`l!prK{f?1+cKjk2VJxSpA72lkoiJ;bkA26~eueXvkbzg3v+E*O0RJB^O`nKBoa% z6v<$~_lf1G%Fbdn?;#|7Mf;EZJzvEK*Jj~)Yny@g`1;kfOkHaS@?G_*>!vx&?5Vf! z0Pcz_7ymNV`{mc{ngNoG{xKwd6HkZ6>Hn3kaD{V7Rp+}7FCa=ykEzcdh)u({hKmhFzE*}gh9 zk{@VYM@T$?*pBpT`aGGHkDGbV3WYQQt&NrtJ0n~~xhVXZ#jQv=?N7Ra_KUF9nG-;r zOq=l*T0LPiiB(xCiT{|8@E5dla&ixrqOogY-q$blShO`%IvMJmzMDR19nkWho>BpR zJfYy9p80Ypm?q-}f8Ck&TlWA-I&IOgRfqsq+k0#f{B+EC)5PTkwW99B7!>J0S@iBx zvSp_W^*}JPZC4wE3&B$NhB-;Tb@WbW!rb>#{rW`6(sSbk#B#8qF99~uX&-u`kM#=5 zxXyZe>0|Kk2Qd?(Z^?gwW8rCTkD}`N<+^J#g?re+O6s?{lW#U+l78pLO~3X)bP9Af z#&%f^%wag~$G+{q8|%M$F|eQK;uLOxRZheE3Pw6E7_^~#xKv< zd4L`fXr+NC6sloYcYUDv7fcb_rFEEqXfr{bcK~pEsh-ngw}rY|m=T@^YNXMQR#^e< z0BbaqF`Si;?yL%1oaK}v?ZZ6rF3Tww=A>NfDdJb!wDM{QP`-65axH$-mhI~7kKD@0 zpH??XKJ$ybmdP{$F8kj4m@Ze;Fw4aDC65IRh8xL4(>S}+d`0#0n|@H;MID^FD>dG{ z1=E7rQcR~sNT>FIb`t%e4j!!Y9&wlgGd%@_g3hw-h-W$xDd)%b%)&GcnC-!xMhazw z)xoolA)9}F7i;cmEyG*<@n7Y^zkmHlRzok~d(DDc#>ZBS8=FC}lx)cxJ?j@9*?JII zLV&!e6=VBbo36sf&LjFib*eX^w})2#jP(%P;GtIE3)@*rK|4-;oN6M}g%l}&j9RZ= zGLmU+DE?xvG1g{T_i8)B?Jv0C2Nt)VyQo=BHEjxCi3Wv%)+yWcmhr4hiE_oq+4kH_cZ;vzV%cJzV(x17C&8RpFC8&QO&a(m}0Bxc+%pIKx`UQ&Bm>Z7s0npEgQYPLsqA_N_XeM7!Z&XjvK z{YNf9ZunJ%sP@*BI0l~rq}yZ~ORF-EZ=0Pnny-Y8f$RH_tek>_0hKhP0(W=iOI`gL zL)%9kUZnmDjaH+QIQd?oYRCS5@0?6s-m&zI8^l)+*AD?}+7idW8c z{{9Np<11j7z*VW0Ta6=TAs>I-;8{hsEP|j+PD)lHLn#uTbpyA_W1A=$r)aRXXg#{j z=y@qdgfp9|_3E!73uoiwLp%-QVq%Et$6Wtur&m{GI&Uj1R4Z5h^r|DB`>I}OCUN@& zRHA#~c;8jXR;N_w`?xfj{dhx=JN!QEnT4U&cA=w0ONfwWwwJox?fXHm%MW2qT2};F zi)ca#re1%7)ESZ&8WDgI1I2#6&7bJc4H_6(287`GXBxgUgz zCcd#BaRHQlpb^Igr=~i;oG`>O^SC*mLi*5vdY=r?l8%l#UxM9NS3^ig{G#g2+2*;l zFqkaGbQVs#r}`T)bRBmJE9@%Tqj_%Y;O%-bz~4`^Q0ytE8C~i@5@zm?I;FVv?{pPS z@w0#bYoX*Nq6813#4vIYbw&U8-i#|(KcXPw@3n5V4if0EA#?}7cl7QwSNjc@Gg$ns z_5vW+F&F%N&n%4kbkXGt$9&E7cKQiw1WNOYld+`sMabi?vnWa^`7`HTGwS&<%M&=u|5bS+$UFyce%xbXP|IDGp$n5KY{8ihi~! zP=({jz#s?06?6g^LM(Q}Y7y0r?N4YXw2pT7K*mC@{$7(yf>|=C67*3jMwH@1eA!-# zu~x%mv?8*>3wxV7(#1+T@PT-;fr~`IpbEW?^>S_+*^M96gug2RK0i=P}X# zY%h(r2#ctt9?PCt2yE^!-VrF3;DmvA?b59w8%|`EN47)5rQCyIB8>h5KivH;@?M<= z?kaKnsh>5POJv<)hY5k>?$ooT8Rre}3}}$E^LV-UAmykh9*Axv%#O-!Da$ zFlGdCR>a5L0zJkSW>28PzjMJ&CSh>^IktBIcV8WM z@z_TVA*^Xcu&C!Y6GZVqJy6}@3U*!&x-DrP4vkNp8eh^3r|qbP3%Z^hY&@R-AfaE< z@ydCd!YG}bP?p2;%;M%I0Ul<;Y~9QqF{?--x=y3eWw+H99V8(_O@!-&^|0v)3v!}$Y=OEQH>5d=2j?1wv#E6@)L2xG54oYkWSODp9d12VuW(ezVn`7s~-yx za7Gr@9^td7_8!RN_{v|)xulgdXU(O!(_?IASPd0ou8IJR&yq{LxE9o(S&X=md}K-T zC8&j(8bzMQOHN^l%A@!Um5^;bm6`jz4owT^0&L9B9h05tN3Cwf20{QVueaOKn;qN0^8iW-{Yof9-jnZNdAwTceO0eUR72tqkcLrfu=JvCVawC(Tn-Dg%Jd-W_>U$bz+Ra#^z- zY<96}USJ$~DA%E7D}OaQ8u-=YC2lRT-XlGl;y;P8SW_r)$04-OqnlKXA@j^)W=m+N zJaWkIEb%ixFQldSJPFDLxb@Xbw(DShl83`9LE9x}6Mp)Wvrr5tt~wWUf%@K%X8QvN ztxzp5?{AqRXBkPR_8xTOB`gCjv!SEN zL7E~A7mBr0rE}Hr7;49*p;N!t1{u=u&nQR z=oWwAZ`HK$`=8f?n(CW7X6eUPr@PnoU&&g^eu+tZRKSxZS^xt}7PAe0i2z>p&p%o- z5Y@+uLV9mAljd6R{b6M2#ErXA$#dcgVpiIswQN{@%zcknFF!>?I>#f|-(_(EM@{hn zPC4f8??=o<#fOmcv?DbxW3`KkUHC*+>O(Ir7$BHh1V{r!GpeFiSXO3yjIlQT;#pJs z6Ze70Q0`+fqe$!}s!p^nHw&I*{6`{Y7Vnt1VXi`}tnI5$-9(#&J{d8w6LDg(<2on6 zYifj#zsnB{a4fuhI>nhHtBDM%4L?7#puZF-HZ9y`K`|cCxqNj>GRvx-q+qj9Mt>>! zmh)tdL-$16S}JFI7&9%?Rp5two*wg$G4|rER{k;R>S(BNiT1Q%+1FM89`PNM4Y^j7 z!gcJcIAQ%sgI6D}-f(+leB-5^Q8xTM8pu_l`|fyg!HjGsY~DfI@yfUR$?Ak+(Dvbw zNT~ia3wjcBAV%(XzmWCNe}p-0KncAEdJno(MGaO(UF)%`tS$@?Z81=aY0Rw6zt=s~ zI}c8`E;%FmDQ!}buFqw57pAwmQQN0zV>J+e8!#NW_5H*5e*bXoSwF42Hyb5HeL4xh zzin530hf;&a2{8JkN$jB`o{INvoU=ICZT+0frzNulU`I@l=J0 zM&>}FxWSQEPgWtz<^G+B(-cn2+PWL$Fm51Oh|O!U;i7#Jq{GFDhXwW1ILPpmN`-$d zTxxf-Uk-T~+VNlYy8m0FQ_RtX4b2>@NsMfg)^LUutpp0pxXKXO!P7u*+OLy-RQD%% zXVn^}KC>XPUP7e^*`BZUiBbg1U|Iy@(Z1}mnQLr*(UQ3!z!}?iRDl zQ9}{)>C!*qqP4{%4gFs0BpYroJ03e;;Ei7C z=iltdPgQ2@oqs5KMJxA^ zc8Fxmw@Hrkkx`C`^)*_xg^Bn$YYhgbqdUq?{{mODQxxh3YMYH3x=$O-IzN=Z7H^&l zM_8|_^DeObx^ebtE3We^?V&*lf{=ijeD9aiYX6qYZ*slwMZ^2W)3^ZgX57+xq1wz7 zivBX+YF+ng;Ub1KIyowwOQrUG`^v#5bD)EV3G5MC?w|4|WxP96S=yF?tpG9@m>*k~ zk=;o#ops4`{o6B(t0q5^pb`92c*nz8zR(kga2%%08*ljSrUWfKy$M8mPb$ST!A%NR zzsko)(}r@xs4H;_eVGhbz$*!#e0_j1o7ujyvapGVH|5CxgyG6kJORUp;B}G_&P2hY@KkiHIB7$+c48HX}-5f?d zU2MM}WPU=7IjclsQA~HPVHhEid9Z4Dr*S0HKy!eQ#5+{?TgVei%AQc0#lfE`aNrug z_k*((O4Gv;mTCvivm-H#@wh^<>za!F8rK4d+(l+`ii{~%%E|JEVxEnD<-T|iM(Ce#RJXE%;-Z&V=Cis5 zM@(h-gmx*(%KLLL&w70_@_c_|zds8-D@8?*pZoU%6$QU#>#vebTh5UU$3L@BsnrRY z6B(}~1pBM_Uu1t&N2WIP4%qppSBlH=erGr1mfoQA zfvgU~UBcRhm^NTjfs`ikFZ#m4Ws2#N7q8~k^`=dlsS@`DW)N5(ecKqYOg2N5>#DOPeM~G{T?T12|qzqm!uT-}4Cbl5^mucc3 z@NU&eW6w8UziViXtL}T^pNK0eIFUp;(xein>KHitpp8Cue~auH*+#;)oh>|zI1t%( z9c04b*8yDJzn@m$Z8i@P6FGG`95$A>n$FObo3eUeKpSc!_hSD<&Q`5-D6o9snFS)@ z;2hlY@QXFds+n=tL5W40n#SkmweVV+@cSzX);(ZDINQR1R}_L9`&Us2pt>v$H}51P zKo)z=i0-s+64{q}HDeEuswTTQ3jxbd_?`mnqY8Fs%?pua<2TLkJg6pxjK@%hgDj$I zV)h*+FcKb{_+5HpT?Z6LnCObaHS43w=tywM8vBnpVw$0%wUjIj#z_^eNRsCBG6bjm zg*-C}^Qt!AUT%)jBP1!D`JP)c(`$V$I_=j&`AS26!zsvlg3da5uBEoVSvek3bkJ^a zYVvlfP4?2fiDe_%zPFt=4^PIbT)b((z<0jw)iVnrX}slb#T!)j^+DZ(nq&tK0y!hu zZOmB7RMTQ>1}ph7pPXpTGQAr6VV2{t^zTK3Z#FL@Ug zx4^|?^lgGlW~rsiT8c!MgFG&RD-8MZ( z|CZza>$r{jpOUjv+t-k17PsRRMm5wm&h1=Vy=H}+JTyV^1&)NDZioXOj8$`f!;TG> zS7eU@vDX4pa?9{Wg@Q6$Gfo{796QB(jN3;oDGkV&4Y~LUBtqyM?jjkb>|`JNQ36Zw zk^7QvGLvpwr}_ytd^Kr>zc(%KEo7J#o0$u?$F(VoePE2f69Qcbkte+iJ4fAB{H16Z zxkh<9gAA}v)YLzEHRRMVY^WlCw7J16E?n+Smy2ij0^8k0*H83TxH`C#gVcIVTah|E zJ@BQe0b=`*0Pv99bE~)1<*xB|$nS?G^(3m9{b9=5!tdaq`Vj+CKprICBV0)~(=MDv zy};Ok~0 zv?hO>Vg2R8ieqd#+t_`gOX4)II?$<6R>ySxAS)yb+&=LReEYM?@%=d+W>pDIo>~ie zEel3b--nTK1M_mlER0&;74XzRCNyj49{G2I#c;@(iC;^ zSNScsv7!>t4|J|Ivd<@!)uRCRM_dJ z6FVCQhO&$&$#Tzj9l&6S)8!OfWtWgq|h7y-4 zb3C)KAy5!s7@3-)KbI#8++Bh14-?C8X*J09wlB@!yvipYB}0Dcu}6-%vp91Cu(v7h zsiz4-YxRDwt1FxAPKQcgM-MFYD63ELbuxdUpH?`>-Q8}z%2I&4e1cmz_fh6(tT7W} zh)(l1s+El~K*{x>k_!+SCmvH2`-Pba!bkiQ04|UdKS>tpS=H6$K@{VP6`?dn9H4qf z9ZU%NlA(Lq_tKTZgVJbFz#F~eykhjWQrnxZSVfzM1nBO_!}+6ICV`7vAS$kUMxtV{ z$vb(Lji8*;!6 z$~q$O%)&p{*M)E5g38n7fLyCldvvW|7}k{aDE_|Vkr`|&hzI#S39I1IZDt`WW%}-) zesHVYMnT7xE$cbJ9yU#6;Cp&li0#tI@`{l}=EBU;wZP|Kx<%0{6`A`1R3v}N1-rF1?!FPwVKq4G89d$nV<^Vb8TZ&DEz-0T=c=+MPHJ#*UAe8*E1J8HP8=AtF8 zsf~(Q?EjvFyG;6+Xsfn`8|Ld?*1{j-0&Qta_mb~#m*ELR>6?oLm>P=VLf5MXTXNI+ z%xnYI9WdZ>cAfECZpr_vsN?@E63hNkvp0Y!(V(!mrYRoS`J~(_=jW5q(HYTs&vk50jE2~Q#7CWs!-Do%?n z7CPaZr66CoM&6|+#+P)M?yf13S*pJ^TSiyKxIyk5r&t)CPsTg)_nKWgte4;(ZKdoQ zKRii4Nv+vdR9-wjL1Dx|){ux8v-yuz5|XSotL6LvwB)8m5HCpDo0avI%=dGI;6@_! z&d>V1I#C}_+b!O8%{H){tEhNxiIsPnBC*KQZ@w`MiT8!DC1VDc8)E|{bRCnAVvP6= za7K+oL`k>#@D#Prrl70#JKS)Q&J=F8;AwSV!|XWJ-DKKQ3!ttvIeE?9IO zC5~*YBCmGu%_v#l!vbt6AS>?HH4tmp+%icZ^EkGZT-_Ct&G2dE`5nm!;5!|O z*1WK9PSE--cNV$T27u}z33HNf%jxQd^~hZ|Y|a*YPxg?%-yEwc*4r5G*Wpc0&!~l- z#+e&i0!R_|BYzivlqhy(4(8_hX*B>Q@q&lZ)%T$oM=zFY_EWzLTsaToe4~O@(MLy*=gs{pHvLd&OR5`tG}8w|8G{ zV46VHq`^@?8%7>bU5q>_(#2}1iICH)lPKaQnLVCl_c@D<0{!u$v#BT zt}AK;54w{AbjtIGW9aeEi9eV|_7hmU^NbKzY0vPKkJXWtr^YU#MS&y61C1l~*({3~ zMP2B=FpmiP)F+CD>I8>oIN7G#+$FngK%%>Jl`F2R7E_kI`KHO#lP0~!Fj@yBl z;D=KnF}$}J;vA`Kj$0nb0q-dOQ0^`X3@~o*Z)*QkDnYAPVtNVr5&wQ<@SAiyJ)K1| zTVW&-d%CYPiV;n|E23V_dL#3-`U%SCNBMTlpetg>D-+|F<+&MY^f2tEnZ~2}2l1s2 zv1MKGU4{0qLknX>CKpff4_D^HNu4BmRyME7>y-juGrc1Cd!2g5a&(6{#d0KUsk4I( zYGHQZ*mN-%K>nRkhB2y{O9gcbPCin{G)L`22RJ*6+YO&znPUxVF$Xq+7vHjeox*P#8X$`nmumyO0}R=-4?5yG4?V+*ZjSX%(jxyN{)Hc%Zit zmm;o@8YLICe0hzk7O&-{O5?Q_q~q7p@RWEXk|L65%0GkKsx|vKdIaTBEJ`&M&mpM2 ztbUeubxc1Q2SPGxwf0YNIu&?XY>3wP6km}d>F}mmk4etuL`o1PlX>5`xmzHF#R7`E z1?sh;c>~6}@p{YWK_Bh#Q#mwK$BCM0Mv7ARqYD6J8ODR@tUt>9r;_E^f3g!d_ZNIB zHbf?eG&I%wGtleAaOLP>KS@t83q(CuVfS>#&!KstCW4>FReaFpk2YRcc}erQpQbzE(XZ*Z2eVm+6@J^!a2Wd&XLkY^9R*7`D*gn=>(`!H zCT4H5IJHYlzO5$V&NbfAg1+={PVCnv+*;zrK{&C`vO$giHsH{^wpffglEda+P`cQ` z+CbN8l(NYM(B{@Ton5ia)%@}IJ^`GOccQ|L92Svkr4o0JFhp-oFhZm#=GhTLFAse% z;GzyK_$|U39Xb>*(&Ch8Tb&08*9Pe&Cb6O23S4zP-5B^j_%Z0r$WCzYa|=QPmwu0| zElLxk4TR5D!!bp&B?g~nvwT%uGU^t7WHn}KQo{eu_woEe-~yNSXu_r7*I4|E2VzX@ z;Dt{6k$CK7@xUqibc|W6i(%!f3WX-OYz|1KliJ~RV38<4-#o{H+ih~ZBm-?Fkj3P~9U!S?~VLXqWm$7Js z4_@&%i`+OSBetA9qU2Gz#d#<8J!nihDldRufLNk5GN-yu@vIE(o*#z1%Bw!7F8-^i zS}bJpWIf}zf?v2>@QNXOPv%(oS93WN)vtNat?~5c7}>e<91jmcFKWKj_3abE)TV_M zNWy|?lkpRJ2Xp<0b>9+kt}62f@)KLg5EO@ukP=I|DX7E?3Ufe6-kpP4+UU{^N)kGW z3y|qbx;Q-%B=a!O7qnYvbi0KA7(l1TQ@CK#@A0CQxyofBeMr7cs_hZXBkfDGi49;{ z%?_JpBl}KZ+I?L4{SyBm9j!)_-btR>%rtc}Io$Vye+~fA_aI_J#1EpCYaBL0@Xyabn;ACCi<)TZq`GUQT4y%kgVHVYIug-JYjSsh=^&MhOxf& z;Piu*?#-{$cbV(b2SL#~x!6XY=HPpN1t%FdhLeQH*^-{dM95z8?7o9Jg7czXZ@{T z@Lf|Y$3!>gTf@nxu;L6+*d0-jnxTD9qdQ#0ri({Et%%_~l{$xDLj_F z)_`8g8r&I)Jwa4pfqz^kKM`doM3NB=_ESlg+J2&b^rrr7f1y>Apm-mt*~tX1lDL-J zBfrV$cej!&VmhWr5Su^3F&EwO?zS|Em&`1;??RI;)*e=|CP75TC4R$FZC{rWW1Y@g ztmJOOK=r;GF_+nwU4(jyHk*hZZ;|J`>y1491~BkK2&5xbt74U|AXRFjs5OX2TGhYM z$>15~O9~i|F=8pQ=@KXRpS*QfU8=&f#L$}gyLN3+A*_wqj`KqsCcr6U|ARA;e2}5C7d#Oj+ zOXPMgY09_zf$|sQ?kj2uLD;pQufL+{Y-pbS;>&Cr#+fg+k%yZS4AC$_Wdh}<#^G?~ zs_qS4eH=zo>dWk2I@`0^A|`Z968R7Tm!7EPwulUxNjPi?VyIdnJ5wgS_&mzKa{hN~ ztt={xqwRSSp=48%8fBJr^EaCE1`PP4xVbAnGQi*ujUvL%tUfGvOYDS*o1Ynq1iGI+C$;~?4~ zYd0LUA9beBpI3|zpjJ*rAnp!>#$A! z&^x)28$kbK-}ZuE;{J+9!Z(DE&zrdG9e*vVTr5?h1u4U&^Qw0|hkowiQkwuys{a)< z9SsQN3PTBJbFuhcfVRef#)o$XdrS!1Pg2GReDh}TQDVEyXfN3&%;k}r_XWHtC1 zTi_?MSrU08rU}ylCqHKcTC~(Dw$rw}$N+{me3+Wm=j{ubKRo^MM+`?^op{k?Cu{RshO^4sdk;;ynO?BH^I!kWH?0Jzk2swkfp z^&|KoNGg!SAPQ+pF$|zL6grv|-Wml+A>lF~lqY;;aiNLr30)AKJ%I0$=N|Tg3p(EH z|Kdb1jg+bMhc3QA^B#g`i@zw^Br6z%6m4XzTv}H_P*A$k(-g-JBWz}RA#1Xa#xW+FTcBGp_#C9kj5-K?t!1QKd!x6k|5YVplRzd8GJ;aSgmV9%jAb8lL41-!L7pqi++#IcyA=dk04H zV;)8;wzTT;?S&`|6xxNB&TI9_Koy4K=hT}_FFXvGMV0iQHuqJg6tL_6hR9oL^X!&Z zGg_a=8PWe?y(D^c`O}8E9kKR~!-#f`2sM2{nN?;^`IUv3^1(cgq6!xqb4;xOgd`G{ zbmg_O`W#kPVkg)A>Gu4`KJ~kJK(>6@&h*>$Xq=#~y_?ZTeq+%v+mFcNw5FZYCn`*( zvm739eJ`gEQqw7+;k7wP)mzKU``h1tBS{{?2A}2m*rG72t*1GTc=p7ymm{CwVGuua z-*grf_xQ(OiyyoJpBhUqv( z{wnVJ&Ht_1{I3dg@Y=3S%yP{l`H44nXwTL?JvOqp%5Q}yJaUL?qt5$SLJ3EzH+CEf znSrVjXbi&Rw+eN=vRLq*^q4V5P^YkForWF!;B)Bz8|nX>9N;?y7Q3>N&s6WI`@y4^%@YzH*;;@v zLXbyv&QO!SbGI3x&=!4Vm5TIPyRB}11#aC9k87c3ZPS){pq7aCUr&>Ahh~|OON(U4 zF6i4dxw%&BC25BO;jtXj`>>@4PlU6)7Y?{&jyNQA0X5=D@iCzy3!vjUA?L<{LXHR* z9y1%0Jgf+(fP}}SDAgFcSzClRm5`zM4I{cJK zs$$AT(aaYrfT1;8m*EsIF>onHU~{=;b>|J6?{TogbmM1En^iAjOx%Ukw&oTNP`zKl;;Sl)V7`ymwd=tsiyJTI zpB2(_r=~r}8$($ZCcp~=E@)z#hyRuCk}mHhH8;@8oNDCnhaVlSzbdo?NdD^8PN^i1 z27$5k7-sz7%ju76u(&p3Y=T21HE zRuSGd{v#~mC}gg8YRZELZG!|FXw+Bis=6ok?!U&V|NHw5B~ftR4t&?-fp;*QM1{+J z2HDD%t@~ue=sWI{XCff7|2BN?PSa&--=qH(f&|-WaoS_^_~Z0T2g15=oS11nM}s_RU!n3x@!6E_vYkh%mFl@*fm(7+m7Mexg&eqsHyNTI0?fL=EIo;f5*?u`)hKV%&j zkn)q&MPojPVH>~aE;;{EcrI?8stNbrr9T}>o2r-dR;u+1t3Zgq%vD9)z7^_eMR*Q= z)>X>(%qt6r>bHS8Yr6GrEKKiv=zhN4iFgu8=i17pvPa*zANiz|+a&lr(mg$bch_Vw z@HP;=^41|VZTvlyDD&hbNpPMAgI=zpmHxDXc+s0r$k=>tK)3-d=)se{KCfM92CPM5 z9&2~L86*2wuD(x$>qBGV!fCCS5TU6ko8){Q(gKt1YAeA^z;oX0fURP8!{}E(^~h!$ zc`dx3fPBU|uDPb7_&&u8x`Z6HniFN$wBprx8*6-%Z-xN{&G^zq7O+e99p+8{rE(;+ zub4`g;+xRlQFiBXEMal*Z0Ksif5<_}9VG$~kAQ&Z@dv^{JG{wq5Es$lOK6e7=d?5K zYmVmnx7n*guPo3gJ*FLNx-F7`2Wy>D;e#C4&UoTWubJ91Yk8_H3O{1$1xTUIy5awl^o(L1 zySho&yelpJC!bB@o@98nk3NDp>WcR2ci;d+?E3`*2ga{y!j5@SMg08tJ7nrSRSD%P zTtgoZL(QW>(Jpd6vg8A&(UQ?cDfA@a=)%KbP$fY)tpfEuGr`x?aNfwF%jl>`qZ?UA zYla7U;0^0m)?Tc6w3U`@WPUsZ)}|0qJnXRql7-Y+*vBhj<&)|cE_?C5vbebj+Ujrl zyEv$Rzr?~y;iXY*XFk~O7bwI#mCu}jM?CqW0BQfilvW4n7h>bDQx}&Oyhrh8R-!5| zm#~r!O09vwCoOJBYI>!Az|LJ7`aFwO*AHFlNn-bD(z)7Bsd+#xhTn(XVwz=(ZxP%Z zo#CkJ&$j`v6bC%M=q02f;hV4)sK;41C%8cCP4y4;Tn;M6pgl(_;+1}m`6MwhhFecu zg{L2D3)ab>Vk4rLN+#s86emUx+xkLpwV62e9Su6lGQL|C^~kLzMf<$r?mK{J@qfit z<&3=K}TppK0F)vqirfbXxF z@hSMu*a7yr6L8->Ur^{xpx^T?V%ylh_&8NtQRQt&^f!B4PqifOu~#;BdR56>0BMj5;j=%s3*L^ zK|ZXrSAMfvz&UfeKkAT1qhejvg**}El=GDGJZZ+ip`xNO^Axjo7gHmEDx)I6?{AcWQ--;~fLsI(N}v9hxz*P42bF*JN7wi<`%J$Vkd0HfX>e#R^6KQ#w&Jf2)jVQ*wZa8)}``6_6xYCEE;P_ zx?Qo7CN(C3W}~NPMOICY1NAG@dz&(##n7PV_XRc-IA~EK?OGoO?cHsDhFAr>JT2SPej5ZfDf5tQzg7MnfUFD z-SbgWUX&K-r5^XP$t)QZc(D45w2pWzpa)9#=S)Y?bIxuHl-8a`qtZfbs>_RJ48NR2_|7N6 zsJyb@rV4*^VuRoU@2}5fLK>HXL6Bk*F9dvJhew~s)nX<-V z=OBl|J7hdsH1CG}LFmAh%4I;c`a^hQcn7cQD+^N?B?1Ks9(5|m>|#@JXgIsve&G;D ziMXc@intsFX;OT`?&YEFqqm_g zarT7efHr_P3^$D23*neg12y63CM4Qquqvw1tcS8337GSa=-YtuLTH+(XkcPljnl#Q zkIYjKH33|~2ZE_N=Zy{l)Wdk2uw_tOJ9{}Pi`UR(eUQ)pHqUBA2naZHmJ5hECDpdY zmH(=Gwk4eW7%2uGpM4a&otZp)2Gd+G&Mnf^4fjL`qO`YV^oSf`u6wMAdzkkX_!RH7 zB04(i+`qE;!Q>_z`oYrumbGvQ>XXqFOrT3tx3@2btO{}q7yGEMZ^O(voS!`u=OoJ} zhv}>IK|vuy4~H}gtgYa*6t@y99Qha;H!krY4@0s3$}7d(q+nBM2JRzWgG^dvLR!U) zrBS*b^@PZ<>ab&d-V-i=V@c+tXHg=5gQ&se=NiE^ji1Q`KH3U>-~d2=l!r5zaQr2Q z{}WD)CjK`8(%-`lfN&%@n-pu4A_Ccv(G(r~z&hLN6(jQX+{=iLQrzjN53D|}-A2cK z1d08~bj$?Tck*Unthy9GDuuz~uJYK9wx}?j#(?8O7u!yE4SywbNG&r|@N*K3`)TNT=k;T@+mt2Qu^z4*QXji=eto&49e`{RK$x zF&>NW_%?S~dFL?PTa$Z`Q-2!q-eDLJPx~gRTBj=VPfR~(@rR!MIkFPnD6T1otA%&^ zvt*mC*|Yp7+r6-f--uaT#5&vI;_V^LD5;of=#HGi(R&l+IS=dylJ`Veo1pY4EpSOU zg9{m}KCdZ#xJ8c9X8RB%UYK#L%$kvic1^+Akua+k>E@z;f&fZXI5Q6C0kx=>yL%vs zIf>x>iq~3j$3pb9Sb!p8xQD8(g_-^Nr``4soOc8sZ$Z#7r8-mTZ#be`ClV-Lr{Pso z4>1qb+JCW{eg4U{R@5EeN}|1855+Y-fj;AdAdCG7DteI{&yy%-ICmjF-8EL-cLTk@ zq~YZ{AJ;rW$h5cFin^FbvR0zrX@Eq;>f> z{U4}_mlBAc8_lQb$g(FmPC3_htJd82 zZ(AZxm~{EGDNnQw)Py84#^y&y%Lq66$y();Vo75A@mFa~1W4hSp{ArJF!txxRd}Q7 z<2KiFI*H1YgBvTXPwHz!$hV7J24?{!>w+BOAmf(NIE`|TF_BOGfrwPMjj8*Mg~Z__{Q}U- z#~RV3G?B4+8m;*#B}Z}mQTZn=?2%Z}#^DMx<`v>X4QL;tjkUymn{Vqj(pP@<4qS?o z_vuknCli3rt6C>*a|DRB@s~whGoDplu}%us(~T}&p7dEc?N3k&+$0Z0u8SniR@u9{nVwe`3jC3| zpW&9^ZB|AFff^HkL2*y0Ry_Chzq6~SR#~jK%HYbAWx3f6QgN%(?&$s?Ng`-}3mh7p zIMm*dL(NKS9}Bm#HI2e?CTM3MyZ>2-q#JHi8{a~;HnmT{%n`@IA8STu1^^N7hASaZ zgsYAo5pJ`SYJC9R)6h3Jk}-Woq7p^t>sJd>ixfo;mo8)+itYZKLUj|E_J$h4Pl)|j z&5;CVCON$5jqc;)xIY7e+1g`h<}Suhm@gID)Y9q8DXJ9uj(E0i<^hev`C#Z5UnVn8 z$Wh=04K2DuE9Om__Tb#D?E@SO)19q-nGeFYhGE=(48Ao675`hCDV`fskRa2+KmHdG zUni*c%bFF8ML&(*n0e{4wB>*E^4oz2cx}D8vx73Wrwu($)IQ%(0?vB_uMp``8gLh| z&E1^7;Mlz%cz4YB^&NC_aPG&s+kn&R?LPE<&mI6hYWLe=4dpqN2`Ja5u+TTv`^ytb zA|1CtX3g^`0|*Cy!-3j@%X41*C4}gpuc6<@rk7z0G2WUha;|_JpRSF-*S+t$5n9(e zNeQ2*+jQn6OX~qHAUxKWByuzVZfs#f#FUt;o=U`c@u7cKj;cOX99QybZmBDxS&#ZX zzkfIz1gTfg1NI!;=Jh5B_(i|@EG)9Fsg3$o7qvgV_uv6Chyo{!zq~hp4b<$!vY#d# zJr8hYl-9KjVL#|e2P?W_sj|2y`E46?&T*Wh_y!ko>mhQW3n8PikzUM4q*-e@syF5y z#jCWSA#{9S7>-iaki^oH%~FgmzZ?_Xu=ySjAA?%*IYmSQE0r{C+$^PWUfPJfWYOWd;_)@-SG%XcHU8WF@T zRer{G9^09*D6|r*8j;F%Z5{IORUq;;N6Fh}7+bf|VG}HOB3ar->Q#t`;wt4Hdix+1 z&6p(;zSXSjB2~OV9C#5J-OTWNuDx$M*Iq#?Ko)*w@e|H5mLQIw^wGuhs{9TZNcy`y zf+uBjtx%u@N<&7tRyddUQBihlI7H{OC>yB(Jr~YeF^W&xv>zWPeIxFC;ioBvOwec{(Wqu_CcA0q56svP)g8Oeoo*a!J^Y2w$k;JyPx+qcRp!Gla@IcBVi9N}_$I%x;75S@>vYl0&xXM#6*!S{Tn*(duS`@~K ziCLO4gWn=fHSUs?=|fL^K_~qjCEhQwLES9WDlz-=ixl#P{tRmy^HQ>4nSWbR{-+n~ zx_CTmg!T6dqE{9{X{x`)H(jDhT?f|6XNH zzr{3zdI#QWStPex`Ef<>N3}##UiD#diO|}s- zohPIZ$KbEKm;&&K;Esr@6a?O{{sc%S=_hEOe{L+^>u~vru+Ad9I^fI1PlTGHS*^?; zH{ADEUcNraUY0-7-hkgAhr^&>bJxq5+HrcsIHYS>oq2W2VjL{PDqSTFH4wnF)^gNh zC1?xX#{{(hvfN^NWwAYPu(e1(rOXnesM~&{W zuhiSuR1^PG&S{aj5mQ;v;sx~URd!(-ed)4EP~DyHYFfWYLzb6?s$DBC`*<;xH*Nr(lsz`Z*QDEeE8=KqB^JD9j!rF)$yi9X zD_!wW{fy!H(Gi0w5#qs{=YloAXtxD}Ux|bVN;;g;otM7>iDe!oiD<)MhDTOhXDp(9 zm(J*40cCzf8rXh>0OQukc$K3-gZ}2Oo^Lt~G6ly4m36RZ3-8_D!-~(v){W%!xs`Hj zgSqeBDsMxM)^hZHHf>&6lx|n!o3l*JT^{mcfncEa^rLE;hg@NYu0m4fT;J&C+Yj1E z^MuVlc>MS5Y_&^l{B(ESFYj!N@KzVw#uPeHD6QWgKJPrlRYb&_a{gS0liRl%k=Ns* zD_AsGlpwJgN+#JLsXWld9*Qou{ouhk@X~M}JnzsDS^f4Wgy?SyYeTNl9jYMwqagdq z)_=_c{`XeN*%tM`+=cVipJ?N1yZ-iV_TTnbQe&HFOv)R*wX!V3!jK`BuideIye;sb zn|$+gaWGEUT*HD0o5o+xF{`XGGXD8Y=!;r=tnTb@btqqwW-Aqjq=;@hteGm#}a7_eqYyjrNREmNE$Ze@(H{Ko7{Vh z=Ct#<=Z@Y=aN6{Tq;q}H0YS3C!NR8~nM*7QTSk!n>BBH`5%&5UQ zmF+fD>=<>3$O3nNPw`#_-n4z2y1p3Oftw-IfN?P$I(Uf%Y$dDEvPN+XFR6@+MU-4A zS=_Jd_AB}!xvV27_}w?{H>^U;UQ-FwqCT!=d|WvoG*+u(3t-fe;rW!d{*4C}V&Wu{ zVw7+&ZH4&Oh(QdkT2Ol-GbDMDL9UwA;jt};#;4*V&Fl#41`QL@&9JUMXb5HgK++DK z+djcq2`}xhNF8mXMK*`o`S?$7qpuD zMBVk|vdW}Mj*UJNnVvCBnLFA%SDr^q))G>#8wN_*$}-)CvNgXsh;jM!W)UWbhVLuBjy6yIEKpcddgoV7ri;k>baQPMbK$psynIuRiYUn2A z_sSotWLPL(aAum0hcs(F4AR-IpPYbyLE>@-mpc`)+>-dDYzWSgnwKJU(3b~T*5WtF zWmvV9CF~~vC4-!`S2iS@fVm3A84hdx_IXR<0|awk+dN*n-qiA6UEnz4Ft(EE&8WZ< zNOIHlKYwn_baF{L-qH~-pDqU0!hV7QRIWWz6@GI+0+ERJb*~X*J4|k19hzlia{a&B z&Z|&dxrgWNGsymmYp`P=uoYIKoL|%G!uRA5rE#kJ2sJ zoiPHf;l4A}ZgobK%){6m=r9cG+bum?Uuc3eUiL45 zb=GXdRewtS7I~ycMZ7_W#Js>xG*sbn0inrLvVz=YRN0s3)lwL4N-N3Px3x)sIY^?R zHu}M1vNg}cDy#j)o=2JJ^mF`sx`i4Y6^#&8(@-7Gm>_@P6eFJw>3j`?%Ip=uufR-Yg4l?_R9 zK@2POP_3{wkkAUF?RGnSevshku~YaMGl5BGQkYE$BxYFcNDa$e!mArYFRj+2 zIJhIk3bZ~HUp1py3VbVW@OTHc#rk4xeb1onyB|r9bq_1PRe;DTPd^N)L3P5g72g_c zZ0RfH`dN?v;7N2A1^%iC|J3c!*9)ThYG}ig0t|~Xqq*1{kg(8Z{Zfdd$<^r=u5ZbZ z>)W=Y)-g6=g$x2=w&#@}Rrq57Ix;mgB7Pm-9%z5#fA z@8X_t?ZC=itF633 zP!ZG=wuUe5!HO&w?5c~>ZwgSq>A|Yvgw7n251HlV>_Bh{q74x%aHH4iU_X`jGztUB z%O5}ZkDi+-%g#Qg>ImTWkbZE@9Y3f@Gs$8}rQ-Q%2%h+)*#Gi|eC2mJf!L z!{2W-GNhynBJ1aiiFzkANSbf2J;~gq5)~Tyy2MCRz0LsO%CBNtmv5Q_F0V zr#AhS1vftSFE6;MLP=1}kV6o@n~7k3oXrZ7i8SgqHo zQa!7@=U2L4jD^!6nxNZ2-an4$@G;4PT6fydZyYS@eG#+_K1N~TsAmKipX3hO%N>J^ z35`;i4mgWzcmRns)RmLh44O$bQ+4xN^or?AVTWVuC# zCSrR^wcc!SH)p7kRD z6=6?m%hD^0euTCop4I&QK=9_rOwi6K3Q(hM zx{S@*tB^Q(aHNsNJeQnc`>=lMWQo&vM%998WsB5QdRwvE6&=zwd?4-Jhlj(n9P98n z){a+V6#{l@=uY*sYPRXv4ukQ9#BH9WqF5jg;(CvDu#P8uc)K1!;C??5itwef2o_O= zGf>`oMXHB5@kE$q$eUi*+CT7I@xWoT;Jw`J= zx%WmqqAMkhd${TNF%^ZX!} zKLIb!NW<-`%jr!AZ&=sHqfzQi<90{RLA_$w5MDpne>|InnpU0k~S6QrmwsC5As4WZ_*n-IVT&&`H>~e^i~m z{{FkmlP!F+3~N{*J$zAb*f+!36NT`-N(Z*x)gMtf+Pw2IP#k?pLcBc<7#uhV=>Q~XkN(e`@4|3|j)VNWy}#U+z&fJVS-++~gwH8PUtBA} zjw&X!WbswkBD4{ zRQ=yX9)J$N<_=g__NZL0hL!>`{p8~KetUd2^waUnVDWQ9#dZ}etMh=F^+Gvd4e{8X z&HCdstzluwet6s)vnY^lH)P2=ZBEuD&K(=S*)o&jrR>x=Y#Gg}f4q+w-}(88j@PHE z7Kboir^jLfj<`ewF?+b{K@AfI>OQjM-O0YJR_Fy{8tA(?!x5BqHufLuar4AimI#tj zxs^dE1%k4qiTZj(;`Q$dmE{uTmFxOk&SPimAYBTHaroBM#&J`Mjg2~e!fZuuvtY(C z4<^mz2oXH77!BEH*YZp}E?M;eA^+}Mn_c6Qer~yMh>WyC8XK8ykM#t$QkY~+XFE(; zTHvI1vaLPK+tfKsK+A_g?=~|Vz8hCvaZ7Z=H%B z8uo%QUsdHYgAOTHtUrC3ea}=_SeAVCa*ei8k>Y?w5^X~mDe3^qEZNUjUG(Sq@fjbg z)kj(iZCrSG*aBx!R4y**Y9k%8ll+d7m}}749l#XiN%`LI4;MgRms0@>%1!mC=X}zn+9U#3do!HIp>Fz&oCxh}NV3e5DW5y^$jB+*PZQvo@ zD}S}gqpzNAi6r;VV{+`x0qqitbDyd{Y3y!l#nGJF9zk$!?i-$KFAR>)YzSUie4rwy zyW?m$5qLCF)i4WN7=8()2u2Ufp#hAKe(HQCj1!S0m<%ZIEYyKM*!zf8<{SmqNa^>z z*y2uzpSZ&NA}%bAQ&sv>Vjfcy*m;~XJWf`2owWVmqj*%;Bxv0b6W~`CJM<;q*BfiC zmkXs%_uOum!l@4FwiF_mFcOrw1Wpk-t&Kw;k-pds@N)cs)8Bj$V9$mFSAg#>dwA6% zCcJy)cuMm+H#1viea zG`aR7oTO2$cP*_;=6Mr}Z7mJA!PTW#(6fPqrQPF zbZj}ZXnC?+2Zk3j_|X@-vXBy4&z1zg*#cqrHg*P+aD`2+FJw1^pLY*Gh1qVLgEsBX zm+rikKnrP@qec7n^TFFZMEBK_Y;ZyBS5z{huC~LkETF7J8QTL%K@hF9V)ve1bt$K= zQy+k&_!g`Dlt42%Ai~I{GcM`H!SeUi^~nJnm-HG-2-0|su4P3yEz-@fa*|)4vs2Aw zxGX&=mw+S7fmwu;YAslbO{wzxL`5 z{W|ZlG4W*XqFwt04D=gu;N;p&faH=&%^xwG?7Hr|U!wGNWo6%;enS=%s92TC1I)VHn*uQ zS^q6^|Br0tNedCW1L(SiG1d}wCCOgqP-X=QO1_aj%h59PBUbAUX>l;Uwp>%&Je7h! z0gko=mGg<121KXFW(ihgEx_*q8@N=39=5T5P8O>c>Ve-W)ma(4$tZwZdNz8GbUa0+ znYs8XKTy? z^I1ZO&DVYr1Ar`f7#?x8#^-!ociZr%{g(+1m2`&Sk`{S$yvLs7_?FhT@iC%h&I$JT%q7^xR)ABJPB0;zn< zD78K{p1@fep-GTnw5ejU;9PFGlWN8sO(a@XNZBRjJXg5vxV z>#0CCjPsWH4kJpboN-xiZ}jH-A_sUfy>F+Y}TdzJ2?Np09htsyUsW&g zL;!l8fOleT`Ro%3rzUZ8MJfV+J8maSgwG<`R9z^*b8O~^aA53Zq)BP~E4v+s0635O zn-|OOh%9^6A9=8}p~$X$5uniV)em1usjfqIk?^a#vH)_!HzyHx;St5Q<5@;#N^g7X z5944*g62Ztc3AOT(KT#YZXK1yW`|{H2{xA7(*NS{vH1TT#Va1>NM2bCTtrVtNs-3= z74fMYQEfaj@w{gl;A32LsoZd7fuSM8H_rg_QV>ZDFX)j;})&PI1OScb( zO6)0^BS--p4_N#(D+#A0SU53SQBLxLE(MeZExNnmg*dBgg$O5WX_I|%iW~p z{>t?DkLYOR@XDZt17Zg>z-KULXuPquqW=Njwk$-gC(x#n9Fuk_8Y zc*qgQDU;)(NU=XBL=lJkyKKu$P&HhJYht8F7f8>NS9KVd;O%Ibz*qb7dU5+gj&}e^ zLj{xKin1J09ZZYaH%BK1hkm(bAGAXdJs;*gLT@Ty|3&P5g8%tvK>_@8LO(pAx;?Wb zxtyqh7#&rUP*pjiei6;c2E4QVY~ ze0H&8?6kQ~&k25h&Qq`gfQ_JhPH)&gOL48FdkGG{?6&b%oC3{0iU+iw_R|3=>Xs~j zE9(PNEMwd#jQb+LbbK}#OZan}<)47EC7X|okVCOYw%PsC&|A#Q*E{^eGcOh5UQX3?kH1s7Cpf5SRsXF)bX!r<=s9q%j zZg!ALSHfSs1WoMlgbxrobf!I&VrdK~gG#O}0`tTwL0^M&XCs9e5w0|Nwu-ez@a#c0 z!o-+(JJt7@i_$ri-wH9Jgi6g6>peMIcSs_`(gssa%=jd>n{k43N%v>qX* ztiH)IF9xq+KcOM#n=4KKi>!rJIdSAK`oCvYmkKPBr1!l^=)4n3p@?Y|79c<6;T6 z>hi#_qW(Ll_zHT#yN%>mF8>D&U=hFnw0=H&r;pWTU$^)f>!180xg+8x%m3P!jQS2G z*aRCt0v*v;S%PL5Gc-ht%KWJ0p$^6(b?nuwsXaxpL99xtS>u%KIEWJ$sFHtfzn_^m z9y9z=(;A7u2+kx)VkwZ)VN{s%Gsbm?$-mS1oB!0fR@_7s;t@%cKnMp7{-L>Cn_Pv* zn>06eM5)I77+*geAFj_oZ*Hvx8bRH+&31)m?bD5B=U1EUgyAq_o;PSJ^4?Nl$ z%FQa_->`}~@^ZIkZNw5}Eu z#!(rn7G&ygiOmO-X6l1Mex-s1`@svJ<2eev^%5?%g^j-(sN;2<2O}7>3j@{-h+G?R zY>Yl$DW0o{d%i!!`TemwtSRF`hlGFY7Ya)$Knq;xj14+g)jNxhT7w93vB}mGscmd4 zw&`!t4cN@8S1jHb7u7EIn4n}$4c-ZS|MIZpc;Ey+P`(~td=lSOJk0J^H5I!gX}zu0 z3%ehgv%yF_(IT93;zikYMctBnWsyUh5mWfcY*F^*LxWL$l96hE{*>z4-&iCH+*s5_ zHs7us5~kdo_91;Uqx*Y&@6nW6wlm8xqWzMwn#}0vrVps^NH&A!S$_5`Avij z8pNe!^?l9la1IW8U9evfX`CNa0GT{)hp$-VA-5)={k=eEhvbE_Sf?gs!7(4aVNkRy zV4s?0&hFFVx&xLcQIaBH2y7UH5rP|{bFPdV^1`U_fqofp}} zwSD^kC^*ls6Re?ihTf1%-x>QQ8de$J<>8mX`c}|t|DQ71F_P*7sf}Zx{O} zes9PNARtOKD+A-l5zyC_azED*_!or(NO81Ept-ECfbI)6jC7RllV!CC*8`~80*qw; zM7Km2T_iXh=%p+4Du6(oszhAbnGUvqEn*+SuW@4_R*1XB_I*(V;Gm=uZoZr0m4*7Z zy>=AU>5Dzfc2VN?#1zfpdf;C>C5sUB#t+OB-owB4`*ol&qGTxkC&x6Uol=A#^*ry= zA^8i@5dm&7PPz0n>tnS-(v72}MFxB>#DU-L#zeI8hb&5dH2AHO(V~jV@$j`_RT{LD zvmqhWlv|aD!iDOlTv*OTD>YFEb*NhVkvWOQ`DKJ}x7fT6^u)Tp@Mop9<(wZqrg!!6 zx5rSxWmU8Ksa;vd-%>1Xs|gGv-mqWPnY9tD(h7Wyp~z4L`%RYiy)TwRU_zsv9|}?I z>6aL`0doeAU{B!w_2;$YE9!BSDcK|@#2*bK)lOtCGGs0OY~1TUGMc%gU}d4c=bZG) zB1_f0{T{aV5{&uCD#^Xo&O`C&lF5kLvZk-OA1&qG&-2LDQyhuvN0X4XIRMidMoKa1 zq>mz0&#(rzTOtGmBL@c8EmwRLg<>}|;1ZJcv-V&K_9AE{k)oaE4Dfk{9090|-E=ag z;NAoikC`Z$43)5xWQN<>txG(i3KH$4uQ9q)epjuy42^hN@H z3@*W*gULaKYs%449?F9}y~kEC;2)6>j(t{_L6QQq#7SP$4ZhFge|EKp1(ZE`#xk=UJZ$S6kp{f)k5jc;xZE)v==xrIz;3yu6)Lf3VF%P14yYj9enM);Gn4-U|7pwqw2pxXS* zBgf)nvpi;&RC=X_;)srGlfjwg_Ry!LsrvRX4|Qb;^)GdHp|iRsm)-Z`Xwj`1)@X&_ z>RoN>W~$a!Zkj?q)mzJ3IWfp+Ts=7zkzllp5#!9<+$ZU+6iW(p_S;I(S1UOe8zV$rFI@jm!^ z%RU=sGs|B2ACT*Q_Rd$iWcg*{&@m2KIkpCOQapBEB6QuPvaF$Up&7+J>yik?Hmyf9s-uV#A0PtN_`b}*j;;G+fYI>X5hKA zYYs9fb}Yx^S_%>F^E4|kRJ-Z?=-)>X1K%nqiC&?bCGnSn2X}mefqrg1%h#?|`_3KDlra!EOB_9%QQE1XafJ zC1IxgBAOOW22<2(ycMz(%126$H3@jhbMFzso(e0uQEAbiCA$*v`ItAD01JxQ5pq-Y zV~S%+xCqTU);^j}i&(Kr&v1r2On}jF()Lgj0stix6B7v}#?jN9n0St0o}U^J7GMhqi;}8LI8JkAjp=!G25Qgj~RmKR`_tbw>=4~>pldL#5 zzYqkR)nO~kS>|bp6Lv5n&T>GX(?STj(>IsSKom+wy|^T2!%^|RKYb+%@t>as`5B-6 zhW!VTO|0?ghWeKRT@Wa}YPtUShSGqjre0a#TU9o)h>8g9?ZPa7gm#cb>cn1-TK?&X zVWnE*xb+H%zb${tIJG+;l%NuXnZU|59oW$4@2y}B2q25|>&H=vUJ2gyJSGKCvU-`> zORooXX(k7a-j}@2*;Ch|tr&Fa7PU|iBNBHOc@nEMMseT^*W=oiwwqXc>xs5&&HwS> z`TvXl&IiSB6b|sx@AZX6n7+JPq?)0M!1OQX|3}zcFvS@*ZJUETK?V;xxJwvZgS%VM z!6mpRxCD21cO4{XaF<{Kh6I8JcLKp@>wR~V+O4hUd;Y>v-PhfB_t|~A50E?t79WcA z5KZj~>p2^n{w8bzp6W7?bYJmSg6$ATlUYjdZ6^0LzYU7GFt!|fmL^g+%qF5_NV$D| zR2bzwjd3Ti7z`U3+tTZ$f`&bjV-d0y75rrpEgECh3grf!NEXOXF&6M>$8}gHB1e0u zI8KA8CKJWTqS3v@?kD3qnh#&Xnvr=iPiBK&S{&qrL2gdXNgEC%Jn_}h12WTX9eQJ@x7;Qg8a`-l(fuW%fdmdL@*m@2F>h5gTSXV7^JsVME~QQL8Zty`4(*L}L!5gd z*F0v(+^Q}w@EiSLWEwNKL0T1JstEytY`D$ODEPV)P@FIewJPG@->uG<{ z!>69gU6fS>fb1aiXIwxqS-m>8o^`%|1m36M>ZB99;(G^Hd)-WK5?2V%qdUDZDf^1~ zF2|A8WUN6-mrjed(7ln{mmJdE8KVHG%d+8L7F2OteYh^B;F|p?{zG;r)*lj|9$s(F zhNxyu3uQSI%dr$D5U?dTCvDnr+z)bpkLEX1!U&gC4jjY*L197TvGTN3JD@xBY^%3S zq6|MfcsR?#g>-YWv;(9~ogOON?ja%a^WFeSEi@zGNKqjNE6#XaVI>NA1?s!&$`T}s zx3^doxGo7*uJ5%T#KegV%e0?REu8BY=C{TkUo}zMHsQ z-yTcF*iXz}`G26U(L8;gGv&7avT>qJUnQZj`mYB6B@T)xR`<>zw0piStUl2=VW#VS zQNERU;^V&!k|+Op0foopwgoq1rB`&fi%j=!5if@yL|9VbQ1M(ivmbh2Wv?E0?%^LYEG`dGF zJU&)NhOhXa$1qh})jJpID=z@vsTOG`G4@o!wj?O_N_fgmx8b(h z)2W~4v5_z458R8}e^*(O*aN@VZ1PsRSvst#q)M|>p86aR?1n>VC#!{YfTK$+!6BI1 zNbKAow{y&7ER~uW@!F3oc-lepZSgBvwJbNoqMB<^`bTMJ_aNOY!XM8SeA~XVUwdD#Rt|Ok3{$n&PtizDknlmSVxRHT5-? zz(IP2?_^q68su+|yrC0p{)yeyh)Eni@iy_-G$YxV$+}qm@M>XG9QxR(98b4_Flz|7S$P&lYi02|s?xE?e_ZNeGK`=7KKAUbIha_x$+{2RZ+w4htB2A_$@u zevkqWx~8t+oy|x_lrZSzOQH~pg;EH5Mn)swGU2`BjLb z_ip)u&%i0)HO@CE0sk+H=b)!sGnA!PrTl#c6pU-LcvLgIj^qEAl;!_Z&Pb4kxCj9x zY45d8v4jZFK!n{ui+#2)M3uLGH|USSZBj&SqkuCto&4GwtIpa)CZ;=BOPqnwEMVOB zsLt7Do#nIqmio#M%hC(bT6)g$;Rnr5>UVEO7)S}f>xTQr_oTLepJksMrCJ)n{U3A0 z%?}Xs_c9~6Tg$lt&xsNm4ZqWfpK!3}nEH727EM z_-I!OSZHe9iN}QHhc79Qq619k_6O?Jr`k&Rp=%VYq2gw!{_ZLP#;wIxO5cs=AX*7o8Ri5JMj8=D=gc5f(kkTa}?_+9<6Es9pZ z&A#RzpW*5k@w9lqC}3eD;5N+4@HjuIin(LR$S$oe0LhVw2OD;UVvS-6PGv8BR8bBH z{LA8dx~TT9Hthzz9wkD{awnoifO3K4d-ZZ8q+9j-)RPK2pR4DjAc@6{?j%uy9^WkM zjo17w+fLzqPxpOkj#u-SKQUep_({OeiRNKS+&cHdEH;faF>#VaV(Z&~L|wABvw