mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01: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(
|
||||
${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=<INSTALL_DIR>
|
||||
PATCH_COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/LibOVRCMakeLists.txt" <SOURCE_DIR>/CMakeLists.txt
|
||||
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)
|
||||
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")
|
||||
|
|
|
@ -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<glm::mat4, 2> 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() {
|
||||
}
|
||||
|
|
|
@ -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<ovrEyeRenderDesc, 2> _eyeRenderDescs;
|
||||
std::array<ovrFovPort, 2> _eyeFovs;
|
||||
ovrHmdDesc _hmdDesc;
|
||||
ovrLayerEyeFov _sceneLayer;
|
||||
ovrViewScaleDesc _viewScaleDesc;
|
||||
// ovrLayerEyeFovDepth _depthLayer;
|
||||
};
|
||||
|
|
|
@ -22,34 +22,23 @@
|
|||
#include <NumericalConstants.h>
|
||||
#include <StreamUtils.h>
|
||||
|
||||
#include <OVR_CAPI.h>
|
||||
#include <ovr_capi.h>
|
||||
|
||||
#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<controller::UserInputMapper>();
|
||||
_remote = std::make_shared<RemoteDevice>(*this);
|
||||
userInputMapper->registerDevice(_remote);
|
||||
if (!_remote && (controllerConnected & ovrControllerType_Remote) == ovrControllerType_Remote) {
|
||||
if (OVR_SUCCESS(ovr_GetInputState(session, ovrControllerType_Remote, &_inputState))) {
|
||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||
_remote = std::make_shared<RemoteDevice>(*this);
|
||||
userInputMapper->registerDevice(_remote);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!_touch && (controllerConnected & ovrControllerType_Touch) != 0) {
|
||||
if (OVR_SUCCESS(ovr_GetInputState(_session, ovrControllerType_Touch, &_inputState))) {
|
||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||
_touch = std::make_shared<TouchDevice>(*this);
|
||||
userInputMapper->registerDevice(_touch);
|
||||
if (!_touch && (controllerConnected & ovrControllerType_Touch) != 0) {
|
||||
if (OVR_SUCCESS(ovr_GetInputState(session, ovrControllerType_Touch, &_inputState))) {
|
||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||
_touch = std::make_shared<TouchDevice>(*this);
|
||||
userInputMapper->registerDevice(_touch);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void OculusControllerManager::deactivate() {
|
||||
InputPlugin::deactivate();
|
||||
|
||||
if (_session) {
|
||||
releaseOculusSession();
|
||||
_session = nullptr;
|
||||
}
|
||||
|
||||
// unregister with UserInputMapper
|
||||
auto userInputMapper = DependencyManager::get<controller::UserInputMapper>();
|
||||
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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -24,41 +24,17 @@
|
|||
#include <NumericalConstants.h>
|
||||
|
||||
Q_LOGGING_CATEGORY(displayplugins, "hifi.plugins.display")
|
||||
Q_LOGGING_CATEGORY(oculus, "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());
|
||||
}
|
||||
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<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;
|
||||
}
|
||||
|
||||
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<void(ovrSession)>& 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
|
||||
|
|
|
@ -7,10 +7,9 @@
|
|||
//
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <QtCore/QLoggingCategory>
|
||||
|
||||
#include <OVR_CAPI_GL.h>
|
||||
#include <ovr_capi.h>
|
||||
#include <GLMHelpers.h>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
@ -18,106 +17,107 @@
|
|||
#include <controllers/Forward.h>
|
||||
|
||||
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<void(ovrSession)>& 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 <typename Function>
|
||||
inline void ovr_for_each_eye(Function function) {
|
||||
for (ovrEyeType eye = ovrEyeType::ovrEye_Left;
|
||||
eye < ovrEyeType::ovrEye_Count;
|
||||
eye = static_cast<ovrEyeType>(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<void(ovrEyeType eye)>& f) {
|
||||
for (ovrEyeType eye = ovrEye_Left; eye < ovrEye_Count; eye = static_cast<ovrEyeType>(eye + 1)) {
|
||||
f(eye);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Function>
|
||||
inline void ovr_for_each_hand(Function function) {
|
||||
for (ovrHandType hand = ovrHandType::ovrHand_Left;
|
||||
hand <= ovrHandType::ovrHand_Right;
|
||||
hand = static_cast<ovrHandType>(hand + 1)) {
|
||||
function(hand);
|
||||
static inline void for_each_hand(const std::function<void(ovrHandType eye)>& f) {
|
||||
for (ovrHandType hand = ovrHand_Left; hand < ovrHand_Count; hand = static_cast<ovrHandType>(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
|
||||
|
|
Loading…
Reference in a new issue