mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 11:28:03 +02:00
Support a debug oculus plugin for performance testing
This commit is contained in:
parent
9fa20207ab
commit
5ba6242bda
7 changed files with 314 additions and 290 deletions
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
#include "openvr/OpenVrDisplayPlugin.h"
|
#include "openvr/OpenVrDisplayPlugin.h"
|
||||||
#include "oculus/OculusDisplayPlugin.h"
|
#include "oculus/OculusDisplayPlugin.h"
|
||||||
|
#include "oculus/OculusDebugDisplayPlugin.h"
|
||||||
#include "oculus/OculusLegacyDisplayPlugin.h"
|
#include "oculus/OculusLegacyDisplayPlugin.h"
|
||||||
|
|
||||||
const QString& DisplayPlugin::MENU_PATH() {
|
const QString& DisplayPlugin::MENU_PATH() {
|
||||||
|
@ -42,6 +43,10 @@ DisplayPluginList getDisplayPlugins() {
|
||||||
|
|
||||||
// Windows Oculus SDK
|
// Windows Oculus SDK
|
||||||
new OculusDisplayPlugin(),
|
new OculusDisplayPlugin(),
|
||||||
|
// Windows Oculus Simulator... uses head tracking and the same rendering
|
||||||
|
// as the connected hardware, but without using the SDK to display to the
|
||||||
|
// Rift. Useful for debugging Rift performance with nSight.
|
||||||
|
new OculusDebugDisplayPlugin(),
|
||||||
// Mac/Linux Oculus SDK (0.5)
|
// Mac/Linux Oculus SDK (0.5)
|
||||||
new OculusLegacyDisplayPlugin(),
|
new OculusLegacyDisplayPlugin(),
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
|
|
|
@ -0,0 +1,151 @@
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis on 2014/04/13.
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
#include "OculusBaseDisplayPlugin.h"
|
||||||
|
|
||||||
|
#include <ViewFrustum.h>
|
||||||
|
|
||||||
|
#include "OculusHelpers.h"
|
||||||
|
|
||||||
|
uvec2 OculusBaseDisplayPlugin::getRecommendedRenderSize() const {
|
||||||
|
return _desiredFramebufferSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OculusBaseDisplayPlugin::preRender() {
|
||||||
|
#if (OVR_MAJOR_VERSION >= 6)
|
||||||
|
ovrFrameTiming ftiming = ovr_GetFrameTiming(_hmd, _frameIndex);
|
||||||
|
_trackingState = ovr_GetTrackingState(_hmd, ftiming.DisplayMidpointSeconds);
|
||||||
|
ovr_CalcEyePoses(_trackingState.HeadPose.ThePose, _eyeOffsets, _eyePoses);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::mat4 OculusBaseDisplayPlugin::getProjection(Eye eye, const glm::mat4& baseProjection) const {
|
||||||
|
return _eyeProjections[eye];
|
||||||
|
}
|
||||||
|
|
||||||
|
void OculusBaseDisplayPlugin::resetSensors() {
|
||||||
|
#if (OVR_MAJOR_VERSION >= 6)
|
||||||
|
ovr_RecenterPose(_hmd);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::mat4 OculusBaseDisplayPlugin::getEyePose(Eye eye) const {
|
||||||
|
return toGlm(_eyePoses[eye]);
|
||||||
|
}
|
||||||
|
|
||||||
|
glm::mat4 OculusBaseDisplayPlugin::getHeadPose() const {
|
||||||
|
return toGlm(_trackingState.HeadPose.ThePose);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OculusBaseDisplayPlugin::isSupported() const {
|
||||||
|
#if (OVR_MAJOR_VERSION >= 6)
|
||||||
|
if (!OVR_SUCCESS(ovr_Initialize(nullptr))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool result = false;
|
||||||
|
if (ovrHmd_Detect() > 0) {
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
ovr_Shutdown();
|
||||||
|
return result;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void OculusBaseDisplayPlugin::init() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void OculusBaseDisplayPlugin::deinit() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void OculusBaseDisplayPlugin::activate() {
|
||||||
|
#if (OVR_MAJOR_VERSION >= 6)
|
||||||
|
if (!OVR_SUCCESS(ovr_Initialize(nullptr))) {
|
||||||
|
qFatal("Could not init OVR");
|
||||||
|
}
|
||||||
|
|
||||||
|
#if (OVR_MAJOR_VERSION == 6)
|
||||||
|
if (!OVR_SUCCESS(ovr_Create(0, &_hmd))) {
|
||||||
|
#elif (OVR_MAJOR_VERSION == 7)
|
||||||
|
if (!OVR_SUCCESS(ovr_Create(&_hmd, &_luid))) {
|
||||||
|
#endif
|
||||||
|
Q_ASSERT(false);
|
||||||
|
qFatal("Failed to acquire HMD");
|
||||||
|
}
|
||||||
|
|
||||||
|
_hmdDesc = ovr_GetHmdDesc(_hmd);
|
||||||
|
|
||||||
|
_ipd = ovr_GetFloat(_hmd, OVR_KEY_IPD, _ipd);
|
||||||
|
|
||||||
|
glm::uvec2 eyeSizes[2];
|
||||||
|
ovr_for_each_eye([&](ovrEyeType eye) {
|
||||||
|
_eyeFovs[eye] = _hmdDesc.DefaultEyeFov[eye];
|
||||||
|
ovrEyeRenderDesc& erd = _eyeRenderDescs[eye] = ovr_GetRenderDesc(_hmd, eye, _eyeFovs[eye]);
|
||||||
|
ovrMatrix4f ovrPerspectiveProjection =
|
||||||
|
ovrMatrix4f_Projection(erd.Fov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_RightHanded);
|
||||||
|
_eyeProjections[eye] = toGlm(ovrPerspectiveProjection);
|
||||||
|
|
||||||
|
ovrPerspectiveProjection =
|
||||||
|
ovrMatrix4f_Projection(erd.Fov, 0.001f, 10.0f, ovrProjection_RightHanded);
|
||||||
|
_compositeEyeProjections[eye] = toGlm(ovrPerspectiveProjection);
|
||||||
|
|
||||||
|
_eyeOffsets[eye] = erd.HmdToEyeViewOffset;
|
||||||
|
eyeSizes[eye] = toGlm(ovr_GetFovTextureSize(_hmd, eye, erd.Fov, 1.0f));
|
||||||
|
});
|
||||||
|
ovrFovPort combined = _eyeFovs[Left];
|
||||||
|
combined.LeftTan = std::max(_eyeFovs[Left].LeftTan, _eyeFovs[Right].LeftTan);
|
||||||
|
combined.RightTan = std::max(_eyeFovs[Left].RightTan, _eyeFovs[Right].RightTan);
|
||||||
|
ovrMatrix4f ovrPerspectiveProjection =
|
||||||
|
ovrMatrix4f_Projection(combined, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_RightHanded);
|
||||||
|
_eyeProjections[Mono] = toGlm(ovrPerspectiveProjection);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
_desiredFramebufferSize = uvec2(
|
||||||
|
eyeSizes[0].x + eyeSizes[1].x,
|
||||||
|
std::max(eyeSizes[0].y, eyeSizes[1].y));
|
||||||
|
|
||||||
|
_frameIndex = 0;
|
||||||
|
|
||||||
|
if (!OVR_SUCCESS(ovr_ConfigureTracking(_hmd,
|
||||||
|
ovrTrackingCap_Orientation | ovrTrackingCap_Position | ovrTrackingCap_MagYawCorrection, 0))) {
|
||||||
|
qFatal("Could not attach to sensor device");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parent class relies on our _hmd intialization, so it must come after that.
|
||||||
|
memset(&_sceneLayer, 0, sizeof(ovrLayerEyeFov));
|
||||||
|
_sceneLayer.Header.Type = ovrLayerType_EyeFov;
|
||||||
|
_sceneLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft;
|
||||||
|
ovr_for_each_eye([&](ovrEyeType eye) {
|
||||||
|
ovrFovPort & fov = _sceneLayer.Fov[eye] = _eyeRenderDescs[eye].Fov;
|
||||||
|
ovrSizei & size = _sceneLayer.Viewport[eye].Size = ovr_GetFovTextureSize(_hmd, eye, fov, 1.0f);
|
||||||
|
_sceneLayer.Viewport[eye].Pos = { eye == ovrEye_Left ? 0 : size.w, 0 };
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!OVR_SUCCESS(ovr_ConfigureTracking(_hmd,
|
||||||
|
ovrTrackingCap_Orientation | ovrTrackingCap_Position | ovrTrackingCap_MagYawCorrection, 0))) {
|
||||||
|
qFatal("Could not attach to sensor device");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
WindowOpenGLDisplayPlugin::activate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OculusBaseDisplayPlugin::deactivate() {
|
||||||
|
WindowOpenGLDisplayPlugin::deactivate();
|
||||||
|
|
||||||
|
#if (OVR_MAJOR_VERSION >= 6)
|
||||||
|
ovr_Destroy(_hmd);
|
||||||
|
_hmd = nullptr;
|
||||||
|
ovr_Shutdown();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void OculusBaseDisplayPlugin::display(GLuint finalTexture, const glm::uvec2& sceneSize) {
|
||||||
|
++_frameIndex;
|
||||||
|
}
|
|
@ -0,0 +1,79 @@
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis on 2015/05/29
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../WindowOpenGLDisplayPlugin.h"
|
||||||
|
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
|
#include <OVR_CAPI_GL.h>
|
||||||
|
|
||||||
|
class OculusBaseDisplayPlugin : public WindowOpenGLDisplayPlugin {
|
||||||
|
public:
|
||||||
|
virtual bool isSupported() const override;
|
||||||
|
|
||||||
|
virtual void init() override final;
|
||||||
|
virtual void deinit() override final;
|
||||||
|
|
||||||
|
virtual void activate() override;
|
||||||
|
virtual void deactivate() override;
|
||||||
|
|
||||||
|
// Stereo specific methods
|
||||||
|
virtual bool isHmd() const override final { return true; }
|
||||||
|
virtual glm::mat4 getProjection(Eye eye, const glm::mat4& baseProjection) const override;
|
||||||
|
virtual glm::uvec2 getRecommendedRenderSize() const override final;
|
||||||
|
virtual glm::uvec2 getRecommendedUiSize() const override final { return uvec2(1920, 1080); }
|
||||||
|
virtual void resetSensors() override final;
|
||||||
|
virtual glm::mat4 getEyePose(Eye eye) const override final;
|
||||||
|
virtual glm::mat4 getHeadPose() const override final;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void preRender() override final;
|
||||||
|
virtual void display(GLuint finalTexture, const glm::uvec2& sceneSize) override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ovrPosef _eyePoses[2];
|
||||||
|
|
||||||
|
mat4 _eyeProjections[3];
|
||||||
|
mat4 _compositeEyeProjections[2];
|
||||||
|
uvec2 _desiredFramebufferSize;
|
||||||
|
ovrTrackingState _trackingState;
|
||||||
|
unsigned int _frameIndex{ 0 };
|
||||||
|
|
||||||
|
#if (OVR_MAJOR_VERSION >= 6)
|
||||||
|
ovrHmd _hmd;
|
||||||
|
float _ipd{ OVR_DEFAULT_IPD };
|
||||||
|
ovrEyeRenderDesc _eyeRenderDescs[2];
|
||||||
|
ovrVector3f _eyeOffsets[2];
|
||||||
|
ovrFovPort _eyeFovs[2];
|
||||||
|
ovrHmdDesc _hmdDesc;
|
||||||
|
ovrLayerEyeFov _sceneLayer;
|
||||||
|
#endif
|
||||||
|
#if (OVR_MAJOR_VERSION == 7)
|
||||||
|
ovrGraphicsLuid _luid;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#if (OVR_MAJOR_VERSION == 6)
|
||||||
|
#define ovr_Create ovrHmd_Create
|
||||||
|
#define ovr_CreateSwapTextureSetGL ovrHmd_CreateSwapTextureSetGL
|
||||||
|
#define ovr_CreateMirrorTextureGL ovrHmd_CreateMirrorTextureGL
|
||||||
|
#define ovr_Destroy ovrHmd_Destroy
|
||||||
|
#define ovr_DestroySwapTextureSet ovrHmd_DestroySwapTextureSet
|
||||||
|
#define ovr_DestroyMirrorTexture ovrHmd_DestroyMirrorTexture
|
||||||
|
#define ovr_GetFloat ovrHmd_GetFloat
|
||||||
|
#define ovr_GetFovTextureSize ovrHmd_GetFovTextureSize
|
||||||
|
#define ovr_GetFrameTiming ovrHmd_GetFrameTiming
|
||||||
|
#define ovr_GetTrackingState ovrHmd_GetTrackingState
|
||||||
|
#define ovr_GetRenderDesc ovrHmd_GetRenderDesc
|
||||||
|
#define ovr_RecenterPose ovrHmd_RecenterPose
|
||||||
|
#define ovr_SubmitFrame ovrHmd_SubmitFrame
|
||||||
|
#define ovr_ConfigureTracking ovrHmd_ConfigureTracking
|
||||||
|
|
||||||
|
#define ovr_GetHmdDesc(X) *X
|
||||||
|
#endif
|
|
@ -0,0 +1,40 @@
|
||||||
|
//
|
||||||
|
// 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 "OculusDebugDisplayPlugin.h"
|
||||||
|
#include <QtCore/QProcessEnvironment>
|
||||||
|
|
||||||
|
const QString OculusDebugDisplayPlugin::NAME("Oculus Rift (Simulator)");
|
||||||
|
|
||||||
|
const QString & OculusDebugDisplayPlugin::getName() const {
|
||||||
|
return NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const QString DEBUG_FLAG("HIFI_DEBUG_OCULUS");
|
||||||
|
static bool enableDebugOculus = QProcessEnvironment::systemEnvironment().contains("HIFI_DEBUG_OCULUS");
|
||||||
|
|
||||||
|
bool OculusDebugDisplayPlugin::isSupported() const {
|
||||||
|
if (!enableDebugOculus) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return OculusBaseDisplayPlugin::isSupported();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OculusDebugDisplayPlugin::customizeContext() {
|
||||||
|
WindowOpenGLDisplayPlugin::customizeContext();
|
||||||
|
enableVsync(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OculusDebugDisplayPlugin::display(GLuint finalTexture, const glm::uvec2& sceneSize) {
|
||||||
|
WindowOpenGLDisplayPlugin::display(finalTexture, sceneSize);
|
||||||
|
OculusBaseDisplayPlugin::display(finalTexture, sceneSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OculusDebugDisplayPlugin::finishFrame() {
|
||||||
|
swapBuffers();
|
||||||
|
doneCurrent();
|
||||||
|
};
|
|
@ -0,0 +1,26 @@
|
||||||
|
//
|
||||||
|
// Created by Bradley Austin Davis on 2015/05/29
|
||||||
|
// Copyright 2015 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "OculusBaseDisplayPlugin.h"
|
||||||
|
|
||||||
|
class OculusDebugDisplayPlugin : public OculusBaseDisplayPlugin {
|
||||||
|
public:
|
||||||
|
virtual const QString & getName() const override;
|
||||||
|
virtual bool isSupported() const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void display(GLuint finalTexture, const glm::uvec2& sceneSize) override;
|
||||||
|
virtual void customizeContext() override;
|
||||||
|
// Do not perform swap in finish
|
||||||
|
virtual void finishFrame() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static const QString NAME;
|
||||||
|
};
|
||||||
|
|
|
@ -7,59 +7,10 @@
|
||||||
//
|
//
|
||||||
#include "OculusDisplayPlugin.h"
|
#include "OculusDisplayPlugin.h"
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include <QMainWindow>
|
|
||||||
#include <QGLWidget>
|
#include <QGLWidget>
|
||||||
#include <GLMHelpers.h>
|
|
||||||
#include <GlWindow.h>
|
|
||||||
#include <QEvent>
|
|
||||||
#include <QResizeEvent>
|
|
||||||
#include <QThread>
|
|
||||||
|
|
||||||
#include <OglplusHelpers.h>
|
|
||||||
#include <oglplus/opt/list_init.hpp>
|
|
||||||
#include <oglplus/shapes/vector.hpp>
|
|
||||||
#include <oglplus/opt/list_init.hpp>
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(__GNUC__) && !defined(__clang__)
|
|
||||||
#pragma GCC diagnostic push
|
|
||||||
#pragma GCC diagnostic ignored "-Wdouble-promotion"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <oglplus/shapes/obj_mesh.hpp>
|
|
||||||
|
|
||||||
#if defined(__GNUC__) && !defined(__clang__)
|
|
||||||
#pragma GCC diagnostic pop
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#include <PerfStat.h>
|
|
||||||
#include <plugins/PluginContainer.h>
|
|
||||||
#include <ViewFrustum.h>
|
|
||||||
|
|
||||||
#include "OculusHelpers.h"
|
#include "OculusHelpers.h"
|
||||||
|
|
||||||
#if (OVR_MAJOR_VERSION == 6)
|
|
||||||
#define ovr_Create ovrHmd_Create
|
|
||||||
#define ovr_CreateSwapTextureSetGL ovrHmd_CreateSwapTextureSetGL
|
|
||||||
#define ovr_CreateMirrorTextureGL ovrHmd_CreateMirrorTextureGL
|
|
||||||
#define ovr_Destroy ovrHmd_Destroy
|
|
||||||
#define ovr_DestroySwapTextureSet ovrHmd_DestroySwapTextureSet
|
|
||||||
#define ovr_DestroyMirrorTexture ovrHmd_DestroyMirrorTexture
|
|
||||||
#define ovr_GetFloat ovrHmd_GetFloat
|
|
||||||
#define ovr_GetFovTextureSize ovrHmd_GetFovTextureSize
|
|
||||||
#define ovr_GetFrameTiming ovrHmd_GetFrameTiming
|
|
||||||
#define ovr_GetTrackingState ovrHmd_GetTrackingState
|
|
||||||
#define ovr_GetRenderDesc ovrHmd_GetRenderDesc
|
|
||||||
#define ovr_RecenterPose ovrHmd_RecenterPose
|
|
||||||
#define ovr_SubmitFrame ovrHmd_SubmitFrame
|
|
||||||
#define ovr_ConfigureTracking ovrHmd_ConfigureTracking
|
|
||||||
|
|
||||||
#define ovr_GetHmdDesc(X) *X
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (OVR_MAJOR_VERSION >= 6)
|
#if (OVR_MAJOR_VERSION >= 6)
|
||||||
|
|
||||||
// A base class for FBO wrappers that need to use the Oculus C
|
// A base class for FBO wrappers that need to use the Oculus C
|
||||||
|
@ -180,160 +131,21 @@ private:
|
||||||
|
|
||||||
const QString OculusDisplayPlugin::NAME("Oculus Rift");
|
const QString OculusDisplayPlugin::NAME("Oculus Rift");
|
||||||
|
|
||||||
uvec2 OculusDisplayPlugin::getRecommendedRenderSize() const {
|
|
||||||
return _desiredFramebufferSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OculusDisplayPlugin::preRender() {
|
|
||||||
#if (OVR_MAJOR_VERSION >= 6)
|
|
||||||
ovrFrameTiming ftiming = ovr_GetFrameTiming(_hmd, _frameIndex);
|
|
||||||
_trackingState = ovr_GetTrackingState(_hmd, ftiming.DisplayMidpointSeconds);
|
|
||||||
ovr_CalcEyePoses(_trackingState.HeadPose.ThePose, _eyeOffsets, _eyePoses);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::mat4 OculusDisplayPlugin::getProjection(Eye eye, const glm::mat4& baseProjection) const {
|
|
||||||
return _eyeProjections[eye];
|
|
||||||
}
|
|
||||||
|
|
||||||
void OculusDisplayPlugin::resetSensors() {
|
|
||||||
#if (OVR_MAJOR_VERSION >= 6)
|
|
||||||
ovr_RecenterPose(_hmd);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::mat4 OculusDisplayPlugin::getEyePose(Eye eye) const {
|
|
||||||
return toGlm(_eyePoses[eye]);
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::mat4 OculusDisplayPlugin::getHeadPose() const {
|
|
||||||
return toGlm(_trackingState.HeadPose.ThePose);
|
|
||||||
}
|
|
||||||
|
|
||||||
const QString & OculusDisplayPlugin::getName() const {
|
const QString & OculusDisplayPlugin::getName() const {
|
||||||
return NAME;
|
return NAME;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OculusDisplayPlugin::isSupported() const {
|
|
||||||
#if (OVR_MAJOR_VERSION >= 6)
|
|
||||||
if (!OVR_SUCCESS(ovr_Initialize(nullptr))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
bool result = false;
|
|
||||||
if (ovrHmd_Detect() > 0) {
|
|
||||||
result = true;
|
|
||||||
}
|
|
||||||
ovr_Shutdown();
|
|
||||||
return result;
|
|
||||||
#else
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void OculusDisplayPlugin::init() {
|
|
||||||
if (!OVR_SUCCESS(ovr_Initialize(nullptr))) {
|
|
||||||
qFatal("Could not init OVR");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void OculusDisplayPlugin::deinit() {
|
|
||||||
ovr_Shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
#if (OVR_MAJOR_VERSION >= 6)
|
|
||||||
ovrLayerEyeFov& OculusDisplayPlugin::getSceneLayer() {
|
|
||||||
return _sceneLayer;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//static gpu::TexturePointer _texture;
|
|
||||||
|
|
||||||
void OculusDisplayPlugin::activate() {
|
|
||||||
#if (OVR_MAJOR_VERSION >= 6)
|
|
||||||
if (!OVR_SUCCESS(ovr_Initialize(nullptr))) {
|
|
||||||
Q_ASSERT(false);
|
|
||||||
qFatal("Failed to Initialize SDK");
|
|
||||||
}
|
|
||||||
|
|
||||||
// CONTAINER->getPrimarySurface()->makeCurrent();
|
|
||||||
#if (OVR_MAJOR_VERSION == 6)
|
|
||||||
if (!OVR_SUCCESS(ovr_Create(0, &_hmd))) {
|
|
||||||
#elif (OVR_MAJOR_VERSION == 7)
|
|
||||||
if (!OVR_SUCCESS(ovr_Create(&_hmd, &_luid))) {
|
|
||||||
#endif
|
|
||||||
Q_ASSERT(false);
|
|
||||||
qFatal("Failed to acquire HMD");
|
|
||||||
}
|
|
||||||
|
|
||||||
_hmdDesc = ovr_GetHmdDesc(_hmd);
|
|
||||||
|
|
||||||
_ipd = ovr_GetFloat(_hmd, OVR_KEY_IPD, _ipd);
|
|
||||||
|
|
||||||
glm::uvec2 eyeSizes[2];
|
|
||||||
ovr_for_each_eye([&](ovrEyeType eye) {
|
|
||||||
_eyeFovs[eye] = _hmdDesc.DefaultEyeFov[eye];
|
|
||||||
ovrEyeRenderDesc& erd = _eyeRenderDescs[eye] = ovr_GetRenderDesc(_hmd, eye, _eyeFovs[eye]);
|
|
||||||
ovrMatrix4f ovrPerspectiveProjection =
|
|
||||||
ovrMatrix4f_Projection(erd.Fov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_RightHanded);
|
|
||||||
_eyeProjections[eye] = toGlm(ovrPerspectiveProjection);
|
|
||||||
|
|
||||||
ovrPerspectiveProjection =
|
|
||||||
ovrMatrix4f_Projection(erd.Fov, 0.001f, 10.0f, ovrProjection_RightHanded);
|
|
||||||
_compositeEyeProjections[eye] = toGlm(ovrPerspectiveProjection);
|
|
||||||
|
|
||||||
_eyeOffsets[eye] = erd.HmdToEyeViewOffset;
|
|
||||||
eyeSizes[eye] = toGlm(ovr_GetFovTextureSize(_hmd, eye, erd.Fov, 1.0f));
|
|
||||||
});
|
|
||||||
ovrFovPort combined = _eyeFovs[Left];
|
|
||||||
combined.LeftTan = std::max(_eyeFovs[Left].LeftTan, _eyeFovs[Right].LeftTan);
|
|
||||||
combined.RightTan = std::max(_eyeFovs[Left].RightTan, _eyeFovs[Right].RightTan);
|
|
||||||
ovrMatrix4f ovrPerspectiveProjection =
|
|
||||||
ovrMatrix4f_Projection(combined, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_RightHanded);
|
|
||||||
_eyeProjections[Mono] = toGlm(ovrPerspectiveProjection);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
_desiredFramebufferSize = uvec2(
|
|
||||||
eyeSizes[0].x + eyeSizes[1].x,
|
|
||||||
std::max(eyeSizes[0].y, eyeSizes[1].y));
|
|
||||||
|
|
||||||
_frameIndex = 0;
|
|
||||||
|
|
||||||
if (!OVR_SUCCESS(ovr_ConfigureTracking(_hmd,
|
|
||||||
ovrTrackingCap_Orientation | ovrTrackingCap_Position | ovrTrackingCap_MagYawCorrection, 0))) {
|
|
||||||
qFatal("Could not attach to sensor device");
|
|
||||||
}
|
|
||||||
|
|
||||||
WindowOpenGLDisplayPlugin::activate();
|
|
||||||
|
|
||||||
// Parent class relies on our _hmd intialization, so it must come after that.
|
|
||||||
ovrLayerEyeFov& sceneLayer = getSceneLayer();
|
|
||||||
memset(&sceneLayer, 0, sizeof(ovrLayerEyeFov));
|
|
||||||
sceneLayer.Header.Type = ovrLayerType_EyeFov;
|
|
||||||
sceneLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft;
|
|
||||||
ovr_for_each_eye([&](ovrEyeType eye) {
|
|
||||||
ovrFovPort & fov = sceneLayer.Fov[eye] = _eyeRenderDescs[eye].Fov;
|
|
||||||
ovrSizei & size = sceneLayer.Viewport[eye].Size = ovr_GetFovTextureSize(_hmd, eye, fov, 1.0f);
|
|
||||||
sceneLayer.Viewport[eye].Pos = { eye == ovrEye_Left ? 0 : size.w, 0 };
|
|
||||||
});
|
|
||||||
// We're rendering both eyes to the same texture, so only one of the
|
|
||||||
// pointers is populated
|
|
||||||
sceneLayer.ColorTexture[0] = _sceneFbo->color;
|
|
||||||
// not needed since the structure was zeroed on init, but explicit
|
|
||||||
sceneLayer.ColorTexture[1] = nullptr;
|
|
||||||
|
|
||||||
if (!OVR_SUCCESS(ovr_ConfigureTracking(_hmd,
|
|
||||||
ovrTrackingCap_Orientation | ovrTrackingCap_Position | ovrTrackingCap_MagYawCorrection, 0))) {
|
|
||||||
qFatal("Could not attach to sensor device");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void OculusDisplayPlugin::customizeContext() {
|
void OculusDisplayPlugin::customizeContext() {
|
||||||
WindowOpenGLDisplayPlugin::customizeContext();
|
WindowOpenGLDisplayPlugin::customizeContext();
|
||||||
#if (OVR_MAJOR_VERSION >= 6)
|
#if (OVR_MAJOR_VERSION >= 6)
|
||||||
_sceneFbo = SwapFboPtr(new SwapFramebufferWrapper(_hmd));
|
_sceneFbo = SwapFboPtr(new SwapFramebufferWrapper(_hmd));
|
||||||
_sceneFbo->Init(getRecommendedRenderSize());
|
_sceneFbo->Init(getRecommendedRenderSize());
|
||||||
|
|
||||||
|
// We're rendering both eyes to the same texture, so only one of the
|
||||||
|
// pointers is populated
|
||||||
|
_sceneLayer.ColorTexture[0] = _sceneFbo->color;
|
||||||
|
// not needed since the structure was zeroed on init, but explicit
|
||||||
|
_sceneLayer.ColorTexture[1] = nullptr;
|
||||||
#endif
|
#endif
|
||||||
enableVsync(false);
|
enableVsync(false);
|
||||||
// Only enable mirroring if we know vsync is disabled
|
// Only enable mirroring if we know vsync is disabled
|
||||||
|
@ -345,13 +157,9 @@ void OculusDisplayPlugin::deactivate() {
|
||||||
makeCurrent();
|
makeCurrent();
|
||||||
_sceneFbo.reset();
|
_sceneFbo.reset();
|
||||||
doneCurrent();
|
doneCurrent();
|
||||||
|
|
||||||
WindowOpenGLDisplayPlugin::deactivate();
|
|
||||||
|
|
||||||
ovr_Destroy(_hmd);
|
|
||||||
_hmd = nullptr;
|
|
||||||
ovr_Shutdown();
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
OculusBaseDisplayPlugin::deactivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OculusDisplayPlugin::display(GLuint finalTexture, const glm::uvec2& sceneSize) {
|
void OculusDisplayPlugin::display(GLuint finalTexture, const glm::uvec2& sceneSize) {
|
||||||
|
@ -379,9 +187,8 @@ void OculusDisplayPlugin::display(GLuint finalTexture, const glm::uvec2& sceneSi
|
||||||
drawUnitQuad();
|
drawUnitQuad();
|
||||||
});
|
});
|
||||||
|
|
||||||
ovrLayerEyeFov& sceneLayer = getSceneLayer();
|
|
||||||
ovr_for_each_eye([&](ovrEyeType eye) {
|
ovr_for_each_eye([&](ovrEyeType eye) {
|
||||||
sceneLayer.RenderPose[eye] = _eyePoses[eye];
|
_sceneLayer.RenderPose[eye] = _eyePoses[eye];
|
||||||
});
|
});
|
||||||
|
|
||||||
auto windowSize = toGlm(_window->size());
|
auto windowSize = toGlm(_window->size());
|
||||||
|
@ -391,7 +198,7 @@ void OculusDisplayPlugin::display(GLuint finalTexture, const glm::uvec2& sceneSi
|
||||||
viewScaleDesc.HmdToEyeViewOffset[0] = _eyeOffsets[0];
|
viewScaleDesc.HmdToEyeViewOffset[0] = _eyeOffsets[0];
|
||||||
viewScaleDesc.HmdToEyeViewOffset[1] = _eyeOffsets[1];
|
viewScaleDesc.HmdToEyeViewOffset[1] = _eyeOffsets[1];
|
||||||
|
|
||||||
ovrLayerHeader* layers = &sceneLayer.Header;
|
ovrLayerHeader* layers = &_sceneLayer.Header;
|
||||||
ovrResult result = ovr_SubmitFrame(_hmd, 0, &viewScaleDesc, &layers, 1);
|
ovrResult result = ovr_SubmitFrame(_hmd, 0, &viewScaleDesc, &layers, 1);
|
||||||
if (!OVR_SUCCESS(result)) {
|
if (!OVR_SUCCESS(result)) {
|
||||||
qDebug() << result;
|
qDebug() << result;
|
||||||
|
@ -403,11 +210,6 @@ void OculusDisplayPlugin::display(GLuint finalTexture, const glm::uvec2& sceneSi
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pass input events on to the application
|
|
||||||
bool OculusDisplayPlugin::eventFilter(QObject* receiver, QEvent* event) {
|
|
||||||
return WindowOpenGLDisplayPlugin::eventFilter(receiver, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The swapbuffer call here is only required if we want to mirror the content to the screen.
|
The swapbuffer call here is only required if we want to mirror the content to the screen.
|
||||||
However, it should only be done if we can reliably disable v-sync on the mirror surface,
|
However, it should only be done if we can reliably disable v-sync on the mirror surface,
|
||||||
|
@ -419,36 +221,3 @@ void OculusDisplayPlugin::finishFrame() {
|
||||||
}
|
}
|
||||||
doneCurrent();
|
doneCurrent();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
/*
|
|
||||||
An alternative way to render the UI is to pass it specifically as a composition layer to
|
|
||||||
the Oculus SDK which should technically result in higher quality. However, the SDK doesn't
|
|
||||||
have a mechanism to present the image as a sphere section, which is our desired look.
|
|
||||||
*/
|
|
||||||
ovrLayerQuad& uiLayer = getUiLayer();
|
|
||||||
if (nullptr == uiLayer.ColorTexture || overlaySize != _uiFbo->size) {
|
|
||||||
_uiFbo->Resize(overlaySize);
|
|
||||||
uiLayer.ColorTexture = _uiFbo->color;
|
|
||||||
uiLayer.Viewport.Size.w = overlaySize.x;
|
|
||||||
uiLayer.Viewport.Size.h = overlaySize.y;
|
|
||||||
float overlayAspect = aspect(overlaySize);
|
|
||||||
uiLayer.QuadSize.x = 1.0f;
|
|
||||||
uiLayer.QuadSize.y = 1.0f / overlayAspect;
|
|
||||||
}
|
|
||||||
|
|
||||||
_uiFbo->Bound([&] {
|
|
||||||
Q_ASSERT(0 == glGetError());
|
|
||||||
using namespace oglplus;
|
|
||||||
Context::Viewport(_uiFbo->size.x, _uiFbo->size.y);
|
|
||||||
glClearColor(0, 0, 0, 0);
|
|
||||||
Context::Clear().ColorBuffer();
|
|
||||||
|
|
||||||
_program->Bind();
|
|
||||||
glBindTexture(GL_TEXTURE_2D, overlayTexture);
|
|
||||||
_plane->Use();
|
|
||||||
_plane->Draw();
|
|
||||||
Q_ASSERT(0 == glGetError());
|
|
||||||
});
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -7,43 +7,17 @@
|
||||||
//
|
//
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../WindowOpenGLDisplayPlugin.h"
|
#include "OculusBaseDisplayPlugin.h"
|
||||||
|
|
||||||
#include <QTimer>
|
|
||||||
|
|
||||||
#include <OVR_CAPI.h>
|
|
||||||
|
|
||||||
class OffscreenGlCanvas;
|
|
||||||
struct SwapFramebufferWrapper;
|
struct SwapFramebufferWrapper;
|
||||||
struct MirrorFramebufferWrapper;
|
|
||||||
|
|
||||||
using SwapFboPtr = QSharedPointer<SwapFramebufferWrapper>;
|
using SwapFboPtr = QSharedPointer<SwapFramebufferWrapper>;
|
||||||
using MirrorFboPtr = QSharedPointer<MirrorFramebufferWrapper>;
|
|
||||||
|
|
||||||
class OculusDisplayPlugin : public WindowOpenGLDisplayPlugin {
|
class OculusDisplayPlugin : public OculusBaseDisplayPlugin {
|
||||||
public:
|
public:
|
||||||
virtual bool isSupported() const override;
|
virtual void deactivate() override;
|
||||||
virtual const QString & getName() const override;
|
virtual const QString & getName() const override;
|
||||||
|
|
||||||
virtual void init() override;
|
|
||||||
virtual void deinit() override;
|
|
||||||
|
|
||||||
virtual void activate() override;
|
|
||||||
virtual void deactivate() override;
|
|
||||||
|
|
||||||
virtual bool eventFilter(QObject* receiver, QEvent* event) override;
|
|
||||||
|
|
||||||
// Stereo specific methods
|
|
||||||
virtual bool isHmd() const override { return true; }
|
|
||||||
virtual glm::mat4 getProjection(Eye eye, const glm::mat4& baseProjection) const override;
|
|
||||||
virtual glm::uvec2 getRecommendedRenderSize() const override;
|
|
||||||
virtual glm::uvec2 getRecommendedUiSize() const override { return uvec2(1920, 1080); }
|
|
||||||
virtual void resetSensors() override;
|
|
||||||
virtual glm::mat4 getEyePose(Eye eye) const override;
|
|
||||||
virtual glm::mat4 getHeadPose() const override;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void preRender() override;
|
|
||||||
virtual void display(GLuint finalTexture, const glm::uvec2& sceneSize) override;
|
virtual void display(GLuint finalTexture, const glm::uvec2& sceneSize) override;
|
||||||
virtual void customizeContext() override;
|
virtual void customizeContext() override;
|
||||||
// Do not perform swap in finish
|
// Do not perform swap in finish
|
||||||
|
@ -51,30 +25,10 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const QString NAME;
|
static const QString NAME;
|
||||||
|
|
||||||
ovrPosef _eyePoses[2];
|
|
||||||
|
|
||||||
mat4 _eyeProjections[3];
|
|
||||||
mat4 _compositeEyeProjections[2];
|
|
||||||
uvec2 _desiredFramebufferSize;
|
|
||||||
ovrTrackingState _trackingState;
|
|
||||||
bool _enableMirror{ false };
|
bool _enableMirror{ false };
|
||||||
|
|
||||||
#if (OVR_MAJOR_VERSION >= 6)
|
#if (OVR_MAJOR_VERSION >= 6)
|
||||||
ovrHmd _hmd;
|
|
||||||
float _ipd{ OVR_DEFAULT_IPD };
|
|
||||||
unsigned int _frameIndex;
|
|
||||||
ovrEyeRenderDesc _eyeRenderDescs[2];
|
|
||||||
ovrVector3f _eyeOffsets[2];
|
|
||||||
ovrFovPort _eyeFovs[2];
|
|
||||||
|
|
||||||
ovrLayerEyeFov& getSceneLayer();
|
|
||||||
ovrHmdDesc _hmdDesc;
|
|
||||||
SwapFboPtr _sceneFbo;
|
SwapFboPtr _sceneFbo;
|
||||||
ovrLayerEyeFov _sceneLayer;
|
|
||||||
#endif
|
|
||||||
#if (OVR_MAJOR_VERSION == 7)
|
|
||||||
ovrGraphicsLuid _luid;
|
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue