Merge pull request #387 from ctrlaltdavid/feature/openvr-linux

Build OpenVR plugin on Linux
This commit is contained in:
kasenvr 2020-07-09 17:10:29 -04:00 committed by GitHub
commit cf2beb6c96
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 218 additions and 78 deletions

View file

@ -21,8 +21,8 @@
These dependencies need not be installed manually. They are automatically downloaded on the platforms where they are required.
- [Bullet Physics Engine](https://github.com/bulletphysics/bullet3/releases): 2.83
- [glm](https://glm.g-truc.net/0.9.8/index.html): 0.9.8
- [Oculus SDK](https://developer.oculus.com/downloads/): 1.11 (Win32) / 0.5 (Mac)
- [OpenVR](https://github.com/ValveSoftware/openvr): 1.11.11 (Win32 only)
- [Oculus SDK](https://developer.oculus.com/downloads/): 1.11 (Windows) / 0.5 (Mac)
- [OpenVR](https://github.com/ValveSoftware/openvr): 1.11.11 (Windows, Linux)
- [Polyvox](http://www.volumesoffun.com/): 0.2.1
- [QuaZip](https://sourceforge.net/projects/quazip/files/quazip/): 0.7.3
- [SDL2](https://www.libsdl.org/download-2.0.php): 2.0.3

View file

@ -1,4 +1,4 @@
Source: hifi-client-deps
Version: 0.1
Description: Collected dependencies for High Fidelity applications
Build-Depends: hifi-deps, aristo (windows), glslang, liblo (windows), nlohmann-json, openvr (windows), quazip (!android), sdl2 (!android), spirv-cross (!android), spirv-tools (!android), sranipal (windows), vulkanmemoryallocator
Build-Depends: hifi-deps, aristo (windows), glslang, liblo (windows), nlohmann-json, openvr (linux|windows), quazip (!android), sdl2 (!android), spirv-cross (!android), spirv-tools (!android), sranipal (windows), vulkanmemoryallocator

View file

@ -11,15 +11,23 @@ vcpkg_from_github(
set(VCPKG_LIBRARY_LINKAGE dynamic)
if(VCPKG_TARGET_ARCHITECTURE STREQUAL "x64")
set(ARCH_PATH "win64")
if(WIN32)
set(ARCH_PATH "win64")
else()
set(ARCH_PATH "linux64")
endif()
elseif(VCPKG_TARGET_ARCHITECTURE STREQUAL "x86")
set(ARCH_PATH "win32")
if(WIN32)
set(ARCH_PATH "win32")
else()
set(ARCH_PATH "linux32")
endif()
else()
message(FATAL_ERROR "Package only supports x64 and x86 windows.")
message(FATAL_ERROR "Package only supports x64 and x86 Windows and Linux.")
endif()
if(VCPKG_CMAKE_SYSTEM_NAME)
message(FATAL_ERROR "Package only supports windows desktop.")
if(VCPKG_CMAKE_SYSTEM_NAME AND NOT (VCPKG_CMAKE_SYSTEM_NAME STREQUAL "Linux"))
message(FATAL_ERROR "Package only supports Windows or Linux desktop.")
endif()
file(MAKE_DIRECTORY
@ -28,18 +36,35 @@ file(MAKE_DIRECTORY
${CURRENT_PACKAGES_DIR}/debug/lib
${CURRENT_PACKAGES_DIR}/debug/bin
)
file(COPY ${SOURCE_PATH}/lib/${ARCH_PATH}/openvr_api.lib DESTINATION ${CURRENT_PACKAGES_DIR}/lib)
file(COPY ${SOURCE_PATH}/lib/${ARCH_PATH}/openvr_api.lib DESTINATION ${CURRENT_PACKAGES_DIR}/debug/lib)
file(COPY
${SOURCE_PATH}/bin/${ARCH_PATH}/openvr_api.dll
${SOURCE_PATH}/bin/${ARCH_PATH}/openvr_api.pdb
DESTINATION ${CURRENT_PACKAGES_DIR}/bin
)
file(COPY
${SOURCE_PATH}/bin/${ARCH_PATH}/openvr_api.dll
${SOURCE_PATH}/bin/${ARCH_PATH}/openvr_api.pdb
DESTINATION ${CURRENT_PACKAGES_DIR}/debug/bin
)
if(WIN32)
file(COPY ${SOURCE_PATH}/lib/${ARCH_PATH}/openvr_api.lib DESTINATION ${CURRENT_PACKAGES_DIR}/lib)
file(COPY ${SOURCE_PATH}/lib/${ARCH_PATH}/openvr_api.lib DESTINATION ${CURRENT_PACKAGES_DIR}/debug/lib)
file(COPY
${SOURCE_PATH}/bin/${ARCH_PATH}/openvr_api.dll
${SOURCE_PATH}/bin/${ARCH_PATH}/openvr_api.pdb
DESTINATION ${CURRENT_PACKAGES_DIR}/bin
)
file(COPY
${SOURCE_PATH}/bin/${ARCH_PATH}/openvr_api.dll
${SOURCE_PATH}/bin/${ARCH_PATH}/openvr_api.pdb
DESTINATION ${CURRENT_PACKAGES_DIR}/debug/bin
)
else()
file(COPY ${SOURCE_PATH}/lib/${ARCH_PATH}/libopenvr_api.so DESTINATION ${CURRENT_PACKAGES_DIR}/lib)
file(COPY ${SOURCE_PATH}/lib/${ARCH_PATH}/libopenvr_api.so DESTINATION ${CURRENT_PACKAGES_DIR}/debug/lib)
file(COPY
${SOURCE_PATH}/bin/${ARCH_PATH}/libopenvr_api.so
${SOURCE_PATH}/bin/${ARCH_PATH}/libopenvr_api.so.dbg
DESTINATION ${CURRENT_PACKAGES_DIR}/bin
)
file(COPY
${SOURCE_PATH}/bin/${ARCH_PATH}/libopenvr_api.so
${SOURCE_PATH}/bin/${ARCH_PATH}/libopenvr_api.so.dbg
DESTINATION ${CURRENT_PACKAGES_DIR}/debug/bin
)
endif()
file(COPY ${SOURCE_PATH}/headers DESTINATION ${CURRENT_PACKAGES_DIR})
file(RENAME ${CURRENT_PACKAGES_DIR}/headers ${CURRENT_PACKAGES_DIR}/include)

View file

@ -1,12 +1,13 @@
#
# Created by Bradley Austin Davis on 2015/11/18
# Copyright 2015 High Fidelity, Inc.
# Copyright 2020 Vircadia contributors.
#
# 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 ((WIN32 OR UNIX AND NOT APPLE) AND NOT USE_GLES)
set(TARGET_NAME openvr)
setup_hifi_plugin(Gui Qml Multimedia)
link_hifi_libraries(shared task gl qml networking controllers ui
@ -15,7 +16,9 @@ if (WIN32 AND (NOT USE_GLES))
include_hifi_library_headers(octree)
target_openvr()
target_sranipal()
target_aristo()
target_link_libraries(${TARGET_NAME} Winmm.lib)
if (WIN32)
target_sranipal()
target_aristo()
target_link_libraries(${TARGET_NAME} Winmm.lib)
endif()
endif()

View file

@ -1,6 +1,7 @@
//
// Created by Bradley Austin Davis on 2015/05/12
// Copyright 2015 High Fidelity, Inc.
// Copyright 2020 Vircadia contributors.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
@ -739,6 +740,8 @@ int OpenVrDisplayPlugin::getRequiredThreadCount() const {
QString OpenVrDisplayPlugin::getPreferredAudioInDevice() const {
QString device = getVrSettingString(vr::k_pch_audio_Section, vr::k_pch_audio_RecordingDeviceOverride_String);
// FIXME: Address Linux.
#ifdef Q_OS_WIN
if (!device.isEmpty()) {
static const WCHAR INIT = 0;
size_t size = device.size() + 1;
@ -748,11 +751,14 @@ QString OpenVrDisplayPlugin::getPreferredAudioInDevice() const {
// FIXME: This may not be necessary if vr::k_pch_audio_RecordingDeviceOverride_StringName is used above.
device = AudioClient::getWinDeviceName(deviceW.data());
}
#endif
return device;
}
QString OpenVrDisplayPlugin::getPreferredAudioOutDevice() const {
QString device = getVrSettingString(vr::k_pch_audio_Section, vr::k_pch_audio_PlaybackDeviceOverride_String);
// FIXME: Address Linux.
#ifdef Q_OS_WIN
if (!device.isEmpty()) {
static const WCHAR INIT = 0;
size_t size = device.size() + 1;
@ -762,6 +768,7 @@ QString OpenVrDisplayPlugin::getPreferredAudioOutDevice() const {
// FIXME: This may not be necessary if vr::k_pch_audio_PlaybackDeviceOverride_StringName is used above.
device = AudioClient::getWinDeviceName(deviceW.data());
}
#endif
return device;
}

View file

@ -1,6 +1,7 @@
//
// Created by Bradley Austin Davis on 2015/11/01
// Copyright 2015 High Fidelity, Inc.
// Copyright 2020 Vircadia contributors.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
@ -18,8 +19,6 @@
#include <QtGui/QInputMethodEvent>
#include <QtQuick/QQuickWindow>
#include <PathUtils.h>
#include <Windows.h>
#include <OffscreenUi.h>
#include <controllers/Pose.h>
#include <NumericalConstants.h>
@ -51,7 +50,7 @@ static const uint32_t RELEASE_OPENVR_HMD_DELAY_MS = 5000;
bool isOculusPresent() {
bool result = false;
#if defined(Q_OS_WIN32)
#ifdef Q_OS_WIN
HANDLE oculusServiceEvent = ::OpenEventW(SYNCHRONIZE, FALSE, L"OculusHMDConnected");
// The existence of the service indicates a running Oculus runtime
if (oculusServiceEvent) {
@ -208,8 +207,10 @@ void finishOpenVrKeyboardInput() {
updateFromOpenVrKeyboardInput();
// Simulate an enter press on the top level window to trigger the action
if (0 == (_currentHints & Qt::ImhMultiLine)) {
qApp->sendEvent(offscreenUi->getWindow(), &QKeyEvent(QEvent::KeyPress, Qt::Key_Return, Qt::KeyboardModifiers(), QString("\n")));
qApp->sendEvent(offscreenUi->getWindow(), &QKeyEvent(QEvent::KeyRelease, Qt::Key_Return, Qt::KeyboardModifiers()));
auto keyPress = QKeyEvent(QEvent::KeyPress, Qt::Key_Return, Qt::KeyboardModifiers(), QString("\n"));
auto keyRelease = QKeyEvent(QEvent::KeyRelease, Qt::Key_Return, Qt::KeyboardModifiers());
qApp->sendEvent(offscreenUi->getWindow(), &keyPress);
qApp->sendEvent(offscreenUi->getWindow(), &keyRelease);
}
}
@ -293,11 +294,20 @@ void handleOpenVrEvents() {
ulong promitySensorFlag = (1UL << ((int)vr::k_EButton_ProximitySensor));
_headInHeadset = (controllerState.ulButtonPressed & promitySensorFlag) == promitySensorFlag;
}
}
#if DEV_BUILD
qDebug() << "OpenVR: Event " << activeHmd->GetEventTypeNameFromEnum((vr::EVREventType)event.eventType) << "(" << event.eventType << ")";
//qDebug() << "OpenVR: Event " << activeHmd->GetEventTypeNameFromEnum((vr::EVREventType)event.eventType) << "(" << event.eventType << ")";
// FIXME: Reinstate the line above and remove the following lines once the problem with excessive occurrences of
// VREvent_ActionBindingReloaded events is fixed in SteamVR for Linux.
// https://github.com/ValveSoftware/SteamVR-for-Linux/issues/307
#ifdef Q_OS_LINUX
if (event.eventType != vr::VREvent_ActionBindingReloaded) {
qDebug() << "OpenVR: Event " << activeHmd->GetEventTypeNameFromEnum((vr::EVREventType)event.eventType) << "(" << event.eventType << ")";
};
#else
qDebug() << "OpenVR: Event " << activeHmd->GetEventTypeNameFromEnum((vr::EVREventType)event.eventType) << "(" << event.eventType << ")";
#endif
#endif
}
@ -407,9 +417,32 @@ void showMinSpecWarning() {
qFatal("Unable to create overlay");
}
// Needed here for PathUtils
#ifdef Q_OS_LINUX
QFile cmdlineFile("/proc/self/cmdline");
if (!cmdlineFile.open(QIODevice::ReadOnly)) {
qFatal("Unable to open /proc/self/cmdline");
}
auto contents = cmdlineFile.readAll();
auto arguments = contents.split('\0');
arguments.pop_back(); // Last element is empty.
cmdlineFile.close();
int __argc = arguments.count();
char** __argv = new char* [__argc];
for (int i = 0; i < __argc; i++) {
__argv[i] = arguments[i].data();
}
#endif
QCoreApplication miniApp(__argc, __argv);
#ifdef Q_OS_LINUX
QObject::connect(&miniApp, &QCoreApplication::destroyed, [=] {
delete[] __argv;
});
#endif
vrSystem->ResetSeatedZeroPose();
QString imagePath = PathUtils::resourcesPath() + "/images/steam-min-spec-failed.png";
vrOverlay->SetOverlayFromFile(minSpecFailedOverlay, imagePath.toLocal8Bit().toStdString().c_str());
@ -487,7 +520,12 @@ bool checkMinSpecImpl() {
}
extern "C" {
#if defined(Q_OS_WIN32)
__declspec(dllexport) int __stdcall CheckMinSpec() {
#else
__attribute__((visibility("default"))) int CheckMinSpec() {
#endif
return checkMinSpecImpl() ? 1 : 0;
}
}

View file

@ -1,6 +1,7 @@
//
// Created by Bradley Austin Davis on 2015/06/12
// Copyright 2015 High Fidelity, Inc.
// Copyright 2020 Vircadia contributors.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
@ -76,7 +77,7 @@ struct PoseData {
}
void update(const glm::mat4& resetMat) {
for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) {
for (uint32_t i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) {
if (!vrPoses[i].bPoseIsValid) {
continue;
}
@ -87,7 +88,7 @@ struct PoseData {
}
void resetToInvalid() {
for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) {
for (uint32_t i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) {
vrPoses[i].bPoseIsValid = false;
}
}

View file

@ -1,9 +1,9 @@
//
// ViveControllerManager.cpp
// input-plugins/src/input-plugins
//
// Created by Sam Gondelman on 6/29/15.
// Copyright 2013 High Fidelity, Inc.
// Copyright 2020 Vircadia contributors.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
@ -19,10 +19,12 @@
#pragma warning( disable : 4334 )
#endif
#ifdef VIVE_PRO_EYE
#include <SRanipal.h>
#include <SRanipal_Eye.h>
#include <SRanipal_Enums.h>
#include <interface_gesture.hpp>
#endif
#ifdef _WIN32
#pragma warning( pop )
@ -49,7 +51,7 @@
#include <plugins/DisplayPlugin.h>
#include <controllers/UserInputMapper.h>
#include <Plugins/InputConfiguration.h>
#include <plugins/InputConfiguration.h>
#include <controllers/StandardControls.h>
#include "OpenVrDisplayPlugin.h"
@ -60,13 +62,8 @@ vr::IVRSystem* acquireOpenVrSystem();
void releaseOpenVrSystem();
static const QString OPENVR_LAYOUT = QString("OpenVrConfiguration.qml");
static const char* CONTROLLER_MODEL_STRING = "vr_controller_05_wireless_b";
const quint64 CALIBRATION_TIMELAPSE = 1 * USECS_PER_SECOND;
static const char* MENU_PARENT = "Avatar";
static const char* MENU_NAME = "Vive Controllers";
static const char* MENU_PATH = "Avatar" ">" "Vive Controllers";
static const int MIN_HEAD = 1;
static const int MIN_PUCK_COUNT = 2;
static const int MIN_FEET_AND_HIPS = 3;
@ -79,6 +76,7 @@ static const int SECOND_FOOT = 1;
static const int HIP = 2;
static const int CHEST = 3;
#ifdef VIVE_PRO_EYE
enum ViveHandJointIndex {
HAND = 0,
THUMB_1,
@ -104,6 +102,7 @@ enum ViveHandJointIndex {
Size
};
#endif
const char* ViveControllerManager::NAME { "OpenVR" };
@ -157,22 +156,7 @@ static QString deviceTrackingResultToString(vr::ETrackingResult trackingResult)
return result;
}
static glm::mat4 calculateResetMat() {
auto chaperone = vr::VRChaperone();
if (chaperone) {
float const UI_RADIUS = 1.0f;
float const UI_HEIGHT = 1.6f;
float const UI_Z_OFFSET = 0.5;
float xSize, zSize;
chaperone->GetPlayAreaSize(&xSize, &zSize);
glm::vec3 uiPos(0.0f, UI_HEIGHT, UI_RADIUS - (0.5f * zSize) - UI_Z_OFFSET);
return glm::inverse(createMatFromQuatAndPos(glm::quat(), uiPos));
}
return glm::mat4();
}
#ifdef VIVE_PRO_EYE
class ViveProEyeReadThread : public QThread {
public:
ViveProEyeReadThread() {
@ -216,6 +200,7 @@ public:
QMutex eyeDataMutex;
EyeDataBuffer eyeDataBuffer;
};
#endif
static QString outOfRangeDataStrategyToString(ViveControllerManager::OutOfRangeDataStrategy strategy) {
@ -328,7 +313,7 @@ bool areBothHandControllersActive(vr::IVRSystem*& system) {
isHandControllerActive(system, vr::TrackedControllerRole_RightHand);
}
#ifdef VIVE_PRO_EYE
void ViveControllerManager::enableGestureDetection() {
if (_viveCameraHandTracker) {
return;
@ -373,6 +358,7 @@ void ViveControllerManager::disableGestureDetection() {
StopGestureDetection();
_viveCameraHandTracker = false;
}
#endif
bool ViveControllerManager::activate() {
InputPlugin::activate();
@ -394,6 +380,7 @@ bool ViveControllerManager::activate() {
userInputMapper->registerDevice(_inputDevice);
_registeredWithInputMapper = true;
#ifdef VIVE_PRO_EYE
if (ViveSR::anipal::Eye::IsViveProEye()) {
qDebug() << "Vive Pro eye-tracking detected";
@ -414,6 +401,7 @@ bool ViveControllerManager::activate() {
_viveProEyeReadThread->start(QThread::HighPriority);
}
}
#endif
return true;
}
@ -436,12 +424,14 @@ void ViveControllerManager::deactivate() {
userInputMapper->removeDevice(_inputDevice->_deviceID);
_registeredWithInputMapper = false;
#ifdef VIVE_PRO_EYE
if (_viveProEyeReadThread) {
_viveProEyeReadThread->quit = true;
_viveProEyeReadThread->wait();
_viveProEyeReadThread = nullptr;
ViveSR::anipal::Release(ViveSR::anipal::Eye::ANIPAL_TYPE_EYE);
}
#endif
saveSettings();
}
@ -454,6 +444,7 @@ bool ViveControllerManager::isHeadControllerMounted() const {
return activityLevel == vr::k_EDeviceActivityLevel_UserInteraction;
}
#ifdef VIVE_PRO_EYE
void ViveControllerManager::invalidateEyeInputs() {
_inputDevice->_poseStateMap[controller::LEFT_EYE].valid = false;
_inputDevice->_poseStateMap[controller::RIGHT_EYE].valid = false;
@ -461,7 +452,6 @@ void ViveControllerManager::invalidateEyeInputs() {
_inputDevice->_axisStateMap[controller::EYEBLINK_R].valid = false;
}
void ViveControllerManager::updateEyeTracker(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) {
if (!isHeadControllerMounted()) {
invalidateEyeInputs();
@ -763,6 +753,7 @@ void ViveControllerManager::updateCameraHandTracker(float deltaTime,
}
_lastHandTrackerFrameIndex = handTrackerFrameIndex;
}
#endif
void ViveControllerManager::pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) {
@ -801,11 +792,14 @@ void ViveControllerManager::pluginUpdate(float deltaTime, const controller::Inpu
_registeredWithInputMapper = true;
}
#ifdef VIVE_PRO_EYE
if (_viveProEye) {
updateEyeTracker(deltaTime, inputCalibrationData);
}
updateCameraHandTracker(deltaTime, inputCalibrationData);
#endif
}
void ViveControllerManager::loadSettings() {
@ -879,7 +873,7 @@ void ViveControllerManager::InputDevice::update(float deltaTime, const controlle
handleHandController(deltaTime, rightHandDeviceIndex, inputCalibrationData, false);
// collect poses for all generic trackers
for (int i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) {
for (uint32_t i = 0; i < vr::k_unMaxTrackedDeviceCount; i++) {
handleTrackedObject(i, inputCalibrationData);
handleHmd(i, inputCalibrationData);
}
@ -954,8 +948,8 @@ void ViveControllerManager::InputDevice::configureCalibrationSettings(const QJso
bool overrideHead = headObject["override"].toBool();
if (overrideHead) {
_headConfig = HeadConfig::Puck;
_headPuckYOffset = headObject["Y"].toDouble() * CM_TO_M;
_headPuckZOffset = headObject["Z"].toDouble() * CM_TO_M;
_headPuckYOffset = (float)headObject["Y"].toDouble() * CM_TO_M;
_headPuckZOffset = (float)headObject["Z"].toDouble() * CM_TO_M;
} else {
_headConfig = HeadConfig::HMD;
}
@ -964,8 +958,8 @@ void ViveControllerManager::InputDevice::configureCalibrationSettings(const QJso
bool overrideHands = handsObject["override"].toBool();
if (overrideHands) {
_handConfig = HandConfig::Pucks;
_handPuckYOffset = handsObject["Y"].toDouble() * CM_TO_M;
_handPuckZOffset = handsObject["Z"].toDouble() * CM_TO_M;
_handPuckYOffset = (float)handsObject["Y"].toDouble() * CM_TO_M;
_handPuckZOffset = (float)handsObject["Z"].toDouble() * CM_TO_M;
} else {
_handConfig = HandConfig::HandController;
}
@ -999,8 +993,8 @@ QJsonObject ViveControllerManager::InputDevice::configurationSettings() {
configurationSettings["HMDHead"] = (_headConfig == HeadConfig::HMD);
configurationSettings["handController"] = (_handConfig == HandConfig::HandController);
configurationSettings["puckCount"] = (int)_validTrackedObjects.size();
configurationSettings["armCircumference"] = (double)_armCircumference * M_TO_CM;
configurationSettings["shoulderWidth"] = (double)_shoulderWidth * M_TO_CM;
configurationSettings["armCircumference"] = (double)(_armCircumference * M_TO_CM);
configurationSettings["shoulderWidth"] = (double)(_shoulderWidth * M_TO_CM);
configurationSettings["outOfRangeDataStrategy"] = outOfRangeDataStrategyToString(_outOfRangeDataStrategy);
return configurationSettings;
}
@ -1217,8 +1211,6 @@ bool ViveControllerManager::InputDevice::configureHead(const glm::mat4& defaultT
bool ViveControllerManager::InputDevice::configureBody(const glm::mat4& defaultToReferenceMat, const controller::InputCalibrationData& inputCalibration) {
std::sort(_validTrackedObjects.begin(), _validTrackedObjects.end(), sortPucksYPosition);
int puckCount = (int)_validTrackedObjects.size();
glm::vec3 headXAxis = getReferenceHeadXAxis(defaultToReferenceMat, inputCalibration.defaultHeadMat);
glm::vec3 headPosition = getReferenceHeadPosition(defaultToReferenceMat, inputCalibration.defaultHeadMat);
if (_config == Config::None) {
return true;
} else if (_config == Config::Feet && puckCount >= MIN_PUCK_COUNT) {
@ -1316,8 +1308,6 @@ controller::Pose ViveControllerManager::InputDevice::addOffsetToPuckPose(const c
}
void ViveControllerManager::InputDevice::handleHmd(uint32_t deviceIndex, const controller::InputCalibrationData& inputCalibrationData) {
uint32_t poseIndex = controller::TRACKED_OBJECT_00 + deviceIndex;
if (_system->IsTrackedDeviceConnected(deviceIndex) &&
_system->GetTrackedDeviceClass(deviceIndex) == vr::TrackedDeviceClass_HMD &&
_nextSimPoseData.vrPoses[deviceIndex].bPoseIsValid) {
@ -1491,11 +1481,11 @@ void ViveControllerManager::InputDevice::printDeviceTrackingResultChange(uint32_
}
bool ViveControllerManager::InputDevice::checkForCalibrationEvent() {
auto& endOfMap = _buttonPressedMap.end();
auto& leftTrigger = _buttonPressedMap.find(controller::LT);
auto& rightTrigger = _buttonPressedMap.find(controller::RT);
auto& leftAppButton = _buttonPressedMap.find(LEFT_APP_MENU);
auto& rightAppButton = _buttonPressedMap.find(RIGHT_APP_MENU);
auto endOfMap = _buttonPressedMap.end();
auto leftTrigger = _buttonPressedMap.find(controller::LT);
auto rightTrigger = _buttonPressedMap.find(controller::RT);
auto leftAppButton = _buttonPressedMap.find(LEFT_APP_MENU);
auto rightAppButton = _buttonPressedMap.find(RIGHT_APP_MENU);
return ((leftTrigger != endOfMap && leftAppButton != endOfMap) && (rightTrigger != endOfMap && rightAppButton != endOfMap));
}
@ -1846,10 +1836,74 @@ void ViveControllerManager::InputDevice::setConfigFromString(const QString& valu
* <tr><td><code>Hips</code></td><td>number</td><td>{@link Pose}</td><td>Hips pose.</td></tr>
* <tr><td><code>Spine2</code></td><td>number</td><td>{@link Pose}</td><td>Spine2 pose.</td></tr>
* <tr><td><code>Head</code></td><td>number</td><td>{@link Pose}</td><td>Head pose.</td></tr>
* <tr><td><code>LeftEye</code></td><td>number</td><td>{@link Pose}</td><td>Left eye pose.</td></tr>
* <tr><td><code>RightEye</code></td><td>number</td><td>{@link Pose}</td><td>Right eye pose.</td></tr>
* <tr><td><code>EyeBlink_L</code></td><td>number</td><td>number</td><td>Left eyelid blink.</td></tr>
* <tr><td><code>EyeBlink_R</code></td><td>number</td><td>number</td><td>Right eyelid blink.</td></tr>
* <tr><td><code>LeftArm</code></td><td>number</td><td>{@link Pose}</td><td>Left arm pose.</td></tr>
* <tr><td><code>RightArm</code></td><td>number</td><td>{@link Pose}</td><td>Right arm pose</td></tr>
* <tr><td><code>LeftHand</code></td><td>number</td><td>{@link Pose}</td><td>Left hand pose.</td></tr>
* <tr><td><code>LeftHandThumb1</code></td><td>number</td><td>{@link Pose}</td><td>Left thumb 1 finger joint pose.</td></tr>
* <tr><td><code>LeftHandThumb2</code></td><td>number</td><td>{@link Pose}</td><td>Left thumb 2 finger joint pose.</td></tr>
* <tr><td><code>LeftHandThumb3</code></td><td>number</td><td>{@link Pose}</td><td>Left thumb 3 finger joint pose.</td></tr>
* <tr><td><code>LeftHandThumb4</code></td><td>number</td><td>{@link Pose}</td><td>Left thumb 4 finger joint pose.</td></tr>
* <tr><td><code>LeftHandIndex1</code></td><td>number</td><td>{@link Pose}</td><td>Left index 1 finger joint pose.</td></tr>
* <tr><td><code>LeftHandIndex2</code></td><td>number</td><td>{@link Pose}</td><td>Left index 2 finger joint pose.</td></tr>
* <tr><td><code>LeftHandIndex3</code></td><td>number</td><td>{@link Pose}</td><td>Left index 3 finger joint pose.</td></tr>
* <tr><td><code>LeftHandIndex4</code></td><td>number</td><td>{@link Pose}</td><td>Left index 4 finger joint pose.</td></tr>
* <tr><td><code>LeftHandMiddle1</code></td><td>number</td><td>{@link Pose}</td><td>Left middle 1 finger joint pose.
* </td></tr>
* <tr><td><code>LeftHandMiddle2</code></td><td>number</td><td>{@link Pose}</td><td>Left middle 2 finger joint pose.
* </td></tr>
* <tr><td><code>LeftHandMiddle3</code></td><td>number</td><td>{@link Pose}</td><td>Left middle 3 finger joint pose.
* </td></tr>
* <tr><td><code>LeftHandMiddle4</code></td><td>number</td><td>{@link Pose}</td><td>Left middle 4 finger joint pose.
* </td></tr>
* <tr><td><code>LeftHandRing1</code></td><td>number</td><td>{@link Pose}</td><td>Left ring 1 finger joint pose.</td></tr>
* <tr><td><code>LeftHandRing2</code></td><td>number</td><td>{@link Pose}</td><td>Left ring 2 finger joint pose.</td></tr>
* <tr><td><code>LeftHandRing3</code></td><td>number</td><td>{@link Pose}</td><td>Left ring 3 finger joint pose.</td></tr>
* <tr><td><code>LeftHandRing4</code></td><td>number</td><td>{@link Pose}</td><td>Left ring 4 finger joint pose.</td></tr>
* <tr><td><code>LeftHandPinky1</code></td><td>number</td><td>{@link Pose}</td><td>Left pinky 1 finger joint pose.</td></tr>
* <tr><td><code>LeftHandPinky2</code></td><td>number</td><td>{@link Pose}</td><td>Left pinky 2 finger joint pose.</td></tr>
* <tr><td><code>LeftHandPinky3</code></td><td>number</td><td>{@link Pose}</td><td>Left pinky 3 finger joint pose.</td></tr>
* <tr><td><code>LeftHandPinky4</code></td><td>number</td><td>{@link Pose}</td><td>Left pinky 4 finger joint pose.</td></tr>
* <tr><td><code>RightHand</code></td><td>number</td><td>{@link Pose}</td><td>Right hand pose.</td></tr>
* <tr><td><code>RightHandThumb1</code></td><td>number</td><td>{@link Pose}</td><td>Right thumb 1 finger joint pose.
* </td></tr>
* <tr><td><code>RightHandThumb2</code></td><td>number</td><td>{@link Pose}</td><td>Right thumb 2 finger joint pose.
* </td></tr>
* <tr><td><code>RightHandThumb3</code></td><td>number</td><td>{@link Pose}</td><td>Right thumb 3 finger joint pose.
* </td></tr>
* <tr><td><code>RightHandThumb4</code></td><td>number</td><td>{@link Pose}</td><td>Right thumb 4 finger joint pose.
* </td></tr>
* <tr><td><code>RightHandIndex1</code></td><td>number</td><td>{@link Pose}</td><td>Right index 1 finger joint pose.
* </td></tr>
* <tr><td><code>RightHandIndex2</code></td><td>number</td><td>{@link Pose}</td><td>Right index 2 finger joint pose.
* </td></tr>
* <tr><td><code>RightHandIndex3</code></td><td>number</td><td>{@link Pose}</td><td>Right index 3 finger joint pose.
* </td></tr>
* <tr><td><code>RightHandIndex4</code></td><td>number</td><td>{@link Pose}</td><td>Right index 4 finger joint pose.
* </td></tr>
* <tr><td><code>RightHandMiddle1</code></td><td>number</td><td>{@link Pose}</td><td>Right middle 1 finger joint pose.
* </td></tr>
* <tr><td><code>RightHandMiddle2</code></td><td>number</td><td>{@link Pose}</td><td>Right middle 2 finger joint pose.
* </td></tr>
* <tr><td><code>RightHandMiddle3</code></td><td>number</td><td>{@link Pose}</td><td>Right middle 3 finger joint pose.
* </td></tr>
* <tr><td><code>RightHandMiddle4</code></td><td>number</td><td>{@link Pose}</td><td>Right middle 4 finger joint pose.
* </td></tr>
* <tr><td><code>RightHandRing1</code></td><td>number</td><td>{@link Pose}</td><td>Right ring 1 finger joint pose.</td></tr>
* <tr><td><code>RightHandRing2</code></td><td>number</td><td>{@link Pose}</td><td>Right ring 2 finger joint pose.</td></tr>
* <tr><td><code>RightHandRing3</code></td><td>number</td><td>{@link Pose}</td><td>Right ring 3 finger joint pose.</td></tr>
* <tr><td><code>RightHandRing4</code></td><td>number</td><td>{@link Pose}</td><td>Right ring 4 finger joint pose.</td></tr>
* <tr><td><code>RightHandPinky1</code></td><td>number</td><td>{@link Pose}</td><td>Right pinky 1 finger joint pose.
* </td></tr>
* <tr><td><code>RightHandPinky2</code></td><td>number</td><td>{@link Pose}</td><td>Right pinky 2 finger joint pose.
* </td></tr>
* <tr><td><code>RightHandPinky3</code></td><td>number</td><td>{@link Pose}</td><td>Right pinky 3 finger joint pose.
* </td></tr>
* <tr><td><code>RightHandPinky4</code></td><td>number</td><td>{@link Pose}</td><td>Right pinky 4 finger joint pose.
* </td></tr>
* <tr><td colspan="4"><strong>Trackers</strong></td></tr>
* <tr><td><code>TrackedObject00</code></td><td>number</td><td>{@link Pose}</td><td>Tracker 0 pose.</td></tr>
* <tr><td><code>TrackedObject01</code></td><td>number</td><td>{@link Pose}</td><td>Tracker 1 pose.</td></tr>

View file

@ -1,9 +1,9 @@
//
// ViveControllerManager.h
// input-plugins/src/input-plugins
//
// Created by Sam Gondelman on 6/29/15.
// Copyright 2013 High Fidelity, Inc.
// Copyright 2020 Vircadia contributors.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
@ -25,12 +25,18 @@
#include <plugins/InputPlugin.h>
#include "OpenVrHelpers.h"
#ifdef Q_OS_WIN
#define VIVE_PRO_EYE
#endif
using PuckPosePair = std::pair<uint32_t, controller::Pose>;
namespace vr {
class IVRSystem;
}
#ifdef VIVE_PRO_EYE
class ViveProEyeReadThread;
class EyeDataBuffer {
@ -45,7 +51,7 @@ public:
float leftEyeOpenness { 0.0f };
float rightEyeOpenness { 0.0f };
};
#endif
class ViveControllerManager : public InputPlugin {
@ -66,18 +72,22 @@ public:
bool isHeadController() const override { return true; }
bool isHeadControllerMounted() const;
#ifdef VIVE_PRO_EYE
void enableGestureDetection();
void disableGestureDetection();
#endif
bool activate() override;
void deactivate() override;
QString getDeviceName() { return QString::fromStdString(_inputDevice->_headsetName); }
QString getDeviceName() override { return QString::fromStdString(_inputDevice->_headsetName); }
void pluginFocusOutEvent() override { _inputDevice->focusOutEvent(); }
#ifdef VIVE_PRO_EYE
void invalidateEyeInputs();
void updateEyeTracker(float deltaTime, const controller::InputCalibrationData& inputCalibrationData);
void updateCameraHandTracker(float deltaTime, const controller::InputCalibrationData& inputCalibrationData);
#endif
void pluginUpdate(float deltaTime, const controller::InputCalibrationData& inputCalibrationData) override;
virtual void saveSettings() const override;
@ -252,6 +262,7 @@ private:
vr::IVRSystem* _system { nullptr };
std::shared_ptr<InputDevice> _inputDevice { std::make_shared<InputDevice>(_system) };
#ifdef VIVE_PRO_EYE
bool _viveProEye { false };
std::shared_ptr<ViveProEyeReadThread> _viveProEyeReadThread;
EyeDataBuffer _prevEyeData;
@ -268,6 +279,7 @@ private:
void trackFinger(int hand, int jointIndex1, int jointIndex2, int jointIndex3, int jointIndex4,
controller::StandardPoseChannel joint1, controller::StandardPoseChannel joint2,
controller::StandardPoseChannel joint3, controller::StandardPoseChannel joint4);
#endif
static const char* NAME;
};