Making (most) plugins into a library

This commit is contained in:
Brad Davis 2015-05-29 16:49:11 -07:00
parent 8686ffb781
commit 912c003d58
44 changed files with 889 additions and 728 deletions

View file

@ -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()

View file

@ -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)

View file

@ -116,7 +116,7 @@
#include "gpu/Batch.h"
#include "gpu/GLBackend.h"
#include "plugins/display/DisplayPlugin.h"
#include <display-plugins/DisplayPlugin.h>
#include "scripting/AccountScriptingInterface.h"
#include "scripting/AudioDeviceScriptingInterface.h"
@ -4582,12 +4582,11 @@ qreal Application::getDevicePixelRatio() {
using DisplayPluginPointer = QSharedPointer<DisplayPlugin>;
#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 <display-plugins/NullDisplayPlugin.h>
#include "LegacyDisplayPlugin.h"
//#include <display-plugins/Oculus.h>
#include <display-plugins/Tv3dDisplayPlugin.h>
//#include <display-plugins/WindowDisplayPlugin.h>
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<OffscreenUi>().data());
pluginWindow->installEventFilter(qApp);
DependencyManager::get<OffscreenUi>()->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<void()> onClicked, bool checkable, bool checked, const QString& groupName) {
}

View file

@ -40,6 +40,7 @@
#include <StDev.h>
#include <TextureCache.h>
#include <ViewFrustum.h>
#include <plugins/PluginContainer.h>
#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<void()> 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

View file

@ -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<OffscreenUi>().data());
DependencyManager::get<OffscreenUi>()->setProxyWindow(_window->windowHandle());
SimpleDisplayPlugin::activate();
_timer.start(8);
}
void LegacyDisplayPlugin::deactivate() {
_timer.stop();
_window->removeEventFilter(DependencyManager::get<OffscreenUi>().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();
}
}
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();
}

View file

@ -9,26 +9,36 @@
//
#pragma once
#include "SimpleDisplayPlugin.h"
#include <display-plugins/OpenGlDisplayPlugin.h>
#include "GLCanvas.h"
class LegacyDisplayPlugin : public SimpleDisplayPlugin<GLCanvas> {
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;
};

View file

@ -34,7 +34,6 @@
#include <UserActivityLogger.h>
#include "Application.h"
#include "plugins/display/DisplayPlugin.h"
#include "AvatarManager.h"
#include "Environment.h"
#include "Menu.h"

View file

@ -1 +0,0 @@
#include "Plugin.h"

View file

@ -1,22 +0,0 @@
#pragma once
#include <QString>
#include <QObject>
class PluginContainer {
virtual void addMenuItem(const QString& path, std::function<void()> 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() {}
};

View file

@ -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"

View file

@ -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; }
};

View file

@ -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 <QOpenGLContext>
#include <QCursor>
#include <QCoreApplication>
#include <RenderUtil.h>
#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<OffscreenUi>();
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<OffscreenUi>()->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();
}

View file

@ -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 <QCursor>
#include <QOpenGLContext>
#include <GLMHelpers.h>
#include <RenderUtil.h>
#include <GlWindow.h>
class SimpleGlDisplayPlugin : public DisplayPlugin {
public:
virtual void activate();
virtual void display(GLuint sceneTexture, const glm::uvec2& sceneSize,
GLuint overlayTexture, const glm::uvec2& overlaySize);
};
template <typename T>
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<GlWindow> {
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);
};

View file

@ -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"

View file

@ -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; }
};

View file

