mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-25 17:14:59 +02:00
Merge pull request #5180 from jherico/hmd_offset
Fixing HMD position offset bug in picking & stereo rendering in HMD
This commit is contained in:
commit
81541e6013
4 changed files with 140 additions and 170 deletions
|
@ -4748,3 +4748,10 @@ mat4 Application::getEyePose(int eye) const {
|
|||
|
||||
return mat4();
|
||||
}
|
||||
|
||||
mat4 Application::getHeadPose() const {
|
||||
if (isHMDMode()) {
|
||||
return OculusManager::getHeadPose();
|
||||
}
|
||||
return mat4();
|
||||
}
|
||||
|
|
|
@ -11,10 +11,10 @@
|
|||
//
|
||||
|
||||
#include "InterfaceConfig.h"
|
||||
|
||||
#include "OculusManager.h"
|
||||
#include "ui/overlays/Text3DOverlay.h"
|
||||
|
||||
#include <CursorManager.h>
|
||||
#include <QDesktopWidget>
|
||||
#include <QGuiApplication>
|
||||
#include <QScreen>
|
||||
|
@ -37,7 +37,6 @@
|
|||
#include "InterfaceLogging.h"
|
||||
#include "Application.h"
|
||||
|
||||
|
||||
template <typename Function>
|
||||
void for_each_eye(Function function) {
|
||||
for (ovrEyeType eye = ovrEyeType::ovrEye_Left;
|
||||
|
@ -54,6 +53,71 @@ void for_each_eye(const ovrHmd & hmd, Function function) {
|
|||
function(eye);
|
||||
}
|
||||
}
|
||||
enum CalibrationState {
|
||||
UNCALIBRATED,
|
||||
WAITING_FOR_DELTA,
|
||||
WAITING_FOR_ZERO,
|
||||
WAITING_FOR_ZERO_HELD,
|
||||
CALIBRATED
|
||||
};
|
||||
|
||||
inline glm::mat4 toGlm(const ovrMatrix4f & om) {
|
||||
return glm::transpose(glm::make_mat4(&om.M[0][0]));
|
||||
}
|
||||
|
||||
inline glm::mat4 toGlm(const ovrFovPort & fovport, float nearPlane = 0.01f, float farPlane = 10000.0f) {
|
||||
return toGlm(ovrMatrix4f_Projection(fovport, nearPlane, farPlane, true));
|
||||
}
|
||||
|
||||
inline glm::vec3 toGlm(const ovrVector3f & ov) {
|
||||
return glm::make_vec3(&ov.x);
|
||||
}
|
||||
|
||||
inline glm::vec2 toGlm(const ovrVector2f & ov) {
|
||||
return glm::make_vec2(&ov.x);
|
||||
}
|
||||
|
||||
inline glm::ivec2 toGlm(const ovrVector2i & ov) {
|
||||
return glm::ivec2(ov.x, ov.y);
|
||||
}
|
||||
|
||||
inline glm::uvec2 toGlm(const ovrSizei & ov) {
|
||||
return glm::uvec2(ov.w, ov.h);
|
||||
}
|
||||
|
||||
inline glm::quat toGlm(const ovrQuatf & oq) {
|
||||
return glm::make_quat(&oq.x);
|
||||
}
|
||||
|
||||
inline glm::mat4 toGlm(const ovrPosef & op) {
|
||||
glm::mat4 orientation = glm::mat4_cast(toGlm(op.Orientation));
|
||||
glm::mat4 translation = glm::translate(glm::mat4(), toGlm(op.Position));
|
||||
return translation * orientation;
|
||||
}
|
||||
|
||||
inline ovrMatrix4f ovrFromGlm(const glm::mat4 & m) {
|
||||
ovrMatrix4f result;
|
||||
glm::mat4 transposed(glm::transpose(m));
|
||||
memcpy(result.M, &(transposed[0][0]), sizeof(float) * 16);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline ovrVector3f ovrFromGlm(const glm::vec3 & v) {
|
||||
return{ v.x, v.y, v.z };
|
||||
}
|
||||
|
||||
inline ovrVector2f ovrFromGlm(const glm::vec2 & v) {
|
||||
return{ v.x, v.y };
|
||||
}
|
||||
|
||||
inline ovrSizei ovrFromGlm(const glm::uvec2 & v) {
|
||||
return{ (int)v.x, (int)v.y };
|
||||
}
|
||||
|
||||
inline ovrQuatf ovrFromGlm(const glm::quat & q) {
|
||||
return{ q.x, q.y, q.z, q.w };
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
|
@ -171,50 +235,54 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
SwapFramebufferWrapper* OculusManager::_swapFbo{ nullptr };
|
||||
MirrorFramebufferWrapper* OculusManager::_mirrorFbo{ nullptr };
|
||||
ovrLayerEyeFov OculusManager::_sceneLayer;
|
||||
static SwapFramebufferWrapper* _swapFbo{ nullptr };
|
||||
static MirrorFramebufferWrapper* _mirrorFbo{ nullptr };
|
||||
static ovrLayerEyeFov _sceneLayer;
|
||||
|
||||
#else
|
||||
|
||||
ovrTexture OculusManager::_eyeTextures[ovrEye_Count];
|
||||
GlWindow* OculusManager::_outputWindow{ nullptr };
|
||||
static ovrTexture _eyeTextures[ovrEye_Count];
|
||||
static GlWindow* _outputWindow{ nullptr };
|
||||
|
||||
#endif
|
||||
|
||||
bool OculusManager::_isConnected = false;
|
||||
ovrHmd OculusManager::_ovrHmd;
|
||||
ovrFovPort OculusManager::_eyeFov[ovrEye_Count];
|
||||
ovrVector3f OculusManager::_eyeOffset[ovrEye_Count];
|
||||
ovrEyeRenderDesc OculusManager::_eyeRenderDesc[ovrEye_Count];
|
||||
ovrSizei OculusManager::_renderTargetSize;
|
||||
glm::mat4 OculusManager::_eyeProjection[ovrEye_Count];
|
||||
unsigned int OculusManager::_frameIndex = 0;
|
||||
bool OculusManager::_frameTimingActive = false;
|
||||
Camera* OculusManager::_camera = NULL;
|
||||
ovrEyeType OculusManager::_activeEye = ovrEye_Count;
|
||||
bool OculusManager::_hswDismissed = false;
|
||||
static bool _isConnected = false;
|
||||
static ovrHmd _ovrHmd;
|
||||
static ovrFovPort _eyeFov[ovrEye_Count];
|
||||
static ovrVector3f _eyeOffset[ovrEye_Count];
|
||||
static ovrEyeRenderDesc _eyeRenderDesc[ovrEye_Count];
|
||||
static ovrSizei _renderTargetSize;
|
||||
static glm::mat4 _eyeProjection[ovrEye_Count];
|
||||
static unsigned int _frameIndex = 0;
|
||||
static bool _frameTimingActive = false;
|
||||
static Camera* _camera = NULL;
|
||||
static ovrEyeType _activeEye = ovrEye_Count;
|
||||
static bool _hswDismissed = false;
|
||||
|
||||
float OculusManager::CALIBRATION_DELTA_MINIMUM_LENGTH = 0.02f;
|
||||
float OculusManager::CALIBRATION_DELTA_MINIMUM_ANGLE = 5.0f * RADIANS_PER_DEGREE;
|
||||
float OculusManager::CALIBRATION_ZERO_MAXIMUM_LENGTH = 0.01f;
|
||||
float OculusManager::CALIBRATION_ZERO_MAXIMUM_ANGLE = 2.0f * RADIANS_PER_DEGREE;
|
||||
quint64 OculusManager::CALIBRATION_ZERO_HOLD_TIME = 3000000; // usec
|
||||
float OculusManager::CALIBRATION_MESSAGE_DISTANCE = 2.5f;
|
||||
OculusManager::CalibrationState OculusManager::_calibrationState;
|
||||
glm::vec3 OculusManager::_calibrationPosition;
|
||||
glm::quat OculusManager::_calibrationOrientation;
|
||||
quint64 OculusManager::_calibrationStartTime;
|
||||
int OculusManager::_calibrationMessage = 0;
|
||||
glm::vec3 OculusManager::_eyePositions[ovrEye_Count];
|
||||
static const float CALIBRATION_DELTA_MINIMUM_LENGTH = 0.02f;
|
||||
static const float CALIBRATION_DELTA_MINIMUM_ANGLE = 5.0f * RADIANS_PER_DEGREE;
|
||||
static const float CALIBRATION_ZERO_MAXIMUM_LENGTH = 0.01f;
|
||||
static const float CALIBRATION_ZERO_MAXIMUM_ANGLE = 2.0f * RADIANS_PER_DEGREE;
|
||||
static const quint64 CALIBRATION_ZERO_HOLD_TIME = 3000000; // usec
|
||||
static const float CALIBRATION_MESSAGE_DISTANCE = 2.5f;
|
||||
static CalibrationState _calibrationState;
|
||||
static glm::vec3 _calibrationPosition;
|
||||
static glm::quat _calibrationOrientation;
|
||||
static quint64 _calibrationStartTime;
|
||||
static int _calibrationMessage = 0;
|
||||
static glm::vec3 _eyePositions[ovrEye_Count];
|
||||
// TODO expose this as a developer toggle
|
||||
bool OculusManager::_eyePerFrameMode = false;
|
||||
ovrEyeType OculusManager::_lastEyeRendered = ovrEye_Count;
|
||||
ovrSizei OculusManager::_recommendedTexSize = { 0, 0 };
|
||||
float OculusManager::_offscreenRenderScale = 1.0;
|
||||
static bool _eyePerFrameMode = false;
|
||||
static ovrEyeType _lastEyeRendered = ovrEye_Count;
|
||||
static ovrSizei _recommendedTexSize = { 0, 0 };
|
||||
static float _offscreenRenderScale = 1.0;
|
||||
static glm::mat4 _combinedProjection;
|
||||
static ovrPosef _eyeRenderPoses[ovrEye_Count];
|
||||
ovrRecti OculusManager::_eyeViewports[ovrEye_Count];
|
||||
static ovrRecti _eyeViewports[ovrEye_Count];
|
||||
static ovrVector3f _eyeOffsets[ovrEye_Count];
|
||||
|
||||
glm::vec3 OculusManager::getLeftEyePosition() { return _eyePositions[ovrEye_Left]; }
|
||||
glm::vec3 OculusManager::getRightEyePosition() { return _eyePositions[ovrEye_Right]; }
|
||||
|
||||
void OculusManager::connect(QOpenGLContext* shareContext) {
|
||||
qCDebug(interfaceapp) << "Oculus SDK" << OVR_VERSION_STRING;
|
||||
|
@ -267,6 +335,8 @@ void OculusManager::connect(QOpenGLContext* shareContext) {
|
|||
_eyeFov[eye] = _ovrHmd->DefaultEyeFov[eye];
|
||||
_eyeProjection[eye] = toGlm(ovrMatrix4f_Projection(_eyeFov[eye],
|
||||
DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_RightHanded));
|
||||
ovrEyeRenderDesc erd = ovrHmd_GetRenderDesc(_ovrHmd, eye, _eyeFov[eye]);
|
||||
_eyeOffsets[eye] = erd.HmdToEyeViewOffset;
|
||||
});
|
||||
ovrFovPort combinedFov = _ovrHmd->MaxEyeFov[0];
|
||||
combinedFov.RightTan = _ovrHmd->MaxEyeFov[1].RightTan;
|
||||
|
@ -389,7 +459,7 @@ void OculusManager::disconnect() {
|
|||
}
|
||||
}
|
||||
|
||||
void OculusManager::positionCalibrationBillboard(Text3DOverlay* billboard) {
|
||||
void positionCalibrationBillboard(Text3DOverlay* billboard) {
|
||||
MyAvatar* myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
glm::quat headOrientation = myAvatar->getHeadOrientation();
|
||||
headOrientation.x = 0;
|
||||
|
@ -400,7 +470,7 @@ void OculusManager::positionCalibrationBillboard(Text3DOverlay* billboard) {
|
|||
billboard->setRotation(headOrientation);
|
||||
}
|
||||
|
||||
void OculusManager::calibrate(glm::vec3 position, glm::quat orientation) {
|
||||
void calibrate(const glm::vec3& position, const glm::quat& orientation) {
|
||||
static QString instructionMessage = "Hold still to calibrate";
|
||||
static QString progressMessage;
|
||||
static Text3DOverlay* billboard;
|
||||
|
@ -605,9 +675,8 @@ void OculusManager::display(QGLWidget * glCanvas, RenderArgs* renderArgs, const
|
|||
}
|
||||
|
||||
trackerPosition = bodyOrientation * trackerPosition;
|
||||
static ovrVector3f eyeOffsets[2] = { { 0, 0, 0 }, { 0, 0, 0 } };
|
||||
ovrPosef eyePoses[ovrEye_Count];
|
||||
ovrHmd_GetEyePoses(_ovrHmd, _frameIndex, eyeOffsets, eyePoses, nullptr);
|
||||
ovrHmd_GetEyePoses(_ovrHmd, _frameIndex, _eyeOffsets, eyePoses, nullptr);
|
||||
#ifndef Q_OS_WIN
|
||||
ovrHmd_BeginFrame(_ovrHmd, _frameIndex);
|
||||
#endif
|
||||
|
@ -721,7 +790,18 @@ void OculusManager::display(QGLWidget * glCanvas, RenderArgs* renderArgs, const
|
|||
ovrHmd_EndFrame(_ovrHmd, _eyeRenderPoses, _eyeTextures);
|
||||
glCanvas->makeCurrent();
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// in order to account account for changes in the pick ray caused by head movement
|
||||
// we need to force a mouse move event on every frame (perhaps we could change this
|
||||
// to based on the head moving a minimum distance from the last position in which we
|
||||
// sent?)
|
||||
{
|
||||
QMouseEvent mouseEvent(QEvent::MouseMove, glCanvas->mapFromGlobal(QCursor::pos()),
|
||||
Qt::NoButton, Qt::NoButton, 0);
|
||||
qApp->mouseMoveEvent(&mouseEvent, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -826,3 +906,8 @@ mat4 OculusManager::getEyeProjection(int eye) {
|
|||
mat4 OculusManager::getEyePose(int eye) {
|
||||
return toGlm(_eyeRenderPoses[eye]);
|
||||
}
|
||||
|
||||
mat4 OculusManager::getHeadPose() {
|
||||
ovrTrackingState ts = ovrHmd_GetTrackingState(_ovrHmd, ovr_GetTimeInSeconds());
|
||||
return toGlm(ts.HeadPose.ThePose);
|
||||
}
|
|
@ -13,8 +13,6 @@
|
|||
#ifndef hifi_OculusManager_h
|
||||
#define hifi_OculusManager_h
|
||||
|
||||
#include <OVR_CAPI.h>
|
||||
|
||||
#include <ProgramObject.h>
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
@ -23,17 +21,7 @@
|
|||
#include "RenderArgs.h"
|
||||
|
||||
class QOpenGLContext;
|
||||
|
||||
class Camera;
|
||||
class GlWindow;
|
||||
class PalmData;
|
||||
class Text3DOverlay;
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
struct SwapFramebufferWrapper;
|
||||
struct MirrorFramebufferWrapper;
|
||||
#endif
|
||||
|
||||
|
||||
/// Handles interaction with the Oculus Rift.
|
||||
class OculusManager {
|
||||
|
@ -57,124 +45,14 @@ public:
|
|||
static void overrideOffAxisFrustum(float& left, float& right, float& bottom, float& top, float& nearVal,
|
||||
float& farVal, glm::vec4& nearClipPlane, glm::vec4& farClipPlane);
|
||||
|
||||
static glm::vec3 getLeftEyePosition() { return _eyePositions[ovrEye_Left]; }
|
||||
static glm::vec3 getRightEyePosition() { return _eyePositions[ovrEye_Right]; }
|
||||
static glm::vec3 getLeftEyePosition();
|
||||
static glm::vec3 getRightEyePosition();
|
||||
|
||||
static int getHMDScreen();
|
||||
|
||||
static glm::mat4 getEyeProjection(int eye);
|
||||
static glm::mat4 getEyePose(int eye);
|
||||
|
||||
private:
|
||||
static void initSdk();
|
||||
static void shutdownSdk();
|
||||
|
||||
static bool _isConnected;
|
||||
static glm::vec3 _eyePositions[ovrEye_Count];
|
||||
static ovrHmd _ovrHmd;
|
||||
static ovrFovPort _eyeFov[ovrEye_Count];
|
||||
static ovrVector3f _eyeOffset[ovrEye_Count];
|
||||
static glm::mat4 _eyeProjection[ovrEye_Count];
|
||||
static ovrEyeRenderDesc _eyeRenderDesc[ovrEye_Count];
|
||||
static ovrRecti _eyeViewports[ovrEye_Count];
|
||||
static ovrSizei _renderTargetSize;
|
||||
static unsigned int _frameIndex;
|
||||
static bool _frameTimingActive;
|
||||
static Camera* _camera;
|
||||
static ovrEyeType _activeEye;
|
||||
static bool _hswDismissed;
|
||||
|
||||
static void calibrate(const glm::vec3 position, const glm::quat orientation);
|
||||
enum CalibrationState {
|
||||
UNCALIBRATED,
|
||||
WAITING_FOR_DELTA,
|
||||
WAITING_FOR_ZERO,
|
||||
WAITING_FOR_ZERO_HELD,
|
||||
CALIBRATED
|
||||
};
|
||||
static void positionCalibrationBillboard(Text3DOverlay* message);
|
||||
static float CALIBRATION_DELTA_MINIMUM_LENGTH;
|
||||
static float CALIBRATION_DELTA_MINIMUM_ANGLE;
|
||||
static float CALIBRATION_ZERO_MAXIMUM_LENGTH;
|
||||
static float CALIBRATION_ZERO_MAXIMUM_ANGLE;
|
||||
static quint64 CALIBRATION_ZERO_HOLD_TIME;
|
||||
static float CALIBRATION_MESSAGE_DISTANCE;
|
||||
static CalibrationState _calibrationState;
|
||||
static glm::vec3 _calibrationPosition;
|
||||
static glm::quat _calibrationOrientation;
|
||||
static quint64 _calibrationStartTime;
|
||||
static int _calibrationMessage;
|
||||
// TODO drop this variable and use the existing 'Developer | Render | Scale Resolution' value
|
||||
static ovrSizei _recommendedTexSize;
|
||||
static float _offscreenRenderScale;
|
||||
static bool _eyePerFrameMode;
|
||||
static ovrEyeType _lastEyeRendered;
|
||||
#ifdef Q_OS_WIN
|
||||
static SwapFramebufferWrapper* _swapFbo;
|
||||
static MirrorFramebufferWrapper* _mirrorFbo;
|
||||
static ovrLayerEyeFov _sceneLayer;
|
||||
#else
|
||||
static ovrTexture _eyeTextures[ovrEye_Count];
|
||||
static GlWindow* _outputWindow;
|
||||
#endif
|
||||
static glm::mat4 getHeadPose();
|
||||
};
|
||||
|
||||
|
||||
inline glm::mat4 toGlm(const ovrMatrix4f & om) {
|
||||
return glm::transpose(glm::make_mat4(&om.M[0][0]));
|
||||
}
|
||||
|
||||
inline glm::mat4 toGlm(const ovrFovPort & fovport, float nearPlane = 0.01f, float farPlane = 10000.0f) {
|
||||
return toGlm(ovrMatrix4f_Projection(fovport, nearPlane, farPlane, true));
|
||||
}
|
||||
|
||||
inline glm::vec3 toGlm(const ovrVector3f & ov) {
|
||||
return glm::make_vec3(&ov.x);
|
||||
}
|
||||
|
||||
inline glm::vec2 toGlm(const ovrVector2f & ov) {
|
||||
return glm::make_vec2(&ov.x);
|
||||
}
|
||||
|
||||
inline glm::ivec2 toGlm(const ovrVector2i & ov) {
|
||||
return glm::ivec2(ov.x, ov.y);
|
||||
}
|
||||
|
||||
inline glm::uvec2 toGlm(const ovrSizei & ov) {
|
||||
return glm::uvec2(ov.w, ov.h);
|
||||
}
|
||||
|
||||
inline glm::quat toGlm(const ovrQuatf & oq) {
|
||||
return glm::make_quat(&oq.x);
|
||||
}
|
||||
|
||||
inline glm::mat4 toGlm(const ovrPosef & op) {
|
||||
glm::mat4 orientation = glm::mat4_cast(toGlm(op.Orientation));
|
||||
glm::mat4 translation = glm::translate(glm::mat4(), toGlm(op.Position));
|
||||
return translation * orientation;
|
||||
}
|
||||
|
||||
inline ovrMatrix4f ovrFromGlm(const glm::mat4 & m) {
|
||||
ovrMatrix4f result;
|
||||
glm::mat4 transposed(glm::transpose(m));
|
||||
memcpy(result.M, &(transposed[0][0]), sizeof(float) * 16);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline ovrVector3f ovrFromGlm(const glm::vec3 & v) {
|
||||
return{ v.x, v.y, v.z };
|
||||
}
|
||||
|
||||
inline ovrVector2f ovrFromGlm(const glm::vec2 & v) {
|
||||
return{ v.x, v.y };
|
||||
}
|
||||
|
||||
inline ovrSizei ovrFromGlm(const glm::uvec2 & v) {
|
||||
return{ (int)v.x, (int)v.y };
|
||||
}
|
||||
|
||||
inline ovrQuatf ovrFromGlm(const glm::quat & q) {
|
||||
return{ q.x, q.y, q.z, q.w };
|
||||
}
|
||||
|
||||
#endif // hifi_OculusManager_h
|
||||
|
|
|
@ -334,12 +334,12 @@ void ApplicationCompositor::computeHmdPickRay(glm::vec2 cursorPos, glm::vec3& or
|
|||
|
||||
// Intersection UI overlay space
|
||||
glm::vec3 worldSpaceDirection = overlayOrientation * overlaySpaceDirection;
|
||||
glm::vec3 intersectionWithUi = glm::normalize(worldSpaceDirection) * _oculusUIRadius;
|
||||
intersectionWithUi += overlayPosition;
|
||||
glm::vec3 worldSpaceIntersection = (glm::normalize(worldSpaceDirection) * _oculusUIRadius) + overlayPosition;
|
||||
glm::vec3 worldSpaceHeadPosition = (overlayOrientation * glm::vec3(qApp->getHeadPose()[3])) + overlayPosition;
|
||||
|
||||
// Intersection in world space
|
||||
origin = overlayPosition;
|
||||
direction = glm::normalize(intersectionWithUi - origin);
|
||||
origin = worldSpaceHeadPosition;
|
||||
direction = glm::normalize(worldSpaceIntersection - worldSpaceHeadPosition);
|
||||
}
|
||||
|
||||
//Caculate the click location using one of the sixense controllers. Scale is not applied
|
||||
|
|
Loading…
Reference in a new issue