From e38059797dd8d9e8450e97eec8a3a85dc28f7c9d Mon Sep 17 00:00:00 2001 From: Bradley Austin Davis Date: Wed, 6 Jun 2018 11:57:36 -0700 Subject: [PATCH] Update Oculus integration --- cmake/externals/LibOVR/CMakeLists.txt | 4 +- cmake/externals/LibOVR/LibOVRCMakeLists.txt | 2 +- .../oculus/src/OculusBaseDisplayPlugin.cpp | 66 ++--- plugins/oculus/src/OculusBaseDisplayPlugin.h | 19 +- .../oculus/src/OculusControllerManager.cpp | 164 +++++------ plugins/oculus/src/OculusControllerManager.h | 3 - plugins/oculus/src/OculusDisplayPlugin.cpp | 18 +- plugins/oculus/src/OculusHelpers.cpp | 274 ++++++++++-------- plugins/oculus/src/OculusHelpers.h | 166 +++++------ 9 files changed, 359 insertions(+), 357 deletions(-) diff --git a/cmake/externals/LibOVR/CMakeLists.txt b/cmake/externals/LibOVR/CMakeLists.txt index 97508be0c5..ed76f181e7 100644 --- a/cmake/externals/LibOVR/CMakeLists.txt +++ b/cmake/externals/LibOVR/CMakeLists.txt @@ -17,8 +17,8 @@ if (WIN32) ExternalProject_Add( ${EXTERNAL_NAME} - URL https://static.oculus.com/sdk-downloads/1.11.0/Public/1486063832/ovr_sdk_win_1.11.0_public.zip - URL_MD5 ea484403757cbfdfa743b6577fb1f9d2 + URL http://hifi-public.s3.amazonaws.com/dependencies/ovr_sdk_win_1.26.0_public.zip + URL_MD5 06804ff9727b910dcd04a37c800053b5 CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH= PATCH_COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/LibOVRCMakeLists.txt" /CMakeLists.txt LOG_DOWNLOAD 1 diff --git a/cmake/externals/LibOVR/LibOVRCMakeLists.txt b/cmake/externals/LibOVR/LibOVRCMakeLists.txt index 556533f0c2..a52cff5463 100644 --- a/cmake/externals/LibOVR/LibOVRCMakeLists.txt +++ b/cmake/externals/LibOVR/LibOVRCMakeLists.txt @@ -4,7 +4,7 @@ project(LibOVR) include_directories(LibOVR/Include LibOVR/Src) file(GLOB HEADER_FILES LibOVR/Include/*.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") add_library(LibOVR STATIC ${SOURCE_FILES} ${HEADER_FILES} ${EXTRA_HEADER_FILES}) set_target_properties(LibOVR PROPERTIES DEBUG_POSTFIX "d") diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp index 7e337070d3..5aa1e45943 100644 --- a/plugins/oculus/src/OculusBaseDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusBaseDisplayPlugin.cpp @@ -15,19 +15,25 @@ #include "OculusHelpers.h" +using namespace hifi; + void OculusBaseDisplayPlugin::resetSensors() { ovr_RecenterTrackingOrigin(_session); - _currentRenderFrameInfo.renderPose = glm::mat4(); // identity } bool OculusBaseDisplayPlugin::beginFrameRender(uint32_t frameIndex) { - handleOVREvents(); - if (quitRequested()) { + ovrSessionStatus status{}; + 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"); return false; } - if (reorientRequested()) { + if (ovr::reorientRequested(status)) { emit resetSensorsRequested(); } @@ -35,18 +41,18 @@ bool OculusBaseDisplayPlugin::beginFrameRender(uint32_t frameIndex) { _currentRenderFrameInfo.sensorSampleTime = ovr_GetTimeInSeconds(); _currentRenderFrameInfo.predictedDisplayTime = ovr_GetPredictedDisplayTime(_session, frameIndex); 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; std::array handPoses; // 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; if (REQUIRED_HAND_STATUS != (trackingState.HandStatusFlags[hand] & REQUIRED_HAND_STATUS)) { 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); 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 { - return oculusAvailable(); + return ovr::available(); } 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]; ovrEyeRenderDesc& erd = ovr_GetRenderDesc(_session, ovrEye, fovPort); ovrMatrix4f ovrPerspectiveProjection = ovrMatrix4f_Projection(erd.Fov, baseNearClip, baseFarClip, ovrProjection_ClipRangeOpenGL); - return toGlm(ovrPerspectiveProjection); + return ovr::toGlm(ovrPerspectiveProjection); } else { return baseProjection; } @@ -85,7 +91,7 @@ glm::mat4 OculusBaseDisplayPlugin::getCullingProjection(const glm::mat4& basePro float baseFarClip = baseFrustum.getFarClip(); auto combinedFov = _eyeFovs[0]; 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 { return baseProjection; } @@ -102,7 +108,7 @@ void OculusBaseDisplayPlugin::uncustomizeContext() { } bool OculusBaseDisplayPlugin::internalActivate() { - _session = acquireOculusSession(); + _session = ovr::acquireRenderSession(); if (!_session) { return false; } @@ -113,21 +119,21 @@ bool OculusBaseDisplayPlugin::internalActivate() { _viewScaleDesc.HmdSpaceToWorldScaleInMeters = 1.0f; _ipd = 0; - ovr_for_each_eye([&](ovrEyeType eye) { + ovr::for_each_eye([&](ovrEyeType eye) { _eyeFovs[eye] = _hmdDesc.DefaultEyeFov[eye]; ovrEyeRenderDesc& erd = _eyeRenderDescs[eye] = ovr_GetRenderDesc(_session, eye, _eyeFovs[eye]); ovrMatrix4f ovrPerspectiveProjection = ovrMatrix4f_Projection(erd.Fov, DEFAULT_NEAR_CLIP, DEFAULT_FAR_CLIP, ovrProjection_ClipRangeOpenGL); - _eyeProjections[eye] = toGlm(ovrPerspectiveProjection); - _eyeOffsets[eye] = glm::translate(mat4(), toGlm(erd.HmdToEyeOffset)); - eyeSizes[eye] = toGlm(ovr_GetFovTextureSize(_session, eye, erd.Fov, 1.0f)); - _viewScaleDesc.HmdToEyeOffset[eye] = erd.HmdToEyeOffset; - _ipd += glm::abs(glm::length(toGlm(erd.HmdToEyeOffset))); + _eyeProjections[eye] = ovr::toGlm(ovrPerspectiveProjection); + _eyeOffsets[eye] = ovr::toGlm(erd.HmdToEyePose); + eyeSizes[eye] = ovr::toGlm(ovr_GetFovTextureSize(_session, eye, erd.Fov, 1.0f)); + _viewScaleDesc.HmdToEyePose[eye] = erd.HmdToEyePose; + _ipd += glm::abs(glm::length(ovr::toGlm(erd.HmdToEyePose.Position))); }); auto combinedFov = _eyeFovs[0]; 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( eyeSizes[0].x + eyeSizes[1].x, @@ -136,7 +142,7 @@ bool OculusBaseDisplayPlugin::internalActivate() { memset(&_sceneLayer, 0, sizeof(ovrLayerEyeFov)); _sceneLayer.Header.Type = ovrLayerType_EyeFov; _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; ovrSizei & size = _sceneLayer.Viewport[eye].Size = ovr_GetFovTextureSize(_session, eye, fov, 1.0f); _sceneLayer.Viewport[eye].Pos = { eye == ovrEye_Left ? 0 : size.w, 0 }; @@ -150,28 +156,14 @@ bool OculusBaseDisplayPlugin::internalActivate() { void OculusBaseDisplayPlugin::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() { + ovrTrackingState trackingState; _currentPresentFrameInfo.sensorSampleTime = ovr_GetTimeInSeconds(); _currentPresentFrameInfo.predictedDisplayTime = ovr_GetPredictedDisplayTime(_session, 0); - auto trackingState = ovr_GetTrackingState(_session, _currentRenderFrameInfo.predictedDisplayTime, ovrFalse); - _currentPresentFrameInfo.presentPose = toGlm(trackingState.HeadPose.ThePose); + trackingState = ovr_GetTrackingState(_session, _currentRenderFrameInfo.predictedDisplayTime, ovrFalse); + _currentPresentFrameInfo.presentPose = ovr::toGlm(trackingState.HeadPose.ThePose); _currentPresentFrameInfo.renderPose = _currentPresentFrameInfo.presentPose; } - -OculusBaseDisplayPlugin::~OculusBaseDisplayPlugin() { -} diff --git a/plugins/oculus/src/OculusBaseDisplayPlugin.h b/plugins/oculus/src/OculusBaseDisplayPlugin.h index b3b99c0ad1..d70d14dc28 100644 --- a/plugins/oculus/src/OculusBaseDisplayPlugin.h +++ b/plugins/oculus/src/OculusBaseDisplayPlugin.h @@ -16,37 +16,32 @@ class OculusBaseDisplayPlugin : public HmdDisplayPlugin { using Parent = HmdDisplayPlugin; public: - ~OculusBaseDisplayPlugin(); 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 getCullingProjection(const glm::mat4& baseProjection) const override; - bool hasAsyncReprojection() const override { return true; } - - // Stereo specific methods void resetSensors() override final; bool beginFrameRender(uint32_t frameIndex) override; float getTargetFrameRate() const override { return _hmdDesc.DisplayRefreshRate; } - bool getSupportsAutoSwitch() override final { return true; } - - + protected: void customizeContext() override; void uncustomizeContext() override; bool internalActivate() override; void internalDeactivate() override; - bool activateStandBySession() override; - void deactivateSession() override; void updatePresentPose() override; protected: - ovrSession _session { nullptr }; + ovrSession _session{ nullptr }; ovrGraphicsLuid _luid; - ovrEyeRenderDesc _eyeRenderDescs[2]; - ovrFovPort _eyeFovs[2]; + std::array _eyeRenderDescs; + std::array _eyeFovs; ovrHmdDesc _hmdDesc; ovrLayerEyeFov _sceneLayer; ovrViewScaleDesc _viewScaleDesc; + // ovrLayerEyeFovDepth _depthLayer; }; diff --git a/plugins/oculus/src/OculusControllerManager.cpp b/plugins/oculus/src/OculusControllerManager.cpp index 7a176d36fb..943af301a2 100644 --- a/plugins/oculus/src/OculusControllerManager.cpp +++ b/plugins/oculus/src/OculusControllerManager.cpp @@ -22,34 +22,23 @@ #include #include -#include +#include #include "OculusHelpers.h" -Q_DECLARE_LOGGING_CATEGORY(oculus) - - -static const char* MENU_PARENT = "Avatar"; -static const char* MENU_NAME = "Oculus Touch Controllers"; -static const char* MENU_PATH = "Avatar" ">" "Oculus Touch Controllers"; +using namespace hifi; const char* OculusControllerManager::NAME = "Oculus"; const quint64 LOST_TRACKING_DELAY = 3000000; bool OculusControllerManager::isSupported() const { - return oculusAvailable(); + return hifi::ovr::available(); } bool OculusControllerManager::activate() { InputPlugin::activate(); - if (!_session) { - _session = acquireOculusSession(); - } - Q_ASSERT(_session); - checkForConnectedDevices(); - return true; } @@ -58,33 +47,30 @@ void OculusControllerManager::checkForConnectedDevices() { 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 (OVR_SUCCESS(ovr_GetInputState(_session, ovrControllerType_Remote, &_inputState))) { - auto userInputMapper = DependencyManager::get(); - _remote = std::make_shared(*this); - userInputMapper->registerDevice(_remote); + if (!_remote && (controllerConnected & ovrControllerType_Remote) == ovrControllerType_Remote) { + if (OVR_SUCCESS(ovr_GetInputState(session, ovrControllerType_Remote, &_inputState))) { + auto userInputMapper = DependencyManager::get(); + _remote = std::make_shared(*this); + userInputMapper->registerDevice(_remote); + } } - } - if (!_touch && (controllerConnected & ovrControllerType_Touch) != 0) { - if (OVR_SUCCESS(ovr_GetInputState(_session, ovrControllerType_Touch, &_inputState))) { - auto userInputMapper = DependencyManager::get(); - _touch = std::make_shared(*this); - userInputMapper->registerDevice(_touch); + if (!_touch && (controllerConnected & ovrControllerType_Touch) != 0) { + if (OVR_SUCCESS(ovr_GetInputState(session, ovrControllerType_Touch, &_inputState))) { + auto userInputMapper = DependencyManager::get(); + _touch = std::make_shared(*this); + userInputMapper->registerDevice(_touch); + } } - } + }); } void OculusControllerManager::deactivate() { InputPlugin::deactivate(); - if (_session) { - releaseOculusSession(); - _session = nullptr; - } - // unregister with UserInputMapper auto userInputMapper = DependencyManager::get(); if (_touch) { @@ -100,20 +86,30 @@ void OculusControllerManager::pluginUpdate(float deltaTime, const controller::In checkForConnectedDevices(); - if (_touch) { - if (OVR_SUCCESS(ovr_GetInputState(_session, ovrControllerType_Touch, &_inputState))) { - _touch->update(deltaTime, inputCalibrationData); - } else { - qCWarning(oculus) << "Unable to read Oculus touch input state"; + bool updateRemote = false, updateTouch = false; + + ovr::withSession([&](ovrSession session) { + if (_touch) { + 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 (OVR_SUCCESS(ovr_GetInputState(_session, ovrControllerType_Remote, &_inputState))) { - _remote->update(deltaTime, inputCalibrationData); - } else { - qCWarning(oculus) << "Unable to read Oculus remote input state"; - } + if (_remote && updateRemote) { + _remote->update(deltaTime, inputCalibrationData); } } @@ -210,15 +206,6 @@ void OculusControllerManager::RemoteDevice::focusOutEvent() { _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, const controller::InputCalibrationData& inputCalibrationData) { _buttonPressedMap.clear(); @@ -226,10 +213,19 @@ void OculusControllerManager::TouchDevice::update(float deltaTime, int numTrackedControllers = 0; quint64 currentTime = usecTimestampNow(); static const auto REQUIRED_HAND_STATUS = ovrStatus_OrientationTracked | ovrStatus_PositionTracked; - auto tracking = ovr_GetTrackingState(_parent._session, 0, false); - ovr_for_each_hand([&](ovrHandType hand) { + bool hasInputFocus = ovr::hasInputFocus(); + auto tracking = ovr::getTrackingState(); // ovr_GetTrackingState(_parent._session, 0, false); + ovr::for_each_hand([&](ovrHandType hand) { ++numTrackedControllers; 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)) { _poseStateMap.erase(controller); handlePose(deltaTime, inputCalibrationData, hand, tracking.HandPoses[hand]); @@ -253,7 +249,7 @@ void OculusControllerManager::TouchDevice::update(float deltaTime, handleRotationForUntrackedHand(inputCalibrationData, hand, tracking.HandPoses[hand]); }); - if (_parent.isHeadControllerMounted()) { + if (ovr::hmdMounted()) { handleHeadPose(deltaTime, inputCalibrationData, tracking.HeadPose); } else { _poseStateMap[controller::HEAD].valid = false; @@ -311,7 +307,7 @@ void OculusControllerManager::TouchDevice::handlePose(float deltaTime, ovrHandType hand, const ovrPoseStatef& handPose) { auto poseId = hand == ovrHand_Left ? controller::LEFT_HAND : controller::RIGHT_HAND; auto& pose = _poseStateMap[poseId]; - pose = ovrControllerPoseToHandPose(hand, handPose); + pose = ovr::toControllerPose(hand, handPose); // transform into avatar frame glm::mat4 controllerToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat; pose = pose.transform(controllerToAvatar); @@ -320,15 +316,15 @@ void OculusControllerManager::TouchDevice::handlePose(float deltaTime, void OculusControllerManager::TouchDevice::handleHeadPose(float deltaTime, const controller::InputCalibrationData& inputCalibrationData, const ovrPoseStatef& headPose) { - glm::mat4 mat = createMatFromQuatAndPos(toGlm(headPose.ThePose.Orientation), - toGlm(headPose.ThePose.Position)); + glm::mat4 mat = createMatFromQuatAndPos(ovr::toGlm(headPose.ThePose.Orientation), + ovr::toGlm(headPose.ThePose.Position)); //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; controller::Pose pose(extractTranslation(matYFlip), glmExtractRotation(matYFlip), - toGlm(headPose.LinearVelocity), // XXX * matYFlip ? - toGlm(headPose.AngularVelocity)); + ovr::toGlm(headPose.LinearVelocity), // XXX * matYFlip ? + ovr::toGlm(headPose.AngularVelocity)); glm::mat4 sensorToAvatar = glm::inverse(inputCalibrationData.avatarMat) * inputCalibrationData.sensorToWorldMat; 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& pose = _poseStateMap[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; pose = pose.transform(controllerToAvatar); } @@ -351,36 +347,40 @@ void OculusControllerManager::TouchDevice::handleRotationForUntrackedHand(const bool OculusControllerManager::TouchDevice::triggerHapticPulse(float strength, float duration, controller::Hand hand) { Locker locker(_lock); bool toReturn = true; - if (hand == controller::BOTH || hand == controller::LEFT) { - if (strength == 0.0f) { - _leftHapticStrength = 0.0f; - _leftHapticDuration = 0.0f; - } else { - _leftHapticStrength = (duration > _leftHapticDuration) ? strength : _leftHapticStrength; - if (ovr_SetControllerVibration(_parent._session, ovrControllerType_LTouch, 1.0f, _leftHapticStrength) != ovrSuccess) { - toReturn = false; + ovr::withSession([&](ovrSession session) { + if (hand == controller::BOTH || hand == controller::LEFT) { + if (strength == 0.0f) { + _leftHapticStrength = 0.0f; + _leftHapticDuration = 0.0f; + } else { + _leftHapticStrength = (duration > _leftHapticDuration) ? strength : _leftHapticStrength; + 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 (strength == 0.0f) { - _rightHapticStrength = 0.0f; - _rightHapticDuration = 0.0f; - } else { - _rightHapticStrength = (duration > _rightHapticDuration) ? strength : _rightHapticStrength; - if (ovr_SetControllerVibration(_parent._session, ovrControllerType_RTouch, 1.0f, _rightHapticStrength) != ovrSuccess) { - toReturn = false; + if (hand == controller::BOTH || hand == controller::RIGHT) { + if (strength == 0.0f) { + _rightHapticStrength = 0.0f; + _rightHapticDuration = 0.0f; + } else { + _rightHapticStrength = (duration > _rightHapticDuration) ? strength : _rightHapticStrength; + if (ovr_SetControllerVibration(session, ovrControllerType_RTouch, 1.0f, _rightHapticStrength) != ovrSuccess) { + toReturn = false; + } + _rightHapticDuration = std::max(duration, _rightHapticDuration); } - _rightHapticDuration = std::max(duration, _rightHapticDuration); } - } + }); return toReturn; } void OculusControllerManager::TouchDevice::stopHapticPulse(bool leftHand) { 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 diff --git a/plugins/oculus/src/OculusControllerManager.h b/plugins/oculus/src/OculusControllerManager.h index 69187f94a6..b08d54babe 100644 --- a/plugins/oculus/src/OculusControllerManager.h +++ b/plugins/oculus/src/OculusControllerManager.h @@ -26,10 +26,8 @@ public: // Plugin functions bool isSupported() const override; const QString getName() const override { return NAME; } - bool isHandController() const override { return _touch != nullptr; } bool isHeadController() const override { return true; } - bool isHeadControllerMounted() const; QStringList getSubdeviceNames() override; bool activate() override; @@ -105,7 +103,6 @@ private: void checkForConnectedDevices(); - ovrSession _session { nullptr }; ovrInputState _inputState {}; RemoteDevice::Pointer _remote; TouchDevice::Pointer _touch; diff --git a/plugins/oculus/src/OculusDisplayPlugin.cpp b/plugins/oculus/src/OculusDisplayPlugin.cpp index 0fd8467e38..308652cacd 100644 --- a/plugins/oculus/src/OculusDisplayPlugin.cpp +++ b/plugins/oculus/src/OculusDisplayPlugin.cpp @@ -19,6 +19,8 @@ #include "OculusHelpers.h" +using namespace hifi; + const char* OculusDisplayPlugin::NAME { "Oculus Rift" }; static ovrPerfHudMode currentDebugMode = ovrPerfHud_Off; @@ -63,7 +65,7 @@ void OculusDisplayPlugin::cycleDebugOutput() { void OculusDisplayPlugin::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 = { }; desc.Type = ovrTexture_2D; desc.ArraySize = 1; @@ -76,14 +78,14 @@ void OculusDisplayPlugin::customizeContext() { ovrResult result = ovr_CreateTextureSwapChainGL(_session, &desc, &_textureSwapChain); if (!OVR_SUCCESS(result)) { - logCritical("Failed to create swap textures"); + qCritical(oculusLog) << "Failed to create swap textures" << ovr::getError(); return; } int length = 0; result = ovr_GetTextureSwapChainLength(_session, _textureSwapChain, &length); if (!OVR_SUCCESS(result) || !length) { - logCritical("Unable to count swap chain textures"); + qCritical(oculusLog) << "Unable to count swap chain textures" << ovr::getError(); return; } for (int i = 0; i < length; ++i) { @@ -164,8 +166,8 @@ void OculusDisplayPlugin::hmdPresent() { auto result = ovr_CommitTextureSwapChain(_session, _textureSwapChain); Q_ASSERT(OVR_SUCCESS(result)); _sceneLayer.SensorSampleTime = _currentPresentFrameInfo.sensorSampleTime; - _sceneLayer.RenderPose[ovrEyeType::ovrEye_Left] = ovrPoseFromGlm(_currentPresentFrameInfo.renderPose); - _sceneLayer.RenderPose[ovrEyeType::ovrEye_Right] = ovrPoseFromGlm(_currentPresentFrameInfo.renderPose); + _sceneLayer.RenderPose[ovrEyeType::ovrEye_Left] = ovr::poseFromGlm(_currentPresentFrameInfo.renderPose); + _sceneLayer.RenderPose[ovrEyeType::ovrEye_Right] = ovr::poseFromGlm(_currentPresentFrameInfo.renderPose); auto submitStart = usecTimestampNow(); uint64_t nonSubmitInterval = 0; @@ -192,7 +194,7 @@ void OculusDisplayPlugin::hmdPresent() { } if (!OVR_SUCCESS(result)) { - logWarning("Failed to present"); + qWarning(oculusLog) << "Failed to present" << ovr::getError(); } static int compositorDroppedFrames = 0; @@ -234,9 +236,7 @@ QJsonObject OculusDisplayPlugin::getHardwareStats() const { } bool OculusDisplayPlugin::isHmdMounted() const { - ovrSessionStatus status; - return (OVR_SUCCESS(ovr_GetSessionStatus(_session, &status)) && - (ovrFalse != status.HmdMounted)); + return ovr::hmdMounted(); } QString OculusDisplayPlugin::getPreferredAudioInDevice() const { diff --git a/plugins/oculus/src/OculusHelpers.cpp b/plugins/oculus/src/OculusHelpers.cpp index 4632c8ab76..511984c657 100644 --- a/plugins/oculus/src/OculusHelpers.cpp +++ b/plugins/oculus/src/OculusHelpers.cpp @@ -24,41 +24,17 @@ #include Q_LOGGING_CATEGORY(displayplugins, "hifi.plugins.display") -Q_LOGGING_CATEGORY(oculus, "hifi.plugins.display.oculus") - -static std::atomic 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()); -} +Q_LOGGING_CATEGORY(oculusLog, "hifi.plugins.display.oculus") +using namespace hifi; static wchar_t* REQUIRED_OCULUS_DLL = L"LibOVRRT64_1.dll"; static wchar_t FOUND_PATH[MAX_PATH]; -bool oculusAvailable() { +bool ovr::available() { static std::once_flag once; - static bool result { false }; + static bool result{ false }; std::call_once(once, [&] { - static const QString DEBUG_FLAG("HIFI_DEBUG_OPENVR"); static bool enableDebugOpenVR = QProcessEnvironment::systemEnvironment().contains(DEBUG_FLAG); if (enableDebugOpenVR) { @@ -81,113 +57,107 @@ bool oculusAvailable() { return result; } -ovrSession acquireOculusSession() { - if (!session && !oculusAvailable()) { - qCDebug(oculus) << "oculus: no runtime or HMD present"; +class ovrImpl { + using Mutex = std::mutex; + using Lock = std::unique_lock; + 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& f) { + Lock lock(mutex); + if (!session) { + setupSession(false); + } + f(session); + } + + ovrSession acquireRenderSession() { + Lock lock(mutex); + if (renderCount++ == 0) { + releaseSession(); + setupSession(true); + } return session; } - if (!session) { - ovrInitParams initParams { - ovrInit_RequestVersion | ovrInit_MixedRendering, OVR_MINOR_VERSION, nullptr, 0, 0 - }; - - 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; + void releaseRenderSession(ovrSession session) { + Lock lock(mutex); + if (--renderCount == 0) { + releaseSession(); } } +} _ovr; - ++refCount; - return session; +ovrSession ovr::acquireRenderSession() { + return _ovr.acquireRenderSession(); } -void releaseOculusSession() { - Q_ASSERT(refCount > 0 && 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 ovr::releaseRenderSession(ovrSession session) { + _ovr.releaseRenderSession(session); } -void handleOVREvents() { - if (!session) { - return; - } +void ovr::withSession(const std::function& f) { + _ovr.withSession(f); +} - ovrSessionStatus status; - if (!OVR_SUCCESS(ovr_GetSessionStatus(session, &status))) { - return; - } - - _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(); +ovrSessionStatus ovr::getStatus() { + ovrSessionStatus status{}; + withSession([&](ovrSession session) { + if (!OVR_SUCCESS(ovr_GetSessionStatus(session, &status))) { + qCWarning(oculusLog) << "Failed to get session status" << ovr::getError(); } - } -#endif + }); + return status; } -bool quitRequested() { - return _quitRequested; -} -bool reorientRequested() { - return _reorientRequested; +ovrTrackingState ovr::getTrackingState() { + ovrTrackingState result{}; + withSession([&](ovrSession session) { result = ovr_GetTrackingState(session, 0, ovrFalse); }); + return result; } -controller::Pose ovrControllerPoseToHandPose( - ovrHandType hand, - const ovrPoseStatef& handPose) { +QString ovr::getError() { + static ovrErrorInfo error; + 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: // // user @@ -247,9 +217,8 @@ controller::Pose ovrControllerPoseToHandPose( static const glm::quat rightRotationOffset = glm::inverse(rightQuarterZ) * touchToHand; static const float CONTROLLER_LENGTH_OFFSET = 0.0762f; // three inches - static const glm::vec3 CONTROLLER_OFFSET = glm::vec3(CONTROLLER_LENGTH_OFFSET / 2.0f, - -CONTROLLER_LENGTH_OFFSET / 2.0f, - CONTROLLER_LENGTH_OFFSET * 1.5f); + static const glm::vec3 CONTROLLER_OFFSET = + glm::vec3(CONTROLLER_LENGTH_OFFSET / 2.0f, -CONTROLLER_LENGTH_OFFSET / 2.0f, CONTROLLER_LENGTH_OFFSET * 1.5f); static const glm::vec3 leftTranslationOffset = glm::vec3(-1.0f, 1.0f, 1.0f) * CONTROLLER_OFFSET; static const glm::vec3 rightTranslationOffset = CONTROLLER_OFFSET; @@ -268,12 +237,13 @@ controller::Pose ovrControllerPoseToHandPose( return pose; } -controller::Pose ovrControllerRotationToHandRotation(ovrHandType hand, const ovrPoseStatef& handPose, - const ovrPoseStatef& lastHandPose) { +controller::Pose hifi::ovr::toControllerPose(ovrHandType hand, + const ovrPoseStatef& handPose, + const ovrPoseStatef& lastHandPose) { 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 touchToHand = yFlip * quarterX; - + 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); @@ -281,9 +251,8 @@ controller::Pose ovrControllerRotationToHandRotation(ovrHandType hand, const ovr static const glm::quat rightRotationOffset = glm::inverse(rightQuarterZ) * touchToHand; static const float CONTROLLER_LENGTH_OFFSET = 0.0762f; // three inches - static const glm::vec3 CONTROLLER_OFFSET = glm::vec3(CONTROLLER_LENGTH_OFFSET / 2.0f, - -CONTROLLER_LENGTH_OFFSET / 2.0f, - CONTROLLER_LENGTH_OFFSET * 1.5f); + static const glm::vec3 CONTROLLER_OFFSET = + glm::vec3(CONTROLLER_LENGTH_OFFSET / 2.0f, -CONTROLLER_LENGTH_OFFSET / 2.0f, CONTROLLER_LENGTH_OFFSET * 1.5f); static const glm::vec3 leftTranslationOffset = glm::vec3(-1.0f, 1.0f, 1.0f) * CONTROLLER_OFFSET; static const glm::vec3 rightTranslationOffset = CONTROLLER_OFFSET; @@ -301,3 +270,52 @@ controller::Pose ovrControllerRotationToHandRotation(ovrHandType hand, const ovr pose.valid = true; 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 diff --git a/plugins/oculus/src/OculusHelpers.h b/plugins/oculus/src/OculusHelpers.h index 5743f8576b..6588d9754b 100644 --- a/plugins/oculus/src/OculusHelpers.h +++ b/plugins/oculus/src/OculusHelpers.h @@ -7,10 +7,9 @@ // #pragma once - #include -#include +#include #include #include #include @@ -18,106 +17,107 @@ #include Q_DECLARE_LOGGING_CATEGORY(displayplugins) -Q_DECLARE_LOGGING_CATEGORY(oculus) +Q_DECLARE_LOGGING_CATEGORY(oculusLog) -void logWarning(const char* what); -void logCritical(const char* what); -bool oculusAvailable(); -ovrSession acquireOculusSession(); -void releaseOculusSession(); +namespace hifi { + +struct ovr { + static bool available(); + static ovrSession acquireRenderSession(); + static void releaseRenderSession(ovrSession session); + static void withSession(const std::function& f); + static ovrSessionStatus getStatus(); + static ovrTrackingState getTrackingState(); + static QString getError(); -void handleOVREvents(); -bool quitRequested(); -bool reorientRequested(); + static inline bool quitRequested() { return quitRequested(getStatus()); } + static inline bool reorientRequested() { return reorientRequested(getStatus()); } + static inline bool hmdMounted() { return hmdMounted(getStatus()); } + static inline bool hasInputFocus() { return hasInputFocus(getStatus()); } -// Convenience method for looping over each eye with a lambda -template -inline void ovr_for_each_eye(Function function) { - for (ovrEyeType eye = ovrEyeType::ovrEye_Left; - eye < ovrEyeType::ovrEye_Count; - eye = static_cast(eye + 1)) { - function(eye); + static inline bool quitRequested(const ovrSessionStatus& status) { return status.ShouldQuit != ovrFalse; } + static inline bool reorientRequested(const ovrSessionStatus& status) { return status.ShouldRecenter != ovrFalse; } + static inline bool hmdMounted(const ovrSessionStatus& status) { return status.HmdMounted != ovrFalse; } + static inline bool hasInputFocus(const ovrSessionStatus& status) { return status.HasInputFocus != ovrFalse; } + + // Convenience method for looping over each eye with a lambda + static inline void for_each_eye(const std::function& f) { + for (ovrEyeType eye = ovrEye_Left; eye < ovrEye_Count; eye = static_cast(eye + 1)) { + f(eye); + } } -} -template -inline void ovr_for_each_hand(Function function) { - for (ovrHandType hand = ovrHandType::ovrHand_Left; - hand <= ovrHandType::ovrHand_Right; - hand = static_cast(hand + 1)) { - function(hand); + static inline void for_each_hand(const std::function& f) { + for (ovrHandType hand = ovrHand_Left; hand < ovrHand_Count; hand = static_cast(hand + 1)) { + f(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) { - return glm::transpose(glm::make_mat4(&om.M[0][0])); -} + static inline glm::uvec2 toGlm(const ovrSizei& ov) { + return glm::uvec2(ov.w, ov.h); + } -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::quat toGlm(const ovrQuatf& oq) { + return glm::make_quat(&oq.x); + } -inline glm::vec3 toGlm(const ovrVector3f & ov) { - return glm::make_vec3(&ov.x); -} + static 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 glm::vec2 toGlm(const ovrVector2f & ov) { - return glm::make_vec2(&ov.x); -} + static inline ovrMatrix4f fromGlm(const glm::mat4& m) { + 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) { - return glm::uvec2(ov.w, ov.h); -} + static inline ovrVector3f fromGlm(const glm::vec3& v) { + return { v.x, v.y, v.z }; + } -inline glm::quat toGlm(const ovrQuatf & oq) { - return glm::make_quat(&oq.x); -} + static inline ovrVector2f fromGlm(const glm::vec2& v) { + return { v.x, v.y }; + } -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; -} + static inline ovrSizei fromGlm(const glm::uvec2& v) { + return { (int)v.x, (int)v.y }; + } -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; -} + static inline ovrQuatf fromGlm(const glm::quat& q) { + return { q.x, q.y, q.z, q.w }; + } -inline ovrVector3f ovrFromGlm(const glm::vec3 & v) { - return{ v.x, v.y, v.z }; -} + static inline ovrPosef poseFromGlm(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 = fromGlm(orientation); + result.Position = fromGlm(translation); + return result; + } -inline ovrVector2f ovrFromGlm(const glm::vec2 & v) { - return{ v.x, v.y }; -} + static controller::Pose toControllerPose(ovrHandType hand, const ovrPoseStatef& handPose); + 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) { - 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); +} // namespace hifi