@ -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 <GlWindow.h>
#include <QApplication>
#include <QDesktopWidget>
#include "gpu/Texture.h"
#include "gpu/GLBackend.h"
#include "PathUtils.h"
#include "Application.h"
#include "ui/ApplicationOverlay.h"
#include <GL/glew.h>
#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 <oglplus/gl.hpp>
#pragma warning(disable : 4068)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
#pragma warning( disable : 4244 4267 4065 4101)
#include <oglplus/all.hpp>
#include <oglplus/interop/glm.hpp>
#include <oglplus/bound/texture.hpp>
#include <oglplus/bound/framebuffer.hpp>
#include <oglplus/bound/renderbuffer.hpp>
#include <oglplus/shapes/wrapper.hpp>
#include <oglplus/shapes/plane.hpp>
#pragma warning( default : 4244 4267 4065 4101)
#pragma clang diagnostic pop
typedef std::shared_ptr<oglplus::shapes::ShapeWrapper> ShapeWrapperPtr;
typedef std::shared_ptr<oglplus::Buffer> BufferPtr;
typedef std::shared_ptr<oglplus::VertexArray> VertexArrayPtr;
typedef std::shared_ptr<oglplus::Program> ProgramPtr;
typedef oglplus::Uniform<mat4> 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<TextureCache>()->
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();
}

View file

@ -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();
}

View file

@ -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})

View file

@ -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.

View file

@ -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";

View file

@ -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 <GLMHelpers.h>
#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 <oglplus/shapes/plane.hpp>
typedef std::shared_ptr<oglplus::Framebuffer> FramebufferPtr;
typedef std::shared_ptr<oglplus::shapes::ShapeWrapper> ShapeWrapperPtr;
typedef std::shared_ptr<oglplus::Buffer> BufferPtr;
typedef std::shared_ptr<oglplus::VertexArray> VertexArrayPtr;
typedef std::shared_ptr<oglplus::Program> ProgramPtr;
typedef oglplus::Uniform<mat4> Mat4Uniform;
ProgramPtr loadDefaultShader();
void compileProgram(ProgramPtr & result, const std::string& vs, const std::string& fs);
ShapeWrapperPtr loadPlane(ProgramPtr program, float aspect = 1.0f);

View file

@ -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()))));
}
}

View file

@ -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<QPointF(const QPointF&)> 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() {}
};

View file

@ -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 <QOpenGLContext>
#include <QCursor>
#include <QTimer>
#include <QCoreApplication>
#include <GLWindow.h>
#include <GLMHelpers.h>
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<OffscreenUi>();
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<OffscreenUi>()->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();
}

View file

@ -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 };
};

View file

@ -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() {}

View file

@ -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();
};

View file

@ -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 <ViewFrustum.h>
#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 =

View file

@ -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 <OVR_CAPI.h>
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;

View file

@ -7,11 +7,16 @@
//
#include "OculusWin32DisplayPlugin.h"
#include <memory>
#include <GLMHelpers.h>
#include <OVR_CAPI_GL.h>
#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 <typename C = GLuint, typename D = GLuint>
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<MirrorFramebufferWrapper>;
#endif

View file

@ -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.

View file

@ -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 <QOpenGLContext>
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();
}

View file

@ -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;
};

View file

@ -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 <QApplication>
#include <QDesktopWidget>
#include <GlWindow.h>
#include <ViewFrustum.h>
#include <MatrixStack.h>
#include <PathUtils.h>
#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<TextureCache>()->
// 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();
}

View file

@ -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 <QTimer>
#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<QPointF(const QPointF&)> getMouseTranslator();
//virtual glm::ivec2 trueMouseToUiMouse(const glm::ivec2 & position) const;
private:
QTimer _timer;
};

View file

@ -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;
}

View file

@ -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 <GlWindow.h>
#include <QTimer>
#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;
};

View file

@ -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)

View file

@ -1,20 +0,0 @@
#pragma once
#include <QString>
#include <QObject>
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() {}
};

View file

@ -0,0 +1,9 @@
#include "Plugin.h"
bool Plugin::isSupported() const { return true; }
void Plugin::init() {}
void Plugin::deinit() {}
void Plugin::idle() {}

View file

@ -0,0 +1,29 @@
#pragma once
#include <QString>
#include <QObject>
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();
};

View file

@ -1,12 +1,10 @@
#pragma once
#include "plugins/Plugin.h"
#include "plugins/display/DisplayPlugin.h"
#include "Plugin.h"
#include <QList>
#include <QSharedPointer>
class PluginManager : public QObject {
public:
static PluginManager * getInstance();
const QList<QSharedPointer<DisplayPlugin>> getDisplayPlugins();
};