Stereo rendering work

This commit is contained in:
Brad Davis 2015-08-20 17:04:53 -07:00
parent fe44442ffe
commit d3135dcfa6
24 changed files with 397 additions and 202 deletions

View file

@ -58,6 +58,8 @@
#include <AutoUpdater.h>
#include <DeferredLightingEffect.h>
#include <DependencyManager.h>
#include <plugins/PluginContainer.h>
#include <plugins/PluginManager.h>
#include <display-plugins/DisplayPlugin.h>
#include <EntityScriptingInterface.h>
@ -148,6 +150,8 @@
#include "ui/overlays/Cube3DOverlay.h"
#include "PluginContainerProxy.h"
// ON WIndows PC, NVidia Optimus laptop, we want to enable NVIDIA GPU
// FIXME seems to be broken.
#if defined(Q_OS_WIN)
@ -301,7 +305,7 @@ bool setupEssentials(int& argc, char** argv) {
// continuing to overburden Application.cpp
Cube3DOverlay* _keyboardFocusHighlight{ nullptr };
int _keyboardFocusHighlightID{ -1 };
PluginContainer* _pluginContainer;
Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
QApplication(argc, argv),
@ -351,7 +355,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
_applicationOverlay()
{
setInstance(this);
Plugin::setContainer(this);
_pluginContainer = new PluginContainerProxy();
Plugin::setContainer(_pluginContainer);
#ifdef Q_OS_WIN
installNativeEventFilter(&MyNativeEventFilter::getInstance());
#endif
@ -1262,6 +1268,7 @@ void Application::resizeGL() {
// Possible change in aspect ratio
loadViewFrustum(_myCamera, _viewFrustum);
float fov = glm::radians(DEFAULT_FIELD_OF_VIEW_DEGREES);
// FIXME the aspect ratio for stereo displays is incorrect based on this.
float aspectRatio = aspect(_renderResolution);
_myCamera.setProjection(glm::perspective(fov, aspectRatio, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP));
}
@ -1421,7 +1428,15 @@ void Application::keyPressEvent(QKeyEvent* event) {
break;
case Qt::Key_Enter:
case Qt::Key_Return:
Menu::getInstance()->triggerOption(MenuOption::AddressBar);
if (isOption) {
if (_window->isFullScreen()) {
_pluginContainer->unsetFullscreen();
} else {
_pluginContainer->setFullscreen(nullptr);
}
} else {
Menu::getInstance()->triggerOption(MenuOption::AddressBar);
}
break;
case Qt::Key_B:
@ -4617,10 +4632,6 @@ void Application::checkSkeleton() {
}
}
bool Application::isForeground() {
return _isForeground && !getWindow()->isMinimized();
}
void Application::activeChanged(Qt::ApplicationState state) {
switch (state) {
case Qt::ApplicationActive:
@ -4726,6 +4737,10 @@ const DisplayPlugin * Application::getActiveDisplayPlugin() const {
return ((Application*)this)->getActiveDisplayPlugin();
}
bool _activatingDisplayPlugin{ false };
QVector<QPair<QString, QString>> _currentDisplayPluginActions;
QVector<QPair<QString, QString>> _currentInputPluginActions;
static void addDisplayPluginToMenu(DisplayPluginPointer displayPlugin, bool active = false) {
auto menu = Menu::getInstance();
@ -4747,9 +4762,6 @@ static void addDisplayPluginToMenu(DisplayPluginPointer displayPlugin, bool acti
Q_ASSERT(menu->menuItemExists(MenuOption::OutputMenu, name));
}
static QVector<QPair<QString, QString>> _currentDisplayPluginActions;
static bool _activatingDisplayPlugin{false};
void Application::updateDisplayMode() {
auto menu = Menu::getInstance();
auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins();
@ -4816,7 +4828,7 @@ void Application::updateDisplayMode() {
// Only show the hmd tools after the correct plugin has
// been activated so that it's UI is setup correctly
if (newPluginWantsHMDTools) {
showDisplayPluginsTools();
_pluginContainer->showDisplayPluginsTools();
}
if (oldDisplayPlugin) {
@ -4834,9 +4846,6 @@ void Application::updateDisplayMode() {
Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin");
}
static QVector<QPair<QString, QString>> _currentInputPluginActions;
static void addInputPluginToMenu(InputPluginPointer inputPlugin, bool active = false) {
auto menu = Menu::getInstance();
QString name = inputPlugin->getName();
@ -4910,42 +4919,6 @@ void Application::updateInputModes() {
//}
}
void Application::addMenu(const QString& menuName) {
Menu::getInstance()->addMenu(menuName);
}
void Application::removeMenu(const QString& menuName) {
Menu::getInstance()->removeMenu(menuName);
}
void Application::addMenuItem(const QString& path, const QString& name, std::function<void(bool)> onClicked, bool checkable, bool checked, const QString& groupName) {
auto menu = Menu::getInstance();
MenuWrapper* parentItem = menu->getMenu(path);
QAction* action = menu->addActionToQMenuAndActionHash(parentItem, name);
connect(action, &QAction::triggered, [=] {
onClicked(action->isChecked());
});
action->setCheckable(checkable);
action->setChecked(checked);
if (_activatingDisplayPlugin) {
_currentDisplayPluginActions.push_back({ path, name });
} else {
_currentInputPluginActions.push_back({ path, name });
}
}
void Application::removeMenuItem(const QString& menuName, const QString& menuItem) {
Menu::getInstance()->removeMenuItem(menuName, menuItem);
}
bool Application::isOptionChecked(const QString& name) {
return Menu::getInstance()->isOptionChecked(name);
}
void Application::setIsOptionChecked(const QString& path, bool checked) {
Menu::getInstance()->setIsOptionChecked(path, checked);
}
mat4 Application::getEyeProjection(int eye) const {
if (isHMDMode()) {
return getActiveDisplayPlugin()->getProjection((Eye)eye, _viewFrustum.getProjection());
@ -4978,89 +4951,6 @@ mat4 Application::getHMDSensorPose() const {
return mat4();
}
// FIXME there is a bug in the fullscreen setting, where leaving
// fullscreen does not restore the window frame, making it difficult
// or impossible to move or size the window.
// Additionally, setting fullscreen isn't hiding the menu on windows
// make it useless for stereoscopic modes.
void Application::setFullscreen(const QScreen* target) {
if (!_window->isFullScreen()) {
_savedGeometry = _window->geometry();
}
#ifdef Q_OS_MAC
_window->setGeometry(target->availableGeometry());
#endif
_window->windowHandle()->setScreen((QScreen*)target);
_window->showFullScreen();
#ifndef Q_OS_MAC
// also hide the QMainWindow's menuBar
QMenuBar* menuBar = _window->menuBar();
if (menuBar) {
menuBar->setVisible(false);
}
#endif
}
void Application::unsetFullscreen(const QScreen* avoid) {
_window->showNormal();
QRect targetGeometry = _savedGeometry;
if (avoid != nullptr) {
QRect avoidGeometry = avoid->geometry();
if (avoidGeometry.contains(targetGeometry.topLeft())) {
QScreen* newTarget = primaryScreen();
if (newTarget == avoid) {
foreach(auto screen, screens()) {
if (screen != avoid) {
newTarget = screen;
break;
}
}
}
targetGeometry = newTarget->availableGeometry();
}
}
#ifdef Q_OS_MAC
QTimer* timer = new QTimer();
timer->singleShot(2000, [=] {
_window->setGeometry(targetGeometry);
timer->deleteLater();
});
#else
_window->setGeometry(targetGeometry);
#endif
#ifndef Q_OS_MAC
// also show the QMainWindow's menuBar
QMenuBar* menuBar = _window->menuBar();
if (menuBar) {
menuBar->setVisible(true);
}
#endif
}
void Application::showDisplayPluginsTools() {
DependencyManager::get<DialogsManager>()->hmdTools(true);
}
QGLWidget* Application::getPrimarySurface() {
return _glWidget;
}
void Application::setActiveDisplayPlugin(const QString& pluginName) {
auto menu = Menu::getInstance();
foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) {
QString name = displayPlugin->getName();
QAction* action = menu->getActionForOption(name);
if (pluginName == name) {
action->setChecked(true);
}
}
updateDisplayMode();
}
void Application::setPalmData(Hand* hand, UserInputMapper::PoseValue pose, float deltaTime, int index) {
PalmData* palm;
bool foundHand = false;

View file

@ -26,18 +26,18 @@
#include <EntityEditPacketSender.h>
#include <EntityTreeRenderer.h>
#include <GeometryCache.h>
#include <input-plugins/KeyboardMouseDevice.h>
#include <NodeList.h>
#include <OctreeQuery.h>
#include <OffscreenUi.h>
#include <PhysicalEntitySimulation.h>
#include <PhysicsEngine.h>
#include <plugins/Forward.h>
#include <ScriptEngine.h>
#include <ShapeManager.h>
#include <StDev.h>
#include <udt/PacketHeaders.h>
#include <ViewFrustum.h>
#include <plugins/PluginContainer.h>
#include <plugins/PluginManager.h>
#include <SimpleMovingAverage.h>
#include "AudioClient.h"
@ -50,7 +50,6 @@
#include "Stars.h"
#include "avatar/Avatar.h"
#include "avatar/MyAvatar.h"
#include <input-plugins/KeyboardMouseDevice.h>
#include "scripting/ControllerScriptingInterface.h"
#include "scripting/DialogsManagerScriptingInterface.h"
#include "scripting/WebWindowClass.h"
@ -132,7 +131,7 @@ class Application;
typedef bool (Application::* AcceptURLMethod)(const QString &);
class Application : public QApplication, public AbstractViewStateInterface, public AbstractScriptingServicesInterface, PluginContainer {
class Application : public QApplication, public AbstractViewStateInterface, public AbstractScriptingServicesInterface {
Q_OBJECT
friend class OctreePacketProcessor;
@ -280,23 +279,10 @@ public:
virtual void endOverrideEnvironmentData() { _environment.endOverride(); }
virtual qreal getDevicePixelRatio();
// Plugin container support
virtual void addMenu(const QString& menuName);
virtual void removeMenu(const QString& menuName);
virtual void addMenuItem(const QString& path, const QString& name, std::function<void(bool)> onClicked, bool checkable, bool checked, const QString& groupName);
virtual void removeMenuItem(const QString& menuName, const QString& menuItem);
virtual bool isOptionChecked(const QString& name);
virtual void setIsOptionChecked(const QString& path, bool checked);
virtual void setFullscreen(const QScreen* target) override;
virtual void unsetFullscreen(const QScreen* avoid) override;
virtual void showDisplayPluginsTools() override;
virtual QGLWidget* getPrimarySurface() override;
virtual bool isForeground() override;
void setActiveDisplayPlugin(const QString& pluginName);
DisplayPlugin * getActiveDisplayPlugin();
const DisplayPlugin * getActiveDisplayPlugin() const;
DisplayPlugin* getActiveDisplayPlugin();
const DisplayPlugin* getActiveDisplayPlugin() const;
public:
@ -691,6 +677,8 @@ private:
int _simsPerSecondReport = 0;
quint64 _lastSimsPerSecondUpdate = 0;
bool _isForeground = true; // starts out assumed to be in foreground
friend class PluginContainerProxy;
};
#endif // hifi_Application_h

View file

@ -16,11 +16,13 @@
#include <AddressManager.h>
#include <AudioClient.h>
#include <DependencyManager.h>
#include <display-plugins/DisplayPlugin.h>
#include <PathUtils.h>
#include <SettingHandle.h>
#include <UserActivityLogger.h>
#include <VrMenu.h>
#include "Application.h"
#include "AccountManager.h"
#include "audio/AudioScope.h"
@ -220,7 +222,7 @@ Menu::Menu() {
addActionToQMenuAndActionHash(toolsMenu, MenuOption::PackageModel, 0,
qApp, SLOT(packageModel()));
MenuWrapper* displayMenu = addMenu("Display");
MenuWrapper* displayMenu = addMenu(DisplayPlugin::MENU_PATH);
{
MenuWrapper* displayModeMenu = addMenu(MenuOption::OutputMenu);
QActionGroup* displayModeGroup = new QActionGroup(displayModeMenu);

View file

@ -0,0 +1,161 @@
#include "PluginContainerProxy.h"
#include <QScreen>
#include <QWindow>
#include <plugins/Plugin.h>
#include <plugins/PluginManager.h>
#include <display-plugins/DisplayPlugin.h>
#include "Application.h"
#include "MainWindow.h"
#include "GLCanvas.h"
#include "ui/DialogsManager.h"
PluginContainerProxy::PluginContainerProxy() {
Plugin::setContainer(this);
}
bool PluginContainerProxy::isForeground() {
return qApp->_isForeground && !qApp->getWindow()->isMinimized();
}
void PluginContainerProxy::addMenu(const QString& menuName) {
Menu::getInstance()->addMenu(menuName);
}
void PluginContainerProxy::removeMenu(const QString& menuName) {
Menu::getInstance()->removeMenu(menuName);
}
extern bool _activatingDisplayPlugin;
extern QVector<QPair<QString, QString>> _currentDisplayPluginActions;
extern QVector<QPair<QString, QString>> _currentInputPluginActions;
std::map<QString, QActionGroup*> _exclusiveGroups;
QAction* PluginContainerProxy::addMenuItem(const QString& path, const QString& name, std::function<void(bool)> onClicked, bool checkable, bool checked, const QString& groupName) {
auto menu = Menu::getInstance();
MenuWrapper* parentItem = menu->getMenu(path);
QAction* action = menu->addActionToQMenuAndActionHash(parentItem, name);
if (!groupName.isEmpty()) {
QActionGroup* group{ nullptr };
if (!_exclusiveGroups.count(groupName)) {
group = _exclusiveGroups[groupName] = new QActionGroup(menu);
group->setExclusive(true);
} else {
group = _exclusiveGroups[groupName];
}
group->addAction(action);
}
connect(action, &QAction::triggered, [=] {
onClicked(action->isChecked());
});
action->setCheckable(checkable);
action->setChecked(checked);
if (_activatingDisplayPlugin) {
_currentDisplayPluginActions.push_back({ path, name });
} else {
_currentInputPluginActions.push_back({ path, name });
}
return action;
}
void PluginContainerProxy::removeMenuItem(const QString& menuName, const QString& menuItem) {
Menu::getInstance()->removeMenuItem(menuName, menuItem);
}
bool PluginContainerProxy::isOptionChecked(const QString& name) {
return Menu::getInstance()->isOptionChecked(name);
}
void PluginContainerProxy::setIsOptionChecked(const QString& path, bool checked) {
Menu::getInstance()->setIsOptionChecked(path, checked);
}
// FIXME there is a bug in the fullscreen setting, where leaving
// fullscreen does not restore the window frame, making it difficult
// or impossible to move or size the window.
// Additionally, setting fullscreen isn't hiding the menu on windows
// make it useless for stereoscopic modes.
void PluginContainerProxy::setFullscreen(const QScreen* target, bool hideMenu) {
auto _window = qApp->_window;
if (!_window->isFullScreen()) {
_savedGeometry = _window->geometry();
}
if (nullptr == target) {
// FIXME target the screen where the window currently is
target = qApp->primaryScreen();
}
_window->setGeometry(target->availableGeometry());
_window->windowHandle()->setScreen((QScreen*)target);
_window->showFullScreen();
#ifndef Q_OS_MAC
// also hide the QMainWindow's menuBar
QMenuBar* menuBar = _window->menuBar();
if (menuBar && hideMenu) {
menuBar->setVisible(false);
}
#endif
}
void PluginContainerProxy::unsetFullscreen(const QScreen* avoid) {
auto _window = qApp->_window;
_window->showNormal();
QRect targetGeometry = _savedGeometry;
if (avoid != nullptr) {
QRect avoidGeometry = avoid->geometry();
if (avoidGeometry.contains(targetGeometry.topLeft())) {
QScreen* newTarget = qApp->primaryScreen();
if (newTarget == avoid) {
foreach(auto screen, qApp->screens()) {
if (screen != avoid) {
newTarget = screen;
break;
}
}
}
targetGeometry = newTarget->availableGeometry();
}
}
#ifdef Q_OS_MAC
QTimer* timer = new QTimer();
timer->singleShot(2000, [=] {
_window->setGeometry(targetGeometry);
timer->deleteLater();
});
#else
_window->setGeometry(targetGeometry);
#endif
#ifndef Q_OS_MAC
// also show the QMainWindow's menuBar
QMenuBar* menuBar = _window->menuBar();
if (menuBar) {
menuBar->setVisible(true);
}
#endif
}
void PluginContainerProxy::showDisplayPluginsTools() {
DependencyManager::get<DialogsManager>()->hmdTools(true);
}
QGLWidget* PluginContainerProxy::getPrimarySurface() {
return qApp->_glWidget;
}
void Application::setActiveDisplayPlugin(const QString& pluginName) {
auto menu = Menu::getInstance();
foreach(DisplayPluginPointer displayPlugin, PluginManager::getInstance()->getDisplayPlugins()) {
QString name = displayPlugin->getName();
QAction* action = menu->getActionForOption(name);
if (pluginName == name) {
action->setChecked(true);
}
}
updateDisplayMode();
}

View file

@ -0,0 +1,30 @@
#pragma once
#ifndef hifi_PluginContainerProxy_h
#define hifi_PluginContainerProxy_h
#include <QObject>
#include <QRect>
#include <plugins/Forward.h>
#include <plugins/PluginContainer.h>
class PluginContainerProxy : public QObject, PluginContainer {
Q_OBJECT
PluginContainerProxy();
virtual void addMenu(const QString& menuName) override;
virtual void removeMenu(const QString& menuName) override;
virtual QAction* addMenuItem(const QString& path, const QString& name, std::function<void(bool)> onClicked, bool checkable = false, bool checked = false, const QString& groupName = "") override;
virtual void removeMenuItem(const QString& menuName, const QString& menuItem) override;
virtual bool isOptionChecked(const QString& name) override;
virtual void setIsOptionChecked(const QString& path, bool checked);
virtual void setFullscreen(const QScreen* targetScreen, bool hideMenu = true) override;
virtual void unsetFullscreen(const QScreen* avoidScreen = nullptr) override;
virtual void showDisplayPluginsTools() override;
virtual QGLWidget* getPrimarySurface() override;
virtual bool isForeground() override;
QRect _savedGeometry{ 10, 120, 800, 600 };
friend class Application;
};
#endif

View file

@ -13,7 +13,6 @@
const QString Basic2DWindowOpenGLDisplayPlugin::NAME("2D Display");
static const QString MENU_PATH = "Display";
static const QString FULLSCREEN = "Fullscreen";
const QString& Basic2DWindowOpenGLDisplayPlugin::getName() const {

View file

@ -18,6 +18,8 @@
#include "oculus/OculusDisplayPlugin.h"
#include "oculus/OculusLegacyDisplayPlugin.h"
const QString DisplayPlugin::MENU_PATH{ "Display" };
// TODO migrate to a DLL model where plugins are discovered and loaded at runtime by the PluginManager class
DisplayPluginList getDisplayPlugins() {
DisplayPlugin* PLUGIN_POOL[] = {
@ -27,9 +29,11 @@ DisplayPluginList getDisplayPlugins() {
#endif
// Stereo modes
// FIXME fix stereo display plugins
// SBS left/right
new SideBySideStereoDisplayPlugin(),
//new InterleavedStereoDisplayPlugin(),
// Interleaved left/right
new InterleavedStereoDisplayPlugin(),
// HMDs

View file

@ -115,7 +115,7 @@ public:
virtual void resetSensors() {}
virtual float devicePixelRatio() { return 1.0; }
static const QString MENU_PATH;
signals:
void recommendedFramebufferSizeChanged(const QSize & size);
void requestRender();

View file

@ -105,7 +105,7 @@ bool OpenGLDisplayPlugin::eventFilter(QObject* receiver, QEvent* event) {
void OpenGLDisplayPlugin::display(
GLuint finalTexture, const glm::uvec2& sceneSize) {
using namespace oglplus;
uvec2 size = getRecommendedRenderSize();
uvec2 size = getSurfaceSize();
Context::Viewport(size.x, size.y);
glBindTexture(GL_TEXTURE_2D, finalTexture);
drawUnitQuad();

View file

@ -33,6 +33,7 @@ public:
protected:
virtual void customizeContext();
virtual void drawUnitQuad();
virtual glm::uvec2 getSurfaceSize() const = 0;
virtual void makeCurrent() = 0;
virtual void doneCurrent() = 0;
virtual void swapBuffers() = 0;

View file

@ -16,6 +16,10 @@ WindowOpenGLDisplayPlugin::WindowOpenGLDisplayPlugin() {
}
glm::uvec2 WindowOpenGLDisplayPlugin::getRecommendedRenderSize() const {
return getSurfaceSize();
}
glm::uvec2 WindowOpenGLDisplayPlugin::getSurfaceSize() const {
uvec2 result;
if (_window) {
result = toGlm(_window->geometry().size() * _window->devicePixelRatio());
@ -23,6 +27,7 @@ glm::uvec2 WindowOpenGLDisplayPlugin::getRecommendedRenderSize() const {
return result;
}
glm::uvec2 WindowOpenGLDisplayPlugin::getRecommendedUiSize() const {
uvec2 result;
if (_window) {

View file

@ -21,6 +21,7 @@ public:
virtual void deactivate() override;
protected:
virtual glm::uvec2 getSurfaceSize() const override final;
virtual void makeCurrent() override;
virtual void doneCurrent() override;
virtual void swapBuffers() override;

View file

@ -17,6 +17,42 @@
#include <gpu/GLBackend.h>
static const char * INTERLEAVED_TEXTURED_VS = R"VS(#version 410 core
#pragma line __LINE__
in vec3 Position;
in vec2 TexCoord;
out vec2 vTexCoord;
void main() {
gl_Position = vec4(Position, 1);
vTexCoord = TexCoord;
}
)VS";
static const char * INTERLEAVED_TEXTURED_FS = R"FS(#version 410 core
#pragma line __LINE__
uniform sampler2D sampler;
uniform ivec2 textureSize;
in vec2 vTexCoord;
out vec4 FragColor;
void main() {
ivec2 texCoord = ivec2(floor(vTexCoord * textureSize));
texCoord.x /= 2;
int row = int(floor(gl_FragCoord.y));
if (row % 2 > 0) {
texCoord.x += (textureSize.x / 2);
}
FragColor = texelFetch(sampler, texCoord, 0); //texture(sampler, texCoord);
}
)FS";
const QString InterleavedStereoDisplayPlugin::NAME("Interleaved Stereo Display");
const QString & InterleavedStereoDisplayPlugin::getName() const {
@ -29,5 +65,20 @@ InterleavedStereoDisplayPlugin::InterleavedStereoDisplayPlugin() {
void InterleavedStereoDisplayPlugin::customizeContext() {
StereoDisplayPlugin::customizeContext();
// Set up the stencil buffers? Or use a custom shader?
compileProgram(_program, INTERLEAVED_TEXTURED_VS, INTERLEAVED_TEXTURED_FS);
}
glm::uvec2 InterleavedStereoDisplayPlugin::getRecommendedRenderSize() const {
uvec2 result = WindowOpenGLDisplayPlugin::getRecommendedRenderSize();
result.x *= 2;
result.y /= 2;
return result;
}
void InterleavedStereoDisplayPlugin::display(
GLuint finalTexture, const glm::uvec2& sceneSize) {
using namespace oglplus;
_program->Bind();
Uniform<ivec2>(*_program, "textureSize").SetValue(sceneSize);
WindowOpenGLDisplayPlugin::display(finalTexture, sceneSize);
}

View file

@ -18,6 +18,9 @@ public:
// initialize OpenGL context settings needed by the plugin
virtual void customizeContext() override;
virtual glm::uvec2 getRecommendedRenderSize() const override;
void display(GLuint finalTexture, const glm::uvec2& sceneSize) override;
private:
static const QString NAME;
};

View file

@ -21,9 +21,6 @@
const QString SideBySideStereoDisplayPlugin::NAME("3D TV - Side by Side Stereo");
static const QString MENU_PATH = "Display";
static const QString FULLSCREEN = "Fullscreen";
const QString & SideBySideStereoDisplayPlugin::getName() const {
return NAME;
}
@ -31,20 +28,10 @@ const QString & SideBySideStereoDisplayPlugin::getName() const {
SideBySideStereoDisplayPlugin::SideBySideStereoDisplayPlugin() {
}
void SideBySideStereoDisplayPlugin::activate() {
CONTAINER->addMenu(MENU_PATH);
CONTAINER->addMenuItem(MENU_PATH, FULLSCREEN,
[this](bool clicked) {
if (clicked) {
CONTAINER->setFullscreen(getFullscreenTarget());
} else {
CONTAINER->unsetFullscreen();
}
}, true, false);
StereoDisplayPlugin::activate();
glm::uvec2 SideBySideStereoDisplayPlugin::getRecommendedRenderSize() const {
uvec2 result = WindowOpenGLDisplayPlugin::getRecommendedRenderSize();
result.x *= 2;
return result;
}
// FIXME target the screen the window is currently on
QScreen* SideBySideStereoDisplayPlugin::getFullscreenTarget() {
return qApp->primaryScreen();
}

View file

@ -16,8 +16,7 @@ class SideBySideStereoDisplayPlugin : public StereoDisplayPlugin {
public:
SideBySideStereoDisplayPlugin();
virtual const QString& getName() const override;
virtual void activate() override;
virtual glm::uvec2 getRecommendedRenderSize() const override;
private:
QScreen* getFullscreenTarget();
static const QString NAME;
};

View file

@ -10,11 +10,14 @@
#include <QApplication>
#include <QDesktopWidget>
#include <QAction>
#include <gpu/GLBackend.h>
#include <ViewFrustum.h>
#include <MatrixStack.h>
#include <plugins/PluginContainer.h>
#include <QGuiApplication>
#include <QScreen>
StereoDisplayPlugin::StereoDisplayPlugin() {
}
@ -29,11 +32,14 @@ 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 {
// FIXME check for mono eye and provide a combined matrix, needed for proper
// culling
// 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.
if (eye == Mono) {
// FIXME provide a combined matrix, needed for proper culling
return baseProjection;
}
float nearZ = DEFAULT_NEAR_CLIP; // near clipping plane
float screenZ = 0.25f; // screen projection plane
// FIXME verify this is the right calculation
@ -52,10 +58,36 @@ glm::mat4 StereoDisplayPlugin::getEyePose(Eye eye) const {
return glm::translate(mat4(), vec3(modelviewShift, 0, 0));
}
std::vector<QAction*> _screenActions;
void StereoDisplayPlugin::activate() {
auto screens = qApp->screens();
_screenActions.resize(screens.size());
for (int i = 0; i < screens.size(); ++i) {
auto screen = screens.at(i);
QString name = QString("Screen %1: %2").arg(i + 1).arg(screen->name());
bool checked = false;
if (screen == qApp->primaryScreen()) {
checked = true;
}
auto action = CONTAINER->addMenuItem(MENU_PATH, name,
[this](bool clicked) { updateScreen(); }, true, checked, "Screens");
_screenActions[i] = action;
}
CONTAINER->setFullscreen(qApp->primaryScreen());
WindowOpenGLDisplayPlugin::activate();
// FIXME there is a bug in the fullscreen setting, see
// Application::setFullscreen
//CONTAINER->setFullscreen(qApp->primaryScreen());
// FIXME Add menu items
}
void StereoDisplayPlugin::updateScreen() {
for (int i = 0; i < _screenActions.size(); ++i) {
if (_screenActions[i]->isChecked()) {
CONTAINER->setFullscreen(qApp->screens().at(i));
break;
}
}
}
void StereoDisplayPlugin::deactivate() {
_screenActions.clear();
CONTAINER->unsetFullscreen();
WindowOpenGLDisplayPlugin::deactivate();
}

View file

@ -17,10 +17,12 @@ public:
virtual bool isSupported() const override final;
virtual void activate() override;
virtual void deactivate() override;
virtual glm::mat4 getProjection(Eye eye, const glm::mat4& baseProjection) const override;
virtual glm::mat4 getEyePose(Eye eye) const override;
protected:
void updateScreen();
float _ipd{ 0.064f };
};

View file

@ -0,0 +1,23 @@
//
// Created by Bradley Austin Davis on 2015/08/08
// 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 <QList>
#include <QVector>
#include <QSharedPointer>
class DisplayPlugin;
class InputPlugin;
class Plugin;
class PluginContainer;
class PluginManager;
using DisplayPluginPointer = QSharedPointer<DisplayPlugin>;
using DisplayPluginList = QVector<DisplayPluginPointer>;
using InputPluginPointer = QSharedPointer<InputPlugin>;
using InputPluginList = QVector<InputPluginPointer>;

View file

@ -1,3 +1,10 @@
//
// Created by Bradley Austin Davis on 2015/08/08
// 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 "Plugin.h"
PluginContainer* Plugin::CONTAINER{ nullptr };

View file

@ -1,9 +1,16 @@
//
// Created by Bradley Austin Davis on 2015/08/08
// 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 <QString>
#include <QObject>
class PluginContainer;
#include "Forward.h"
class Plugin : public QObject {
public:

View file

@ -7,9 +7,10 @@
//
#pragma once
#include <QString>
#include <functional>
#include <QString>
class QAction;
class QGLWidget;
class QScreen;
@ -18,11 +19,11 @@ public:
PluginContainer();
virtual void addMenu(const QString& menuName) = 0;
virtual void removeMenu(const QString& menuName) = 0;
virtual void addMenuItem(const QString& path, const QString& name, std::function<void(bool)> onClicked, bool checkable = false, bool checked = false, const QString& groupName = "") = 0;
virtual QAction* addMenuItem(const QString& path, const QString& name, std::function<void(bool)> onClicked, bool checkable = false, bool checked = false, const QString& groupName = "") = 0;
virtual void removeMenuItem(const QString& menuName, const QString& menuItem) = 0;
virtual bool isOptionChecked(const QString& name) = 0;
virtual void setIsOptionChecked(const QString& path, bool checked) = 0;
virtual void setFullscreen(const QScreen* targetScreen) = 0;
virtual void setFullscreen(const QScreen* targetScreen, bool hideMenu = false) = 0;
virtual void unsetFullscreen(const QScreen* avoidScreen = nullptr) = 0;
virtual void showDisplayPluginsTools() = 0;
virtual QGLWidget* getPrimarySurface() = 0;

View file

@ -1,7 +1,13 @@
//
// Created by Bradley Austin Davis on 2015/08/08
// 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 "PluginManager.h"
#include <mutex>
PluginManager* PluginManager::getInstance() {
static PluginManager _manager;
return &_manager;

View file

@ -1,17 +1,13 @@
//
// Created by Bradley Austin Davis on 2015/08/08
// 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 "Plugin.h"
#include <QList>
#include <QVector>
#include <QSharedPointer>
class DisplayPlugin;
class InputPlugin;
using DisplayPluginPointer = QSharedPointer<DisplayPlugin>;
using DisplayPluginList = QVector<DisplayPluginPointer>;
using InputPluginPointer = QSharedPointer<InputPlugin>;
using InputPluginList = QVector<InputPluginPointer>;
#include "Forward.h"
class PluginManager : public QObject {
public: