Moving OpenVR to external plugin and updating to latest version

This commit is contained in:
Brad Davis 2015-11-18 15:20:29 -08:00 committed by Bradley Austin Davis
parent a99542e298
commit 978d39b7f4
16 changed files with 175 additions and 128 deletions

View file

@ -7,9 +7,8 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER)
ExternalProject_Add(
${EXTERNAL_NAME}
#URL https://github.com/ValveSoftware/openvr/archive/0.9.1.zip
URL http://hifi-public.s3.amazonaws.com/dependencies/openvr-0.9.1.zip
URL_MD5 f986f5a6815e9454c53c5bf58ce02fdc
URL https://github.com/ValveSoftware/openvr/archive/v0.9.12.zip
URL_MD5 c08dced68ce4e341e1467e6814ae419d
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""

View file

@ -14,8 +14,6 @@
#include "stereo/InterleavedStereoDisplayPlugin.h"
#include "Basic2DWindowOpenGLDisplayPlugin.h"
#include "openvr/OpenVrDisplayPlugin.h"
const QString& DisplayPlugin::MENU_PATH() {
static const QString value = "Display";
return value;
@ -25,22 +23,14 @@ const QString& DisplayPlugin::MENU_PATH() {
DisplayPluginList getDisplayPlugins() {
DisplayPlugin* PLUGIN_POOL[] = {
new Basic2DWindowOpenGLDisplayPlugin(),
new NullDisplayPlugin(),
#ifdef DEBUG
new NullDisplayPlugin(),
#endif
// Stereo modes
// SBS left/right
new SideBySideStereoDisplayPlugin(),
// Interleaved left/right
new InterleavedStereoDisplayPlugin(),
// HMDs
//#ifdef Q_OS_WIN
// // SteamVR SDK
// new OpenVrDisplayPlugin(),
//#endif
nullptr
};

View file

@ -15,6 +15,7 @@
#include <QtOpenGL/QGLWidget>
#include <QtGui/QImage>
#include <QtGui/QOpenGLContext>
#include <gl/GLWidget.h>
#include <NumericalConstants.h>
@ -103,8 +104,12 @@ public:
// take the latest texture and present it
_context->makeCurrent();
currentPlugin->present();
_context->doneCurrent();
if (QOpenGLContext::currentContext() == _context->contextHandle()) {
_activePlugin->present();
_context->doneCurrent();
} else {
qWarning() << "Makecurrent failed";
}
}
_context->makeCurrent();

View file

@ -74,7 +74,7 @@ protected:
ProgramPtr _program;
ShapeWrapperPtr _plane;
Mutex _mutex;
mutable Mutex _mutex;
SimpleMovingAverage _usecsPerFrame { 10 };
QMap<uint32_t, uint32_t> _sceneTextureToFrameIndexMap;

View file

@ -1,15 +1,5 @@
set(TARGET_NAME input-plugins)
setup_hifi_library()
link_hifi_libraries(shared plugins controllers script-engine render-utils)
link_hifi_libraries(shared plugins controllers)
GroupSources("src/input-plugins")
if (WIN32)
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})
endif()
target_sdl2()
target_sixense()

View file

@ -15,7 +15,6 @@
#include "KeyboardMouseDevice.h"
#include "SDL2Manager.h"
#include "SixenseManager.h"
#include "ViveControllerManager.h"
// TODO migrate to a DLL model where plugins are discovered and loaded at runtime by the PluginManager class
InputPluginList getInputPlugins() {
@ -23,7 +22,6 @@ InputPluginList getInputPlugins() {
new KeyboardMouseDevice(),
new SDL2Manager(),
new SixenseManager(),
new ViveControllerManager(),
nullptr
};

View file

@ -82,7 +82,7 @@ void avatarDataFromScriptValue(const QScriptValue &object, AvatarData* &out) {
}
Q_DECLARE_METATYPE(controller::InputController*)
static int inputControllerPointerId = qRegisterMetaType<controller::InputController*>();
//static int inputControllerPointerId = qRegisterMetaType<controller::InputController*>();
QScriptValue inputControllerToScriptValue(QScriptEngine *engine, controller::InputController* const &in) {
return engine->newQObject(in);

View file

@ -0,0 +1,25 @@
#
# Created by Bradley Austin Davis on 2015/11/18
# 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
#
if (WIN32)
# we're using static GLEW, so define GLEW_STATIC
add_definitions(-DGLEW_STATIC)
set(TARGET_NAME openvr)
setup_hifi_plugin(OpenGL Script Qml Widgets)
link_hifi_libraries(shared gl networking controllers
plugins display-plugins input-plugins script-engine
render-utils model gpu render model-networking fbx)
include_hifi_library_headers(octree)
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})
endif()

View file

@ -7,24 +7,23 @@
//
#include "OpenVrDisplayPlugin.h"
#if defined(Q_OS_WIN)
#include <memory>
#include <QMainWindow>
#include <QLoggingCategory>
#include <QGLWidget>
#include <GLMHelpers.h>
#include <QEvent>
#include <QResizeEvent>
#include <GLMHelpers.h>
#include <gl/GlWindow.h>
#include <PerfStat.h>
#include <plugins/PluginContainer.h>
#include <ViewFrustum.h>
#include "OpenVrHelpers.h"
#include "GLMHelpers.h"
#include <QLoggingCategory>
Q_DECLARE_LOGGING_CATEGORY(displayplugins)
Q_LOGGING_CATEGORY(displayplugins, "hifi.displayplugins")
@ -41,12 +40,11 @@ vr::TrackedDevicePose_t _trackedDevicePose[vr::k_unMaxTrackedDeviceCount];
mat4 _trackedDevicePoseMat4[vr::k_unMaxTrackedDeviceCount];
static mat4 _sensorResetMat;
static uvec2 _windowSize;
static ivec2 _windowPosition;
static uvec2 _renderTargetSize;
struct PerEyeData {
uvec2 _viewportOrigin;
uvec2 _viewportSize;
//uvec2 _viewportOrigin;
//uvec2 _viewportSize;
mat4 _projectionMatrix;
mat4 _eyeOffset;
mat4 _pose;
@ -89,36 +87,17 @@ void OpenVrDisplayPlugin::activate() {
}
Q_ASSERT(_hmd);
_hmd->GetWindowBounds(&_windowPosition.x, &_windowPosition.y, &_windowSize.x, &_windowSize.y);
_hmd->GetRecommendedRenderTargetSize(&_renderTargetSize.x, &_renderTargetSize.y);
// Recommended render target size is per-eye, so double the X size for
// left + right eyes
_renderTargetSize.x *= 2;
openvr_for_each_eye([&](vr::Hmd_Eye eye) {
PerEyeData& eyeData = _eyesData[eye];
_hmd->GetEyeOutputViewport(eye,
&eyeData._viewportOrigin.x, &eyeData._viewportOrigin.y,
&eyeData._viewportSize.x, &eyeData._viewportSize.y);
eyeData._projectionMatrix = toGlm(_hmd->GetProjectionMatrix(eye, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, vr::API_OpenGL));
eyeData._eyeOffset = toGlm(_hmd->GetEyeToHeadTransform(eye));
});
vr::HmdError eError = vr::HmdError_None;
_compositor = (vr::IVRCompositor*)vr::VR_GetGenericInterface(vr::IVRCompositor_Version, &eError);
Q_ASSERT(eError == vr::HmdError_None);
_compositor = vr::VRCompositor();
Q_ASSERT(_compositor);
_compositor->SetGraphicsDevice(vr::Compositor_DeviceType_OpenGL, NULL);
uint32_t unSize = _compositor->GetLastError(NULL, 0);
if (unSize > 1) {
char* buffer = new char[unSize];
_compositor->GetLastError(buffer, unSize);
printf("Compositor - %s\n", buffer);
delete[] buffer;
}
Q_ASSERT(unSize <= 1);
WindowOpenGLDisplayPlugin::activate();
}
@ -132,6 +111,16 @@ void OpenVrDisplayPlugin::deactivate() {
WindowOpenGLDisplayPlugin::deactivate();
}
void OpenVrDisplayPlugin::customizeContext() {
static std::once_flag once;
std::call_once(once, []{
glewExperimental = true;
GLenum err = glewInit();
glGetError();
});
WindowOpenGLDisplayPlugin::customizeContext();
}
uvec2 OpenVrDisplayPlugin::getRecommendedRenderSize() const {
return _renderTargetSize;
}
@ -153,33 +142,41 @@ glm::mat4 OpenVrDisplayPlugin::getEyeToHeadTransform(Eye eye) const {
}
glm::mat4 OpenVrDisplayPlugin::getHeadPose(uint32_t frameIndex) const {
return _trackedDevicePoseMat4[0];
glm::mat4 result;
{
Lock lock(_mutex);
result = _trackedDevicePoseMat4[0];
}
return result;
}
void OpenVrDisplayPlugin::customizeContext() {
WindowOpenGLDisplayPlugin::customizeContext();
void OpenVrDisplayPlugin::submitSceneTexture(uint32_t frameIndex, uint32_t sceneTexture, const glm::uvec2& sceneSize) {
WindowOpenGLDisplayPlugin::submitSceneTexture(frameIndex, sceneTexture, sceneSize);
}
//void OpenVrDisplayPlugin::display(uint32_t frameIndex, uint32_t finalTexture, const glm::uvec2& sceneSize) {
// // Flip y-axis since GL UV coords are backwards.
// static vr::Compositor_TextureBounds leftBounds{ 0, 1, 0.5f, 0 };
// static vr::Compositor_TextureBounds rightBounds{ 0.5f, 1, 1, 0 };
// _compositor->Submit(vr::Eye_Left, (void*)finalTexture, &leftBounds);
// _compositor->Submit(vr::Eye_Right, (void*)finalTexture, &rightBounds);
// glFinish();
//}
//void OpenVrDisplayPlugin::finishFrame() {
//// swapBuffers();
// doneCurrent();
// _compositor->WaitGetPoses(_trackedDevicePose, vr::k_unMaxTrackedDeviceCount);
// for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) {
// _trackedDevicePoseMat4[i] = _sensorResetMat * toGlm(_trackedDevicePose[i].mDeviceToAbsoluteTracking);
// }
// openvr_for_each_eye([&](vr::Hmd_Eye eye) {
// _eyesData[eye]._pose = _trackedDevicePoseMat4[0];
// });
//};
#endif
void OpenVrDisplayPlugin::internalPresent() {
// Flip y-axis since GL UV coords are backwards.
static vr::VRTextureBounds_t leftBounds{ 0, 0, 0.5f, 1 };
static vr::VRTextureBounds_t rightBounds{ 0.5f, 0, 1, 1 };
vr::Texture_t texture{ (void*)_currentSceneTexture, vr::API_OpenGL, vr::ColorSpace_Auto };
{
Lock lock(_mutex);
_compositor->Submit(vr::Eye_Left, &texture, &leftBounds);
_compositor->Submit(vr::Eye_Right, &texture, &rightBounds);
}
glFinish();
{
Lock lock(_mutex);
_compositor->WaitGetPoses(_trackedDevicePose, vr::k_unMaxTrackedDeviceCount, nullptr, 0);
for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) {
_trackedDevicePoseMat4[i] = _sensorResetMat * toGlm(_trackedDevicePose[i].mDeviceToAbsoluteTracking);
}
openvr_for_each_eye([&](vr::Hmd_Eye eye) {
_eyesData[eye]._pose = _trackedDevicePoseMat4[0];
});
}
//WindowOpenGLDisplayPlugin::internalPresent();
}

View file

@ -9,10 +9,9 @@
#include <QtGlobal>
#if defined(Q_OS_WIN)
#include <openvr.h>
#include "../WindowOpenGLDisplayPlugin.h"
#include <display-plugins/WindowOpenGLDisplayPlugin.h>
class OpenVrDisplayPlugin : public WindowOpenGLDisplayPlugin {
public:
@ -23,6 +22,8 @@ public:
virtual void activate() override;
virtual void deactivate() override;
virtual void customizeContext() override;
virtual glm::uvec2 getRecommendedRenderSize() const override;
virtual glm::uvec2 getRecommendedUiSize() const override { return uvec2(1920, 1080); }
@ -32,15 +33,13 @@ public:
virtual glm::mat4 getEyeToHeadTransform(Eye eye) const override;
virtual glm::mat4 getHeadPose(uint32_t frameIndex) const override;
virtual void submitSceneTexture(uint32_t frameIndex, uint32_t sceneTexture, const glm::uvec2& sceneSize) override;
protected:
// virtual void display(uint32_t frameIndex, uint32_t finalTexture, const glm::uvec2& sceneSize) override;
virtual void customizeContext() override;
virtual void internalPresent() override;
private:
vr::IVRSystem* _hmd { nullptr };
static const QString NAME;
};
#endif

View file

@ -7,14 +7,15 @@
//
#include "OpenVrHelpers.h"
#if defined(Q_OS_WIN)
#include <QtCore/QTimer>
#include <atomic>
#include <mutex>
#include "../Logging.h"
#include <QtCore/QDebug>
#include <QtCore/QTimer>
#include <QtCore/QLoggingCategory>
Q_DECLARE_LOGGING_CATEGORY(displayplugins)
using Mutex = std::mutex;
using Lock = std::unique_lock<Mutex>;
@ -30,13 +31,13 @@ vr::IVRSystem* acquireOpenVrSystem() {
if (hmdPresent) {
Lock lock(mutex);
if (!activeHmd) {
qCDebug(displayPlugins) << "openvr: No vr::IVRSystem instance active, building";
vr::HmdError eError = vr::HmdError_None;
qCDebug(displayplugins) << "openvr: No vr::IVRSystem instance active, building";
vr::EVRInitError eError = vr::VRInitError_None;
activeHmd = vr::VR_Init(&eError);
qCDebug(displayPlugins) << "openvr display: HMD is " << activeHmd << " error is " << eError;
qCDebug(displayplugins) << "openvr display: HMD is " << activeHmd << " error is " << eError;
}
if (activeHmd) {
qCDebug(displayPlugins) << "openvr: incrementing refcount";
qCDebug(displayplugins) << "openvr: incrementing refcount";
++refCount;
}
}
@ -46,10 +47,10 @@ vr::IVRSystem* acquireOpenVrSystem() {
void releaseOpenVrSystem() {
if (activeHmd) {
Lock lock(mutex);
qDebug() << "openvr: decrementing refcount";
qCDebug(displayplugins) << "openvr: decrementing refcount";
--refCount;
if (0 == refCount) {
qDebug() << "openvr: zero refcount, deallocate VR system";
qCDebug(displayplugins) << "openvr: zero refcount, deallocate VR system";
// Avoid spamming the VR system with activate/deactivate calls at system startup by
// putting in a delay before we destory the shutdown the VR subsystem
@ -71,5 +72,3 @@ void releaseOpenVrSystem() {
}
}
}
#endif

View file

@ -7,9 +7,6 @@
//
#pragma once
#include <QtGlobal>
#if defined(Q_OS_WIN)
#include <openvr.h>
#include <GLMHelpers.h>
#include <glm/gtc/type_ptr.hpp>
@ -18,5 +15,3 @@
vr::IVRSystem* acquireOpenVrSystem();
void releaseOpenVrSystem();
#endif

View file

@ -0,0 +1,60 @@
//
// Created by Bradley Austin Davis on 2015/10/25
// 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 <mutex>
#include <QtCore/QObject>
#include <QtCore/QtPlugin>
#include <QtCore/QStringList>
#include <plugins/RuntimePlugin.h>
#include "OpenVrDisplayPlugin.h"
#include "ViveControllerManager.h"
class OpenVrProvider : public QObject, public DisplayProvider, InputProvider
{
Q_OBJECT
Q_PLUGIN_METADATA(IID DisplayProvider_iid FILE "plugin.json")
Q_INTERFACES(DisplayProvider)
Q_PLUGIN_METADATA(IID InputProvider_iid FILE "plugin.json")
Q_INTERFACES(InputProvider)
public:
OpenVrProvider(QObject* parent = nullptr) : QObject(parent) {}
virtual ~OpenVrProvider() {}
virtual DisplayPluginList getDisplayPlugins() override {
static std::once_flag once;
std::call_once(once, [&] {
DisplayPluginPointer plugin(new OpenVrDisplayPlugin());
if (plugin->isSupported()) {
_displayPlugins.push_back(plugin);
}
});
return _displayPlugins;
}
virtual InputPluginList getInputPlugins() override {
static std::once_flag once;
std::call_once(once, [&] {
InputPluginPointer plugin(new ViveControllerManager());
if (plugin->isSupported()) {
_inputPlugins.push_back(plugin);
}
});
return _inputPlugins;
}
private:
DisplayPluginList _displayPlugins;
InputPluginList _inputPlugins;
};
#include "OpenVrProvider.moc"

View file

@ -17,7 +17,6 @@
#include <gpu/Batch.h>
#include <gpu/Context.h>
#include <DeferredLightingEffect.h>
#include <display-plugins/openvr/OpenVrHelpers.h>
#include <NumericalConstants.h>
#include <plugins/PluginContainer.h>
#include <UserActivityLogger.h>
@ -26,10 +25,10 @@
#include <controllers/StandardControls.h>
#ifdef Q_OS_WIN
#include "OpenVrHelpers.h"
extern vr::TrackedDevicePose_t _trackedDevicePose[vr::k_unMaxTrackedDeviceCount];
extern mat4 _trackedDevicePoseMat4[vr::k_unMaxTrackedDeviceCount];
#endif
vr::IVRSystem* acquireOpenVrSystem();
void releaseOpenVrSystem();
@ -39,7 +38,7 @@ static const float CONTROLLER_LENGTH_OFFSET = 0.0762f; // three inches
static const glm::vec3 CONTROLLER_OFFSET = glm::vec3(CONTROLLER_LENGTH_OFFSET / 2.0f,
CONTROLLER_LENGTH_OFFSET / 2.0f,
CONTROLLER_LENGTH_OFFSET * 2.0f);
static const QString CONTROLLER_MODEL_STRING = "vr_controller_05_wireless_b";
static const char* CONTROLLER_MODEL_STRING = "vr_controller_05_wireless_b";
static const QString MENU_PARENT = "Avatar";
static const QString MENU_NAME = "Vive Controllers";
@ -49,19 +48,14 @@ static const QString RENDER_CONTROLLERS = "Render Hand Controllers";
const QString ViveControllerManager::NAME = "OpenVR";
bool ViveControllerManager::isSupported() const {
#ifdef Q_OS_WIN
auto hmd = acquireOpenVrSystem();
bool success = hmd != nullptr;
releaseOpenVrSystem();
return success;
#else
return false;
#endif
}
void ViveControllerManager::activate() {
InputPlugin::activate();
#ifdef Q_OS_WIN
_container->addMenu(MENU_PATH);
_container->addMenuItem(PluginType::INPUT_PLUGIN, MENU_PATH, RENDER_CONTROLLERS,
[this] (bool clicked) { this->setRenderControllers(clicked); },
@ -72,8 +66,11 @@ void ViveControllerManager::activate() {
}
Q_ASSERT(_hmd);
auto renderModels = vr::VRRenderModels();
vr::RenderModel_t model;
if (!_hmd->LoadRenderModel(CONTROLLER_MODEL_STRING.toStdString().c_str(), &model)) {
/*
if (!_hmd->LoadRenderModel(CONTROLLER_MODEL_STRING, &model)) {
qDebug() << QString("Unable to load render model %1\n").arg(CONTROLLER_MODEL_STRING);
} else {
model::Mesh* mesh = new model::Mesh();
@ -118,7 +115,7 @@ void ViveControllerManager::activate() {
_modelLoaded = true;
_renderControllers = true;
}
#endif
*/
// unregister with UserInputMapper
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
@ -129,7 +126,6 @@ void ViveControllerManager::activate() {
void ViveControllerManager::deactivate() {
InputPlugin::deactivate();
#ifdef Q_OS_WIN
_container->removeMenuItem(MENU_NAME, RENDER_CONTROLLERS);
_container->removeMenu(MENU_PATH);
@ -139,7 +135,6 @@ void ViveControllerManager::deactivate() {
}
_inputDevice->_poseStateMap.clear();
#endif
// unregister with UserInputMapper
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
@ -225,7 +220,6 @@ void ViveControllerManager::pluginUpdate(float deltaTime, bool jointsCaptured) {
}
void ViveControllerManager::InputDevice::update(float deltaTime, bool jointsCaptured) {
#ifdef Q_OS_WIN
_poseStateMap.clear();
_buttonPressedMap.clear();
@ -276,7 +270,6 @@ void ViveControllerManager::InputDevice::update(float deltaTime, bool jointsCapt
}
_trackedControllers = numTrackedControllers;
#endif
}
void ViveControllerManager::InputDevice::focusOutEvent() {
@ -286,7 +279,6 @@ void ViveControllerManager::InputDevice::focusOutEvent() {
// These functions do translation from the Steam IDs to the standard controller IDs
void ViveControllerManager::InputDevice::handleAxisEvent(uint32_t axis, float x, float y, bool left) {
#ifdef Q_OS_WIN
//FIX ME? It enters here every frame: probably we want to enter only if an event occurs
axis += vr::k_EButton_Axis0;
using namespace controller;
@ -296,12 +288,10 @@ void ViveControllerManager::InputDevice::handleAxisEvent(uint32_t axis, float x,
} else if (axis == vr::k_EButton_SteamVR_Trigger) {
_axisStateMap[left ? LT : RT] = x;
}
#endif
}
// These functions do translation from the Steam IDs to the standard controller IDs
void ViveControllerManager::InputDevice::handleButtonEvent(uint32_t button, bool pressed, bool left) {
#ifdef Q_OS_WIN
if (!pressed) {
return;
}
@ -319,7 +309,6 @@ void ViveControllerManager::InputDevice::handleButtonEvent(uint32_t button, bool
//FIX ME: not able to ovrewrite the behaviour of this button
_buttonPressedMap.insert(left ? controller::LEFT_SECONDARY_THUMB : controller::RIGHT_SECONDARY_THUMB);
}
#endif
}
void ViveControllerManager::InputDevice::handlePoseEvent(const mat4& mat, bool left) {

View file

@ -20,7 +20,7 @@
#include <model/Geometry.h>
#include <gpu/Texture.h>
#include <controllers/InputDevice.h>
#include "InputPlugin.h"
#include <plugins/InputPlugin.h>
#include <RenderArgs.h>
#include <render/Scene.h>

View file

@ -0,0 +1 @@
{}