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 <AutoUpdater.h>
#include <DeferredLightingEffect.h> #include <DeferredLightingEffect.h>
#include <DependencyManager.h> #include <DependencyManager.h>
#include <plugins/PluginContainer.h>
#include <plugins/PluginManager.h>
#include <display-plugins/DisplayPlugin.h> #include <display-plugins/DisplayPlugin.h>
#include <EntityScriptingInterface.h> #include <EntityScriptingInterface.h>
@ -148,6 +150,8 @@
#include "ui/overlays/Cube3DOverlay.h" #include "ui/overlays/Cube3DOverlay.h"
#include "PluginContainerProxy.h"
// ON WIndows PC, NVidia Optimus laptop, we want to enable NVIDIA GPU // ON WIndows PC, NVidia Optimus laptop, we want to enable NVIDIA GPU
// FIXME seems to be broken. // FIXME seems to be broken.
#if defined(Q_OS_WIN) #if defined(Q_OS_WIN)
@ -301,7 +305,7 @@ bool setupEssentials(int& argc, char** argv) {
// continuing to overburden Application.cpp // continuing to overburden Application.cpp
Cube3DOverlay* _keyboardFocusHighlight{ nullptr }; Cube3DOverlay* _keyboardFocusHighlight{ nullptr };
int _keyboardFocusHighlightID{ -1 }; int _keyboardFocusHighlightID{ -1 };
PluginContainer* _pluginContainer;
Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
QApplication(argc, argv), QApplication(argc, argv),
@ -351,7 +355,9 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
_applicationOverlay() _applicationOverlay()
{ {
setInstance(this); setInstance(this);
Plugin::setContainer(this);
_pluginContainer = new PluginContainerProxy();
Plugin::setContainer(_pluginContainer);
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
installNativeEventFilter(&MyNativeEventFilter::getInstance()); installNativeEventFilter(&MyNativeEventFilter::getInstance());
#endif #endif
@ -1262,6 +1268,7 @@ void Application::resizeGL() {
// Possible change in aspect ratio // Possible change in aspect ratio
loadViewFrustum(_myCamera, _viewFrustum); loadViewFrustum(_myCamera, _viewFrustum);
float fov = glm::radians(DEFAULT_FIELD_OF_VIEW_DEGREES); 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); float aspectRatio = aspect(_renderResolution);
_myCamera.setProjection(glm::perspective(fov, aspectRatio, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP)); _myCamera.setProjection(glm::perspective(fov, aspectRatio, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP));
} }
@ -1421,7 +1428,15 @@ void Application::keyPressEvent(QKeyEvent* event) {
break; break;
case Qt::Key_Enter: case Qt::Key_Enter:
case Qt::Key_Return: 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; break;
case Qt::Key_B: case Qt::Key_B:
@ -4617,10 +4632,6 @@ void Application::checkSkeleton() {
} }
} }
bool Application::isForeground() {
return _isForeground && !getWindow()->isMinimized();
}
void Application::activeChanged(Qt::ApplicationState state) { void Application::activeChanged(Qt::ApplicationState state) {
switch (state) { switch (state) {
case Qt::ApplicationActive: case Qt::ApplicationActive:
@ -4726,6 +4737,10 @@ const DisplayPlugin * Application::getActiveDisplayPlugin() const {
return ((Application*)this)->getActiveDisplayPlugin(); 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) { static void addDisplayPluginToMenu(DisplayPluginPointer displayPlugin, bool active = false) {
auto menu = Menu::getInstance(); auto menu = Menu::getInstance();
@ -4747,9 +4762,6 @@ static void addDisplayPluginToMenu(DisplayPluginPointer displayPlugin, bool acti
Q_ASSERT(menu->menuItemExists(MenuOption::OutputMenu, name)); Q_ASSERT(menu->menuItemExists(MenuOption::OutputMenu, name));
} }
static QVector<QPair<QString, QString>> _currentDisplayPluginActions;
static bool _activatingDisplayPlugin{false};
void Application::updateDisplayMode() { void Application::updateDisplayMode() {
auto menu = Menu::getInstance(); auto menu = Menu::getInstance();
auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins(); auto displayPlugins = PluginManager::getInstance()->getDisplayPlugins();
@ -4816,7 +4828,7 @@ void Application::updateDisplayMode() {
// Only show the hmd tools after the correct plugin has // Only show the hmd tools after the correct plugin has
// been activated so that it's UI is setup correctly // been activated so that it's UI is setup correctly
if (newPluginWantsHMDTools) { if (newPluginWantsHMDTools) {
showDisplayPluginsTools(); _pluginContainer->showDisplayPluginsTools();
} }
if (oldDisplayPlugin) { if (oldDisplayPlugin) {
@ -4834,9 +4846,6 @@ void Application::updateDisplayMode() {
Q_ASSERT_X(_displayPlugin, "Application::updateDisplayMode", "could not find an activated display plugin"); 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) { static void addInputPluginToMenu(InputPluginPointer inputPlugin, bool active = false) {
auto menu = Menu::getInstance(); auto menu = Menu::getInstance();
QString name = inputPlugin->getName(); 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 { mat4 Application::getEyeProjection(int eye) const {
if (isHMDMode()) { if (isHMDMode()) {
return getActiveDisplayPlugin()->getProjection((Eye)eye, _viewFrustum.getProjection()); return getActiveDisplayPlugin()->getProjection((Eye)eye, _viewFrustum.getProjection());
@ -4978,89 +4951,6 @@ mat4 Application::getHMDSensorPose() const {
return mat4(); 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) { void Application::setPalmData(Hand* hand, UserInputMapper::PoseValue pose, float deltaTime, int index) {
PalmData* palm; PalmData* palm;
bool foundHand = false; bool foundHand = false;

View file

@ -26,18 +26,18 @@
#include <EntityEditPacketSender.h> #include <EntityEditPacketSender.h>
#include <EntityTreeRenderer.h> #include <EntityTreeRenderer.h>
#include <GeometryCache.h> #include <GeometryCache.h>
#include <input-plugins/KeyboardMouseDevice.h>
#include <NodeList.h> #include <NodeList.h>
#include <OctreeQuery.h> #include <OctreeQuery.h>
#include <OffscreenUi.h> #include <OffscreenUi.h>
#include <PhysicalEntitySimulation.h> #include <PhysicalEntitySimulation.h>
#include <PhysicsEngine.h> #include <PhysicsEngine.h>
#include <plugins/Forward.h>
#include <ScriptEngine.h> #include <ScriptEngine.h>
#include <ShapeManager.h> #include <ShapeManager.h>
#include <StDev.h> #include <StDev.h>
#include <udt/PacketHeaders.h> #include <udt/PacketHeaders.h>
#include <ViewFrustum.h> #include <ViewFrustum.h>
#include <plugins/PluginContainer.h>
#include <plugins/PluginManager.h>
#include <SimpleMovingAverage.h> #include <SimpleMovingAverage.h>
#include "AudioClient.h" #include "AudioClient.h"
@ -50,7 +50,6 @@
#include "Stars.h" #include "Stars.h"
#include "avatar/Avatar.h" #include "avatar/Avatar.h"
#include "avatar/MyAvatar.h" #include "avatar/MyAvatar.h"
#include <input-plugins/KeyboardMouseDevice.h>
#include "scripting/ControllerScriptingInterface.h" #include "scripting/ControllerScriptingInterface.h"
#include "scripting/DialogsManagerScriptingInterface.h" #include "scripting/DialogsManagerScriptingInterface.h"
#include "scripting/WebWindowClass.h" #include "scripting/WebWindowClass.h"
@ -132,7 +131,7 @@ class Application;
typedef bool (Application::* AcceptURLMethod)(const QString &); 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 Q_OBJECT
friend class OctreePacketProcessor; friend class OctreePacketProcessor;
@ -280,23 +279,10 @@ public:
virtual void endOverrideEnvironmentData() { _environment.endOverride(); } virtual void endOverrideEnvironmentData() { _environment.endOverride(); }
virtual qreal getDevicePixelRatio(); 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); void setActiveDisplayPlugin(const QString& pluginName);
DisplayPlugin * getActiveDisplayPlugin(); DisplayPlugin* getActiveDisplayPlugin();
const DisplayPlugin * getActiveDisplayPlugin() const; const DisplayPlugin* getActiveDisplayPlugin() const;
public: public:
@ -691,6 +677,8 @@ private:
int _simsPerSecondReport = 0; int _simsPerSecondReport = 0;
quint64 _lastSimsPerSecondUpdate = 0; quint64 _lastSimsPerSecondUpdate = 0;
bool _isForeground = true; // starts out assumed to be in foreground bool _isForeground = true; // starts out assumed to be in foreground
friend class PluginContainerProxy;
}; };
#endif // hifi_Application_h #endif // hifi_Application_h

View file

@ -16,11 +16,13 @@
#include <AddressManager.h> #include <AddressManager.h>
#include <AudioClient.h> #include <AudioClient.h>
#include <DependencyManager.h> #include <DependencyManager.h>
#include <display-plugins/DisplayPlugin.h>
#include <PathUtils.h> #include <PathUtils.h>
#include <SettingHandle.h> #include <SettingHandle.h>
#include <UserActivityLogger.h> #include <UserActivityLogger.h>
#include <VrMenu.h> #include <VrMenu.h>
#include "Application.h" #include "Application.h"
#include "AccountManager.h" #include "AccountManager.h"
#include "audio/AudioScope.h" #include "audio/AudioScope.h"
@ -220,7 +222,7 @@ Menu::Menu() {
addActionToQMenuAndActionHash(toolsMenu, MenuOption::PackageModel, 0, addActionToQMenuAndActionHash(toolsMenu, MenuOption::PackageModel, 0,
qApp, SLOT(packageModel())); qApp, SLOT(packageModel()));
MenuWrapper* displayMenu = addMenu("Display"); MenuWrapper* displayMenu = addMenu(DisplayPlugin::MENU_PATH);
{ {
MenuWrapper* displayModeMenu = addMenu(MenuOption::OutputMenu); MenuWrapper* displayModeMenu = addMenu(MenuOption::OutputMenu);
QActionGroup* displayModeGroup = new QActionGroup(displayModeMenu); 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"); const QString Basic2DWindowOpenGLDisplayPlugin::NAME("2D Display");
static const QString MENU_PATH = "Display";
static const QString FULLSCREEN = "Fullscreen"; static const QString FULLSCREEN = "Fullscreen";
const QString& Basic2DWindowOpenGLDisplayPlugin::getName() const { const QString& Basic2DWindowOpenGLDisplayPlugin::getName() const {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -17,6 +17,42 @@
#include <gpu/GLBackend.h> #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::NAME("Interleaved Stereo Display");
const QString & InterleavedStereoDisplayPlugin::getName() const { const QString & InterleavedStereoDisplayPlugin::getName() const {
@ -29,5 +65,20 @@ InterleavedStereoDisplayPlugin::InterleavedStereoDisplayPlugin() {
void InterleavedStereoDisplayPlugin::customizeContext() { void InterleavedStereoDisplayPlugin::customizeContext() {
StereoDisplayPlugin::customizeContext(); StereoDisplayPlugin::customizeContext();
// Set up the stencil buffers? Or use a custom shader? // 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 // initialize OpenGL context settings needed by the plugin
virtual void customizeContext() override; virtual void customizeContext() override;
virtual glm::uvec2 getRecommendedRenderSize() const override;
void display(GLuint finalTexture, const glm::uvec2& sceneSize) override;
private: private:
static const QString NAME; static const QString NAME;
}; };

View file

@ -21,9 +21,6 @@
const QString SideBySideStereoDisplayPlugin::NAME("3D TV - Side by Side Stereo"); 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 { const QString & SideBySideStereoDisplayPlugin::getName() const {
return NAME; return NAME;
} }
@ -31,20 +28,10 @@ const QString & SideBySideStereoDisplayPlugin::getName() const {
SideBySideStereoDisplayPlugin::SideBySideStereoDisplayPlugin() { SideBySideStereoDisplayPlugin::SideBySideStereoDisplayPlugin() {
} }
void SideBySideStereoDisplayPlugin::activate() { glm::uvec2 SideBySideStereoDisplayPlugin::getRecommendedRenderSize() const {
CONTAINER->addMenu(MENU_PATH); uvec2 result = WindowOpenGLDisplayPlugin::getRecommendedRenderSize();
CONTAINER->addMenuItem(MENU_PATH, FULLSCREEN, result.x *= 2;
[this](bool clicked) { return result;
if (clicked) {
CONTAINER->setFullscreen(getFullscreenTarget());
} else {
CONTAINER->unsetFullscreen();
}
}, true, false);
StereoDisplayPlugin::activate();
} }
// 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: public:
SideBySideStereoDisplayPlugin(); SideBySideStereoDisplayPlugin();
virtual const QString& getName() const override; virtual const QString& getName() const override;
virtual void activate() override; virtual glm::uvec2 getRecommendedRenderSize() const override;
private: private:
QScreen* getFullscreenTarget();
static const QString NAME; static const QString NAME;
}; };

View file

@ -10,11 +10,14 @@
#include <QApplication> #include <QApplication>
#include <QDesktopWidget> #include <QDesktopWidget>
#include <QAction>
#include <gpu/GLBackend.h> #include <gpu/GLBackend.h>
#include <ViewFrustum.h> #include <ViewFrustum.h>
#include <MatrixStack.h> #include <MatrixStack.h>
#include <plugins/PluginContainer.h> #include <plugins/PluginContainer.h>
#include <QGuiApplication>
#include <QScreen>
StereoDisplayPlugin::StereoDisplayPlugin() { StereoDisplayPlugin::StereoDisplayPlugin() {
} }
@ -29,11 +32,14 @@ const float DEFAULT_IPD = 0.064f;
const float HALF_DEFAULT_IPD = DEFAULT_IPD / 2.0f; const float HALF_DEFAULT_IPD = DEFAULT_IPD / 2.0f;
glm::mat4 StereoDisplayPlugin::getProjection(Eye eye, const glm::mat4& baseProjection) const { 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 // 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. // 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 nearZ = DEFAULT_NEAR_CLIP; // near clipping plane
float screenZ = 0.25f; // screen projection plane float screenZ = 0.25f; // screen projection plane
// FIXME verify this is the right calculation // 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)); return glm::translate(mat4(), vec3(modelviewShift, 0, 0));
} }
std::vector<QAction*> _screenActions;
void StereoDisplayPlugin::activate() { 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(); WindowOpenGLDisplayPlugin::activate();
// FIXME there is a bug in the fullscreen setting, see }
// Application::setFullscreen
//CONTAINER->setFullscreen(qApp->primaryScreen()); void StereoDisplayPlugin::updateScreen() {
// FIXME Add menu items 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 bool isSupported() const override final;
virtual void activate() override; virtual void activate() override;
virtual void deactivate() override;
virtual glm::mat4 getProjection(Eye eye, const glm::mat4& baseProjection) const override; virtual glm::mat4 getProjection(Eye eye, const glm::mat4& baseProjection) const override;
virtual glm::mat4 getEyePose(Eye eye) const override; virtual glm::mat4 getEyePose(Eye eye) const override;
protected: protected:
void updateScreen();
float _ipd{ 0.064f }; 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" #include "Plugin.h"
PluginContainer* Plugin::CONTAINER{ nullptr }; 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 #pragma once
#include <QString> #include <QString>
#include <QObject> #include <QObject>
class PluginContainer; #include "Forward.h"
class Plugin : public QObject { class Plugin : public QObject {
public: public:

View file

@ -7,9 +7,10 @@
// //
#pragma once #pragma once
#include <QString>
#include <functional> #include <functional>
#include <QString>
class QAction;
class QGLWidget; class QGLWidget;
class QScreen; class QScreen;
@ -18,11 +19,11 @@ public:
PluginContainer(); PluginContainer();
virtual void addMenu(const QString& menuName) = 0; virtual void addMenu(const QString& menuName) = 0;
virtual void removeMenu(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 void removeMenuItem(const QString& menuName, const QString& menuItem) = 0;
virtual bool isOptionChecked(const QString& name) = 0; virtual bool isOptionChecked(const QString& name) = 0;
virtual void setIsOptionChecked(const QString& path, bool checked) = 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 unsetFullscreen(const QScreen* avoidScreen = nullptr) = 0;
virtual void showDisplayPluginsTools() = 0; virtual void showDisplayPluginsTools() = 0;
virtual QGLWidget* getPrimarySurface() = 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 "PluginManager.h"
#include <mutex> #include <mutex>
PluginManager* PluginManager::getInstance() { PluginManager* PluginManager::getInstance() {
static PluginManager _manager; static PluginManager _manager;
return &_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 #pragma once
#include "Plugin.h" #include "Forward.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>;
class PluginManager : public QObject { class PluginManager : public QObject {
public: public: