mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 14:37:46 +02:00
Merge pull request #13314 from jherico/feature/oculus_update
Update Oculus integration
This commit is contained in:
commit
c53a15ec78
9 changed files with 359 additions and 357 deletions
4
cmake/externals/LibOVR/CMakeLists.txt
vendored
4
cmake/externals/LibOVR/CMakeLists.txt
vendored
|
@ -17,8 +17,8 @@ if (WIN32)
|
||||||
|
|
||||||
ExternalProject_Add(
|
ExternalProject_Add(
|
||||||
${EXTERNAL_NAME}
|
${EXTERNAL_NAME}
|
||||||
URL https://static.oculus.com/sdk-downloads/1.11.0/Public/1486063832/ovr_sdk_win_1.11.0_public.zip
|
URL http://hifi-public.s3.amazonaws.com/dependencies/ovr_sdk_win_1.26.0_public.zip
|
||||||
URL_MD5 ea484403757cbfdfa743b6577fb1f9d2
|
URL_MD5 06804ff9727b910dcd04a37c800053b5
|
||||||
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
|
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
|
||||||
PATCH_COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/LibOVRCMakeLists.txt" <SOURCE_DIR>/CMakeLists.txt
|
PATCH_COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/LibOVRCMakeLists.txt" <SOURCE_DIR>/CMakeLists.txt
|
||||||
LOG_DOWNLOAD 1
|
LOG_DOWNLOAD 1
|
||||||
|
|
2
cmake/externals/LibOVR/LibOVRCMakeLists.txt
vendored
2
cmake/externals/LibOVR/LibOVRCMakeLists.txt
vendored
|
@ -4,7 +4,7 @@ project(LibOVR)
|
||||||
include_directories(LibOVR/Include LibOVR/Src)
|
include_directories(LibOVR/Include LibOVR/Src)
|
||||||
file(GLOB HEADER_FILES LibOVR/Include/*.h)
|
file(GLOB HEADER_FILES LibOVR/Include/*.h)
|
||||||
file(GLOB EXTRA_HEADER_FILES LibOVR/Include/Extras/*.h)
|
file(GLOB EXTRA_HEADER_FILES LibOVR/Include/Extras/*.h)
|
||||||
file(GLOB_RECURSE SOURCE_FILES LibOVR/Src/*.c LibOVR/Src/*.cpp)
|
file(GLOB_RECURSE SOURCE_FILES LibOVR/Shim/*.c LibOVR/Shim/*.cpp)
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DOVR_BUILD_DEBUG")
|
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DOVR_BUILD_DEBUG")
|
||||||
add_library(LibOVR STATIC ${SOURCE_FILES} ${HEADER_FILES} ${EXTRA_HEADER_FILES})
|
add_library(LibOVR STATIC ${SOURCE_FILES} ${HEADER_FILES} ${EXTRA_HEADER_FILES})
|
||||||
set_target_properties(LibOVR PROPERTIES DEBUG_POSTFIX "d")
|
set_target_properties(LibOVR PROPERTIES DEBUG_POSTFIX "d")
|
||||||
|
|
|
@ -15,19 +15,25 @@
|
||||||
|
|
||||||
#include "OculusHelpers.h"
|
#include "OculusHelpers.h"
|
||||||
|
|
||||||
|
using namespace hifi;
|
||||||
|
|
||||||
void OculusBaseDisplayPlugin::resetSensors() {
|
void OculusBaseDisplayPlugin::resetSensors() {
|
||||||
ovr_RecenterTrackingOrigin(_session);
|
ovr_RecenterTrackingOrigin(_session);
|
||||||
|
|
||||||
_currentRenderFrameInfo.renderPose = glm::mat4(); // identity
|
_currentRenderFrameInfo.renderPose = glm::mat4(); // identity
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OculusBaseDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
bool OculusBaseDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||||
handleOVREvents();
|
ovrSessionStatus status{};
|
||||||
if (quitRequested()) {
|
if (!OVR_SUCCESS(ovr_GetSessionStatus(_session, &status))) {
|
||||||
|
qCWarning(oculusLog) << "Unable to fetch Oculus session status" << ovr::getError();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ovr::quitRequested(status)) {
|
||||||
QMetaObject::invokeMethod(qApp, "quit");
|
QMetaObject::invokeMethod(qApp, "quit");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (reorientRequested()) {
|
if (ovr::reorientRequested(status)) {
|
||||||
emit resetSensorsRequested();
|
emit resetSensorsRequested();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,18 +41,18 @@ bool OculusBaseDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||||
_currentRenderFrameInfo.sensorSampleTime = ovr_GetTimeInSeconds();
|
_currentRenderFrameInfo.sensorSampleTime = ovr_GetTimeInSeconds();
|
||||||
_currentRenderFrameInfo.predictedDisplayTime = ovr_GetPredictedDisplayTime(_session, frameIndex);
|
_currentRenderFrameInfo.predictedDisplayTime = ovr_GetPredictedDisplayTime(_session, frameIndex);
|
||||||
auto trackingState = ovr_GetTrackingState(_session, _currentRenderFrameInfo.predictedDisplayTime, ovrTrue);
|
auto trackingState = ovr_GetTrackingState(_session, _currentRenderFrameInfo.predictedDisplayTime, ovrTrue);
|
||||||
_currentRenderFrameInfo.renderPose = toGlm(trackingState.HeadPose.ThePose);
|
_currentRenderFrameInfo.renderPose = ovr::toGlm(trackingState.HeadPose.ThePose);
|
||||||
_currentRenderFrameInfo.presentPose = _currentRenderFrameInfo.renderPose;
|
_currentRenderFrameInfo.presentPose = _currentRenderFrameInfo.renderPose;
|
||||||
|
|
||||||
std::array<glm::mat4, 2> handPoses;
|
std::array<glm::mat4, 2> handPoses;
|
||||||
// Make controller poses available to the presentation thread
|
// Make controller poses available to the presentation thread
|
||||||
ovr_for_each_hand([&](ovrHandType hand) {
|
ovr::for_each_hand([&](ovrHandType hand) {
|
||||||
static const auto REQUIRED_HAND_STATUS = ovrStatus_OrientationTracked | ovrStatus_PositionTracked;
|
static const auto REQUIRED_HAND_STATUS = ovrStatus_OrientationTracked | ovrStatus_PositionTracked;
|
||||||
if (REQUIRED_HAND_STATUS != (trackingState.HandStatusFlags[hand] & REQUIRED_HAND_STATUS)) {
|
if (REQUIRED_HAND_STATUS != (trackingState.HandStatusFlags[hand] & REQUIRED_HAND_STATUS)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto correctedPose = ovrControllerPoseToHandPose(hand, trackingState.HandPoses[hand]);
|
auto correctedPose = ovr::toControllerPose(hand, trackingState.HandPoses[hand]);
|
||||||
static const glm::quat HAND_TO_LASER_ROTATION = glm::rotation(Vectors::UNIT_Z, Vectors::UNIT_NEG_Y);
|
static const glm::quat HAND_TO_LASER_ROTATION = glm::rotation(Vectors::UNIT_Z, Vectors::UNIT_NEG_Y);
|
||||||
handPoses[hand] = glm::translate(glm::mat4(), correctedPose.translation) * glm::mat4_cast(correctedPose.rotation * HAND_TO_LASER_ROTATION);
|
handPoses[hand] = glm::translate(glm::mat4(), correctedPose.translation) * glm::mat4_cast(correctedPose.rotation * HAND_TO_LASER_ROTATION);
|
||||||
});
|
});
|
||||||
|
@ -58,7 +64,7 @@ bool OculusBaseDisplayPlugin::beginFrameRender(uint32_t frameIndex) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OculusBaseDisplayPlugin::isSupported() const {
|
bool OculusBaseDisplayPlugin::isSupported() const {
|
||||||
return oculusAvailable();
|
return ovr::available();
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::mat4 OculusBaseDisplayPlugin::getEyeProjection(Eye eye, const glm::mat4& baseProjection) const {
|
glm::mat4 OculusBaseDisplayPlugin::getEyeProjection(Eye eye, const glm::mat4& baseProjection) const {
|
||||||
|
@ -71,7 +77,7 @@ glm::mat4 OculusBaseDisplayPlugin::getEyeProjection(Eye eye, const glm::mat4& ba
|
||||||
ovrFovPort fovPort = _hmdDesc.DefaultEyeFov[eye];
|
ovrFovPort fovPort = _hmdDesc.DefaultEyeFov[eye];
|
||||||
ovrEyeRenderDesc& erd = ovr_GetRenderDesc(_session, ovrEye, fovPort);
|
ovrEyeRenderDesc& erd = ovr_GetRenderDesc(_session, ovrEye, fovPort);
|
||||||
ovrMatrix4f ovrPerspectiveProjection = ovrMatrix4f_Projection(erd.Fov, baseNearClip, baseFarClip, ovrProjection_ClipRangeOpenGL);
|
ovrMatrix4f ovrPerspectiveProjection = ovrMatrix4f_Projection(erd.Fov, baseNearClip, baseFarClip, ovrProjection_ClipRangeOpenGL);
|
||||||
return toGlm(ovrPerspectiveProjection);
|
return ovr::toGlm(ovrPerspectiveProjection);
|
||||||
} else {
|
} else {
|
||||||
return baseProjection;
|
return baseProjection;
|
||||||
}
|
}
|
||||||
|
@ -85,7 +91,7 @@ glm::mat4 OculusBaseDisplayPlugin::getCullingProjection(const glm::mat4& basePro
|
||||||
float baseFarClip = baseFrustum.getFarClip();
|
float baseFarClip = baseFrustum.getFarClip();
|
||||||
auto combinedFov = _eyeFovs[0];
|
auto combinedFov = _eyeFovs[0];
|
||||||
combinedFov.LeftTan = combinedFov.RightTan = std::max(combinedFov.LeftTan, combinedFov.RightTan);
|
combinedFov.LeftTan = combinedFov.RightTan = std::max(combinedFov.LeftTan, combinedFov.RightTan);
|
||||||
return toGlm(ovrMatrix4f_Projection(combinedFov, baseNearClip, baseFarClip, ovrProjection_ClipRangeOpenGL));
|
return ovr::toGlm(ovrMatrix4f_Projection(combinedFov, baseNearClip, baseFarClip, ovrProjection_ClipRangeOpenGL));
|
||||||
} else {
|
} else {
|
||||||
return baseProjection;
|
return baseProjection;
|
||||||
}
|
}
|
||||||
|
@ -102,7 +108,7 @@ void OculusBaseDisplayPlugin::uncustomizeContext() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OculusBaseDisplayPlugin::internalActivate() {
|
bool OculusBaseDisplayPlugin::internalActivate() {
|
||||||
_session = acquireOculusSession();
|
_session = ovr::acquireRenderSession();
|
||||||
if (!_session) {
|
if (!_session) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -113,21 +119,21 @@ bool OculusBaseDisplayPlugin::internalActivate() {
|
||||||
_viewScaleDesc.HmdSpaceToWorldScaleInMeters = 1.0f;
|
_viewScaleDesc.HmdSpaceToWorldScaleInMeters = 1.0f;
|
||||||
|
|
||||||
_ipd = 0;
|
_ipd = 0;
|
||||||
ovr_for_each_eye([&](ovrEyeType eye) {
|
ovr::for_each_eye([&](ovrEyeType eye) {
|
||||||
_eyeFovs[eye] = _hmdDesc.DefaultEyeFov[eye];
|
_eyeFovs[eye] = _hmdDesc.DefaultEyeFov[eye];
|
||||||
ovrEyeRenderDesc& erd = _eyeRenderDescs[eye] = ovr_GetRenderDesc(_session, eye, _eyeFovs[eye]);
|
ovrEyeRenderDesc& erd = _eyeRenderDescs[eye] = ovr_GetRenderDesc(_session, eye, _eyeFovs[eye]);
|
||||||
ovrMatrix4f ovrPerspectiveProjection =
|
ovrMatrix4f ovrPerspectiveProjection =
|
||||||
ovrMatrix4f_Projection(erd.Fov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_ClipRangeOpenGL);
|
ovrMatrix4f_Projection(erd.Fov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_ClipRangeOpenGL);
|
||||||
_eyeProjections[eye] = toGlm(ovrPerspectiveProjection);
|
_eyeProjections[eye] = ovr::toGlm(ovrPerspectiveProjection);
|
||||||
_eyeOffsets[eye] = glm::translate(mat4(), toGlm(erd.HmdToEyeOffset));
|
_eyeOffsets[eye] = ovr::toGlm(erd.HmdToEyePose);
|
||||||
eyeSizes[eye] = toGlm(ovr_GetFovTextureSize(_session, eye, erd.Fov, 1.0f));
|
eyeSizes[eye] = ovr::toGlm(ovr_GetFovTextureSize(_session, eye, erd.Fov, 1.0f));
|
||||||
_viewScaleDesc.HmdToEyeOffset[eye] = erd.HmdToEyeOffset;
|
_viewScaleDesc.HmdToEyePose[eye] = erd.HmdToEyePose;
|
||||||
_ipd += glm::abs(glm::length(toGlm(erd.HmdToEyeOffset)));
|
_ipd += glm::abs(glm::length(ovr::toGlm(erd.HmdToEyePose.Position)));
|
||||||
});
|
});
|
||||||
|
|
||||||
auto combinedFov = _eyeFovs[0];
|
auto combinedFov = _eyeFovs[0];
|
||||||
combinedFov.LeftTan = combinedFov.RightTan = std::max(combinedFov.LeftTan, combinedFov.RightTan);
|
combinedFov.LeftTan = combinedFov.RightTan = std::max(combinedFov.LeftTan, combinedFov.RightTan);
|
||||||
_cullingProjection = toGlm(ovrMatrix4f_Projection(combinedFov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_ClipRangeOpenGL));
|
_cullingProjection = ovr::toGlm(ovrMatrix4f_Projection(combinedFov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_ClipRangeOpenGL));
|
||||||
|
|
||||||
_renderTargetSize = uvec2(
|
_renderTargetSize = uvec2(
|
||||||
eyeSizes[0].x + eyeSizes[1].x,
|
eyeSizes[0].x + eyeSizes[1].x,
|
||||||
|
@ -136,7 +142,7 @@ bool OculusBaseDisplayPlugin::internalActivate() {
|
||||||
memset(&_sceneLayer, 0, sizeof(ovrLayerEyeFov));
|
memset(&_sceneLayer, 0, sizeof(ovrLayerEyeFov));
|
||||||
_sceneLayer.Header.Type = ovrLayerType_EyeFov;
|
_sceneLayer.Header.Type = ovrLayerType_EyeFov;
|
||||||
_sceneLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft;
|
_sceneLayer.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft;
|
||||||
ovr_for_each_eye([&](ovrEyeType eye) {
|
ovr::for_each_eye([&](ovrEyeType eye) {
|
||||||
ovrFovPort & fov = _sceneLayer.Fov[eye] = _eyeRenderDescs[eye].Fov;
|
ovrFovPort & fov = _sceneLayer.Fov[eye] = _eyeRenderDescs[eye].Fov;
|
||||||
ovrSizei & size = _sceneLayer.Viewport[eye].Size = ovr_GetFovTextureSize(_session, eye, fov, 1.0f);
|
ovrSizei & size = _sceneLayer.Viewport[eye].Size = ovr_GetFovTextureSize(_session, eye, fov, 1.0f);
|
||||||
_sceneLayer.Viewport[eye].Pos = { eye == ovrEye_Left ? 0 : size.w, 0 };
|
_sceneLayer.Viewport[eye].Pos = { eye == ovrEye_Left ? 0 : size.w, 0 };
|
||||||
|
@ -150,28 +156,14 @@ bool OculusBaseDisplayPlugin::internalActivate() {
|
||||||
|
|
||||||
void OculusBaseDisplayPlugin::internalDeactivate() {
|
void OculusBaseDisplayPlugin::internalDeactivate() {
|
||||||
Parent::internalDeactivate();
|
Parent::internalDeactivate();
|
||||||
|
ovr::releaseRenderSession(_session);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OculusBaseDisplayPlugin::activateStandBySession() {
|
|
||||||
if (!_session) {
|
|
||||||
_session = acquireOculusSession();
|
|
||||||
}
|
|
||||||
return _session;
|
|
||||||
}
|
|
||||||
void OculusBaseDisplayPlugin::deactivateSession() {
|
|
||||||
// FIXME
|
|
||||||
// Switching to Qt 5.9 exposed a race condition or similar issue that caused a crash when putting on an Rift
|
|
||||||
// while already in VR mode. Commenting these out is a workaround.
|
|
||||||
//releaseOculusSession();
|
|
||||||
//_session = nullptr;
|
|
||||||
}
|
|
||||||
void OculusBaseDisplayPlugin::updatePresentPose() {
|
void OculusBaseDisplayPlugin::updatePresentPose() {
|
||||||
|
ovrTrackingState trackingState;
|
||||||
_currentPresentFrameInfo.sensorSampleTime = ovr_GetTimeInSeconds();
|
_currentPresentFrameInfo.sensorSampleTime = ovr_GetTimeInSeconds();
|
||||||
_currentPresentFrameInfo.predictedDisplayTime = ovr_GetPredictedDisplayTime(_session, 0);
|
_currentPresentFrameInfo.predictedDisplayTime = ovr_GetPredictedDisplayTime(_session, 0);
|
||||||
auto trackingState = ovr_GetTrackingState(_session, _currentRenderFrameInfo.predictedDisplayTime, ovrFalse);
|
trackingState = ovr_GetTrackingState(_session, _currentRenderFrameInfo.predictedDisplayTime, ovrFalse);
|
||||||
_currentPresentFrameInfo.presentPose = toGlm(trackingState.HeadPose.ThePose);
|
_currentPresentFrameInfo.presentPose = ovr::toGlm(trackingState.HeadPose.ThePose);
|
||||||
_currentPresentFrameInfo.renderPose = _currentPresentFrameInfo.presentPose;
|
_currentPresentFrameInfo.renderPose = _currentPresentFrameInfo.presentPose;
|
||||||
}
|
}
|
||||||
|
|
||||||
OculusBaseDisplayPlugin::~OculusBaseDisplayPlugin() {
|
|
||||||
}
|
|
||||||
|
|
|
@ -16,37 +16,32 @@
|
||||||
class OculusBaseDisplayPlugin : public HmdDisplayPlugin {
|
class OculusBaseDisplayPlugin : public HmdDisplayPlugin {
|
||||||
using Parent = HmdDisplayPlugin;
|
using Parent = HmdDisplayPlugin;
|
||||||
public:
|
public:
|
||||||
~OculusBaseDisplayPlugin();
|
|
||||||
bool isSupported() const override;
|
bool isSupported() const override;
|
||||||
|
bool hasAsyncReprojection() const override { return true; }
|
||||||
|
bool getSupportsAutoSwitch() override final { return true; }
|
||||||
|
|
||||||
glm::mat4 getEyeProjection(Eye eye, const glm::mat4& baseProjection) const override;
|
glm::mat4 getEyeProjection(Eye eye, const glm::mat4& baseProjection) const override;
|
||||||
glm::mat4 getCullingProjection(const glm::mat4& baseProjection) const override;
|
glm::mat4 getCullingProjection(const glm::mat4& baseProjection) const override;
|
||||||
|
|
||||||
bool hasAsyncReprojection() const override { return true; }
|
|
||||||
|
|
||||||
|
|
||||||
// Stereo specific methods
|
// Stereo specific methods
|
||||||
void resetSensors() override final;
|
void resetSensors() override final;
|
||||||
bool beginFrameRender(uint32_t frameIndex) override;
|
bool beginFrameRender(uint32_t frameIndex) override;
|
||||||
float getTargetFrameRate() const override { return _hmdDesc.DisplayRefreshRate; }
|
float getTargetFrameRate() const override { return _hmdDesc.DisplayRefreshRate; }
|
||||||
bool getSupportsAutoSwitch() override final { return true; }
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void customizeContext() override;
|
void customizeContext() override;
|
||||||
void uncustomizeContext() override;
|
void uncustomizeContext() override;
|
||||||
bool internalActivate() override;
|
bool internalActivate() override;
|
||||||
void internalDeactivate() override;
|
void internalDeactivate() override;
|
||||||
bool activateStandBySession() override;
|
|
||||||
void deactivateSession() override;
|
|
||||||
void updatePresentPose() override;
|
void updatePresentPose() override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
ovrSession _session { nullptr };
|
ovrSession _session{ nullptr };
|
||||||
ovrGraphicsLuid _luid;
|
ovrGraphicsLuid _luid;
|
||||||
ovrEyeRenderDesc _eyeRenderDescs[2];
|
std::array<ovrEyeRenderDesc, 2> _eyeRenderDescs;
|
||||||
ovrFovPort _eyeFovs[2];
|
std::array<ovrFovPort, 2> _eyeFovs;
|
||||||
ovrHmdDesc _hmdDesc;
|
ovrHmdDesc _hmdDesc;
|
||||||
ovrLayerEyeFov _sceneLayer;
|
ovrLayerEyeFov _sceneLayer;
|
||||||
ovrViewScaleDesc _viewScaleDesc;
|
ovrViewScaleDesc _viewScaleDesc;
|
||||||
|
// ovrLayerEyeFovDepth _depthLayer;
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,34 +22,23 @@
|
||||||
#include <NumericalConstants.h>
|
#include <NumericalConstants.h>
|
||||||
#include <StreamUtils.h>
|
#include <StreamUtils.h>
|
||||||
|
|
||||||
#include <OVR_CAPI.h>
|
#include <ovr_capi.h>
|
||||||
|
|
||||||
#include "OculusHelpers.h"
|
#include "OculusHelpers.h"
|
||||||
|
|
||||||
Q_DECLARE_LOGGING_CATEGORY(oculus)
|
using namespace hifi;
|
||||||
|
|
||||||
|
|
||||||
static const char* MENU_PARENT = "Avatar";
|
|
||||||
static const char* MENU_NAME = "Oculus Touch Controllers";
|
|
||||||
static const char* MENU_PATH = "Avatar" ">" "Oculus Touch Controllers";
|
|
||||||
|
|
||||||
const char* OculusControllerManager::NAME = "Oculus";
|
const char* OculusControllerManager::NAME = "Oculus";
|
||||||
|
|
||||||
const quint64 LOST_TRACKING_DELAY = 3000000;
|
const quint64 LOST_TRACKING_DELAY = 3000000;
|
||||||
|
|
||||||
bool OculusControllerManager::isSupported() const {
|
bool OculusControllerManager::isSupported() const {
|
||||||
return oculusAvailable();
|
return hifi::ovr::available();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OculusControllerManager::activate() {
|
bool OculusControllerManager::activate() {
|
||||||
InputPlugin::activate();
|
InputPlugin::activate();
|
||||||
if (!_session) {
|
|
||||||
_session = acquireOculusSession();
|
|
||||||
}
|
|
||||||
Q_ASSERT(_session);
|
|
||||||
|
|
||||||
checkForConnectedDevices();
|
checkForConnectedDevices();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,33 +47,30 @@ void OculusControllerManager::checkForConnectedDevices() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int controllerConnected = ovr_GetConnectedControllerTypes(_session);
|
ovr::withSession([&] (ovrSession session) {
|
||||||
|
unsigned int controllerConnected = ovr_GetConnectedControllerTypes(session);
|
||||||
|
|
||||||
if (!_remote && (controllerConnected & ovrControllerType_Remote) == ovrControllerType_Remote) {
|
if (!_remote && (controllerConnected & ovrControllerType_Remote) == ovrControllerType_Remote) {
|
||||||
if (OVR_SUCCESS(ovr_GetInputState(_session, ovrControllerType_Remote, &_inputState))) {
|
if (OVR_SUCCESS(ovr_GetInputState(session, ovrControllerType_Remote, &_inputState))) {
|
||||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||||
_remote = std::make_shared<RemoteDevice>(*this);
|
_remote = std::make_shared<RemoteDevice>(*this);
|
||||||
userInputMapper->registerDevice(_remote);
|
userInputMapper->registerDevice(_remote);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!_touch && (controllerConnected & ovrControllerType_Touch) != 0) {
|
if (!_touch && (controllerConnected & ovrControllerType_Touch) != 0) {
|
||||||
if (OVR_SUCCESS(ovr_GetInputState(_session, ovrControllerType_Touch, &_inputState))) {
|
if (OVR_SUCCESS(ovr_GetInputState(session, ovrControllerType_Touch, &_inputState))) {
|
||||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||||
_touch = std::make_shared<TouchDevice>(*this);
|
_touch = std::make_shared<TouchDevice>(*this);
|
||||||
userInputMapper->registerDevice(_touch);
|
userInputMapper->registerDevice(_touch);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void OculusControllerManager::deactivate() {
|
void OculusControllerManager::deactivate() {
|
||||||
InputPlugin::deactivate();
|
InputPlugin::deactivate();
|
||||||
|
|
||||||
if (_session) {
|
|
||||||
releaseOculusSession();
|
|
||||||
_session = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// unregister with UserInputMapper
|
// unregister with UserInputMapper
|
||||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||||
if (_touch) {
|
if (_touch) {
|
||||||
|
@ -100,20 +86,30 @@ void OculusControllerManager::pluginUpdate(float deltaTime, const controller::In
|
||||||
|
|
||||||
checkForConnectedDevices();
|
checkForConnectedDevices();
|
||||||
|
|
||||||
if (_touch) {
|
bool updateRemote = false, updateTouch = false;
|
||||||
if (OVR_SUCCESS(ovr_GetInputState(_session, ovrControllerType_Touch, &_inputState))) {
|
|
||||||
_touch->update(deltaTime, inputCalibrationData);
|
ovr::withSession([&](ovrSession session) {
|
||||||
} else {
|
if (_touch) {
|
||||||
qCWarning(oculus) << "Unable to read Oculus touch input state";
|
updateTouch = OVR_SUCCESS(ovr_GetInputState(session, ovrControllerType_Touch, &_inputState));
|
||||||
|
if (!updateTouch) {
|
||||||
|
qCWarning(oculusLog) << "Unable to read Oculus touch input state" << ovr::getError();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
if (_remote) {
|
||||||
|
updateRemote = OVR_SUCCESS(ovr_GetInputState(session, ovrControllerType_Remote, &_inputState));
|
||||||
|
if (!updateRemote) {
|
||||||
|
qCWarning(oculusLog) << "Unable to read Oculus remote input state" << ovr::getError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
if (_touch && updateTouch) {
|
||||||
|
_touch->update(deltaTime, inputCalibrationData);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_remote) {
|
if (_remote && updateRemote) {
|
||||||
if (OVR_SUCCESS(ovr_GetInputState(_session, ovrControllerType_Remote, &_inputState))) {
|
_remote->update(deltaTime, inputCalibrationData);
|
||||||
_remote->update(deltaTime, inputCalibrationData);
|
|
||||||
} else {
|
|
||||||
qCWarning(oculus) << "Unable to read Oculus remote input state";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,15 +206,6 @@ void OculusControllerManager::RemoteDevice::focusOutEvent() {
|
||||||
_buttonPressedMap.clear();
|
_buttonPressedMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OculusControllerManager::isHeadControllerMounted() const {
|
|
||||||
ovrSessionStatus status;
|
|
||||||
bool success = OVR_SUCCESS(ovr_GetSessionStatus(_session, &status));
|
|
||||||
if (!success) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return status.HmdMounted == ovrTrue;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OculusControllerManager::TouchDevice::update(float deltaTime,
|
void OculusControllerManager::TouchDevice::update(float deltaTime,
|
||||||
const controller::InputCalibrationData& inputCalibrationData) {
|
const controller::InputCalibrationData& inputCalibrationData) {
|
||||||
_buttonPressedMap.clear();
|
_buttonPressedMap.clear();
|
||||||
|
@ -226,10 +213,19 @@ void OculusControllerManager::TouchDevice::update(float deltaTime,
|
||||||
int numTrackedControllers = 0;
|
int numTrackedControllers = 0;
|
||||||
quint64 currentTime = usecTimestampNow();
|
quint64 currentTime = usecTimestampNow();
|
||||||
static const auto REQUIRED_HAND_STATUS = ovrStatus_OrientationTracked | ovrStatus_PositionTracked;
|
static const auto REQUIRED_HAND_STATUS = ovrStatus_OrientationTracked | ovrStatus_PositionTracked;
|
||||||
auto tracking = ovr_GetTrackingState(_parent._session, 0, false);
|
bool hasInputFocus = ovr::hasInputFocus();
|
||||||
ovr_for_each_hand([&](ovrHandType hand) {
|
auto tracking = ovr::getTrackingState(); // ovr_GetTrackingState(_parent._session, 0, false);
|
||||||
|
ovr::for_each_hand([&](ovrHandType hand) {
|
||||||
++numTrackedControllers;
|
++numTrackedControllers;
|
||||||
int controller = (hand == ovrHand_Left ? controller::LEFT_HAND : controller::RIGHT_HAND);
|
int controller = (hand == ovrHand_Left ? controller::LEFT_HAND : controller::RIGHT_HAND);
|
||||||
|
|
||||||
|
// Disable hand tracking while in Oculus Dash (Dash renders it's own hands)
|
||||||
|
if (!hasInputFocus) {
|
||||||
|
_poseStateMap.erase(controller);
|
||||||
|
_poseStateMap[controller].valid = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (REQUIRED_HAND_STATUS == (tracking.HandStatusFlags[hand] & REQUIRED_HAND_STATUS)) {
|
if (REQUIRED_HAND_STATUS == (tracking.HandStatusFlags[hand] & REQUIRED_HAND_STATUS)) {
|
||||||
_poseStateMap.erase(controller);
|
_poseStateMap.erase(controller);
|
||||||
handlePose(deltaTime, inputCalibrationData, hand, tracking.HandPoses[hand]);
|
handlePose(deltaTime, inputCalibrationData, hand, tracking.HandPoses[hand]);
|
||||||
|
@ -253,7 +249,7 @@ void OculusControllerManager::TouchDevice::update(float deltaTime,
|
||||||
handleRotationForUntrackedHand(inputCalibrationData, hand, tracking.HandPoses[hand]);
|
handleRotationForUntrackedHand(inputCalibrationData, hand, tracking.HandPoses[hand]);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (_parent.isHeadControllerMounted()) {
|
if (ovr::hmdMounted()) {
|
||||||
handleHeadPose(deltaTime, inputCalibrationData, tracking.HeadPose);
|
handleHeadPose(deltaTime, inputCalibrationData, tracking.HeadPose);
|
||||||
} else {
|
} else {
|
||||||
_poseStateMap[controller::HEAD].valid = false;
|
_poseStateMap[controller::HEAD].valid = false;
|
||||||
|
@ -311,7 +307,7 @@ void OculusControllerManager::TouchDevice::handlePose(float deltaTime,
|
||||||
ovrHandType hand, const ovrPoseStatef& handPose) {
|
ovrHandType hand, const ovrPoseStatef& handPose) {
|
||||||
auto poseId = hand == ovrHand_Left ? controller::LEFT_HAND : controller::RIGHT_HAND;
|
auto poseId = hand == ovrHand_Left ? controller::LEFT_HAND : controller::RIGHT_HAND;
|
||||||
auto& pose = _poseStateMap[poseId];
|
auto& pose = _poseStateMap[poseId];
|
||||||
pose = ovrControllerPoseToHandPose(hand, handPose);
|
pose = ovr::toControllerPose(hand, handPose);
|
||||||
// transform into avatar frame
|
// transform into avatar frame
|
||||||
glm::mat4 controllerToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat;
|
glm::mat4 controllerToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat;
|
||||||
pose = pose.transform(controllerToAvatar);
|
pose = pose.transform(controllerToAvatar);
|
||||||
|
@ -320,15 +316,15 @@ void OculusControllerManager::TouchDevice::handlePose(float deltaTime,
|
||||||
void OculusControllerManager::TouchDevice::handleHeadPose(float deltaTime,
|
void OculusControllerManager::TouchDevice::handleHeadPose(float deltaTime,
|
||||||
const controller::InputCalibrationData& inputCalibrationData,
|
const controller::InputCalibrationData& inputCalibrationData,
|
||||||
const ovrPoseStatef& headPose) {
|
const ovrPoseStatef& headPose) {
|
||||||
glm::mat4 mat = createMatFromQuatAndPos(toGlm(headPose.ThePose.Orientation),
|
glm::mat4 mat = createMatFromQuatAndPos(ovr::toGlm(headPose.ThePose.Orientation),
|
||||||
toGlm(headPose.ThePose.Position));
|
ovr::toGlm(headPose.ThePose.Position));
|
||||||
|
|
||||||
//perform a 180 flip to make the HMD face the +z instead of -z, beacuse the head faces +z
|
//perform a 180 flip to make the HMD face the +z instead of -z, beacuse the head faces +z
|
||||||
glm::mat4 matYFlip = mat * Matrices::Y_180;
|
glm::mat4 matYFlip = mat * Matrices::Y_180;
|
||||||
controller::Pose pose(extractTranslation(matYFlip),
|
controller::Pose pose(extractTranslation(matYFlip),
|
||||||
glmExtractRotation(matYFlip),
|
glmExtractRotation(matYFlip),
|
||||||
toGlm(headPose.LinearVelocity), // XXX * matYFlip ?
|
ovr::toGlm(headPose.LinearVelocity), // XXX * matYFlip ?
|
||||||
toGlm(headPose.AngularVelocity));
|
ovr::toGlm(headPose.AngularVelocity));
|
||||||
|
|
||||||
glm::mat4 sensorToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat;
|
glm::mat4 sensorToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat;
|
||||||
glm::mat4 defaultHeadOffset = glm::inverse(inputCalibrationData.defaultCenterEyeMat) *
|
glm::mat4 defaultHeadOffset = glm::inverse(inputCalibrationData.defaultCenterEyeMat) *
|
||||||
|
@ -343,7 +339,7 @@ void OculusControllerManager::TouchDevice::handleRotationForUntrackedHand(const
|
||||||
auto poseId = (hand == ovrHand_Left ? controller::LEFT_HAND : controller::RIGHT_HAND);
|
auto poseId = (hand == ovrHand_Left ? controller::LEFT_HAND : controller::RIGHT_HAND);
|
||||||
auto& pose = _poseStateMap[poseId];
|
auto& pose = _poseStateMap[poseId];
|
||||||
auto lastHandPose = _lastControllerPose[poseId];
|
auto lastHandPose = _lastControllerPose[poseId];
|
||||||
pose = ovrControllerRotationToHandRotation(hand, handPose, lastHandPose);
|
pose = ovr::toControllerPose(hand, handPose, lastHandPose);
|
||||||
glm::mat4 controllerToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat;
|
glm::mat4 controllerToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat;
|
||||||
pose = pose.transform(controllerToAvatar);
|
pose = pose.transform(controllerToAvatar);
|
||||||
}
|
}
|
||||||
|
@ -351,36 +347,40 @@ void OculusControllerManager::TouchDevice::handleRotationForUntrackedHand(const
|
||||||
bool OculusControllerManager::TouchDevice::triggerHapticPulse(float strength, float duration, controller::Hand hand) {
|
bool OculusControllerManager::TouchDevice::triggerHapticPulse(float strength, float duration, controller::Hand hand) {
|
||||||
Locker locker(_lock);
|
Locker locker(_lock);
|
||||||
bool toReturn = true;
|
bool toReturn = true;
|
||||||
if (hand == controller::BOTH || hand == controller::LEFT) {
|
ovr::withSession([&](ovrSession session) {
|
||||||
if (strength == 0.0f) {
|
if (hand == controller::BOTH || hand == controller::LEFT) {
|
||||||
_leftHapticStrength = 0.0f;
|
if (strength == 0.0f) {
|
||||||
_leftHapticDuration = 0.0f;
|
_leftHapticStrength = 0.0f;
|
||||||
} else {
|
_leftHapticDuration = 0.0f;
|
||||||
_leftHapticStrength = (duration > _leftHapticDuration) ? strength : _leftHapticStrength;
|
} else {
|
||||||
if (ovr_SetControllerVibration(_parent._session, ovrControllerType_LTouch, 1.0f, _leftHapticStrength) != ovrSuccess) {
|
_leftHapticStrength = (duration > _leftHapticDuration) ? strength : _leftHapticStrength;
|
||||||
toReturn = false;
|
if (ovr_SetControllerVibration(session, ovrControllerType_LTouch, 1.0f, _leftHapticStrength) != ovrSuccess) {
|
||||||
|
toReturn = false;
|
||||||
|
}
|
||||||
|
_leftHapticDuration = std::max(duration, _leftHapticDuration);
|
||||||
}
|
}
|
||||||
_leftHapticDuration = std::max(duration, _leftHapticDuration);
|
|
||||||
}
|
}
|
||||||
}
|
if (hand == controller::BOTH || hand == controller::RIGHT) {
|
||||||
if (hand == controller::BOTH || hand == controller::RIGHT) {
|
if (strength == 0.0f) {
|
||||||
if (strength == 0.0f) {
|
_rightHapticStrength = 0.0f;
|
||||||
_rightHapticStrength = 0.0f;
|
_rightHapticDuration = 0.0f;
|
||||||
_rightHapticDuration = 0.0f;
|
} else {
|
||||||
} else {
|
_rightHapticStrength = (duration > _rightHapticDuration) ? strength : _rightHapticStrength;
|
||||||
_rightHapticStrength = (duration > _rightHapticDuration) ? strength : _rightHapticStrength;
|
if (ovr_SetControllerVibration(session, ovrControllerType_RTouch, 1.0f, _rightHapticStrength) != ovrSuccess) {
|
||||||
if (ovr_SetControllerVibration(_parent._session, ovrControllerType_RTouch, 1.0f, _rightHapticStrength) != ovrSuccess) {
|
toReturn = false;
|
||||||
toReturn = false;
|
}
|
||||||
|
_rightHapticDuration = std::max(duration, _rightHapticDuration);
|
||||||
}
|
}
|
||||||
_rightHapticDuration = std::max(duration, _rightHapticDuration);
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OculusControllerManager::TouchDevice::stopHapticPulse(bool leftHand) {
|
void OculusControllerManager::TouchDevice::stopHapticPulse(bool leftHand) {
|
||||||
auto handType = (leftHand ? ovrControllerType_LTouch : ovrControllerType_RTouch);
|
auto handType = (leftHand ? ovrControllerType_LTouch : ovrControllerType_RTouch);
|
||||||
ovr_SetControllerVibration(_parent._session, handType, 0.0f, 0.0f);
|
ovr::withSession([&](ovrSession session) {
|
||||||
|
ovr_SetControllerVibration(session, handType, 0.0f, 0.0f);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**jsdoc
|
/**jsdoc
|
||||||
|
|
|
@ -26,10 +26,8 @@ public:
|
||||||
// Plugin functions
|
// Plugin functions
|
||||||
bool isSupported() const override;
|
bool isSupported() const override;
|
||||||
const QString getName() const override { return NAME; }
|
const QString getName() const override { return NAME; }
|
||||||
|
|
||||||
bool isHandController() const override { return _touch != nullptr; }
|
bool isHandController() const override { return _touch != nullptr; }
|
||||||
bool isHeadController() const override { return true; }
|
bool isHeadController() const override { return true; }
|
||||||
bool isHeadControllerMounted() const;
|
|
||||||
QStringList getSubdeviceNames() override;
|
QStringList getSubdeviceNames() override;
|
||||||
|
|
||||||
bool activate() override;
|
bool activate() override;
|
||||||
|
@ -105,7 +103,6 @@ private:
|
||||||
|
|
||||||
void checkForConnectedDevices();
|
void checkForConnectedDevices();
|
||||||
|
|
||||||
ovrSession _session { nullptr };
|
|
||||||
ovrInputState _inputState {};
|
ovrInputState _inputState {};
|
||||||
RemoteDevice::Pointer _remote;
|
RemoteDevice::Pointer _remote;
|
||||||
TouchDevice::Pointer _touch;
|
TouchDevice::Pointer _touch;
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
|
|
||||||
#include "OculusHelpers.h"
|
#include "OculusHelpers.h"
|
||||||
|
|
||||||
|
using namespace hifi;
|
||||||
|
|
||||||
const char* OculusDisplayPlugin::NAME { "Oculus Rift" };
|
const char* OculusDisplayPlugin::NAME { "Oculus Rift" };
|
||||||
static ovrPerfHudMode currentDebugMode = ovrPerfHud_Off;
|
static ovrPerfHudMode currentDebugMode = ovrPerfHud_Off;
|
||||||
|
|
||||||
|
@ -63,7 +65,7 @@ void OculusDisplayPlugin::cycleDebugOutput() {
|
||||||
|
|
||||||
void OculusDisplayPlugin::customizeContext() {
|
void OculusDisplayPlugin::customizeContext() {
|
||||||
Parent::customizeContext();
|
Parent::customizeContext();
|
||||||
_outputFramebuffer = gpu::FramebufferPointer(gpu::Framebuffer::create("OculusOutput", gpu::Element::COLOR_SRGBA_32, _renderTargetSize.x, _renderTargetSize.y));
|
_outputFramebuffer.reset(gpu::Framebuffer::create("OculusOutput", gpu::Element::COLOR_SRGBA_32, _renderTargetSize.x, _renderTargetSize.y));
|
||||||
ovrTextureSwapChainDesc desc = { };
|
ovrTextureSwapChainDesc desc = { };
|
||||||
desc.Type = ovrTexture_2D;
|
desc.Type = ovrTexture_2D;
|
||||||
desc.ArraySize = 1;
|
desc.ArraySize = 1;
|
||||||
|
@ -76,14 +78,14 @@ void OculusDisplayPlugin::customizeContext() {
|
||||||
|
|
||||||
ovrResult result = ovr_CreateTextureSwapChainGL(_session, &desc, &_textureSwapChain);
|
ovrResult result = ovr_CreateTextureSwapChainGL(_session, &desc, &_textureSwapChain);
|
||||||
if (!OVR_SUCCESS(result)) {
|
if (!OVR_SUCCESS(result)) {
|
||||||
logCritical("Failed to create swap textures");
|
qCritical(oculusLog) << "Failed to create swap textures" << ovr::getError();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int length = 0;
|
int length = 0;
|
||||||
result = ovr_GetTextureSwapChainLength(_session, _textureSwapChain, &length);
|
result = ovr_GetTextureSwapChainLength(_session, _textureSwapChain, &length);
|
||||||
if (!OVR_SUCCESS(result) || !length) {
|
if (!OVR_SUCCESS(result) || !length) {
|
||||||
logCritical("Unable to count swap chain textures");
|
qCritical(oculusLog) << "Unable to count swap chain textures" << ovr::getError();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < length; ++i) {
|
for (int i = 0; i < length; ++i) {
|
||||||
|
@ -164,8 +166,8 @@ void OculusDisplayPlugin::hmdPresent() {
|
||||||
auto result = ovr_CommitTextureSwapChain(_session, _textureSwapChain);
|
auto result = ovr_CommitTextureSwapChain(_session, _textureSwapChain);
|
||||||
Q_ASSERT(OVR_SUCCESS(result));
|
Q_ASSERT(OVR_SUCCESS(result));
|
||||||
_sceneLayer.SensorSampleTime = _currentPresentFrameInfo.sensorSampleTime;
|
_sceneLayer.SensorSampleTime = _currentPresentFrameInfo.sensorSampleTime;
|
||||||
_sceneLayer.RenderPose[ovrEyeType::ovrEye_Left] = ovrPoseFromGlm(_currentPresentFrameInfo.renderPose);
|
_sceneLayer.RenderPose[ovrEyeType::ovrEye_Left] = ovr::poseFromGlm(_currentPresentFrameInfo.renderPose);
|
||||||
_sceneLayer.RenderPose[ovrEyeType::ovrEye_Right] = ovrPoseFromGlm(_currentPresentFrameInfo.renderPose);
|
_sceneLayer.RenderPose[ovrEyeType::ovrEye_Right] = ovr::poseFromGlm(_currentPresentFrameInfo.renderPose);
|
||||||
|
|
||||||
auto submitStart = usecTimestampNow();
|
auto submitStart = usecTimestampNow();
|
||||||
uint64_t nonSubmitInterval = 0;
|
uint64_t nonSubmitInterval = 0;
|
||||||
|
@ -192,7 +194,7 @@ void OculusDisplayPlugin::hmdPresent() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!OVR_SUCCESS(result)) {
|
if (!OVR_SUCCESS(result)) {
|
||||||
logWarning("Failed to present");
|
qWarning(oculusLog) << "Failed to present" << ovr::getError();
|
||||||
}
|
}
|
||||||
|
|
||||||
static int compositorDroppedFrames = 0;
|
static int compositorDroppedFrames = 0;
|
||||||
|
@ -234,9 +236,7 @@ QJsonObject OculusDisplayPlugin::getHardwareStats() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OculusDisplayPlugin::isHmdMounted() const {
|
bool OculusDisplayPlugin::isHmdMounted() const {
|
||||||
ovrSessionStatus status;
|
return ovr::hmdMounted();
|
||||||
return (OVR_SUCCESS(ovr_GetSessionStatus(_session, &status)) &&
|
|
||||||
(ovrFalse != status.HmdMounted));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString OculusDisplayPlugin::getPreferredAudioInDevice() const {
|
QString OculusDisplayPlugin::getPreferredAudioInDevice() const {
|
||||||
|
|
|
@ -24,41 +24,17 @@
|
||||||
#include <NumericalConstants.h>
|
#include <NumericalConstants.h>
|
||||||
|
|
||||||
Q_LOGGING_CATEGORY(displayplugins, "hifi.plugins.display")
|
Q_LOGGING_CATEGORY(displayplugins, "hifi.plugins.display")
|
||||||
Q_LOGGING_CATEGORY(oculus, "hifi.plugins.display.oculus")
|
Q_LOGGING_CATEGORY(oculusLog, "hifi.plugins.display.oculus")
|
||||||
|
|
||||||
static std::atomic<uint32_t> refCount { 0 };
|
|
||||||
static ovrSession session { nullptr };
|
|
||||||
|
|
||||||
static bool _quitRequested { false };
|
|
||||||
static bool _reorientRequested { false };
|
|
||||||
|
|
||||||
inline ovrErrorInfo getError() {
|
|
||||||
ovrErrorInfo error;
|
|
||||||
ovr_GetLastErrorInfo(&error);
|
|
||||||
return error;
|
|
||||||
}
|
|
||||||
|
|
||||||
void logWarning(const char* what) {
|
|
||||||
qWarning(oculus) << what << ":" << getError().ErrorString;
|
|
||||||
}
|
|
||||||
|
|
||||||
void logCritical(const char* what) {
|
|
||||||
std::string error("[oculus] ");
|
|
||||||
error += what;
|
|
||||||
error += ": ";
|
|
||||||
error += getError().ErrorString;
|
|
||||||
qCritical(error.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
using namespace hifi;
|
||||||
|
|
||||||
static wchar_t* REQUIRED_OCULUS_DLL = L"LibOVRRT64_1.dll";
|
static wchar_t* REQUIRED_OCULUS_DLL = L"LibOVRRT64_1.dll";
|
||||||
static wchar_t FOUND_PATH[MAX_PATH];
|
static wchar_t FOUND_PATH[MAX_PATH];
|
||||||
|
|
||||||
bool oculusAvailable() {
|
bool ovr::available() {
|
||||||
static std::once_flag once;
|
static std::once_flag once;
|
||||||
static bool result { false };
|
static bool result{ false };
|
||||||
std::call_once(once, [&] {
|
std::call_once(once, [&] {
|
||||||
|
|
||||||
static const QString DEBUG_FLAG("HIFI_DEBUG_OPENVR");
|
static const QString DEBUG_FLAG("HIFI_DEBUG_OPENVR");
|
||||||
static bool enableDebugOpenVR = QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG);
|
static bool enableDebugOpenVR = QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG);
|
||||||
if (enableDebugOpenVR) {
|
if (enableDebugOpenVR) {
|
||||||
|
@ -81,113 +57,107 @@ bool oculusAvailable() {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
ovrSession acquireOculusSession() {
|
class ovrImpl {
|
||||||
if (!session && !oculusAvailable()) {
|
using Mutex = std::mutex;
|
||||||
qCDebug(oculus) << "oculus: no runtime or HMD present";
|
using Lock = std::unique_lock<Mutex>;
|
||||||
|
std::mutex mutex;
|
||||||
|
ovrSession session{ nullptr };
|
||||||
|
size_t renderCount{ 0 };
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setupSession(bool render) {
|
||||||
|
if (session) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ovrInitParams initParams{ ovrInit_RequestVersion | ovrInit_FocusAware, OVR_MINOR_VERSION, nullptr, 0, 0 };
|
||||||
|
if (render) {
|
||||||
|
initParams.Flags |= ovrInit_MixedRendering;
|
||||||
|
} else {
|
||||||
|
initParams.Flags |= ovrInit_Invisible;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!OVR_SUCCESS(ovr_Initialize(&initParams))) {
|
||||||
|
qCWarning(oculusLog) << "Failed to initialze Oculus SDK" << ovr::getError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ovrGraphicsLuid luid;
|
||||||
|
if (!OVR_SUCCESS(ovr_Create(&session, &luid))) {
|
||||||
|
qCWarning(oculusLog) << "Failed to acquire Oculus session" << ovr::getError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void releaseSession() {
|
||||||
|
if (!session) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ovr_Destroy(session);
|
||||||
|
session = nullptr;
|
||||||
|
ovr_Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
void withSession(const std::function<void(ovrSession)>& f) {
|
||||||
|
Lock lock(mutex);
|
||||||
|
if (!session) {
|
||||||
|
setupSession(false);
|
||||||
|
}
|
||||||
|
f(session);
|
||||||
|
}
|
||||||
|
|
||||||
|
ovrSession acquireRenderSession() {
|
||||||
|
Lock lock(mutex);
|
||||||
|
if (renderCount++ == 0) {
|
||||||
|
releaseSession();
|
||||||
|
setupSession(true);
|
||||||
|
}
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!session) {
|
void releaseRenderSession(ovrSession session) {
|
||||||
ovrInitParams initParams {
|
Lock lock(mutex);
|
||||||
ovrInit_RequestVersion | ovrInit_MixedRendering, OVR_MINOR_VERSION, nullptr, 0, 0
|
if (--renderCount == 0) {
|
||||||
};
|
releaseSession();
|
||||||
|
|
||||||
if (!OVR_SUCCESS(ovr_Initialize(&initParams))) {
|
|
||||||
logWarning("Failed to initialize Oculus SDK");
|
|
||||||
return session;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef OCULUS_APP_ID
|
|
||||||
if (qApp->property(hifi::properties::OCULUS_STORE).toBool()) {
|
|
||||||
if (ovr_PlatformInitializeWindows(OCULUS_APP_ID) != ovrPlatformInitialize_Success) {
|
|
||||||
// we were unable to initialize the platform for entitlement check - fail the check
|
|
||||||
_quitRequested = true;
|
|
||||||
} else {
|
|
||||||
qCDebug(oculus) << "Performing Oculus Platform entitlement check";
|
|
||||||
ovr_Entitlement_GetIsViewerEntitled();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Q_ASSERT(0 == refCount);
|
|
||||||
ovrGraphicsLuid luid;
|
|
||||||
if (!OVR_SUCCESS(ovr_Create(&session, &luid))) {
|
|
||||||
logWarning("Failed to acquire Oculus session");
|
|
||||||
return session;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} _ovr;
|
||||||
|
|
||||||
++refCount;
|
ovrSession ovr::acquireRenderSession() {
|
||||||
return session;
|
return _ovr.acquireRenderSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
void releaseOculusSession() {
|
void ovr::releaseRenderSession(ovrSession session) {
|
||||||
Q_ASSERT(refCount > 0 && session);
|
_ovr.releaseRenderSession(session);
|
||||||
// HACK the Oculus runtime doesn't seem to play well with repeated shutdown / restart.
|
|
||||||
// So for now we'll just hold on to the session
|
|
||||||
#if 0
|
|
||||||
if (!--refCount) {
|
|
||||||
qCDebug(oculus) << "oculus: zero refcount, shutdown SDK and session";
|
|
||||||
ovr_Destroy(session);
|
|
||||||
ovr_Shutdown();
|
|
||||||
session = nullptr;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void handleOVREvents() {
|
void ovr::withSession(const std::function<void(ovrSession)>& f) {
|
||||||
if (!session) {
|
_ovr.withSession(f);
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ovrSessionStatus status;
|
ovrSessionStatus ovr::getStatus() {
|
||||||
if (!OVR_SUCCESS(ovr_GetSessionStatus(session, &status))) {
|
ovrSessionStatus status{};
|
||||||
return;
|
withSession([&](ovrSession session) {
|
||||||
}
|
if (!OVR_SUCCESS(ovr_GetSessionStatus(session, &status))) {
|
||||||
|
qCWarning(oculusLog) << "Failed to get session status" << ovr::getError();
|
||||||
_quitRequested = status.ShouldQuit;
|
|
||||||
_reorientRequested = status.ShouldRecenter;
|
|
||||||
|
|
||||||
#ifdef OCULUS_APP_ID
|
|
||||||
|
|
||||||
if (qApp->property(hifi::properties::OCULUS_STORE).toBool()) {
|
|
||||||
// pop messages to see if we got a return for an entitlement check
|
|
||||||
ovrMessageHandle message = ovr_PopMessage();
|
|
||||||
|
|
||||||
while (message) {
|
|
||||||
switch (ovr_Message_GetType(message)) {
|
|
||||||
case ovrMessage_Entitlement_GetIsViewerEntitled: {
|
|
||||||
if (!ovr_Message_IsError(message)) {
|
|
||||||
// this viewer is entitled, no need to flag anything
|
|
||||||
qCDebug(oculus) << "Oculus Platform entitlement check succeeded, proceeding normally";
|
|
||||||
} else {
|
|
||||||
// we failed the entitlement check, set our flag so the app can stop
|
|
||||||
qCDebug(oculus) << "Oculus Platform entitlement check failed, app will now quit" << OCULUS_APP_ID;
|
|
||||||
_quitRequested = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// free the message handle to cleanup and not leak
|
|
||||||
ovr_FreeMessage(message);
|
|
||||||
|
|
||||||
// pop the next message to check, if there is one
|
|
||||||
message = ovr_PopMessage();
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
#endif
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool quitRequested() {
|
ovrTrackingState ovr::getTrackingState() {
|
||||||
return _quitRequested;
|
ovrTrackingState result{};
|
||||||
}
|
withSession([&](ovrSession session) { result = ovr_GetTrackingState(session, 0, ovrFalse); });
|
||||||
bool reorientRequested() {
|
return result;
|
||||||
return _reorientRequested;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
controller::Pose ovrControllerPoseToHandPose(
|
QString ovr::getError() {
|
||||||
ovrHandType hand,
|
static ovrErrorInfo error;
|
||||||
const ovrPoseStatef& handPose) {
|
ovr_GetLastErrorInfo(&error);
|
||||||
|
return QString(error.ErrorString);
|
||||||
|
}
|
||||||
|
|
||||||
|
controller::Pose hifi::ovr::toControllerPose(ovrHandType hand, const ovrPoseStatef& handPose) {
|
||||||
// When the sensor-to-world rotation is identity the coordinate axes look like this:
|
// When the sensor-to-world rotation is identity the coordinate axes look like this:
|
||||||
//
|
//
|
||||||
// user
|
// user
|
||||||
|
@ -247,9 +217,8 @@ controller::Pose ovrControllerPoseToHandPose(
|
||||||
static const glm::quat rightRotationOffset = glm::inverse(rightQuarterZ) * touchToHand;
|
static const glm::quat rightRotationOffset = glm::inverse(rightQuarterZ) * touchToHand;
|
||||||
|
|
||||||
static const float CONTROLLER_LENGTH_OFFSET = 0.0762f; // three inches
|
static const float CONTROLLER_LENGTH_OFFSET = 0.0762f; // three inches
|
||||||
static const glm::vec3 CONTROLLER_OFFSET = glm::vec3(CONTROLLER_LENGTH_OFFSET / 2.0f,
|
static const glm::vec3 CONTROLLER_OFFSET =
|
||||||
-CONTROLLER_LENGTH_OFFSET / 2.0f,
|
glm::vec3(CONTROLLER_LENGTH_OFFSET / 2.0f, -CONTROLLER_LENGTH_OFFSET / 2.0f, CONTROLLER_LENGTH_OFFSET * 1.5f);
|
||||||
CONTROLLER_LENGTH_OFFSET * 1.5f);
|
|
||||||
static const glm::vec3 leftTranslationOffset = glm::vec3(-1.0f, 1.0f, 1.0f) * CONTROLLER_OFFSET;
|
static const glm::vec3 leftTranslationOffset = glm::vec3(-1.0f, 1.0f, 1.0f) * CONTROLLER_OFFSET;
|
||||||
static const glm::vec3 rightTranslationOffset = CONTROLLER_OFFSET;
|
static const glm::vec3 rightTranslationOffset = CONTROLLER_OFFSET;
|
||||||
|
|
||||||
|
@ -268,12 +237,13 @@ controller::Pose ovrControllerPoseToHandPose(
|
||||||
return pose;
|
return pose;
|
||||||
}
|
}
|
||||||
|
|
||||||
controller::Pose ovrControllerRotationToHandRotation(ovrHandType hand, const ovrPoseStatef& handPose,
|
controller::Pose hifi::ovr::toControllerPose(ovrHandType hand,
|
||||||
const ovrPoseStatef& lastHandPose) {
|
const ovrPoseStatef& handPose,
|
||||||
|
const ovrPoseStatef& lastHandPose) {
|
||||||
static const glm::quat yFlip = glm::angleAxis(PI, Vectors::UNIT_Y);
|
static const glm::quat yFlip = glm::angleAxis(PI, Vectors::UNIT_Y);
|
||||||
static const glm::quat quarterX = glm::angleAxis(PI_OVER_TWO, Vectors::UNIT_X);
|
static const glm::quat quarterX = glm::angleAxis(PI_OVER_TWO, Vectors::UNIT_X);
|
||||||
static const glm::quat touchToHand = yFlip * quarterX;
|
static const glm::quat touchToHand = yFlip * quarterX;
|
||||||
|
|
||||||
static const glm::quat leftQuarterZ = glm::angleAxis(-PI_OVER_TWO, Vectors::UNIT_Z);
|
static const glm::quat leftQuarterZ = glm::angleAxis(-PI_OVER_TWO, Vectors::UNIT_Z);
|
||||||
static const glm::quat rightQuarterZ = glm::angleAxis(PI_OVER_TWO, Vectors::UNIT_Z);
|
static const glm::quat rightQuarterZ = glm::angleAxis(PI_OVER_TWO, Vectors::UNIT_Z);
|
||||||
|
|
||||||
|
@ -281,9 +251,8 @@ controller::Pose ovrControllerRotationToHandRotation(ovrHandType hand, const ovr
|
||||||
static const glm::quat rightRotationOffset = glm::inverse(rightQuarterZ) * touchToHand;
|
static const glm::quat rightRotationOffset = glm::inverse(rightQuarterZ) * touchToHand;
|
||||||
|
|
||||||
static const float CONTROLLER_LENGTH_OFFSET = 0.0762f; // three inches
|
static const float CONTROLLER_LENGTH_OFFSET = 0.0762f; // three inches
|
||||||
static const glm::vec3 CONTROLLER_OFFSET = glm::vec3(CONTROLLER_LENGTH_OFFSET / 2.0f,
|
static const glm::vec3 CONTROLLER_OFFSET =
|
||||||
-CONTROLLER_LENGTH_OFFSET / 2.0f,
|
glm::vec3(CONTROLLER_LENGTH_OFFSET / 2.0f, -CONTROLLER_LENGTH_OFFSET / 2.0f, CONTROLLER_LENGTH_OFFSET * 1.5f);
|
||||||
CONTROLLER_LENGTH_OFFSET * 1.5f);
|
|
||||||
static const glm::vec3 leftTranslationOffset = glm::vec3(-1.0f, 1.0f, 1.0f) * CONTROLLER_OFFSET;
|
static const glm::vec3 leftTranslationOffset = glm::vec3(-1.0f, 1.0f, 1.0f) * CONTROLLER_OFFSET;
|
||||||
static const glm::vec3 rightTranslationOffset = CONTROLLER_OFFSET;
|
static const glm::vec3 rightTranslationOffset = CONTROLLER_OFFSET;
|
||||||
|
|
||||||
|
@ -301,3 +270,52 @@ controller::Pose ovrControllerRotationToHandRotation(ovrHandType hand, const ovr
|
||||||
pose.valid = true;
|
pose.valid = true;
|
||||||
return pose;
|
return pose;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME These should be moved to an oculusPlatform plugin, they don't interact with the controller or session state
|
||||||
|
#if 0
|
||||||
|
void handleOVREvents() {
|
||||||
|
updateSessionStatus(true);
|
||||||
|
|
||||||
|
#ifdef OCULUS_APP_ID
|
||||||
|
|
||||||
|
if (qApp->property(hifi::properties::OCULUS_STORE).toBool()) {
|
||||||
|
// pop messages to see if we got a return for an entitlement check
|
||||||
|
ovrMessageHandle message = ovr_PopMessage();
|
||||||
|
|
||||||
|
while (message) {
|
||||||
|
switch (ovr_Message_GetType(message)) {
|
||||||
|
case ovrMessage_Entitlement_GetIsViewerEntitled:
|
||||||
|
{
|
||||||
|
if (!ovr_Message_IsError(message)) {
|
||||||
|
// this viewer is entitled, no need to flag anything
|
||||||
|
qCDebug(oculus) << "Oculus Platform entitlement check succeeded, proceeding normally";
|
||||||
|
} else {
|
||||||
|
// we failed the entitlement check, set our flag so the app can stop
|
||||||
|
qCDebug(oculus) << "Oculus Platform entitlement check failed, app will now quit" << OCULUS_APP_ID;
|
||||||
|
_quitRequested = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// free the message handle to cleanup and not leak
|
||||||
|
ovr_FreeMessage(message);
|
||||||
|
|
||||||
|
// pop the next message to check, if there is one
|
||||||
|
message = ovr_PopMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef OCULUS_APP_ID
|
||||||
|
if (qApp->property(hifi::properties::OCULUS_STORE).toBool()) {
|
||||||
|
if (ovr_PlatformInitializeWindows(OCULUS_APP_ID) != ovrPlatformInitialize_Success) {
|
||||||
|
// we were unable to initialize the platform for entitlement check - fail the check
|
||||||
|
_quitRequested = true;
|
||||||
|
} else {
|
||||||
|
qCDebug(oculusLog) << "Performing Oculus Platform entitlement check";
|
||||||
|
ovr_Entitlement_GetIsViewerEntitled();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
|
@ -7,10 +7,9 @@
|
||||||
//
|
//
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
#include <QtCore/QLoggingCategory>
|
#include <QtCore/QLoggingCategory>
|
||||||
|
|
||||||
#include <OVR_CAPI_GL.h>
|
#include <ovr_capi.h>
|
||||||
#include <GLMHelpers.h>
|
#include <GLMHelpers.h>
|
||||||
#include <glm/gtc/type_ptr.hpp>
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
@ -18,106 +17,107 @@
|
||||||
#include <controllers/Forward.h>
|
#include <controllers/Forward.h>
|
||||||
|
|
||||||
Q_DECLARE_LOGGING_CATEGORY(displayplugins)
|
Q_DECLARE_LOGGING_CATEGORY(displayplugins)
|
||||||
Q_DECLARE_LOGGING_CATEGORY(oculus)
|
Q_DECLARE_LOGGING_CATEGORY(oculusLog)
|
||||||
|
|
||||||
void logWarning(const char* what);
|
namespace hifi {
|
||||||
void logCritical(const char* what);
|
|
||||||
bool oculusAvailable();
|
struct ovr {
|
||||||
ovrSession acquireOculusSession();
|
static bool available();
|
||||||
void releaseOculusSession();
|
static ovrSession acquireRenderSession();
|
||||||
|
static void releaseRenderSession(ovrSession session);
|
||||||
|
static void withSession(const std::function<void(ovrSession)>& f);
|
||||||
|
static ovrSessionStatus getStatus();
|
||||||
|
static ovrTrackingState getTrackingState();
|
||||||
|
static QString getError();
|
||||||
|
|
||||||
void handleOVREvents();
|
static inline bool quitRequested() { return quitRequested(getStatus()); }
|
||||||
bool quitRequested();
|
static inline bool reorientRequested() { return reorientRequested(getStatus()); }
|
||||||
bool reorientRequested();
|
static inline bool hmdMounted() { return hmdMounted(getStatus()); }
|
||||||
|
static inline bool hasInputFocus() { return hasInputFocus(getStatus()); }
|
||||||
|
|
||||||
// Convenience method for looping over each eye with a lambda
|
static inline bool quitRequested(const ovrSessionStatus& status) { return status.ShouldQuit != ovrFalse; }
|
||||||
template <typename Function>
|
static inline bool reorientRequested(const ovrSessionStatus& status) { return status.ShouldRecenter != ovrFalse; }
|
||||||
inline void ovr_for_each_eye(Function function) {
|
static inline bool hmdMounted(const ovrSessionStatus& status) { return status.HmdMounted != ovrFalse; }
|
||||||
for (ovrEyeType eye = ovrEyeType::ovrEye_Left;
|
static inline bool hasInputFocus(const ovrSessionStatus& status) { return status.HasInputFocus != ovrFalse; }
|
||||||
eye < ovrEyeType::ovrEye_Count;
|
|
||||||
eye = static_cast<ovrEyeType>(eye + 1)) {
|
// Convenience method for looping over each eye with a lambda
|
||||||
function(eye);
|
static inline void for_each_eye(const std::function<void(ovrEyeType eye)>& f) {
|
||||||
|
for (ovrEyeType eye = ovrEye_Left; eye < ovrEye_Count; eye = static_cast<ovrEyeType>(eye + 1)) {
|
||||||
|
f(eye);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Function>
|
static inline void for_each_hand(const std::function<void(ovrHandType eye)>& f) {
|
||||||
inline void ovr_for_each_hand(Function function) {
|
for (ovrHandType hand = ovrHand_Left; hand < ovrHand_Count; hand = static_cast<ovrHandType>(hand + 1)) {
|
||||||
for (ovrHandType hand = ovrHandType::ovrHand_Left;
|
f(hand);
|
||||||
hand <= ovrHandType::ovrHand_Right;
|
}
|
||||||
hand = static_cast<ovrHandType>(hand + 1)) {
|
|
||||||
function(hand);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
static inline glm::mat4 toGlm(const ovrMatrix4f& om) {
|
||||||
|
return glm::transpose(glm::make_mat4(&om.M[0][0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline glm::mat4 toGlm(const ovrFovPort& fovport, float nearPlane = 0.01f, float farPlane = 10000.0f) {
|
||||||
|
return toGlm(ovrMatrix4f_Projection(fovport, nearPlane, farPlane, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline glm::vec3 toGlm(const ovrVector3f& ov) {
|
||||||
|
return glm::make_vec3(&ov.x);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline glm::vec2 toGlm(const ovrVector2f& ov) {
|
||||||
|
return glm::make_vec2(&ov.x);
|
||||||
|
}
|
||||||
|
|
||||||
inline glm::mat4 toGlm(const ovrMatrix4f & om) {
|
static inline glm::uvec2 toGlm(const ovrSizei& ov) {
|
||||||
return glm::transpose(glm::make_mat4(&om.M[0][0]));
|
return glm::uvec2(ov.w, ov.h);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline glm::mat4 toGlm(const ovrFovPort & fovport, float nearPlane = 0.01f, float farPlane = 10000.0f) {
|
static inline glm::quat toGlm(const ovrQuatf& oq) {
|
||||||
return toGlm(ovrMatrix4f_Projection(fovport, nearPlane, farPlane, true));
|
return glm::make_quat(&oq.x);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline glm::vec3 toGlm(const ovrVector3f & ov) {
|
static inline glm::mat4 toGlm(const ovrPosef& op) {
|
||||||
return glm::make_vec3(&ov.x);
|
glm::mat4 orientation = glm::mat4_cast(toGlm(op.Orientation));
|
||||||
}
|
glm::mat4 translation = glm::translate(glm::mat4(), toGlm(op.Position));
|
||||||
|
return translation * orientation;
|
||||||
|
}
|
||||||
|
|
||||||
inline glm::vec2 toGlm(const ovrVector2f & ov) {
|
static inline ovrMatrix4f fromGlm(const glm::mat4& m) {
|
||||||
return glm::make_vec2(&ov.x);
|
ovrMatrix4f result;
|
||||||
}
|
glm::mat4 transposed(glm::transpose(m));
|
||||||
|
memcpy(result.M, &(transposed[0][0]), sizeof(float) * 16);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
inline glm::uvec2 toGlm(const ovrSizei & ov) {
|
static inline ovrVector3f fromGlm(const glm::vec3& v) {
|
||||||
return glm::uvec2(ov.w, ov.h);
|
return { v.x, v.y, v.z };
|
||||||
}
|
}
|
||||||
|
|
||||||
inline glm::quat toGlm(const ovrQuatf & oq) {
|
static inline ovrVector2f fromGlm(const glm::vec2& v) {
|
||||||
return glm::make_quat(&oq.x);
|
return { v.x, v.y };
|
||||||
}
|
}
|
||||||
|
|
||||||
inline glm::mat4 toGlm(const ovrPosef & op) {
|
static inline ovrSizei fromGlm(const glm::uvec2& v) {
|
||||||
glm::mat4 orientation = glm::mat4_cast(toGlm(op.Orientation));
|
return { (int)v.x, (int)v.y };
|
||||||
glm::mat4 translation = glm::translate(glm::mat4(), toGlm(op.Position));
|
}
|
||||||
return translation * orientation;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline ovrMatrix4f ovrFromGlm(const glm::mat4 & m) {
|
static inline ovrQuatf fromGlm(const glm::quat& q) {
|
||||||
ovrMatrix4f result;
|
return { q.x, q.y, q.z, q.w };
|
||||||
glm::mat4 transposed(glm::transpose(m));
|
}
|
||||||
memcpy(result.M, &(transposed[0][0]), sizeof(float) * 16);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline ovrVector3f ovrFromGlm(const glm::vec3 & v) {
|
static inline ovrPosef poseFromGlm(const glm::mat4& m) {
|
||||||
return{ v.x, v.y, v.z };
|
glm::vec3 translation = glm::vec3(m[3]) / m[3].w;
|
||||||
}
|
glm::quat orientation = glm::quat_cast(m);
|
||||||
|
ovrPosef result;
|
||||||
|
result.Orientation = fromGlm(orientation);
|
||||||
|
result.Position = fromGlm(translation);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
inline ovrVector2f ovrFromGlm(const glm::vec2 & v) {
|
static controller::Pose toControllerPose(ovrHandType hand, const ovrPoseStatef& handPose);
|
||||||
return{ v.x, v.y };
|
static controller::Pose toControllerPose(ovrHandType hand, const ovrPoseStatef& handPose, const ovrPoseStatef& lastHandPose);
|
||||||
}
|
|
||||||
|
|
||||||
inline ovrSizei ovrFromGlm(const glm::uvec2 & v) {
|
};
|
||||||
return{ (int)v.x, (int)v.y };
|
|
||||||
}
|
|
||||||
|
|
||||||
inline ovrQuatf ovrFromGlm(const glm::quat & q) {
|
} // namespace hifi
|
||||||
return{ q.x, q.y, q.z, q.w };
|
|
||||||
}
|
|
||||||
|
|
||||||
inline ovrPosef ovrPoseFromGlm(const glm::mat4 & m) {
|
|
||||||
glm::vec3 translation = glm::vec3(m[3]) / m[3].w;
|
|
||||||
glm::quat orientation = glm::quat_cast(m);
|
|
||||||
ovrPosef result;
|
|
||||||
result.Orientation = ovrFromGlm(orientation);
|
|
||||||
result.Position = ovrFromGlm(translation);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
controller::Pose ovrControllerPoseToHandPose(
|
|
||||||
ovrHandType hand,
|
|
||||||
const ovrPoseStatef& handPose);
|
|
||||||
|
|
||||||
controller::Pose ovrControllerRotationToHandRotation(ovrHandType hand,
|
|
||||||
const ovrPoseStatef& handPose, const ovrPoseStatef& lastHandPose);
|
|
||||||
|
|
Loading…
Reference in a new issue