mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
adding new plugin
This commit is contained in:
parent
db06533018
commit
ebb9cd7de6
8 changed files with 707 additions and 0 deletions
35
libraries/plugins/src/plugins/OculusPlatformPlugin.h
Normal file
35
libraries/plugins/src/plugins/OculusPlatformPlugin.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
// Created by Wayne Chen on 2018/12/20
|
||||
// Copyright 2018 High Fidelity Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2-0.html
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QString>
|
||||
|
||||
#include <functional>
|
||||
|
||||
using Ticket = QByteArray;
|
||||
using TicketRequestCallback = std::function<void(Ticket)>;
|
||||
|
||||
|
||||
class OculusPlatformPlugin {
|
||||
public:
|
||||
virtual ~OculusPlatformPlugin() = default;
|
||||
|
||||
virtual bool init() = 0;
|
||||
virtual void shutdown() = 0;
|
||||
|
||||
virtual bool isRunning() = 0;
|
||||
|
||||
virtual void runCallbacks() = 0;
|
||||
|
||||
virtual void requestTicket(TicketRequestCallback callback) = 0;
|
||||
|
||||
virtual QString getLoggedInUserID() = 0;
|
||||
|
||||
virtual QString getOculusVRBuildID() = 0;
|
||||
};
|
36
plugins/oculusPlatform/CMakeLists.txt
Normal file
36
plugins/oculusPlatform/CMakeLists.txt
Normal file
|
@ -0,0 +1,36 @@
|
|||
#
|
||||
# Created by Bradley Austin Davis on 2015/10/25
|
||||
# Copyright 2015 High Fidelity, Inc.
|
||||
#
|
||||
# Distributed under the Apache License, Version 2.0.
|
||||
# See the accompanying file LICENSE or http:#www.apache.org/licenses/LICENSE-2.0.html
|
||||
#
|
||||
|
||||
if (WIN32 AND (NOT USE_GLES))
|
||||
|
||||
# if we were passed an Oculus App ID for entitlement checks, send that along
|
||||
if (DEFINED ENV{OCULUS_APP_ID})
|
||||
add_definitions(-DOCULUS_APP_ID="$ENV{OCULUS_APP_ID}")
|
||||
endif ()
|
||||
|
||||
set(TARGET_NAME oculusPlatform)
|
||||
setup_hifi_plugin(Multimedia)
|
||||
link_hifi_libraries(
|
||||
shared task gl shaders gpu ${PLATFORM_GL_BACKEND} controllers ui qml
|
||||
plugins ui-plugins display-plugins input-plugins
|
||||
audio-client networking render-utils
|
||||
${PLATFORM_GL_BACKEND}
|
||||
)
|
||||
include_hifi_library_headers(octree)
|
||||
|
||||
add_dependency_external_projects(LibOVR)
|
||||
find_package(LibOVR REQUIRED)
|
||||
target_include_directories(${TARGET_NAME} PRIVATE ${LIBOVR_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_NAME} ${LIBOVR_LIBRARIES})
|
||||
target_link_libraries(${TARGET_NAME} Winmm.lib)
|
||||
|
||||
add_dependency_external_projects(LibOVRPlatform)
|
||||
find_package(LibOVRPlatform REQUIRED)
|
||||
target_include_directories(${TARGET_NAME} PRIVATE ${LIBOVRPLATFORM_INCLUDE_DIRS})
|
||||
target_link_libraries(${TARGET_NAME} ${LIBOVRPLATFORM_LIBRARIES})
|
||||
endif()
|
116
plugins/oculusPlatform/src/OculusAPIPlugin.cpp
Normal file
116
plugins/oculusPlatform/src/OculusAPIPlugin.cpp
Normal file
|
@ -0,0 +1,116 @@
|
|||
//
|
||||
// Created by Wayne Chen on 2018/12/20
|
||||
// Copyright 2018 High Fidelity Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2-0.html
|
||||
//
|
||||
|
||||
#include "OculusAPIPlugin.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
|
||||
#include <QtCore/QTimer>
|
||||
|
||||
#define OVRPL_DISABLED
|
||||
#include <OVR_Platform.h>
|
||||
|
||||
#include <shared/GlobalAppProperties.h>
|
||||
#include "OculusHelpers.h"
|
||||
|
||||
static const Ticket INVALID_TICKET = Ticket();
|
||||
//static std::atomic_bool initialized { false };
|
||||
static std::atomic_bool initialized { false };
|
||||
static ovrSession session { nullptr };
|
||||
|
||||
bool OculusAPIPlugin::init() {
|
||||
if (session) {
|
||||
return initialized;
|
||||
}
|
||||
|
||||
ovrInitParams initParams{ ovrInit_RequestVersion | ovrInit_FocusAware, OVR_MINOR_VERSION, nullptr, 0, 0 };
|
||||
initParams.Flags |= ovrInit_Invisible;
|
||||
|
||||
if (!OVR_SUCCESS(ovr_Initialize(&initParams))) {
|
||||
qCWarning(oculusLog) << "Failed to initialze Oculus SDK" << hifi::ovr::getError();
|
||||
return initialized;
|
||||
}
|
||||
|
||||
#ifdef OCULUS_APP_ID
|
||||
|
||||
if (qApp->property(hifi::properties::OCULUS_STORE).toBool()) {
|
||||
auto result = ovr_PlatformInitializeWindows(OCULUS_APP_ID);
|
||||
if (result != ovrPlatformInitialize_Success && result != ovrPlatformInitialize_PreLoaded) {
|
||||
qCWarning(oculusLog) << "Unable to initialize the platform for entitlement check - fail the check" << hifi::ovr::getError();
|
||||
} else {
|
||||
qCDebug(oculusLog) << "Performing Oculus Platform entitlement check";
|
||||
ovr_Entitlement_GetIsViewerEntitled();
|
||||
using namespace std::chrono_literals;
|
||||
std::this_thread::sleep_for(100ms);
|
||||
auto message = ovr_PopMessage();
|
||||
if (ovr_Message_GetType(message) == ovrMessage_Entitlement_GetIsViewerEntitled && ovr_Message_IsError(message)) {
|
||||
qDebug() << QString(ovr_Error_GetMessage(ovr_Message_GetError(message)));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//ovrGraphicsLuid luid;
|
||||
//if (!OVR_SUCCESS(ovr_Create(&session, &luid))) {
|
||||
// qCWarning(oculusLog) << "Failed to acquire Oculus session" << hifi::ovr::getError();
|
||||
// return initialized;
|
||||
//} else {
|
||||
// ovrResult setFloorLevelOrigin = ovr_SetTrackingOriginType(session, ovrTrackingOrigin::ovrTrackingOrigin_FloorLevel);
|
||||
// if (!OVR_SUCCESS(setFloorLevelOrigin)) {
|
||||
// qCWarning(oculusLog) << "Failed to set the Oculus tracking origin to floor level" << hifi::ovr::getError();
|
||||
// }
|
||||
//}
|
||||
initialized = true;
|
||||
return initialized;
|
||||
}
|
||||
|
||||
void OculusAPIPlugin::shutdown() {
|
||||
}
|
||||
|
||||
void OculusAPIPlugin::runCallbacks() {
|
||||
}
|
||||
|
||||
void OculusAPIPlugin::requestTicket(TicketRequestCallback callback) {
|
||||
}
|
||||
|
||||
bool OculusAPIPlugin::isRunning() {
|
||||
return initialized;
|
||||
}
|
||||
|
||||
QString OculusAPIPlugin::getLoggedInUserID() {
|
||||
if (initialized) {
|
||||
QTimer timer;
|
||||
timer.start(1000);
|
||||
auto request = ovr_User_GetLoggedInUser();
|
||||
ovrMessageHandle message { nullptr };
|
||||
using namespace std::chrono_literals;
|
||||
std::this_thread::sleep_for(100ms);
|
||||
while ((message = ovr_PopMessage()) != nullptr) {
|
||||
if (!timer.isActive()) {
|
||||
qCDebug(oculusLog) << "login user id timeout after 1 second";
|
||||
return "";
|
||||
} else if (ovr_Message_GetType(message) == ovrMessage_User_GetLoggedInUser) {
|
||||
if (!ovr_Message_IsError(message)) {
|
||||
ovrUserHandle user = ovr_Message_GetUser(message);
|
||||
qCDebug(oculusLog) << "UserID: " << ovr_User_GetID(user) << ", Oculus ID: " << ovr_User_GetOculusID(user);
|
||||
return ovr_User_GetOculusID(user);
|
||||
} else {
|
||||
qDebug() << "Error getting user id: " << QString(ovr_Error_GetMessage(ovr_Message_GetError(message)));
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
QString OculusAPIPlugin::getOculusVRBuildID() {
|
||||
return QString(OVR_MAJOR_VERSION + "." + OVR_MINOR_VERSION);
|
||||
}
|
26
plugins/oculusPlatform/src/OculusAPIPlugin.h
Normal file
26
plugins/oculusPlatform/src/OculusAPIPlugin.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
//
|
||||
// Created by Wayne Chen on 2018/12/20
|
||||
// Copyright 2018 High Fidelity Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2-0.html
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include <plugins/OculusPlatformPlugin.h>
|
||||
|
||||
class OculusAPIPlugin : public OculusPlatformPlugin {
|
||||
public:
|
||||
bool init() override;
|
||||
void shutdown() override;
|
||||
|
||||
bool isRunning() override;
|
||||
|
||||
void runCallbacks() override;
|
||||
|
||||
void requestTicket(TicketRequestCallback callback) override;
|
||||
|
||||
QString getLoggedInUserID() override;
|
||||
|
||||
QString getOculusVRBuildID() override;
|
||||
};
|
326
plugins/oculusPlatform/src/OculusHelpers.cpp
Normal file
326
plugins/oculusPlatform/src/OculusHelpers.cpp
Normal file
|
@ -0,0 +1,326 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis on 2015/08/08
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include "OculusHelpers.h"
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include <Windows.h>
|
||||
#include <QtCore/QFile>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QProcessEnvironment>
|
||||
|
||||
#define OVRPL_DISABLED
|
||||
#include <OVR_Platform.h>
|
||||
|
||||
#include <controllers/Input.h>
|
||||
#include <controllers/Pose.h>
|
||||
#include <shared/GlobalAppProperties.h>
|
||||
#include <NumericalConstants.h>
|
||||
|
||||
Q_LOGGING_CATEGORY(displayplugins, "hifi.plugins.display")
|
||||
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 ovr::available() {
|
||||
static std::once_flag once;
|
||||
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) {
|
||||
return;
|
||||
}
|
||||
|
||||
ovrDetectResult detect = ovr_Detect(0);
|
||||
if (!detect.IsOculusServiceRunning || !detect.IsOculusHMDConnected) {
|
||||
return;
|
||||
}
|
||||
|
||||
DWORD searchResult = SearchPathW(NULL, REQUIRED_OCULUS_DLL, NULL, MAX_PATH, FOUND_PATH, NULL);
|
||||
if (searchResult <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
result = true;
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#ifdef OCULUS_APP_ID
|
||||
if (qApp->property(hifi::properties::OCULUS_STORE).toBool()) {
|
||||
if (ovr_PlatformInitializeWindows(OCULUS_APP_ID) != ovrPlatformInitialize_Success) {
|
||||
qCWarning(oculusLog) << "Unable to initialize the platform for entitlement check - fail the check" << ovr::getError();
|
||||
return;
|
||||
} else {
|
||||
qCDebug(oculusLog) << "Performing Oculus Platform entitlement check";
|
||||
ovr_Entitlement_GetIsViewerEntitled();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ovrGraphicsLuid luid;
|
||||
if (!OVR_SUCCESS(ovr_Create(&session, &luid))) {
|
||||
qCWarning(oculusLog) << "Failed to acquire Oculus session" << ovr::getError();
|
||||
return;
|
||||
} else {
|
||||
ovrResult setFloorLevelOrigin = ovr_SetTrackingOriginType(session, ovrTrackingOrigin::ovrTrackingOrigin_FloorLevel);
|
||||
if (!OVR_SUCCESS(setFloorLevelOrigin)) {
|
||||
qCWarning(oculusLog) << "Failed to set the Oculus tracking origin to floor level" << ovr::getError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
void releaseRenderSession(ovrSession session) {
|
||||
Lock lock(mutex);
|
||||
if (--renderCount == 0) {
|
||||
releaseSession();
|
||||
}
|
||||
}
|
||||
} _ovr;
|
||||
|
||||
ovrSession ovr::acquireRenderSession() {
|
||||
return _ovr.acquireRenderSession();
|
||||
}
|
||||
|
||||
void ovr::releaseRenderSession(ovrSession session) {
|
||||
_ovr.releaseRenderSession(session);
|
||||
}
|
||||
|
||||
void ovr::withSession(const std::function<void(ovrSession)>& f) {
|
||||
_ovr.withSession(f);
|
||||
}
|
||||
|
||||
ovrSessionStatus ovr::getStatus() {
|
||||
ovrResult result;
|
||||
return ovr::getStatus(result);
|
||||
}
|
||||
|
||||
ovrSessionStatus ovr::getStatus(ovrResult& result) {
|
||||
ovrSessionStatus status{};
|
||||
withSession([&](ovrSession session) {
|
||||
result = ovr_GetSessionStatus(session, &status);
|
||||
if (!OVR_SUCCESS(result)) {
|
||||
qCWarning(oculusLog) << "Failed to get session status" << ovr::getError();
|
||||
}
|
||||
});
|
||||
return status;
|
||||
}
|
||||
|
||||
ovrTrackingState ovr::getTrackingState(double absTime, ovrBool latencyMarker) {
|
||||
ovrTrackingState result{};
|
||||
withSession([&](ovrSession session) { result = ovr_GetTrackingState(session, absTime, latencyMarker); });
|
||||
return result;
|
||||
}
|
||||
|
||||
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
|
||||
// forward
|
||||
// -z
|
||||
// |
|
||||
// y| user
|
||||
// y o----x right
|
||||
// o-----x user
|
||||
// | up
|
||||
// |
|
||||
// z
|
||||
//
|
||||
// Rift
|
||||
|
||||
// From ABOVE the hand canonical axes looks like this:
|
||||
//
|
||||
// | | | | y | | | |
|
||||
// | | | | | | | | |
|
||||
// | | | | |
|
||||
// |left | / x---- + \ |right|
|
||||
// | _/ z \_ |
|
||||
// | | | |
|
||||
// | | | |
|
||||
//
|
||||
|
||||
// So when the user is in Rift space facing the -zAxis with hands outstretched and palms down
|
||||
// the rotation to align the Touch axes with those of the hands is:
|
||||
//
|
||||
// touchToHand = halfTurnAboutY * quaterTurnAboutX
|
||||
|
||||
// Due to how the Touch controllers fit into the palm there is an offset that is different for each hand.
|
||||
// You can think of this offset as the inverse of the measured rotation when the hands are posed, such that
|
||||
// the combination (measurement * offset) is identity at this orientation.
|
||||
//
|
||||
// Qoffset = glm::inverse(deltaRotation when hand is posed fingers forward, palm down)
|
||||
//
|
||||
// An approximate offset for the Touch can be obtained by inspection:
|
||||
//
|
||||
// Qoffset = glm::inverse(glm::angleAxis(sign * PI/2.0f, zAxis) * glm::angleAxis(PI/4.0f, xAxis))
|
||||
//
|
||||
// So the full equation is:
|
||||
//
|
||||
// Q = combinedMeasurement * touchToHand
|
||||
//
|
||||
// Q = (deltaQ * QOffset) * (yFlip * quarterTurnAboutX)
|
||||
//
|
||||
// Q = (deltaQ * inverse(deltaQForAlignedHand)) * (yFlip * quarterTurnAboutX)
|
||||
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);
|
||||
|
||||
static const glm::quat leftRotationOffset = glm::inverse(leftQuarterZ) * touchToHand;
|
||||
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 leftTranslationOffset = glm::vec3(-1.0f, 1.0f, 1.0f) * CONTROLLER_OFFSET;
|
||||
static const glm::vec3 rightTranslationOffset = CONTROLLER_OFFSET;
|
||||
|
||||
auto translationOffset = (hand == ovrHand_Left ? leftTranslationOffset : rightTranslationOffset);
|
||||
auto rotationOffset = (hand == ovrHand_Left ? leftRotationOffset : rightRotationOffset);
|
||||
|
||||
glm::quat rotation = toGlm(handPose.ThePose.Orientation);
|
||||
|
||||
controller::Pose pose;
|
||||
pose.translation = toGlm(handPose.ThePose.Position);
|
||||
pose.translation += rotation * translationOffset;
|
||||
pose.rotation = rotation * rotationOffset;
|
||||
pose.angularVelocity = rotation * toGlm(handPose.AngularVelocity);
|
||||
pose.velocity = toGlm(handPose.LinearVelocity);
|
||||
pose.valid = true;
|
||||
return pose;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
static const glm::quat leftRotationOffset = glm::inverse(leftQuarterZ) * touchToHand;
|
||||
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 leftTranslationOffset = glm::vec3(-1.0f, 1.0f, 1.0f) * CONTROLLER_OFFSET;
|
||||
static const glm::vec3 rightTranslationOffset = CONTROLLER_OFFSET;
|
||||
|
||||
auto translationOffset = (hand == ovrHand_Left ? leftTranslationOffset : rightTranslationOffset);
|
||||
auto rotationOffset = (hand == ovrHand_Left ? leftRotationOffset : rightRotationOffset);
|
||||
|
||||
glm::quat rotation = toGlm(handPose.ThePose.Orientation);
|
||||
|
||||
controller::Pose pose;
|
||||
pose.translation = toGlm(lastHandPose.ThePose.Position);
|
||||
pose.translation += rotation * translationOffset;
|
||||
pose.rotation = rotation * rotationOffset;
|
||||
pose.angularVelocity = toGlm(lastHandPose.AngularVelocity);
|
||||
pose.velocity = toGlm(lastHandPose.LinearVelocity);
|
||||
pose.valid = true;
|
||||
return pose;
|
||||
}
|
||||
|
||||
bool hifi::ovr::handleOVREvents() {
|
||||
#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(oculusLog) << "Oculus Platform entitlement check succeeded, proceeding normally";
|
||||
} else {
|
||||
// we failed the entitlement check, quit
|
||||
qCDebug(oculusLog) << "Oculus Platform entitlement check failed, app will now quit" << OCULUS_APP_ID;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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 true;
|
||||
}
|
127
plugins/oculusPlatform/src/OculusHelpers.h
Normal file
127
plugins/oculusPlatform/src/OculusHelpers.h
Normal file
|
@ -0,0 +1,127 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis on 2015/05/26
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
#pragma once
|
||||
|
||||
#include <QtCore/QLoggingCategory>
|
||||
|
||||
#include <ovr_capi.h>
|
||||
#include <GLMHelpers.h>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
|
||||
#include <controllers/Forward.h>
|
||||
|
||||
Q_DECLARE_LOGGING_CATEGORY(displayplugins)
|
||||
Q_DECLARE_LOGGING_CATEGORY(oculusLog)
|
||||
|
||||
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 ovrSessionStatus getStatus(ovrResult& result);
|
||||
static ovrTrackingState getTrackingState(double absTime = 0.0, ovrBool latencyMarker = ovrFalse);
|
||||
static QString getError();
|
||||
static bool handleOVREvents();
|
||||
|
||||
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()); }
|
||||
|
||||
static inline bool quitRequested(const ovrSessionStatus& status) { return status.ShouldQuit != ovrFalse; }
|
||||
static inline bool displayLost(const ovrSessionStatus& status) { return status.DisplayLost != ovrFalse; }
|
||||
static inline bool isVisible(const ovrSessionStatus& status) { return status.IsVisible != 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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static inline glm::uvec2 toGlm(const ovrSizei& ov) {
|
||||
return glm::uvec2(ov.w, ov.h);
|
||||
}
|
||||
|
||||
static inline glm::quat toGlm(const ovrQuatf& oq) {
|
||||
return glm::make_quat(&oq.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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static inline ovrVector3f fromGlm(const glm::vec3& v) {
|
||||
return { v.x, v.y, v.z };
|
||||
}
|
||||
|
||||
static inline ovrVector2f fromGlm(const glm::vec2& v) {
|
||||
return { v.x, v.y };
|
||||
}
|
||||
|
||||
static inline ovrSizei fromGlm(const glm::uvec2& v) {
|
||||
return { (int)v.x, (int)v.y };
|
||||
}
|
||||
|
||||
static inline ovrQuatf fromGlm(const glm::quat& q) {
|
||||
return { q.x, q.y, q.z, q.w };
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static controller::Pose toControllerPose(ovrHandType hand, const ovrPoseStatef& handPose);
|
||||
static controller::Pose toControllerPose(ovrHandType hand, const ovrPoseStatef& handPose, const ovrPoseStatef& lastHandPose);
|
||||
|
||||
};
|
||||
|
||||
} // namespace hifi
|
40
plugins/oculusPlatform/src/OculusPlatformProvider.cpp
Normal file
40
plugins/oculusPlatform/src/OculusPlatformProvider.cpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// Created by Clément Brisset on 12/14/16
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include <QtCore/QObject>
|
||||
#include <QtCore/QtPlugin>
|
||||
#include <QtCore/QStringList>
|
||||
|
||||
#include <plugins/RuntimePlugin.h>
|
||||
|
||||
#include "OculusAPIPlugin.h"
|
||||
|
||||
class OculusAPIProvider : public QObject, public OculusPlatformProvider {
|
||||
Q_OBJECT
|
||||
Q_PLUGIN_METADATA(IID OculusPlatformProvider_iid FILE "plugin.json")
|
||||
Q_INTERFACES(OculusPlatformProvider)
|
||||
|
||||
public:
|
||||
OculusAPIProvider(QObject* parent = nullptr) : QObject(parent) {}
|
||||
virtual ~OculusAPIProvider() {}
|
||||
|
||||
virtual OculusPlatformPluginPointer getOculusPlatformPlugin() override {
|
||||
static std::once_flag once;
|
||||
std::call_once(once, [&] {
|
||||
_oculusPlatformPlugin = std::make_shared<OculusAPIPlugin>();
|
||||
});
|
||||
return _oculusPlatformPlugin;
|
||||
}
|
||||
|
||||
private:
|
||||
OculusPlatformPluginPointer _oculusPlatformPlugin;
|
||||
};
|
||||
|
||||
#include "OculusPlatformProvider.moc"
|
1
plugins/oculusPlatform/src/plugin.json
Normal file
1
plugins/oculusPlatform/src/plugin.json
Normal file
|
@ -0,0 +1 @@
|
|||
{"name":"Oculus Platform"}
|
Loading…
Reference in a new issue