migrating platform plugin

This commit is contained in:
Wayne Chen 2019-01-08 17:42:19 -08:00
parent a905310a58
commit 4320f4cbe4
22 changed files with 185 additions and 900 deletions

View file

@ -120,6 +120,7 @@
#include <plugins/PluginManager.h>
#include <plugins/PluginUtils.h>
#include <plugins/SteamClientPlugin.h>
#include <plugins/OculusPlatformPlugin.h>
#include <plugins/InputConfiguration.h>
#include <RecordingScriptingInterface.h>
#include <render/EngineStats.h>
@ -5958,8 +5959,8 @@ void Application::update(float deltaTime) {
}
}
if (auto oculusPlugin = PluginManager::getInstance()->getOculusDisplayPlugin()) {
oculusPlugin->pluginUpdate();
if (auto oculusPlugin = PluginManager::getInstance()->getOculusPlatformPlugin()) {
oculusPlugin->handleOVREvents();
}
userInputMapper->setInputCalibrationData(calibrationData);

View file

@ -18,6 +18,7 @@
#include <plugins/PluginManager.h>
#include <plugins/SteamClientPlugin.h>
#include <plugins/OculusPlatformPlugin.h>
#include <shared/GlobalAppProperties.h>
#include <ui/TabletScriptingInterface.h>
#include <UserActivityLogger.h>
@ -105,8 +106,8 @@ bool LoginDialog::isSteamRunning() const {
}
bool LoginDialog::isOculusRunning() const {
auto oculusDisplay = PluginManager::getInstance()->getOculusDisplayPlugin();
return (oculusDisplay != nullptr);
auto oculusPlatform = PluginManager::getInstance()->getOculusPlatformPlugin();
return (oculusPlatform != nullptr);
}
void LoginDialog::dismissLoginDialog() {
@ -124,8 +125,8 @@ void LoginDialog::login(const QString& username, const QString& password) const
void LoginDialog::loginThroughOculus() {
qDebug() << "Attempting to login through Oculus";
if (auto oculusDisplay = PluginManager::getInstance()->getOculusDisplayPlugin()) {
oculusDisplay->requestTicket([this](QString nonce, QString userID) {
if (auto oculusPlatform = PluginManager::getInstance()->getOculusPlatformPlugin()) {
//oculusPlatform->requestTicket([this](QString nonce, QString userID) {
// if (nonce.isEmpty() || userID.isEmpty()) {
// emit handleLoginFailed();
// return;
@ -138,8 +139,8 @@ void LoginDialog::loginThroughOculus() {
void LoginDialog::linkOculus() {
qDebug() << "Attempting to link Oculus account";
if (auto oculusDisplay = PluginManager::getInstance()->getOculusDisplayPlugin()) {
//oculusDisplay->requestTicket([this](QString nonce, QString userID) {
if (auto oculusPlatform = PluginManager::getInstance()->getOculusPlatformPlugin()) {
//oculusPlatform->requestTicket([this](QString nonce, QString userID) {
// if (nonce.isEmpty() || userID.isEmpty()) {
// emit handleLoginFailed();
// return;
@ -165,8 +166,8 @@ void LoginDialog::linkOculus() {
void LoginDialog::createAccountFromOculus(QString username) {
qDebug() << "Attempting to create account from Oculus info";
if (auto oculusDisplay = PluginManager::getInstance()->getOculusDisplayPlugin()) {
//oculusDisplay->requestTicket([this, username](QString nonce, QString userID) {
if (auto oculusPlatform = PluginManager::getInstance()->getOculusPlatformPlugin()) {
//oculusPlatform->requestTicket([this, username](QString nonce, QString userID) {
// if (nonce.isEmpty() || userID.isEmpty()) {
// emit handleLoginFailed();
// return;

View file

@ -21,7 +21,6 @@ class DisplayPlugin;
class InputPlugin;
class CodecPlugin;
class SteamClientPlugin;
class OculusDisplayPlugin;
class OculusPlatformPlugin;
class Plugin;
class PluginContainer;
@ -37,6 +36,5 @@ using CodecPluginPointer = std::shared_ptr<CodecPlugin>;
using CodecPluginList = std::vector<CodecPluginPointer>;
using CodecPluginProvider = std::function<CodecPluginList()>;
using SteamClientPluginPointer = std::shared_ptr<SteamClientPlugin>;
using OculusDisplayPluginPointer = std::shared_ptr<OculusDisplayPlugin>;
using OculusPlatformPluginPointer = std::shared_ptr<OculusPlatformPlugin>;
using InputPluginSettingsPersister = std::function<void(const InputPluginList&)>;

View file

@ -0,0 +1,14 @@
//
// 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 "OculusPlatformPlugin.h"
OculusPlatformPlugin::OculusPlatformPlugin() {
}
OculusPlatformPlugin::~OculusPlatformPlugin() {
}

View file

@ -7,30 +7,21 @@
//
#pragma once
#include <QtCore/QByteArray>
#include <QObject>
#include <QtCore/QString>
#include <functional>
using OculusTicketRequestCallback = std::function<void(QString, QString)>;
class OculusPlatformPlugin {
class OculusPlatformPlugin : public QObject {
Q_OBJECT
public:
virtual ~OculusPlatformPlugin() = default;
OculusPlatformPlugin();
virtual ~OculusPlatformPlugin();
virtual bool init() = 0;
virtual void shutdown() = 0;
virtual const QString getName() const = 0;
virtual bool isRunning() = 0;
virtual void handleOVREvents() = 0;
virtual void runCallbacks() = 0;
virtual void requestTicket(OculusTicketRequestCallback callback) = 0;
virtual QString getUserProof() = 0;
virtual QString getLoggedInUserID() = 0;
virtual QString getOculusVRBuildID() = 0;
signals:
void nonceAndUserIDChanged(QString nonce, QString userID);
};

View file

@ -179,19 +179,20 @@ const SteamClientPluginPointer PluginManager::getSteamClientPlugin() {
return steamClientPlugin;
}
const OculusDisplayPluginPointer PluginManager::getOculusDisplayPlugin() {
static OculusDisplayPluginPointer oculusDisplayPlugin;
const OculusPlatformPluginPointer PluginManager::getOculusPlatformPlugin() {
static OculusPlatformPluginPointer oculusPlatformPlugin;
static std::once_flag once;
std::call_once(once, [&] {
// Now grab the display plugins - might break in the main update loop if user unplugs the headset I think?
for (auto plugin : getDisplayPlugins()) {
if (plugin->getName() == "Oculus Rift") {
oculusDisplayPlugin = plugin;
// Now grab the dynamic plugins
for (auto loader : getLoadedPlugins()) {
OculusPlatformProvider* oculusPlatformProvider = qobject_cast<OculusPlatformProvider*>(loader->instance());
if (oculusPlatformProvider) {
oculusPlatformPlugin = oculusPlatformProvider->getOculusPlatformPlugin();
break;
}
}
});
return oculusDisplayPlugin;
return oculusPlatformPlugin;
}
const DisplayPluginList& PluginManager::getDisplayPlugins() {

View file

@ -28,7 +28,7 @@ public:
const InputPluginList& getInputPlugins();
const CodecPluginList& getCodecPlugins();
const SteamClientPluginPointer getSteamClientPlugin();
const OculusDisplayPluginPointer getOculusDisplayPlugin();
const OculusPlatformPluginPointer getOculusPlatformPlugin();
DisplayPluginList getPreferredDisplayPlugins();
void setPreferredDisplayPlugins(const QStringList& displays);

View file

@ -34,8 +34,6 @@ if (NOT SERVER_ONLY AND NOT ANDROID)
add_subdirectory(${DIR})
set(DIR "steamClient")
add_subdirectory(${DIR})
set(DIR "oculusPlatform")
add_subdirectory(${DIR})
set(DIR "hifiLeapMotion")
add_subdirectory(${DIR})
endif()

View file

@ -227,73 +227,3 @@ QVector<glm::vec3> OculusBaseDisplayPlugin::getSensorPositions() {
return result;
}
void OculusBaseDisplayPlugin::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: {
_isViewerEntitled = !ovr_Message_IsError(message);
if (_isViewerEntitled) {
// 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;
}
break;
}
case ovrMessage_User_Get: {
if (!ovr_Message_IsError(message)) {
qCDebug(oculusLog) << "Oculus Platform user retrieval succeeded";
ovrUserHandle user = ovr_Message_GetUser(message);
ovr_FreeMessage(message);
_user = ovr_User_GetOculusID(user);
} else {
qCDebug(oculusLog) << "Oculus Platform user retrieval failed" << QString(ovr_Error_GetMessage(ovr_Message_GetError(message)));
_user = "";
}
break;
}
case ovrMessage_User_GetLoggedInUser: {
if (!ovr_Message_IsError(message)) {
ovrUserHandle user = ovr_Message_GetUser(message);
ovr_FreeMessage(message);
_userID = ovr_User_GetID(user);
} else {
qCDebug(oculusLog) << "Oculus Platform user ID retrieval failed" << QString(ovr_Error_GetMessage(ovr_Message_GetError(message)));
}
break;
}
case ovrMessage_User_GetUserProof: {
_nonceChanged = true;
if (!ovr_Message_IsError(message)) {
ovrUserProofHandle userProof = ovr_Message_GetUserProof(message);
_nonce = ovr_UserProof_GetNonce(userProof);
} else {
qCDebug(oculusLog) << "Oculus Platform nonce retrieval failed" << QString(ovr_Error_GetMessage(ovr_Message_GetError(message)));
_nonce = "";
}
break;
}
}
if (_nonceChanged) {
emit nonceAndUserIDChanged(_nonce, _user);
_nonce = _user = "";
_nonceChanged = 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
}

View file

@ -43,7 +43,6 @@ protected:
bool internalActivate() override;
void internalDeactivate() override;
void updatePresentPose() override;
void handleOVREvents();
protected:
bool _isViewerEntitled;

View file

@ -56,10 +56,6 @@ void OculusDisplayPlugin::init() {
emit deviceConnected(getName());
}
void OculusDisplayPlugin::pluginUpdate() {
handleOVREvents();
}
void OculusDisplayPlugin::cycleDebugOutput() {
if (_session) {
currentDebugMode = static_cast<ovrPerfHudMode>((currentDebugMode + 1) % ovrPerfHud_Count);

View file

@ -23,7 +23,6 @@ public:
float getTargetFrameRate() const override;
virtual QJsonObject getHardwareStats() const;
void pluginUpdate() override final;
protected:
QThread::Priority getPresentPriority() override { return QThread::TimeCriticalPriority; }

View file

@ -0,0 +1,95 @@
//
// Created by Wayne Chen on 2019/01/08
// Copyright 2019 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 "OculusPlatformPlugin.h"
#include <shared/GlobalAppProperties.h>
#include <QMetaObject>
#include "OculusHelpers.h"
const char* OculusAPIPlugin::NAME { "Oculus Rift" };
OculusAPIPlugin::OculusAPIPlugin() {
_session = hifi::ovr::acquireRenderSession();
}
OculusAPIPlugin::~OculusAPIPlugin() {
hifi::ovr::releaseRenderSession(_session);
}
void OculusAPIPlugin::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;
QMetaObject::invokeMethod(qApp, "quit");
}
break;
}
case ovrMessage_User_Get: {
if (!ovr_Message_IsError(message)) {
qCDebug(oculusLog) << "Oculus Platform user retrieval succeeded";
ovrUserHandle user = ovr_Message_GetUser(message);
ovr_FreeMessage(message);
_user = ovr_User_GetOculusID(user);
} else {
qCDebug(oculusLog) << "Oculus Platform user retrieval failed" << QString(ovr_Error_GetMessage(ovr_Message_GetError(message)));
_user = "";
}
break;
}
case ovrMessage_User_GetLoggedInUser: {
if (!ovr_Message_IsError(message)) {
ovrUserHandle user = ovr_Message_GetUser(message);
ovr_FreeMessage(message);
_userID = ovr_User_GetID(user);
} else {
qCDebug(oculusLog) << "Oculus Platform user ID retrieval failed" << QString(ovr_Error_GetMessage(ovr_Message_GetError(message)));
}
break;
}
case ovrMessage_User_GetUserProof: {
_nonceChanged = true;
if (!ovr_Message_IsError(message)) {
ovrUserProofHandle userProof = ovr_Message_GetUserProof(message);
_nonce = ovr_UserProof_GetNonce(userProof);
} else {
qCDebug(oculusLog) << "Oculus Platform nonce retrieval failed" << QString(ovr_Error_GetMessage(ovr_Message_GetError(message)));
_nonce = "";
}
break;
}
}
if (_nonceChanged) {
emit nonceAndUserIDChanged(_nonce, _user);
_nonce = _user = "";
_nonceChanged = 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
}

View file

@ -0,0 +1,32 @@
//
// Created by Wayne Chen on 2019/01/08
// Copyright 2019 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>
#include <OVR_CAPI_GL.h>
#define OVRPL_DISABLED
#include <OVR_Platform.h>
class OculusAPIPlugin : public OculusPlatformPlugin {
public:
OculusAPIPlugin();
virtual ~OculusAPIPlugin();
const QString getName() const { return NAME; }
virtual void handleOVREvents();
private:
static const char* NAME;
QString _nonce;
bool _nonceChanged;
QString _user;
ovrID _userID;
ovrSession _session{ nullptr };
};

View file

@ -18,15 +18,18 @@
#include "OculusDisplayPlugin.h"
#include "OculusDebugDisplayPlugin.h"
#include "OculusPlatformPlugin.h"
#include "OculusControllerManager.h"
class OculusProvider : public QObject, public DisplayProvider, InputProvider
class OculusProvider : public QObject, public DisplayProvider, InputProvider, OculusPlatformProvider
{
Q_OBJECT
Q_PLUGIN_METADATA(IID DisplayProvider_iid FILE "oculus.json")
Q_INTERFACES(DisplayProvider)
Q_PLUGIN_METADATA(IID InputProvider_iid FILE "oculus.json")
Q_INTERFACES(InputProvider)
Q_PLUGIN_METADATA(IID OculusPlatformProvider_iid FILE "oculus.json")
Q_INTERFACES(OculusPlatformProvider)
public:
OculusProvider(QObject* parent = nullptr) : QObject(parent) {}
@ -62,6 +65,15 @@ public:
return _inputPlugins;
}
virtual OculusPlatformPluginPointer getOculusPlatformPlugin() override {
static std::once_flag once;
std::call_once(once, [&] {
_oculusPlatformPlugin = std::make_shared<OculusAPIPlugin>();
});
return _oculusPlatformPlugin;
}
virtual void destroyInputPlugins() override {
_inputPlugins.clear();
}
@ -73,6 +85,7 @@ public:
private:
DisplayPluginList _displayPlugins;
InputPluginList _inputPlugins;
OculusPlatformPluginPointer _oculusPlatformPlugin;
};
#include "OculusProvider.moc"

View file

@ -1,36 +0,0 @@
#
# 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()

View file

@ -1,226 +0,0 @@
//
// 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 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();
QTimer timer;
timer.start(1000);
using namespace std::chrono_literals;
std::this_thread::sleep_for(50ms);
while (auto message = ovr_PopMessage()) {
if (timer.remainingTime() == 0) {
qCDebug(oculusLog) << "login user id timeout after 1 second";
break;
}
switch (ovr_Message_GetType(message)) {
case ovrMessage_Entitlement_GetIsViewerEntitled:
if (ovr_Message_IsError(message)) {
qDebug() << QString(ovr_Error_GetMessage(ovr_Message_GetError(message)));
}
initialized = true;
default:
ovr_FreeMessage(message);
break;
}
}
}
}
#endif
return initialized;
}
void OculusAPIPlugin::shutdown() {
}
void OculusAPIPlugin::runCallbacks() {
}
void OculusAPIPlugin::requestTicket(OculusTicketRequestCallback callback) {
if (!initialized) {
if (!ovr_IsPlatformInitialized()) {
init();
}
else {
qWarning() << "Oculus is not running";
callback("", "");
return;
}
}
if (!initialized) {
qDebug() << "Oculus not initialized";
return;
}
auto nonce = getUserProof();
auto userID = getLoggedInUserID();
qDebug() << "Nonce: " << nonce << ", " << userID;
callback(nonce, userID);
return;
}
bool OculusAPIPlugin::isRunning() {
return initialized;
}
QString OculusAPIPlugin::getUserProof() {
if (initialized) {
QTimer timer;
timer.start(5000);
auto request = ovr_User_GetUserProof();
ovrMessageHandle message { nullptr };
bool messageNotReceived = true;
while (messageNotReceived) {
message = ovr_PopMessage();
if (timer.remainingTime() == 0) {
qCDebug(oculusLog) << "user proof timeout after 5 seconds";
return "";
}
if (message != nullptr) {
switch (ovr_Message_GetType(message)) {
case ovrMessage_User_GetUserProof:
messageNotReceived = false;
if (!ovr_Message_IsError(message)) {
ovrUserProofHandle userProof = ovr_Message_GetUserProof(message);
QString nonce = ovr_UserProof_GetNonce(userProof);
ovr_FreeMessage(message);
return nonce;
} else {
qDebug() << "Error getting user proof: " << QString(ovr_Error_GetMessage(ovr_Message_GetError(message)));
ovr_FreeMessage(message);
return "";
}
break;
default:
ovr_FreeMessage(message);
break;
}
}
}
}
return "";
}
QString getOculusUserID(ovrID userID) {
QTimer timer;
timer.start(5000);
timer.setSingleShot(true);
auto request = ovr_User_Get(userID);
bool messageNotReceived = true;
while (messageNotReceived) {
auto message = ovr_PopMessage();
if (timer.remainingTime() == 0) {
qCDebug(oculusLog) << "login user id timeout after 5 seconds";
return "";
}
if (message != nullptr) {
switch (ovr_Message_GetType(message)) {
case ovrMessage_User_Get:
if (!ovr_Message_IsError(message)) {
messageNotReceived = false;
ovrUserHandle user = ovr_Message_GetUser(message);
ovr_FreeMessage(message);
qCDebug(oculusLog) << "UserID: " << userID << "\nOculus ID: " << QString(ovr_User_GetOculusID(user));
return QString(ovr_User_GetOculusID(user));
} else {
qDebug() << "Error getting user id: " << QString(ovr_Error_GetMessage(ovr_Message_GetError(message)));
ovr_FreeMessage(message);
return "";
}
break;
default:
ovr_FreeMessage(message);
break;
}
}
}
}
QString OculusAPIPlugin::getLoggedInUserID() {
if (initialized) {
QTimer timer;
timer.start(5000);
timer.setSingleShot(true);
auto request = ovr_User_GetLoggedInUser();
ovrMessageHandle message { nullptr };
ovrID userID = 0;
bool messageNotReceived = true;
while (messageNotReceived) {
message = ovr_PopMessage();
if (timer.remainingTime() == 0) {
qCDebug(oculusLog) << "login user id timeout after 5 seconds";
return "";
}
if (message != nullptr) {
switch (ovr_Message_GetType(message)) {
case ovrMessage_User_GetLoggedInUser:
if (!ovr_Message_IsError(message)) {
messageNotReceived = false;
ovrUserHandle user = ovr_Message_GetUser(message);
ovr_FreeMessage(message);
userID = ovr_User_GetID(user);
break;
} else {
qDebug() << "Error getting user id: " << QString(ovr_Error_GetMessage(ovr_Message_GetError(message)));
ovr_FreeMessage(message);
return "";
}
break;
default:
ovr_FreeMessage(message);
break;
}
}
}
timer.stop();
return getOculusUserID(userID);
}
return "";
}
QString OculusAPIPlugin::getOculusVRBuildID() {
return QString(OVR_MAJOR_VERSION + "." + OVR_MINOR_VERSION);
}

View file

@ -1,27 +0,0 @@
//
// 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(OculusTicketRequestCallback callback) override;
QString getUserProof() override;
QString getLoggedInUserID() override;
QString getOculusVRBuildID() override;
};

View file

@ -1,326 +0,0 @@
//
// 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;
}

View file

@ -1,127 +0,0 @@
//
// 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

View file

@ -1,40 +0,0 @@
//
// 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"

View file

@ -1 +0,0 @@
{"name":"Oculus Platform"}