diff --git a/CMakeLists.txt b/CMakeLists.txt index 6e1c3a70..488a98f7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -39,11 +39,12 @@ execute_process( find_library(OPENVR_LIB openvr_api HINTS "${CMAKE_CURRENT_SOURCE_DIR}/libraries/openvr/lib/${PLATFORM_NAME}${PROCESSOR_ARCH}/" NO_DEFAULT_PATH ) -add_subdirectory("overlay") set(DRIVER_NAME "openglove") set(OPENGLOVE_PROJECT "driver_${DRIVER_NAME}") +add_subdirectory("overlay") + file(GLOB_RECURSE HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/include/*.h") file(GLOB_RECURSE SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp") @@ -59,7 +60,7 @@ target_compile_definitions("${OPENGLOVE_PROJECT}" PRIVATE source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}/include" PREFIX "Header Files" FILES ${HEADERS}) source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}/src" PREFIX "Source Files" FILES ${SOURCES}) -set_property(TARGET "${OPENGLOVE_PROJECT}" PROPERTY CXX_STANDARD 17) +set_property(TARGET "${OPENGLOVE_PROJECT}" PROPERTY CXX_STANDARD 20) # Copy driver assets to output folder @@ -78,12 +79,4 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E copy $ $/${DRIVER_NAME}/bin/${PLATFORM_NAME}${PROCESSOR_ARCH}/$ -) - -add_custom_command( - TARGET ${OPENGLOVE_PROJECT} - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_directory - $ - $/${DRIVER_NAME}/bin/${PLATFORM_NAME}${PROCESSOR_ARCH} ) \ No newline at end of file diff --git a/include/Communication/BTSerialCommunicationManager.h b/include/Communication/BTSerialCommunicationManager.h index 9abc909d..2951ddf3 100644 --- a/include/Communication/BTSerialCommunicationManager.h +++ b/include/Communication/BTSerialCommunicationManager.h @@ -13,8 +13,7 @@ class BTSerialCommunicationManager : public CommunicationManager { public: - BTSerialCommunicationManager( - std::unique_ptr encodingManager, VRBTSerialConfiguration configuration, const VRDeviceConfiguration& deviceConfiguration); + BTSerialCommunicationManager(const VRCommunicationConfiguration& configuration, std::unique_ptr encodingManager); bool IsConnected() override; @@ -31,9 +30,9 @@ class BTSerialCommunicationManager : public CommunicationManager { bool GetPairedDeviceBtAddress(BTH_ADDR* deviceBtAddress); bool StartupWindowsSocket(); - VRBTSerialConfiguration btSerialConfiguration_; + VRCommunicationBTSerialConfiguration btSerialConfiguration_; - std::atomic isConnected_; + std::atomic isConnected_ = false; - std::atomic btClientSocket_; + std::atomic btClientSocket_ = NULL; }; \ No newline at end of file diff --git a/include/Communication/CommunicationManager.h b/include/Communication/CommunicationManager.h index 703cdff2..ef5cddf5 100644 --- a/include/Communication/CommunicationManager.h +++ b/include/Communication/CommunicationManager.h @@ -12,8 +12,8 @@ class CommunicationManager { public: - explicit CommunicationManager(const VRDeviceConfiguration& deviceConfiguration); - CommunicationManager(std::unique_ptr encodingManager, const VRDeviceConfiguration& deviceConfiguration); + explicit CommunicationManager(VRCommunicationConfiguration configuration); + CommunicationManager(VRCommunicationConfiguration configuration, std::unique_ptr encodingManager); virtual void BeginListener(const std::function& callback); virtual void Disconnect(); @@ -34,8 +34,8 @@ class CommunicationManager { virtual bool ReceiveNextPacket(std::string& buff) = 0; virtual bool SendMessageToDevice() = 0; + VRCommunicationConfiguration configuration_; std::unique_ptr encodingManager_; - VRDeviceConfiguration deviceConfiguration_; std::atomic threadActive_; std::thread thread_; diff --git a/include/Communication/NamedPipeCommunicationManager.h b/include/Communication/NamedPipeCommunicationManager.h index d37953f4..b149a5e5 100644 --- a/include/Communication/NamedPipeCommunicationManager.h +++ b/include/Communication/NamedPipeCommunicationManager.h @@ -1,8 +1,8 @@ #pragma once +#include #include #include -#include #include "Communication/CommunicationManager.h" #include "DeviceConfiguration.h" @@ -10,7 +10,7 @@ class NamedPipeCommunicationManager : public CommunicationManager { public: - NamedPipeCommunicationManager(VRNamedPipeInputConfiguration configuration, const VRDeviceConfiguration& deviceConfiguration); + NamedPipeCommunicationManager(const VRCommunicationConfiguration& configuration); bool IsConnected() override; // no sending for named pipes @@ -31,13 +31,12 @@ class NamedPipeCommunicationManager : public CommunicationManager { return true; }; - private: std::atomic isConnected_; std::function callback_; - VRNamedPipeInputConfiguration configuration_; + VRCommunicationNamedPipeConfiguration namedPipeConfiguration_; std::vector> namedPipeListeners_; }; \ No newline at end of file diff --git a/include/Communication/SerialCommunicationManager.h b/include/Communication/SerialCommunicationManager.h index 8ea585b0..1336ffe4 100644 --- a/include/Communication/SerialCommunicationManager.h +++ b/include/Communication/SerialCommunicationManager.h @@ -12,8 +12,7 @@ class SerialCommunicationManager : public CommunicationManager { public: - SerialCommunicationManager( - std::unique_ptr encodingManager, VRSerialConfiguration configuration, const VRDeviceConfiguration& deviceConfiguration); + SerialCommunicationManager(const VRCommunicationConfiguration& configuration, std::unique_ptr encodingManager); bool IsConnected() override; @@ -36,9 +35,11 @@ class SerialCommunicationManager : public CommunicationManager { unsigned long WriteTotalTimeoutMultiplier, unsigned long WriteTotalTimeoutConstant); - VRSerialConfiguration serialConfiguration_; + VRCommunicationSerialConfiguration serialConfiguration_; std::atomic isConnected_; std::atomic hSerial_; + + DWORD lastError_; }; \ No newline at end of file diff --git a/include/DeviceConfiguration.h b/include/DeviceConfiguration.h index 952e9c9b..1e3afdec 100644 --- a/include/DeviceConfiguration.h +++ b/include/DeviceConfiguration.h @@ -1,7 +1,9 @@ #pragma once -#include +#include +// quaternion used for == overloads +#include "Util/Quaternion.h" #include "openvr_driver.h" extern const char* c_poseSettingsSection; @@ -13,7 +15,7 @@ extern const char* c_lucidGloveDeviceSettingsSection; extern const char* c_alphaEncodingSettingsSection; extern const char* c_legacyEncodingSettingsSection; -extern const char* c_deviceDriverManufacturer; +extern const char* c_deviceManufacturer; enum class VRCommunicationProtocol { Serial, @@ -26,78 +28,102 @@ enum class VREncodingProtocol { Alpha = 1, }; -enum class VRDeviceDriver { +enum class VRDeviceType { LucidGloves = 0, EmulatedKnuckles = 1, }; -struct VRSerialConfiguration { +struct VRAlphaEncodingConfiguration { + bool operator==(const VRAlphaEncodingConfiguration&) const = default; +}; + +struct VRLegacyEncodingConfiguration { + bool operator==(const VRLegacyEncodingConfiguration&) const = default; +}; + +struct VREncodingConfiguration { + VREncodingProtocol encodingProtocol; + unsigned int maxAnalogValue; + + std::variant configuration; + + bool operator==(const VREncodingConfiguration&) const = default; +}; + +struct VRCommunicationSerialConfiguration { std::string port; int baudRate; - VRSerialConfiguration(std::string port, const int baudRate) : port(std::move(port)), baudRate(baudRate) {} + bool operator==(const VRCommunicationSerialConfiguration&) const = default; }; -struct VRBTSerialConfiguration { +struct VRCommunicationBTSerialConfiguration { std::string name; - explicit VRBTSerialConfiguration(std::string name) : name(std::move(name)) {} + bool operator==(const VRCommunicationBTSerialConfiguration&) const = default; }; -struct VRNamedPipeInputConfiguration { +struct VRCommunicationNamedPipeConfiguration { std::string pipeName; - VRNamedPipeInputConfiguration(std::string pipeName) : pipeName(std::move(pipeName)) {} + bool operator==(const VRCommunicationNamedPipeConfiguration&) const = default; +}; + +struct VRCommunicationConfiguration { + VRCommunicationProtocol communicationProtocol; + VREncodingConfiguration encodingConfiguration; + + bool feedbackEnabled; + + std::variant configuration; + + bool operator==(const VRCommunicationConfiguration&) const = default; }; struct VRPoseConfiguration { - vr::HmdVector3_t offsetVector; + vr::HmdVector3d_t offsetVector; vr::HmdQuaternion_t angleOffsetQuaternion; float poseTimeOffset; int controllerIdOverride; bool controllerOverrideEnabled; bool calibrationButtonEnabled; - VRPoseConfiguration( - const vr::HmdVector3_t offsetVector, - const vr::HmdQuaternion_t angleOffsetQuaternion, - const float poseTimeOffset, - const bool controllerOverrideEnabled, - const int controllerIdOverride, - const bool calibrationButtonEnabled) - : offsetVector(offsetVector), - angleOffsetQuaternion(angleOffsetQuaternion), - poseTimeOffset(poseTimeOffset), - controllerIdOverride(controllerIdOverride), - controllerOverrideEnabled(controllerOverrideEnabled), - calibrationButtonEnabled(calibrationButtonEnabled) {} + bool operator==(const VRPoseConfiguration&) const = default; +}; + +struct VRDeviceKnucklesConfiguration { + bool indexCurlTrigger; + bool approximateThumb; + + bool operator==(const VRDeviceKnucklesConfiguration&) const = default; +}; + +struct VRDeviceLucidglovesConfiguration { + std::string serialNumber; + + bool operator==(const VRDeviceLucidglovesConfiguration&) const = default; }; struct VRDeviceConfiguration { + VRDeviceType deviceType; + + std::string serialNumber; vr::ETrackedControllerRole role; - bool enabled; - bool feedbackEnabled; - bool indexCurlTrigger; + VRPoseConfiguration poseConfiguration; - VREncodingProtocol encodingProtocol; - VRCommunicationProtocol communicationProtocol; - VRDeviceDriver deviceDriver; - - VRDeviceConfiguration( - const vr::ETrackedControllerRole role, - const bool enabled, - const bool feedbackEnabled, - const bool indexCurlTrigger, - const VRPoseConfiguration poseConfiguration, - const VREncodingProtocol encodingProtocol, - const VRCommunicationProtocol communicationProtocol, - const VRDeviceDriver deviceDriver) - : role(role), - enabled(enabled), - feedbackEnabled(feedbackEnabled), - indexCurlTrigger(indexCurlTrigger), - poseConfiguration(poseConfiguration), - encodingProtocol(encodingProtocol), - communicationProtocol(communicationProtocol), - deviceDriver(deviceDriver) {} + VRCommunicationConfiguration communicationConfiguration; + + std::variant configuration; + + bool operator==(const VRDeviceConfiguration&) const = default; }; + +struct VRDriverConfiguration { + bool enabled; + + VRDeviceConfiguration deviceConfiguration; + + bool operator==(const VRDriverConfiguration&) const = default; +}; + +VRDriverConfiguration GetDriverConfiguration(const vr::ETrackedControllerRole& role); \ No newline at end of file diff --git a/include/DeviceDriver/DeviceDriver.h b/include/DeviceDriver/DeviceDriver.h index 81bfbfc9..cb0915bc 100644 --- a/include/DeviceDriver/DeviceDriver.h +++ b/include/DeviceDriver/DeviceDriver.h @@ -1,5 +1,8 @@ #pragma once +#undef _WINSOCKAPI_ +#define _WINSOCKAPI_ + #include #include @@ -7,16 +10,12 @@ #include "Communication/CommunicationManager.h" #include "ControllerPose.h" #include "DeviceConfiguration.h" -#include "openvr_driver.h" #include "ForceFeedback.h" +#include "openvr_driver.h" class DeviceDriver : public vr::ITrackedDeviceServerDriver { public: - DeviceDriver( - std::unique_ptr communicationManager, - std::shared_ptr boneAnimator, - std::string serialNumber, - VRDeviceConfiguration configuration); + DeviceDriver(VRDeviceConfiguration configuration); vr::EVRInitError Activate(uint32_t unObjectId) override; void Deactivate() override; @@ -32,6 +31,9 @@ class DeviceDriver : public vr::ITrackedDeviceServerDriver { void OnEvent(vr::VREvent_t vrEvent) const; + void UpdateDeviceConfiguration(VRDeviceConfiguration configuration); + void DisableDevice(); + protected: virtual bool IsRightHand() const; virtual void StartDevice(); @@ -42,10 +44,15 @@ class DeviceDriver : public vr::ITrackedDeviceServerDriver { virtual void StoppingDevice() = 0; void PoseUpdateThread() const; + private: + void SetupDeviceComponents(); + void StopDeviceComponents(); + + protected: std::unique_ptr communicationManager_; - std::shared_ptr boneAnimator_; + std::unique_ptr boneAnimator_; + VRDeviceConfiguration configuration_; - std::string serialNumber_; std::unique_ptr controllerPose_; std::unique_ptr ffbProvider_; @@ -57,6 +64,8 @@ class DeviceDriver : public vr::ITrackedDeviceServerDriver { std::thread poseUpdateThread_; - std::atomic hasActivated_; - uint32_t deviceId_; + std::atomic isRunning_; + std::atomic isActive_; + + int32_t deviceId_; }; \ No newline at end of file diff --git a/include/DeviceDriver/KnuckleDriver.h b/include/DeviceDriver/KnuckleDriver.h index 9684e0b1..94f527d2 100644 --- a/include/DeviceDriver/KnuckleDriver.h +++ b/include/DeviceDriver/KnuckleDriver.h @@ -38,12 +38,7 @@ enum class KnuckleDeviceComponentIndex : int { class KnuckleDeviceDriver : public DeviceDriver { public: - KnuckleDeviceDriver( - std::unique_ptr communicationManager, - std::shared_ptr boneAnimator, - std::string serialNumber, - bool approximateThumb, - VRDeviceConfiguration configuration); + KnuckleDeviceDriver(VRDeviceConfiguration configuration); void HandleInput(VRInputData data) override; void SetupProps(vr::PropertyContainerHandle_t& props) override; @@ -52,5 +47,4 @@ class KnuckleDeviceDriver : public DeviceDriver { private: vr::VRInputComponentHandle_t inputComponentHandles_[static_cast(KnuckleDeviceComponentIndex::_Count)]; - bool approximateThumb_; }; diff --git a/include/DeviceDriver/LucidGloveDriver.h b/include/DeviceDriver/LucidGloveDriver.h index e8dab7b0..24c13c53 100644 --- a/include/DeviceDriver/LucidGloveDriver.h +++ b/include/DeviceDriver/LucidGloveDriver.h @@ -29,11 +29,7 @@ enum class LucidGloveDeviceComponentIndex : int { class LucidGloveDeviceDriver : public DeviceDriver { public: - LucidGloveDeviceDriver( - std::unique_ptr communicationManager, - std::shared_ptr boneAnimator, - const std::string& serialNumber, - VRDeviceConfiguration configuration); + LucidGloveDeviceDriver(const VRDeviceConfiguration& configuration); void HandleInput(VRInputData data) override; void SetupProps(vr::PropertyContainerHandle_t& props) override; diff --git a/include/DeviceProvider.h b/include/DeviceProvider.h index fe874559..31066588 100644 --- a/include/DeviceProvider.h +++ b/include/DeviceProvider.h @@ -1,15 +1,12 @@ #pragma once -#undef _WINSOCKAPI_ -#define _WINSOCKAPI_ - #include #include "Bones.h" +#include "Communication/CommunicationManager.h" #include "DeviceConfiguration.h" #include "DeviceDriver/DeviceDriver.h" #include "openvr_driver.h" - /** This class instantiates all the device drivers you have, meaning if you've created multiple drivers for multiple different controllers, this class will @@ -56,12 +53,12 @@ class DeviceProvider : public vr::IServerTrackedDeviceProvider { void LeaveStandby() override; private: - std::unique_ptr leftHand_; - std::unique_ptr rightHand_; - /** - * returns the configuration set in VRSettings for the device role given - **/ - static VRDeviceConfiguration GetDeviceConfiguration(vr::ETrackedControllerRole role); + std::unique_ptr InstantiateDeviceDriver(const VRDriverConfiguration& configuration) const; + + void InitialiseDeviceDriver(const vr::ETrackedControllerRole& role); + + void HandleSettingsUpdate(const vr::ETrackedControllerRole& role); - std::unique_ptr InstantiateDeviceDriver(VRDeviceConfiguration configuration, std::shared_ptr boneAnimator) const; + std::map> devices_; + std::map deviceConfigurations_; }; \ No newline at end of file diff --git a/include/Encode/AlphaEncodingManager.h b/include/Encode/AlphaEncodingManager.h index 70eabd0a..e574bb69 100644 --- a/include/Encode/AlphaEncodingManager.h +++ b/include/Encode/AlphaEncodingManager.h @@ -1,10 +1,11 @@ #pragma once +#include "DeviceConfiguration.h" #include "Encode/EncodingManager.h" class AlphaEncodingManager : public EncodingManager { public: - explicit AlphaEncodingManager(float maxAnalogValue) : EncodingManager(maxAnalogValue){}; + explicit AlphaEncodingManager(const VREncodingConfiguration& configuration) : EncodingManager(configuration){}; VRInputData Decode(const std::string& input) override; std::string Encode(const VROutput& input) override; diff --git a/include/Encode/EncodingManager.h b/include/Encode/EncodingManager.h index 23cb46ce..a335879c 100644 --- a/include/Encode/EncodingManager.h +++ b/include/Encode/EncodingManager.h @@ -4,6 +4,7 @@ #include #include +#include "DeviceConfiguration.h" #include "DriverLog.h" #include "openvr_driver.h" @@ -130,12 +131,13 @@ struct VROutput { class EncodingManager { public: - explicit EncodingManager(float maxAnalogValue) : maxAnalogValue_(maxAnalogValue){}; + explicit EncodingManager(VREncodingConfiguration configuration) : configuration_(std::move(configuration)){}; + virtual VRInputData Decode(const std::string& input) = 0; virtual std::string Encode(const VROutput& data) = 0; protected: - float maxAnalogValue_; + VREncodingConfiguration configuration_; }; template diff --git a/include/Encode/LegacyEncodingManager.h b/include/Encode/LegacyEncodingManager.h index 26a487e8..c707bec5 100644 --- a/include/Encode/LegacyEncodingManager.h +++ b/include/Encode/LegacyEncodingManager.h @@ -1,10 +1,11 @@ #pragma once +#include "DeviceConfiguration.h" #include "Encode/EncodingManager.h" class LegacyEncodingManager : public EncodingManager { public: - explicit LegacyEncodingManager(float maxAnalogValue); + explicit LegacyEncodingManager(const VREncodingConfiguration& configuration) : EncodingManager(configuration){}; VRInputData Decode(const std::string& input) override; std::string Encode(const VROutput& input) override; diff --git a/include/Util/Quaternion.h b/include/Util/Quaternion.h index da740aa8..383f3f94 100644 --- a/include/Util/Quaternion.h +++ b/include/Util/Quaternion.h @@ -1,27 +1,35 @@ -#define _USE_MATH_DEFINES +#pragma once #include "openvr_driver.h" double DegToRad(double degrees); +float DegToRad(const float degrees); double RadToDeg(double rad); +float RadToDeg(const float rad); + // get the quaternion for rotation from a matrix vr::HmdQuaternion_t GetRotation(const vr::HmdMatrix34_t& matrix); -vr::HmdVector3_t GetPosition(const vr::HmdMatrix34_t& matrix); -vr::HmdVector3_t CombinePosition(const vr::HmdMatrix34_t& matrix, const vr::HmdVector3_t& vec); - -// returns the result of multiplying two quaternions, effectively applying a rotation on a quaternion -vr::HmdQuaternion_t MultiplyQuaternion(const vr::HmdQuaternion_t& q, const vr::HmdQuaternion_t& r); -vr::HmdQuaternionf_t MultiplyQuaternion(const vr::HmdQuaternionf_t& q, const vr::HmdQuaternion_t& r); +vr::HmdVector3d_t GetPosition(const vr::HmdMatrix34_t& matrix); vr::HmdQuaternion_t EulerToQuaternion(const double& yaw, const double& pitch, const double& roll); +vr::HmdVector3d_t QuaternionToEuler(const vr::HmdQuaternion_t& q); vr::HmdMatrix33_t GetRotationMatrix(const vr::HmdMatrix34_t& matrix); -vr::HmdVector3_t MultiplyMatrix(const vr::HmdMatrix33_t& matrix, const vr::HmdVector3_t& vector); - vr::HmdMatrix33_t QuaternionToMatrix(const vr::HmdQuaternion_t& q); -vr::HmdQuaternion_t QuatConjugate(const vr::HmdQuaternion_t& q); +vr::HmdQuaternion_t operator-(const vr::HmdQuaternion_t& q); + +vr::HmdQuaternion_t operator*(const vr::HmdQuaternion_t& q, const vr::HmdQuaternion_t& r); +vr::HmdQuaternionf_t operator*(const vr::HmdQuaternionf_t& q, const vr::HmdQuaternion_t& r); +vr::HmdVector3_t operator+(const vr::HmdMatrix34_t& matrix, const vr::HmdVector3_t& vec); +vr::HmdVector3_t operator*(const vr::HmdMatrix33_t& matrix, const vr::HmdVector3_t& vec); +vr::HmdVector3_t operator-(const vr::HmdVector3_t& vec, const vr::HmdMatrix34_t& matrix); +vr::HmdVector3d_t operator+(const vr::HmdVector3d_t& vec1, const vr::HmdVector3d_t& vec2); +vr::HmdVector3d_t operator-(const vr::HmdVector3d_t& vec1, const vr::HmdVector3d_t& vec2); +vr::HmdVector3d_t operator*(const vr::HmdVector3d_t& vec, const vr::HmdQuaternion_t& q); +vr::HmdVector3_t operator*(const vr::HmdVector3_t& vec, const vr::HmdQuaternion_t& q); -vr::HmdVector3_t QuaternionToEuler(const vr::HmdQuaternion_t& q); \ No newline at end of file +bool operator==(const vr::HmdVector3d_t& v1, const vr::HmdVector3d_t& v2); +bool operator==(const vr::HmdQuaternion_t& q1, const vr::HmdQuaternion_t& q2); \ No newline at end of file diff --git a/openglove/resources/icons/lucidgloves.svg b/openglove/resources/icons/openglove.svg similarity index 100% rename from openglove/resources/icons/lucidgloves.svg rename to openglove/resources/icons/openglove.svg diff --git a/openglove/resources/input/openglove_profile.json b/openglove/resources/input/openglove_profile.json index 4aa2a615..2da3680e 100644 --- a/openglove/resources/input/openglove_profile.json +++ b/openglove/resources/input/openglove_profile.json @@ -1,6 +1,7 @@ { "jsonid": "input_profile", "controller_type": "openglove", + "compatibility_mode_controller_type": "knuckles", "input_bindingui_mode" : "controller_handed", "input_bindingui_left" : { diff --git a/overlay/CMakeLists.txt b/overlay/CMakeLists.txt index a7a9b738..013ffa5e 100644 --- a/overlay/CMakeLists.txt +++ b/overlay/CMakeLists.txt @@ -10,4 +10,12 @@ target_link_libraries("openglove_overlay" PUBLIC "${OPENVR_LIB}") add_custom_command(TARGET openglove_overlay POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different "${PROJECT_SOURCE_DIR}/libraries/openvr/bin/win64/openvr_api.dll" - $) \ No newline at end of file + $) + +add_custom_command( + TARGET openglove_overlay + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + $ + $/${DRIVER_NAME}/bin/${PLATFORM_NAME}${PROCESSOR_ARCH} +) \ No newline at end of file diff --git a/overlay/main.cpp b/overlay/main.cpp index e12056fa..339a445c 100644 --- a/overlay/main.cpp +++ b/overlay/main.cpp @@ -32,8 +32,7 @@ std::string GetLastErrorAsString() { return message; } -void GetAndSendControllerId(const vr::TrackedDeviceIndex_t id, const vr::ETrackedControllerRole role) { - const auto pipeHelper = std::make_unique(); +void DiscoverControllerThread(const vr::ETrackedControllerRole role) { std::string pipeName; if (role == vr::ETrackedControllerRole::TrackedControllerRole_LeftHand) { @@ -42,50 +41,40 @@ void GetAndSendControllerId(const vr::TrackedDeviceIndex_t id, const vr::ETracke pipeName = R"(\\.\pipe\vrapplication\discovery\right)"; } - ControllerPipeData data{}; - data.controllerId = id; + const auto pipeHelper = std::make_unique(pipeName); + pipeHelper->WaitCreatePipe(); - pipeHelper->ConnectAndSendPipe(pipeName, data); -} - -void DiscoverController(const vr::ETrackedControllerRole role) { - vr::TrackedDeviceIndex_t lastFound = -1; - vr::TrackedDeviceIndex_t curFound = -1; + short controllerId = -1; while (appActive) { - for (vr::TrackedDeviceIndex_t i = 1; i < vr::k_unMaxTrackedDeviceCount; i++) { + for (short i = 1; i < vr::k_unMaxTrackedDeviceCount; i++) { char thisManufacturer[1024]; - uint32_t err = vr::VRSystem()->GetStringTrackedDeviceProperty( + + vr::VRSystem()->GetStringTrackedDeviceProperty( i, vr::ETrackedDeviceProperty::Prop_ManufacturerName_String, thisManufacturer, sizeof thisManufacturer); std::string sThisManufacturer(thisManufacturer); - if (ourManufacturer == sThisManufacturer) continue; - const short deviceRole = vr::VRSystem()->GetControllerRoleForTrackedDeviceIndex(i); - const int32_t controllerHint = vr::VRSystem()->GetInt32TrackedDeviceProperty(i, vr::ETrackedDeviceProperty::Prop_ControllerRoleHint_Int32); - if (controllerHint == role) { - curFound = i; + controllerId = i; break; } const int controllerType = vr::VRSystem()->GetInt32TrackedDeviceProperty(i, vr::ETrackedDeviceProperty::Prop_DeviceClass_Int32); + const short deviceRole = vr::VRSystem()->GetControllerRoleForTrackedDeviceIndex(i); - if (controllerType == vr::ETrackedDeviceClass::TrackedDeviceClass_GenericTracker || - controllerType == vr::ETrackedDeviceClass::TrackedDeviceClass_Controller) { - if (role == deviceRole) { - curFound = i; - } + if ((controllerType == vr::ETrackedDeviceClass::TrackedDeviceClass_GenericTracker || + controllerType == vr::ETrackedDeviceClass::TrackedDeviceClass_Controller) && + role == deviceRole) { + controllerId = i; } } - if (curFound != lastFound) { - GetAndSendControllerId(curFound, role); - lastFound = curFound; - } - std::this_thread::sleep_for(std::chrono::milliseconds(500)); + while (!pipeHelper->SendPipe({controllerId})) pipeHelper->WaitCreatePipe(); + + std::this_thread::sleep_for(std::chrono::milliseconds(1000)); } } @@ -94,9 +83,9 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdL VR_Init(&error, vr::VRApplication_Background); if (error == vr::EVRInitError::VRInitError_None) { - auto leftControllerThread = std::thread(&DiscoverController, vr::ETrackedControllerRole::TrackedControllerRole_LeftHand); + auto leftControllerThread = std::thread(&DiscoverControllerThread, vr::ETrackedControllerRole::TrackedControllerRole_LeftHand); - auto rightControllerThread = std::thread(&DiscoverController, vr::ETrackedControllerRole::TrackedControllerRole_RightHand); + auto rightControllerThread = std::thread(&DiscoverControllerThread, vr::ETrackedControllerRole::TrackedControllerRole_RightHand); while (appActive) { vr::VREvent_t event{}; @@ -121,12 +110,12 @@ int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdL return 0; } -PipeHelper::PipeHelper() : pipeHandle_(nullptr) {} +PipeHelper::PipeHelper(const std::string& pipeName) : pipeName_(pipeName), pipeHandle_(nullptr){}; -bool PipeHelper::ConnectAndSendPipe(const std::string& pipeName, ControllerPipeData data) { - while (true) { +void PipeHelper::WaitCreatePipe() { + while (appActive) { pipeHandle_ = CreateFile( - pipeName.c_str(), // pipe name + pipeName_.c_str(), // pipe name GENERIC_READ | GENERIC_WRITE, // read and write access 0, // no sharing nullptr, // default security attributes @@ -136,20 +125,18 @@ bool PipeHelper::ConnectAndSendPipe(const std::string& pipeName, ControllerPipeD if (pipeHandle_ != INVALID_HANDLE_VALUE) break; - if (GetLastError() != ERROR_PIPE_BUSY) { - return false; - } - - if (!WaitNamedPipe(pipeName.c_str(), 1000)) { - return false; - } + WaitNamedPipe(pipeName_.c_str(), 1000); } +} +bool PipeHelper::SendPipe(const ControllerPipeData& data) { DWORD dwWritten; - WriteFile(pipeHandle_, &data, sizeof(ControllerPipeData), &dwWritten, nullptr); + bool success = WriteFile(pipeHandle_, &data, sizeof(ControllerPipeData), &dwWritten, nullptr); - CloseHandle(pipeHandle_); + return success; +} - return true; -} \ No newline at end of file +void PipeHelper::ClosePipe() { + CloseHandle(pipeHandle_); +} diff --git a/overlay/main.h b/overlay/main.h index 3883136d..07486dbf 100644 --- a/overlay/main.h +++ b/overlay/main.h @@ -1,6 +1,6 @@ #pragma once -#include #include +#include struct ControllerPipeData { short controllerId; @@ -8,10 +8,15 @@ struct ControllerPipeData { class PipeHelper { public: - PipeHelper(); + PipeHelper(const std::string& pipeName); + + bool SendPipe(const ControllerPipeData& data); + + void WaitCreatePipe(); - bool ConnectAndSendPipe(const std::string& pipeName, ControllerPipeData data); + void ClosePipe(); private: + std::string pipeName_; HANDLE pipeHandle_; }; \ No newline at end of file diff --git a/src/Bones.cpp b/src/Bones.cpp index c7c0d9ba..5014dbc2 100644 --- a/src/Bones.cpp +++ b/src/Bones.cpp @@ -6,7 +6,7 @@ #include "DriverLog.h" #include "Util/Quaternion.h" -static const float c_maxSplayAngle = 10.0f; +static const float c_maxSplayAngle = 20.0f; static const std::array emptyRotation = {0.0f, 0.0f, 0.0f, 0.0f}; static const std::array emptyTranslation = {0.0f, 0.0f, 0.0f}; @@ -180,8 +180,7 @@ void BoneAnimator::SetTransformForBone( if (splay >= -1.0f && splay <= 1.0f) { // only splay one bone (all the rest are done relative to this one) - if (IsBoneSplayableBone(boneIndex)) - bone.orientation = MultiplyQuaternion(bone.orientation, EulerToQuaternion(0.0, DegToRad(splay * c_maxSplayAngle), 0.0)); + if (IsBoneSplayableBone(boneIndex)) bone.orientation = bone.orientation * EulerToQuaternion(0.0, DegToRad(splay * c_maxSplayAngle), 0.0); } // we're guaranteed to have updated the bone, so we can safely apply a transformation diff --git a/src/Calibration.cpp b/src/Calibration.cpp index 6bcb6746..524a852f 100644 --- a/src/Calibration.cpp +++ b/src/Calibration.cpp @@ -1,6 +1,5 @@ #include "Calibration.h" -#include "DriverLog.h" #include "Util/Quaternion.h" Calibration::Calibration() : maintainPose_(), isCalibrating_(false), calibratingMethod_(CalibrationMethod::None) {} @@ -23,28 +22,32 @@ VRPoseConfiguration Calibration::CompleteCalibration( if (calibratingMethod_ != method) return poseConfiguration; isCalibrating_ = false; - // get the matrix that represents the position of the controller that we are shadowing - const vr::HmdMatrix34_t controllerMatrix = controllerPose.mDeviceToAbsoluteTracking; - const vr::HmdQuaternion_t controllerQuat = GetRotation(controllerMatrix); - const vr::HmdQuaternion_t handQuat = maintainPose_.qRotation; + // controllerPose = new position of controller + // controllerPose contains the position of the controller as qRotation and vecPosition - // qC * qT = qH -> qC*qC^-1 * qT = qH * qC^-1 -> qT = qH * qC^-1 - const vr::HmdQuaternion_t transformQuat = MultiplyQuaternion(QuatConjugate(controllerQuat), handQuat); + // maintainPose = previous position of controller + // maintainPose contains the position of the controller as DriverFromWorld and the offsets we apply as qRotation and + // vecPosition - poseConfiguration.angleOffsetQuaternion.w = transformQuat.w; - poseConfiguration.angleOffsetQuaternion.x = transformQuat.x; - poseConfiguration.angleOffsetQuaternion.y = transformQuat.y; - poseConfiguration.angleOffsetQuaternion.z = transformQuat.z; + const vr::HmdVector3d_t newControllerPosition = GetPosition(controllerPose.mDeviceToAbsoluteTracking); + const vr::HmdQuaternion_t newControllerRotation = GetRotation(controllerPose.mDeviceToAbsoluteTracking); - const vr::HmdVector3_t differenceVector = { - static_cast(maintainPose_.vecPosition[0] - controllerMatrix.m[0][3]), - static_cast(maintainPose_.vecPosition[1] - controllerMatrix.m[1][3]), - static_cast(maintainPose_.vecPosition[2] - controllerMatrix.m[2][3])}; + const vr::HmdQuaternion_t lastControllerRotation = maintainPose_.qWorldFromDriverRotation * poseConfiguration.angleOffsetQuaternion; - const vr::HmdQuaternion_t transformInverse = QuatConjugate(controllerQuat); - const vr::HmdMatrix33_t transformMatrix = QuaternionToMatrix(transformInverse); - const vr::HmdVector3_t transformVector = MultiplyMatrix(transformMatrix, differenceVector); + const vr::HmdVector3d_t lastOffsetVecPosition = poseConfiguration.offsetVector * maintainPose_.qWorldFromDriverRotation; + const vr::HmdVector3d_t lastControllerPosition{ + maintainPose_.vecWorldFromDriverTranslation[0] + lastOffsetVecPosition.v[0], + maintainPose_.vecWorldFromDriverTranslation[1] + lastOffsetVecPosition.v[1], + maintainPose_.vecWorldFromDriverTranslation[2] + lastOffsetVecPosition.v[2], + }; + + const vr::HmdQuaternion_t transformQuat = -newControllerRotation * lastControllerRotation; + + poseConfiguration.angleOffsetQuaternion = transformQuat; + + const vr::HmdVector3d_t differenceVector = lastControllerPosition - newControllerPosition; + const vr::HmdVector3d_t transformVector = differenceVector * -newControllerRotation; poseConfiguration.offsetVector = transformVector; @@ -52,12 +55,10 @@ VRPoseConfiguration Calibration::CompleteCalibration( vr::VRSettings()->SetFloat(c_poseSettingsSection, isRightHand ? "right_y_offset_position" : "left_y_offset_position", transformVector.v[1]); vr::VRSettings()->SetFloat(c_poseSettingsSection, isRightHand ? "right_z_offset_position" : "left_z_offset_position", transformVector.v[2]); - const vr::HmdVector3_t eulerOffset = QuaternionToEuler(transformQuat); - - vr::VRSettings()->SetFloat(c_poseSettingsSection, isRightHand ? "right_x_offset_degrees" : "left_x_offset_degrees", RadToDeg(eulerOffset.v[0])); + const vr::HmdVector3d_t eulerOffset = QuaternionToEuler(transformQuat); + vr::VRSettings()->SetFloat(c_poseSettingsSection, isRightHand ? "right_x_offset_degrees" : "left_x_offset_degrees", RadToDeg(eulerOffset.v[2])); vr::VRSettings()->SetFloat(c_poseSettingsSection, isRightHand ? "right_y_offset_degrees" : "left_y_offset_degrees", RadToDeg(eulerOffset.v[1])); - vr::VRSettings()->SetFloat(c_poseSettingsSection, isRightHand ? "right_z_offset_degrees" : "left_z_offset_degrees", RadToDeg(eulerOffset.v[2])); - + vr::VRSettings()->SetFloat(c_poseSettingsSection, isRightHand ? "right_z_offset_degrees" : "left_z_offset_degrees", RadToDeg(eulerOffset.v[0])); return poseConfiguration; } diff --git a/src/Communication/BTSerialCommunicationManager.cpp b/src/Communication/BTSerialCommunicationManager.cpp index 148c5166..b69ccf93 100644 --- a/src/Communication/BTSerialCommunicationManager.cpp +++ b/src/Communication/BTSerialCommunicationManager.cpp @@ -10,11 +10,9 @@ #include "Util/Windows.h" BTSerialCommunicationManager::BTSerialCommunicationManager( - std::unique_ptr encodingManager, const VRBTSerialConfiguration configuration, const VRDeviceConfiguration& deviceConfiguration) - : CommunicationManager(std::move(encodingManager), deviceConfiguration), - btSerialConfiguration_(configuration), - isConnected_(false), - btClientSocket_(NULL) {} + const VRCommunicationConfiguration& configuration, std::unique_ptr encodingManager) + : CommunicationManager(configuration, std::move(encodingManager)), + btSerialConfiguration_(std::get(configuration.configuration)){}; bool BTSerialCommunicationManager::IsConnected() { return isConnected_; @@ -51,9 +49,9 @@ bool BTSerialCommunicationManager::ReceiveNextPacket(std::string& buff) { char nextChar = 0; do { const int receiveResult = recv(btClientSocket_, &nextChar, 1, 0); - + if (receiveResult == SOCKET_ERROR) { - LogError("Socket error while recieving data over bluetooth"); + LogError("Socket error while receiving data over Bluetooth"); return false; } if (receiveResult <= 0 || nextChar == '\n') continue; @@ -96,7 +94,7 @@ bool BTSerialCommunicationManager::ConnectToDevice(const BTH_ADDR& deviceBtAddre DWORD timeout = 1000; setsockopt(btClientSocket_, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)); setsockopt(btClientSocket_, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(timeout)); - + return true; } diff --git a/src/Communication/CommunicationManager.cpp b/src/Communication/CommunicationManager.cpp index 16e33088..f2a57f19 100644 --- a/src/Communication/CommunicationManager.cpp +++ b/src/Communication/CommunicationManager.cpp @@ -6,10 +6,10 @@ static const uint32_t c_listenerWaitTime = 1000; -CommunicationManager::CommunicationManager(const VRDeviceConfiguration& deviceConfiguration) : CommunicationManager(nullptr, deviceConfiguration) {} +CommunicationManager::CommunicationManager(VRCommunicationConfiguration configuration) : CommunicationManager(std::move(configuration), nullptr) {} -CommunicationManager::CommunicationManager(std::unique_ptr encodingManager, const VRDeviceConfiguration& deviceConfiguration) - : encodingManager_(std::move(encodingManager)), deviceConfiguration_(deviceConfiguration), threadActive_(false) { +CommunicationManager::CommunicationManager(VRCommunicationConfiguration configuration, std::unique_ptr encodingManager) + : encodingManager_(std::move(encodingManager)), configuration_(std::move(configuration)), threadActive_(false) { // initially no force feedback QueueSend(VRFFBData(0, 0, 0, 0, 0)); } @@ -35,7 +35,7 @@ void CommunicationManager::Disconnect() { void CommunicationManager::QueueSend(const VROutput& data) { std::lock_guard lock(writeMutex_); - if (encodingManager_ != nullptr) writeString_ += encodingManager_->Encode(data); + if (encodingManager_ != nullptr && configuration_.feedbackEnabled) writeString_ += encodingManager_->Encode(data); } void CommunicationManager::ListenerThread(const std::function& callback) { @@ -47,7 +47,7 @@ void CommunicationManager::ListenerThread(const std::function const VRInputData commData = encodingManager_->Decode(receivedString); callback(commData); - if (deviceConfiguration_.feedbackEnabled) { + if (configuration_.feedbackEnabled) { std::lock_guard lock(writeMutex_); // append a newline and send @@ -79,9 +79,14 @@ void CommunicationManager::ListenerThread(const std::function } void CommunicationManager::WaitAttemptConnection() { + LogMessage("Attempting connection to device..."); + while (threadActive_ && !IsConnected() && !Connect()) { std::this_thread::sleep_for(std::chrono::milliseconds(c_listenerWaitTime)); } + + LogMessage("Device successfully connected"); + if (!threadActive_) return; // we're now connected diff --git a/src/Communication/NamedPipeCommunicationManager.cpp b/src/Communication/NamedPipeCommunicationManager.cpp index 8c78109d..5e71c350 100644 --- a/src/Communication/NamedPipeCommunicationManager.cpp +++ b/src/Communication/NamedPipeCommunicationManager.cpp @@ -3,17 +3,16 @@ #include #include -NamedPipeCommunicationManager::NamedPipeCommunicationManager( - VRNamedPipeInputConfiguration configuration, const VRDeviceConfiguration& deviceConfiguration) - : CommunicationManager(deviceConfiguration), isConnected_(false), configuration_(std::move(configuration)){}; +NamedPipeCommunicationManager::NamedPipeCommunicationManager(const VRCommunicationConfiguration& configuration) + : CommunicationManager(configuration), namedPipeConfiguration_(std::get(configuration.configuration)){}; bool NamedPipeCommunicationManager::Connect() { namedPipeListeners_.emplace_back(std::make_unique>( - std::regex_replace(configuration_.pipeName, std::regex("\\$version"), "v1"), + std::regex_replace(namedPipeConfiguration_.pipeName, std::regex("\\$version"), "v1"), [&](VRInputDataVersion::v1* data) { callback_(static_cast(*data)); })); - namedPipeListeners_.emplace_back(std::make_unique>( - std::regex_replace(configuration_.pipeName, std::regex("\\$version"), "v2"), + namedPipeListeners_.emplace_back(std::make_unique>( + std::regex_replace(namedPipeConfiguration_.pipeName, std::regex("\\$version"), "v2"), [&](VRInputDataVersion::v2* data) { callback_(static_cast(*data)); })); return true; } @@ -44,10 +43,10 @@ bool NamedPipeCommunicationManager::IsConnected() { void NamedPipeCommunicationManager::LogError(const char* message) { // message with port name and last error - DriverLog("%s (%s) - Error: %s", message, configuration_.pipeName.c_str(), GetLastErrorAsString().c_str()); + DriverLog("%s (%s) - Error: %s", message, namedPipeConfiguration_.pipeName.c_str(), GetLastErrorAsString().c_str()); } void NamedPipeCommunicationManager::LogMessage(const char* message) { // message with port name - DriverLog("%s (%s)", message, configuration_.pipeName.c_str()); + DriverLog("%s (%s)", message, namedPipeConfiguration_.pipeName.c_str()); } \ No newline at end of file diff --git a/src/Communication/SerialCommunicationManager.cpp b/src/Communication/SerialCommunicationManager.cpp index e5127969..8bae19b3 100644 --- a/src/Communication/SerialCommunicationManager.cpp +++ b/src/Communication/SerialCommunicationManager.cpp @@ -6,9 +6,9 @@ #include "Util/Windows.h" SerialCommunicationManager::SerialCommunicationManager( - std::unique_ptr encodingManager, VRSerialConfiguration configuration, const VRDeviceConfiguration& deviceConfiguration) - : CommunicationManager(std::move(encodingManager), deviceConfiguration), - serialConfiguration_(std::move(configuration)), + const VRCommunicationConfiguration& configuration, std::unique_ptr encodingManager) + : CommunicationManager(configuration, std::move(encodingManager)), + serialConfiguration_(std::get(configuration.configuration)), isConnected_(false), hSerial_(nullptr) {} @@ -36,7 +36,6 @@ bool SerialCommunicationManager::SetCommunicationTimeout( } bool SerialCommunicationManager::Connect() { - LogMessage("Attempting connection to device"); // We're not yet connected isConnected_ = false; @@ -163,6 +162,11 @@ bool SerialCommunicationManager::PurgeBuffer() const { void SerialCommunicationManager::LogError(const char* message) { // message with port name and last error + const DWORD thisError = GetLastError(); + + if (thisError == lastError_) return; + + lastError_ = thisError; DriverLog("%s (%s) - Error: %s", message, serialConfiguration_.port.c_str(), GetLastErrorAsString().c_str()); } diff --git a/src/ControllerPose.cpp b/src/ControllerPose.cpp index 9ec165ff..1bda7fc3 100644 --- a/src/ControllerPose.cpp +++ b/src/ControllerPose.cpp @@ -25,6 +25,7 @@ ControllerPose::ControllerPose( shadowControllerId_ = poseConfiguration_.controllerIdOverride; } else { controllerDiscoverer_ = std::make_unique(shadowDeviceOfRole, [&](const ControllerDiscoveryPipeData data) { + if (shadowControllerId_ == data.controllerId) return; shadowControllerId_ = data.controllerId; DriverLog("Received controller id from overlay: %i", data.controllerId); }); @@ -36,7 +37,7 @@ ControllerPose::ControllerPose( ControllerPose::~ControllerPose() { calibrationPipe_->StopListening(); - if (controllerDiscoverer_) controllerDiscoverer_->Stop(); + if (controllerDiscoverer_ != nullptr) controllerDiscoverer_->Stop(); } vr::TrackedDevicePose_t ControllerPose::GetControllerPose() const { @@ -49,61 +50,46 @@ vr::DriverPose_t ControllerPose::UpdatePose() const { if (calibration_->IsCalibrating()) return calibration_->GetMaintainPose(); vr::DriverPose_t newPose = {0}; - newPose.qWorldFromDriverRotation.w = 1; newPose.qDriverFromHeadRotation.w = 1; + newPose.qWorldFromDriverRotation.w = 1; if (shadowControllerId_ != vr::k_unTrackedDeviceIndexInvalid) { const vr::TrackedDevicePose_t controllerPose = GetControllerPose(); if (controllerPose.bPoseIsValid) { - // get the matrix that represents the position of the controller that we are shadowing const vr::HmdMatrix34_t controllerMatrix = controllerPose.mDeviceToAbsoluteTracking; - // get only the rotation (3x3 matrix), as the 3x4 matrix also includes position - const vr::HmdMatrix33_t controllerRotationMatrix = GetRotationMatrix(controllerMatrix); const vr::HmdQuaternion_t controllerRotation = GetRotation(controllerMatrix); + const vr::HmdVector3d_t controllerPosition = GetPosition(controllerMatrix); - const vr::HmdVector3_t vectorOffset = MultiplyMatrix(controllerRotationMatrix, poseConfiguration_.offsetVector); - - // combine these positions to get the resultant position - const vr::HmdVector3_t newControllerPosition = CombinePosition(controllerMatrix, vectorOffset); + newPose.qWorldFromDriverRotation = controllerRotation; - newPose.vecPosition[0] = newControllerPosition.v[0]; - newPose.vecPosition[1] = newControllerPosition.v[1]; - newPose.vecPosition[2] = newControllerPosition.v[2]; + newPose.vecWorldFromDriverTranslation[0] = controllerPosition.v[0]; + newPose.vecWorldFromDriverTranslation[1] = controllerPosition.v[1]; + newPose.vecWorldFromDriverTranslation[2] = controllerPosition.v[2]; - newPose.qRotation = MultiplyQuaternion(controllerRotation, poseConfiguration_.angleOffsetQuaternion); + newPose.vecPosition[0] = poseConfiguration_.offsetVector.v[0]; + newPose.vecPosition[1] = poseConfiguration_.offsetVector.v[1]; + newPose.vecPosition[2] = poseConfiguration_.offsetVector.v[2]; - // Angular velocity - // Converted from euler angle provided in world space to euler angle in object space - vr::HmdVector3_t angularVelocityWorld = controllerPose.vAngularVelocity; - angularVelocityWorld.v[0] /= 100.0; - angularVelocityWorld.v[1] /= 100.0; - angularVelocityWorld.v[2] /= 100.0; + const vr::HmdVector3_t objectVelocity = controllerPose.vVelocity * -controllerRotation; - vr::HmdQuaternion_t qAngularVelocityWorld = EulerToQuaternion( - static_cast(angularVelocityWorld.v[2]), - static_cast(angularVelocityWorld.v[1]), - static_cast(angularVelocityWorld.v[0])); + newPose.vecVelocity[0] = objectVelocity.v[0]; + newPose.vecVelocity[1] = objectVelocity.v[1]; + newPose.vecVelocity[2] = objectVelocity.v[2]; - vr::HmdQuaternion_t qAngularVelocityObject = - MultiplyQuaternion(MultiplyQuaternion(QuatConjugate(newPose.qRotation), qAngularVelocityWorld), newPose.qRotation); + const vr::HmdVector3_t objectAngularVelocity = + controllerPose.vAngularVelocity * -controllerRotation * -poseConfiguration_.angleOffsetQuaternion; - vr::HmdVector3_t angularVelocityObject = QuaternionToEuler(qAngularVelocityObject); + newPose.vecAngularVelocity[0] = objectAngularVelocity.v[0]; + newPose.vecAngularVelocity[1] = objectAngularVelocity.v[1]; + newPose.vecAngularVelocity[2] = objectAngularVelocity.v[2]; - newPose.vecAngularVelocity[0] = angularVelocityObject.v[0] * (double)100.0; - newPose.vecAngularVelocity[1] = angularVelocityObject.v[1] * (double)100.0; - newPose.vecAngularVelocity[2] = angularVelocityObject.v[2] * (double)100.0; - - newPose.vecVelocity[0] = controllerPose.vVelocity.v[0]; - newPose.vecVelocity[1] = controllerPose.vVelocity.v[1]; - newPose.vecVelocity[2] = controllerPose.vVelocity.v[2]; + newPose.qRotation = poseConfiguration_.angleOffsetQuaternion; newPose.poseIsValid = true; newPose.deviceIsConnected = true; newPose.result = vr::TrackingResult_Running_OK; - - newPose.poseTimeOffset = poseConfiguration_.poseTimeOffset; } else { newPose.poseIsValid = false; newPose.deviceIsConnected = true; @@ -111,8 +97,7 @@ vr::DriverPose_t ControllerPose::UpdatePose() const { } } else { - newPose.result = vr::TrackingResult_Uninitialized; - newPose.deviceIsConnected = false; + newPose.deviceIsConnected = true; } return newPose; diff --git a/src/DeviceConfiguration.cpp b/src/DeviceConfiguration.cpp index 47bc289d..4633ba8c 100644 --- a/src/DeviceConfiguration.cpp +++ b/src/DeviceConfiguration.cpp @@ -1,5 +1,8 @@ #include "DeviceConfiguration.h" +#include "DriverLog.h" +#include "Util/Quaternion.h" + const char* c_poseSettingsSection = "pose_settings"; const char* c_driverSettingsSection = "driver_openglove"; const char* c_serialCommunicationSettingsSection = "communication_serial"; @@ -9,4 +12,128 @@ const char* c_lucidGloveDeviceSettingsSection = "device_lucidgloves"; const char* c_alphaEncodingSettingsSection = "encoding_alpha"; const char* c_legacyEncodingSettingsSection = "encoding_legacy"; -const char* c_deviceDriverManufacturer = "LucidVR"; +const char* c_deviceManufacturer = "LucidVR"; + +static VREncodingConfiguration GetEncodingConfiguration() { + switch (static_cast(vr::VRSettings()->GetInt32(c_driverSettingsSection, "encoding_protocol"))) { + case VREncodingProtocol::Legacy: { + const unsigned int maxAnalogueValue = vr::VRSettings()->GetInt32(c_legacyEncodingSettingsSection, "max_analog_value"); + + return {VREncodingProtocol::Legacy, maxAnalogueValue, VRLegacyEncodingConfiguration{}}; + } + + default: + DriverLog("No encoding protocol specified. Configuring from alpha encoding"); + case VREncodingProtocol::Alpha: { + const unsigned int maxAnalogueValue = vr::VRSettings()->GetInt32(c_alphaEncodingSettingsSection, "max_analog_value"); + + return {VREncodingProtocol::Alpha, maxAnalogueValue, VRAlphaEncodingConfiguration{}}; + } + } +} + +static VRCommunicationConfiguration GetCommunicationConfiguration(const bool isRightHand) { + vr::CVRSettingHelper settingHelper(vr::VRSettings()); + + const bool feedbackEnabled = vr::VRSettings()->GetBool(c_driverSettingsSection, "feedback_enabled"); + + const VREncodingConfiguration encodingConfiguration = GetEncodingConfiguration(); + + switch (static_cast(vr::VRSettings()->GetInt32(c_driverSettingsSection, "communication_protocol"))) { + case VRCommunicationProtocol::NamedPipe: { + const std::string pipeName = R"(\\.\pipe\vrapplication\input\glove\$version\)" + std::string(isRightHand ? "right" : "left"); + + return {VRCommunicationProtocol::NamedPipe, encodingConfiguration, feedbackEnabled, VRCommunicationNamedPipeConfiguration{pipeName}}; + } + + case VRCommunicationProtocol::BtSerial: { + const std::string name = settingHelper.GetString(c_btserialCommunicationSettingsSection, isRightHand ? "right_name" : "left_name"); + + return {VRCommunicationProtocol::BtSerial, encodingConfiguration, feedbackEnabled, VRCommunicationBTSerialConfiguration{name}}; + } + + default: + DriverLog("No communication protocol specified. Configuring for serial"); + case VRCommunicationProtocol::Serial: { + const std::string port = settingHelper.GetString(c_serialCommunicationSettingsSection, isRightHand ? "right_port" : "left_port"); + const int baudRate = vr::VRSettings()->GetInt32(c_serialCommunicationSettingsSection, "baud_rate"); + + return {VRCommunicationProtocol::Serial, encodingConfiguration, feedbackEnabled, VRCommunicationSerialConfiguration{port, baudRate}}; + } + } +} + +static VRPoseConfiguration GetPoseConfiguration(bool isRightHand) { + const float poseTimeOffset = vr::VRSettings()->GetFloat(c_poseSettingsSection, "pose_time_offset"); + + const float offsetXPos = vr::VRSettings()->GetFloat(c_poseSettingsSection, isRightHand ? "right_x_offset_position" : "left_x_offset_position"); + const float offsetYPos = vr::VRSettings()->GetFloat(c_poseSettingsSection, isRightHand ? "right_y_offset_position" : "left_y_offset_position"); + const float offsetZPos = vr::VRSettings()->GetFloat(c_poseSettingsSection, isRightHand ? "right_z_offset_position" : "left_z_offset_position"); + const vr::HmdVector3d_t offsetVector = {offsetXPos, offsetYPos, offsetZPos}; + + const float offsetXRot = vr::VRSettings()->GetFloat(c_poseSettingsSection, isRightHand ? "right_x_offset_degrees" : "left_x_offset_degrees"); + const float offsetYRot = vr::VRSettings()->GetFloat(c_poseSettingsSection, isRightHand ? "right_y_offset_degrees" : "left_y_offset_degrees"); + const float offsetZRot = vr::VRSettings()->GetFloat(c_poseSettingsSection, isRightHand ? "right_z_offset_degrees" : "left_z_offset_degrees"); + const vr::HmdQuaternion_t angleOffsetQuaternion = EulerToQuaternion(DegToRad(offsetZRot), DegToRad(offsetYRot), DegToRad(offsetXRot)); + + const bool controllerOverrideEnabled = vr::VRSettings()->GetBool(c_poseSettingsSection, "controller_override"); + const int controllerIdOverride = + controllerOverrideEnabled + ? vr::VRSettings()->GetInt32(c_poseSettingsSection, isRightHand ? "controller_override_right" : "controller_override_left") + : -1; + const bool calibrationButtonEnabled = vr::VRSettings()->GetBool(c_poseSettingsSection, "hardware_calibration_button_enabled"); + + return {offsetVector, angleOffsetQuaternion, poseTimeOffset, controllerIdOverride, controllerOverrideEnabled, calibrationButtonEnabled}; +} + +static VRDeviceConfiguration GetDeviceConfiguration(const vr::ETrackedControllerRole& role) { + const bool isRightHand = role == vr::ETrackedControllerRole::TrackedControllerRole_RightHand; + + vr::CVRSettingHelper settingHelper(vr::VRSettings()); + + const VRPoseConfiguration poseConfiguration = GetPoseConfiguration(isRightHand); + const VRCommunicationConfiguration communicationConfiguration = GetCommunicationConfiguration(isRightHand); + + switch (static_cast(vr::VRSettings()->GetInt32(c_driverSettingsSection, "device_driver"))) { + case VRDeviceType::LucidGloves: { + const std::string serialNumber = + settingHelper.GetString(c_lucidGloveDeviceSettingsSection, isRightHand ? "right_serial_number" : "left_serial_number"); + + return { + VRDeviceType::LucidGloves, + serialNumber, + role, + poseConfiguration, + communicationConfiguration, + VRDeviceLucidglovesConfiguration{serialNumber}}; + } + + default: + DriverLog("No device type specified. Configuring for emulated knuckles"); + case VRDeviceType::EmulatedKnuckles: { + const std::string serialNumber = + settingHelper.GetString(c_knuckleDeviceSettingsSection, isRightHand ? "right_serial_number" : "left_serial_number"); + + const bool indexCurlAsTrigger = vr::VRSettings()->GetBool(c_knuckleDeviceSettingsSection, "index_curl_as_trigger"); + const bool approximateThumb = vr::VRSettings()->GetBool(c_knuckleDeviceSettingsSection, "approximate_thumb"); + + return { + VRDeviceType::EmulatedKnuckles, + serialNumber, + role, + poseConfiguration, + communicationConfiguration, + VRDeviceKnucklesConfiguration{indexCurlAsTrigger, approximateThumb}}; + } + } +} + +VRDriverConfiguration GetDriverConfiguration(const vr::ETrackedControllerRole& role) { + const bool isRightHand = role == vr::TrackedControllerRole_RightHand; + DriverLog("Getting configuration for: %s", isRightHand ? "Right hand" : "Left hand"); + + // main settings + const bool enabled = vr::VRSettings()->GetBool(c_driverSettingsSection, isRightHand ? "right_enabled" : "left_enabled"); + + return {enabled, GetDeviceConfiguration(role)}; +} \ No newline at end of file diff --git a/src/DeviceDriver/DeviceDriver.cpp b/src/DeviceDriver/DeviceDriver.cpp index 640bd034..ec148e80 100644 --- a/src/DeviceDriver/DeviceDriver.cpp +++ b/src/DeviceDriver/DeviceDriver.cpp @@ -2,28 +2,22 @@ #include +#include "Communication/BTSerialCommunicationManager.h" +#include "Communication/NamedPipeCommunicationManager.h" +#include "Communication/SerialCommunicationManager.h" #include "DriverLog.h" +#include "Encode/AlphaEncodingManager.h" +#include "Encode/LegacyEncodingManager.h" -DeviceDriver::DeviceDriver( - std::unique_ptr communicationManager, - std::shared_ptr boneAnimator, - std::string serialNumber, - const VRDeviceConfiguration configuration) - : communicationManager_(std::move(communicationManager)), - boneAnimator_(std::move(boneAnimator)), - configuration_(configuration), - serialNumber_(std::move(serialNumber)), +DeviceDriver::DeviceDriver(VRDeviceConfiguration configuration) + : configuration_(std::move(configuration)), skeletalComponentHandle_(), handTransforms_(), - hasActivated_(false), - deviceId_(vr::k_unTrackedDeviceIndexInvalid) { - // Load in a default skeleton - boneAnimator_->LoadDefaultSkeletonByHand(handTransforms_, configuration_.role == vr::ETrackedControllerRole::TrackedControllerRole_RightHand); -} + isRunning_(false), + deviceId_(vr::k_unTrackedDeviceIndexInvalid) {} vr::EVRInitError DeviceDriver::Activate(uint32_t unObjectId) { deviceId_ = unObjectId; - controllerPose_ = std::make_unique(configuration_.role, std::string(c_deviceDriverManufacturer), configuration_.poseConfiguration); vr::PropertyContainerHandle_t props = vr::VRProperties()->TrackedDeviceToPropertyContainer( deviceId_); // this gets a container object where you store all the information about your driver @@ -41,36 +35,22 @@ vr::EVRInitError DeviceDriver::Activate(uint32_t unObjectId) { NUM_BONES, &skeletalComponentHandle_); - if (configuration_.feedbackEnabled) { - ffbProvider_ = std::make_unique( - [&](const VRFFBData data) { - // Queue the force feedback data for sending. - communicationManager_->QueueSend(data); - }, - configuration_.role); - - ffbProvider_->Start(); - }; - StartDevice(); - hasActivated_ = true; + isRunning_ = true; return vr::VRInitError_None; } void DeviceDriver::Deactivate() { - if (hasActivated_.exchange(false)) { - StoppingDevice(); - - if (ffbProvider_) ffbProvider_->Stop(); - - communicationManager_->Disconnect(); - deviceId_ = vr::k_unTrackedDeviceIndexInvalid; - hasActivated_ = false; + DriverLog("Deactivating device"); + if (isRunning_.exchange(false)) { + StopDeviceComponents(); - poseUpdateThread_.join(); + StoppingDevice(); } + + DriverLog("Finished deactivating device, invalidating pose..."); } void DeviceDriver::DebugRequest(const char* pchRequest, char* pchResponseBuffer, const uint32_t unResponseBufferSize) { @@ -84,13 +64,13 @@ void* DeviceDriver::GetComponent(const char* pchComponentNameAndVersion) { } vr::DriverPose_t DeviceDriver::GetPose() { - if (hasActivated_) return controllerPose_->UpdatePose(); + if (isActive_) return controllerPose_->UpdatePose(); return vr::DriverPose_t{0}; } std::string DeviceDriver::GetSerialNumber() { - return serialNumber_; + return configuration_.serialNumber; } int32_t DeviceDriver::GetDeviceId() const { @@ -98,11 +78,11 @@ int32_t DeviceDriver::GetDeviceId() const { } bool DeviceDriver::IsActive() { - return hasActivated_; + return isRunning_; } void DeviceDriver::PoseUpdateThread() const { - while (hasActivated_) { + while (isActive_) { vr::DriverPose_t pose = controllerPose_->UpdatePose(); vr::VRServerDriverHost()->TrackedDevicePoseUpdated(deviceId_, pose, sizeof(vr::DriverPose_t)); @@ -117,10 +97,92 @@ bool DeviceDriver::IsRightHand() const { } void DeviceDriver::StartDevice() { + isActive_ = true; + StartingDevice(); + SetupDeviceComponents(); + vr::VRDriverInput()->UpdateSkeletonComponent(skeletalComponentHandle_, vr::VRSkeletalMotionRange_WithoutController, handTransforms_, NUM_BONES); vr::VRDriverInput()->UpdateSkeletonComponent(skeletalComponentHandle_, vr::VRSkeletalMotionRange_WithController, handTransforms_, NUM_BONES); +} + +void DeviceDriver::OnEvent(vr::VREvent_t vrEvent) const { + if (vrEvent.eventType == vr::EVREventType::VREvent_Input_HapticVibration && haptic_ == vrEvent.data.hapticVibration.componentHandle) + communicationManager_->QueueSend(VRHapticData(vrEvent.data.hapticVibration)); +} + +void DeviceDriver::UpdateDeviceConfiguration(VRDeviceConfiguration configuration) { + configuration_ = std::move(configuration); + + DriverLog("Attempting to stop device components..."); + + StopDeviceComponents(); + + DriverLog("Restarting device components..."); + + isActive_ = true; + SetupDeviceComponents(); + + DriverLog("Restarted device components successfully"); +} + +void DeviceDriver::SetupDeviceComponents() { + const VRCommunicationConfiguration& communicationConfiguration = configuration_.communicationConfiguration; + std::unique_ptr encodingManager; + + switch (communicationConfiguration.encodingConfiguration.encodingProtocol) { + case VREncodingProtocol::Legacy: { + DriverLog("Using legacy encoding"); + encodingManager = std::make_unique(communicationConfiguration.encodingConfiguration); + + break; + } + + case VREncodingProtocol::Alpha: { + DriverLog("Using alpha encoding"); + encodingManager = std::make_unique(communicationConfiguration.encodingConfiguration); + + break; + } + } + + switch (communicationConfiguration.communicationProtocol) { + case VRCommunicationProtocol::NamedPipe: { + DriverLog("Using named pipe communication"); + communicationManager_ = std::make_unique(communicationConfiguration); + + break; + } + + case VRCommunicationProtocol::BtSerial: { + DriverLog("Using bluetooth serial communication"); + communicationManager_ = std::make_unique(communicationConfiguration, std::move(encodingManager)); + + break; + } + + case VRCommunicationProtocol::Serial: { + DriverLog("Using usb serial communication"); + communicationManager_ = std::make_unique(communicationConfiguration, std::move(encodingManager)); + + break; + } + } + + controllerPose_ = std::make_unique(configuration_.role, std::string(c_deviceManufacturer), configuration_.poseConfiguration); + + boneAnimator_ = std::make_unique(GetDriverPath() + R"(\resources\anims\glove_anim.glb)"); + boneAnimator_->LoadDefaultSkeletonByHand(handTransforms_, configuration_.role == vr::ETrackedControllerRole::TrackedControllerRole_RightHand); + + ffbProvider_ = std::make_unique( + [&](const VRFFBData data) { + // Queue the force feedback data for sending. + communicationManager_->QueueSend(data); + }, + configuration_.role); + + ffbProvider_->Start(); communicationManager_->BeginListener([&](VRInputData data) { try { @@ -146,7 +208,22 @@ void DeviceDriver::StartDevice() { poseUpdateThread_ = std::thread(&DeviceDriver::PoseUpdateThread, this); } -void DeviceDriver::OnEvent(vr::VREvent_t vrEvent) const { - if (vrEvent.eventType == vr::EVREventType::VREvent_Input_HapticVibration && haptic_ == vrEvent.data.hapticVibration.componentHandle) - communicationManager_->QueueSend(VRHapticData(vrEvent.data.hapticVibration)); +void DeviceDriver::StopDeviceComponents() { + if (isActive_.exchange(false)) { + ffbProvider_->Stop(); + + communicationManager_->Disconnect(); + + poseUpdateThread_.join(); + } + + vr::DriverPose_t pose; + pose.deviceIsConnected = false; + pose.poseIsValid = false; + vr::VRServerDriverHost()->TrackedDevicePoseUpdated(deviceId_, pose, sizeof(vr::DriverPose_t)); +} + +void DeviceDriver::DisableDevice() { + DriverLog("Disabling device components..."); + StopDeviceComponents(); } diff --git a/src/DeviceDriver/KnuckleDriver.cpp b/src/DeviceDriver/KnuckleDriver.cpp index 450a6e36..036f927e 100644 --- a/src/DeviceDriver/KnuckleDriver.cpp +++ b/src/DeviceDriver/KnuckleDriver.cpp @@ -2,17 +2,10 @@ #include -KnuckleDeviceDriver::KnuckleDeviceDriver( - std::unique_ptr communicationManager, - std::shared_ptr boneAnimator, - std::string serialNumber, - bool approximateThumb, - const VRDeviceConfiguration configuration) - : DeviceDriver(std::move(communicationManager), std::move(boneAnimator), std::move(serialNumber), configuration), - inputComponentHandles_(), - approximateThumb_(approximateThumb) {} +KnuckleDeviceDriver::KnuckleDeviceDriver(VRDeviceConfiguration configuration) : DeviceDriver(std::move(configuration)) {} void KnuckleDeviceDriver::HandleInput(const VRInputData data) { + const VRDeviceKnucklesConfiguration& knucklesConfiguration = std::get(configuration_.configuration); // clang-format off vr::VRDriverInput()->UpdateScalarComponent(inputComponentHandles_[static_cast(KnuckleDeviceComponentIndex::ThumbstickX)], data.joyX, 0); vr::VRDriverInput()->UpdateScalarComponent(inputComponentHandles_[static_cast(KnuckleDeviceComponentIndex::ThumbstickY)], data.joyY, 0); @@ -21,11 +14,11 @@ void KnuckleDeviceDriver::HandleInput(const VRInputData data) { vr::VRDriverInput()->UpdateBooleanComponent(inputComponentHandles_[static_cast(KnuckleDeviceComponentIndex::ThumbstickTouch)], data.joyButton, 0); vr::VRDriverInput()->UpdateBooleanComponent(inputComponentHandles_[static_cast(KnuckleDeviceComponentIndex::TriggerClick)], data.trgButton, 0); - const float triggerValue = configuration_.indexCurlTrigger ? boneAnimator_->GetAverageCurlValue(data.flexion[1]) : data.trgValue; // determine triggerValue + const float triggerValue = knucklesConfiguration.indexCurlTrigger ? boneAnimator_->GetAverageCurlValue(data.flexion[1]) : data.trgValue; // determine triggerValue vr::VRDriverInput()->UpdateScalarComponent(inputComponentHandles_[static_cast(KnuckleDeviceComponentIndex::TriggerValue)], (data.trgButton ? 1 : triggerValue), 0); // TriggerValue always 1 on trigger button press (end of swing) vr::VRDriverInput()->UpdateBooleanComponent(inputComponentHandles_[static_cast(KnuckleDeviceComponentIndex::AClick)], data.aButton, 0); - vr::VRDriverInput()->UpdateBooleanComponent(inputComponentHandles_[static_cast(KnuckleDeviceComponentIndex::ATouch)], data.aButton || (approximateThumb_ && boneAnimator_->GetAverageCurlValue(data.flexion[0]) > 0.6), 0); //Thumb approximation + vr::VRDriverInput()->UpdateBooleanComponent(inputComponentHandles_[static_cast(KnuckleDeviceComponentIndex::ATouch)], data.aButton || (knucklesConfiguration.approximateThumb && boneAnimator_->GetAverageCurlValue(data.flexion[0]) > 0.6), 0); //Thumb approximation vr::VRDriverInput()->UpdateBooleanComponent(inputComponentHandles_[static_cast(KnuckleDeviceComponentIndex::BClick)], data.bButton, 0); vr::VRDriverInput()->UpdateBooleanComponent(inputComponentHandles_[static_cast(KnuckleDeviceComponentIndex::BTouch)], data.bButton, 0); @@ -36,8 +29,6 @@ void KnuckleDeviceDriver::HandleInput(const VRInputData data) { vr::VRDriverInput()->UpdateBooleanComponent(inputComponentHandles_[static_cast(KnuckleDeviceComponentIndex::SystemClick)], data.menu, 0); - // We don't have a thumb on the index - // vr::VRDriverInput()->UpdateScalarComponent(_inputComponentHandles[(int)KnuckleDeviceComponentIndex::THUMB], data.flexion[0], 0); vr::VRDriverInput()->UpdateScalarComponent(inputComponentHandles_[static_cast(KnuckleDeviceComponentIndex::FingerIndex)], boneAnimator_->GetAverageCurlValue(data.flexion[1]), 0); vr::VRDriverInput()->UpdateScalarComponent(inputComponentHandles_[static_cast(KnuckleDeviceComponentIndex::FingerMiddle)], boneAnimator_->GetAverageCurlValue(data.flexion[2]), 0); vr::VRDriverInput()->UpdateScalarComponent(inputComponentHandles_[static_cast(KnuckleDeviceComponentIndex::FingerRing)], boneAnimator_->GetAverageCurlValue(data.flexion[3]), 0); @@ -76,7 +67,7 @@ void KnuckleDeviceDriver::SetupProps(vr::PropertyContainerHandle_t& props) { vr::VRProperties()->SetInt32Property(props, vr::Prop_ControllerHandSelectionPriority_Int32, 2147483647); vr::VRProperties()->SetStringProperty(props, vr::Prop_ModelNumber_String, IsRightHand() ? "Knuckles Right" : "Knuckles Left"); vr::VRProperties()->SetStringProperty(props, vr::Prop_RenderModelName_String, IsRightHand() ? "{indexcontroller}valve_controller_knu_1_0_right" : "{indexcontroller}valve_controller_knu_1_0_left"); - vr::VRProperties()->SetStringProperty(props, vr::Prop_ManufacturerName_String, c_deviceDriverManufacturer); + vr::VRProperties()->SetStringProperty(props, vr::Prop_ManufacturerName_String, c_deviceManufacturer); vr::VRProperties()->SetStringProperty(props, vr::Prop_TrackingFirmwareVersion_String, "1562916277 watchman@ValveBuilder02 2019-07-12 FPGA 538(2.26/10/2) BL 0 VRC 1562916277 Radio 1562882729"); vr::VRProperties()->SetStringProperty(props, vr::Prop_HardwareRevision_String, "product 17 rev 14.1.9 lot 2019/4/20 0"); vr::VRProperties()->SetStringProperty(props, vr::Prop_ConnectedWirelessDongle_String, "C2F75F5986-DIY"); diff --git a/src/DeviceDriver/LucidGloveDriver.cpp b/src/DeviceDriver/LucidGloveDriver.cpp index 69e897e7..0ddc8dbe 100644 --- a/src/DeviceDriver/LucidGloveDriver.cpp +++ b/src/DeviceDriver/LucidGloveDriver.cpp @@ -5,12 +5,7 @@ static const char* c_deviceModelNumber = "lucidgloves1"; static const char* c_basePosePath = "/pose/raw"; static const char* c_inputProfilePath = "{openglove}/input/openglove_profile.json"; -LucidGloveDeviceDriver::LucidGloveDeviceDriver( - std::unique_ptr communicationManager, - std::shared_ptr boneAnimator, - const std::string& serialNumber, - const VRDeviceConfiguration configuration) - : DeviceDriver(std::move(communicationManager), std::move(boneAnimator), serialNumber, configuration), inputComponentHandles_() {} +LucidGloveDeviceDriver::LucidGloveDeviceDriver(const VRDeviceConfiguration& configuration) : DeviceDriver(configuration), inputComponentHandles_() {} void LucidGloveDeviceDriver::HandleInput(const VRInputData data) { // clang-format off @@ -40,13 +35,22 @@ void LucidGloveDeviceDriver::SetupProps(vr::PropertyContainerHandle_t& props) { // clang-format off vr::VRProperties()->SetInt32Property(props, vr::Prop_ControllerHandSelectionPriority_Int32, 2147483647); - vr::VRProperties()->SetStringProperty(props, vr::Prop_InputProfilePath_String, c_inputProfilePath); // tell OpenVR where to get your driver's Input Profile + vr::VRProperties()->SetStringProperty(props, vr::Prop_InputProfilePath_String, "{openglove}/input/openglove_profile.json"); // tell OpenVR where to get your driver's Input Profile vr::VRProperties()->SetInt32Property(props, vr::Prop_ControllerRoleHint_Int32, configuration_.role); // tells OpenVR what kind of device this is vr::VRProperties()->SetStringProperty(props, vr::Prop_SerialNumber_String, GetSerialNumber().c_str()); vr::VRProperties()->SetStringProperty(props, vr::Prop_ModelNumber_String, c_deviceModelNumber); - vr::VRProperties()->SetStringProperty(props, vr::Prop_ManufacturerName_String, c_deviceDriverManufacturer); + vr::VRProperties()->SetStringProperty(props, vr::Prop_ManufacturerName_String, c_deviceManufacturer); vr::VRProperties()->SetInt32Property(props, vr::Prop_DeviceClass_Int32, vr::TrackedDeviceClass_Controller); - vr::VRProperties()->SetStringProperty(props, vr::Prop_ControllerType_String, c_deviceControllerType); + vr::VRProperties()->SetStringProperty(props, vr::Prop_ControllerType_String, "openglove"); + + vr::VRProperties()->SetStringProperty(props, vr::Prop_NamedIconPathDeviceOff_String, IsRightHand() ? "{openglove}/icons/right_controller_status_off.png" : "{openglove}/icons/left_controller_status_off.png"); + vr::VRProperties()->SetStringProperty(props, vr::Prop_NamedIconPathDeviceSearching_String, IsRightHand() ? "{openglove}/icons/right_controller_status_searching.gif" : "{openglove}/icons/left_controller_status_searching.gif"); + vr::VRProperties()->SetStringProperty(props, vr::Prop_NamedIconPathDeviceSearchingAlert_String, IsRightHand() ? "{openglove}/icons/right_controller_status_searching_alert.gif" : "{openglove}/icons/left_controller_status_searching_alert.gif"); + vr::VRProperties()->SetStringProperty(props, vr::Prop_NamedIconPathDeviceReady_String, IsRightHand() ? "{openglove}/icons/right_controller_status_ready.png" : "{openglove}/icons/left_controller_status_ready.png"); + vr::VRProperties()->SetStringProperty(props, vr::Prop_NamedIconPathDeviceReadyAlert_String, IsRightHand() ? "{openglove}/icons/right_controller_status_ready_alert.png" : "{openglove}/icons/left_controller_status_ready_alert.png"); + vr::VRProperties()->SetStringProperty(props, vr::Prop_NamedIconPathDeviceNotReady_String, IsRightHand() ? "{openglove}/icons/right_controller_status_error.png" : "{openglove}/icons/left_controller_status_error.png"); + vr::VRProperties()->SetStringProperty(props, vr::Prop_NamedIconPathDeviceStandby_String, IsRightHand() ? "{openglove}/icons/right_controller_status_off.png" : "{openglove}/icons/left_controller_status_off.png"); + vr::VRProperties()->SetStringProperty(props, vr::Prop_NamedIconPathDeviceAlertLow_String, IsRightHand() ? "{openglove}/icons/right_controller_status_ready_low.png" : "{openglove}/icons/left_controller_status_ready_low.png"); vr::VRDriverInput()->CreateScalarComponent(props, "/input/joystick/x", &inputComponentHandles_[static_cast(LucidGloveDeviceComponentIndex::JoyX)], vr::VRScalarType_Absolute, vr::VRScalarUnits_NormalizedTwoSided); vr::VRDriverInput()->CreateScalarComponent(props, "/input/joystick/y", &inputComponentHandles_[static_cast(LucidGloveDeviceComponentIndex::JoyY)], vr::VRScalarType_Absolute, vr::VRScalarUnits_NormalizedTwoSided); @@ -54,7 +58,7 @@ void LucidGloveDeviceDriver::SetupProps(vr::PropertyContainerHandle_t& props) { vr::VRDriverInput()->CreateBooleanComponent(props, "/input/trigger/click", &inputComponentHandles_[static_cast(LucidGloveDeviceComponentIndex::BtnTrg)]); - vr::VRDriverInput()->CreateBooleanComponent(props, isRightHand ? "/input/A/click" : "/input/system/click", &inputComponentHandles_[static_cast(LucidGloveDeviceComponentIndex::BtnA)]); + vr::VRDriverInput()->CreateBooleanComponent(props, "/input/A/click", &inputComponentHandles_[static_cast(LucidGloveDeviceComponentIndex::BtnA)]); vr::VRDriverInput()->CreateBooleanComponent(props, "/input/B/click", &inputComponentHandles_[static_cast(LucidGloveDeviceComponentIndex::BtnB)]); diff --git a/src/DeviceProvider.cpp b/src/DeviceProvider.cpp index a793fa9a..b6c9291c 100644 --- a/src/DeviceProvider.cpp +++ b/src/DeviceProvider.cpp @@ -1,18 +1,11 @@ #include #include -#include #include -#include "Communication/BTSerialCommunicationManager.h" -#include "Communication/NamedPipeCommunicationManager.h" -#include "Communication/SerialCommunicationManager.h" #include "DeviceDriver/KnuckleDriver.h" #include "DeviceDriver/LucidGloveDriver.h" #include "DriverLog.h" -#include "Encode/AlphaEncodingManager.h" -#include "Encode/LegacyEncodingManager.h" -#include "Util/Quaternion.h" #include "Util/Windows.h" #ifndef GIT_COMMIT_HASH @@ -36,159 +29,103 @@ vr::EVRInitError DeviceProvider::Init(vr::IVRDriverContext* pDriverContext) { // Create background process for the overlay (used for finding controllers to bind to for tracking) if (!CreateBackgroundProcess(driverPath + R"(\bin\win64\openglove_overlay.exe)")) { - DriverLog("Could not create background process: %c", GetLastErrorAsString().c_str()); + DriverLog("Could not create background process: %s", GetLastErrorAsString().c_str()); return vr::VRInitError_Init_FileNotFound; } - const VRDeviceConfiguration leftConfiguration = GetDeviceConfiguration(vr::TrackedControllerRole_LeftHand); - const VRDeviceConfiguration rightConfiguration = GetDeviceConfiguration(vr::TrackedControllerRole_RightHand); - - const auto boneAnimator = std::make_shared(driverPath + R"(\resources\anims\glove_anim.glb)"); - - if (leftConfiguration.enabled) { - leftHand_ = InstantiateDeviceDriver(leftConfiguration, boneAnimator); - vr::VRServerDriverHost()->TrackedDeviceAdded(leftHand_->GetSerialNumber().c_str(), vr::TrackedDeviceClass_Controller, leftHand_.get()); - } - - if (rightConfiguration.enabled) { - rightHand_ = InstantiateDeviceDriver(rightConfiguration, boneAnimator); - vr::VRServerDriverHost()->TrackedDeviceAdded(rightHand_->GetSerialNumber().c_str(), vr::TrackedDeviceClass_Controller, rightHand_.get()); - } + InitialiseDeviceDriver(vr::ETrackedControllerRole::TrackedControllerRole_LeftHand); + InitialiseDeviceDriver(vr::ETrackedControllerRole::TrackedControllerRole_RightHand); return vr::VRInitError_None; } -std::unique_ptr DeviceProvider::InstantiateDeviceDriver( - VRDeviceConfiguration configuration, std::shared_ptr boneAnimator) const { - std::unique_ptr communicationManager; - std::unique_ptr encodingManager; +void DeviceProvider::InitialiseDeviceDriver(const vr::ETrackedControllerRole& role) { + deviceConfigurations_[role] = GetDriverConfiguration(role); + const VRDriverConfiguration& configuration = deviceConfigurations_.at(role); - const bool isRightHand = configuration.role == vr::TrackedControllerRole_RightHand; - - switch (configuration.encodingProtocol) { - default: - DriverLog("No encoding protocol set. Using legacy."); - case VREncodingProtocol::Legacy: { - const float maxAnalogValue = vr::VRSettings()->GetFloat(c_legacyEncodingSettingsSection, "max_analog_value"); - encodingManager = std::make_unique(maxAnalogValue); - break; - } - case VREncodingProtocol::Alpha: { - const float maxAnalogValue = vr::VRSettings()->GetFloat(c_alphaEncodingSettingsSection, "max_analog_value"); - encodingManager = std::make_unique(maxAnalogValue); - break; - } + if (!configuration.enabled) { + DriverLog("Not enabling device as it was disabled in configuration."); + return; } - switch (configuration.communicationProtocol) { - case VRCommunicationProtocol::NamedPipe: { - DriverLog("Communication set to Named Pipe"); - const std::string path = R"(\\.\pipe\vrapplication\input\glove\$version\)" + std::string(isRightHand ? "right" : "left"); - VRNamedPipeInputConfiguration namedPipeConfiguration(path); - communicationManager = std::make_unique(namedPipeConfiguration, configuration); - break; - } - case VRCommunicationProtocol::BtSerial: { - DriverLog("Communication set to BTSerial"); - char name[248]; - vr::VRSettings()->GetString(c_btserialCommunicationSettingsSection, isRightHand ? "right_name" : "left_name", name, sizeof name); - VRBTSerialConfiguration btSerialSettings(name); - communicationManager = std::make_unique(std::move(encodingManager), btSerialSettings, configuration); - break; - } - default: - DriverLog("No communication protocol set. Using serial."); - case VRCommunicationProtocol::Serial: - char port[16]; - vr::VRSettings()->GetString(c_serialCommunicationSettingsSection, isRightHand ? "right_port" : "left_port", port, sizeof port); - const int baudRate = vr::VRSettings()->GetInt32(c_serialCommunicationSettingsSection, "baud_rate"); - VRSerialConfiguration serialSettings(port, baudRate); - - communicationManager = std::make_unique(std::move(encodingManager), serialSettings, configuration); - break; - } + devices_[role] = InstantiateDeviceDriver(configuration); + const std::unique_ptr& device = devices_.at(role); - switch (configuration.deviceDriver) { - case VRDeviceDriver::EmulatedKnuckles: { - char serialNumber[32]; - vr::VRSettings()->GetString( - c_knuckleDeviceSettingsSection, isRightHand ? "right_serial_number" : "left_serial_number", serialNumber, sizeof serialNumber); - bool approximateThumb = vr::VRSettings()->GetBool(c_knuckleDeviceSettingsSection, "approximate_thumb"); - return std::make_unique( - std::move(communicationManager), std::move(boneAnimator), serialNumber, approximateThumb, configuration); - } + // this device hasn't previously been registered, so register it with SteamVR + vr::VRServerDriverHost()->TrackedDeviceAdded(device->GetSerialNumber().c_str(), vr::TrackedDeviceClass_Controller, device.get()); +} - default: - DriverLog("No device driver selected. Using lucidgloves."); - case VRDeviceDriver::LucidGloves: { - char serialNumber[32]; - vr::VRSettings()->GetString( - c_lucidGloveDeviceSettingsSection, isRightHand ? "right_serial_number" : "left_serial_number", serialNumber, sizeof serialNumber); +std::unique_ptr DeviceProvider::InstantiateDeviceDriver(const VRDriverConfiguration& configuration) const { + switch (configuration.deviceConfiguration.deviceType) { + case VRDeviceType::EmulatedKnuckles: { + DriverLog("Using knuckles device driver"); + return std::make_unique(configuration.deviceConfiguration); + } - return std::make_unique(std::move(communicationManager), std::move(boneAnimator), serialNumber, configuration); + case VRDeviceType::LucidGloves: { + DriverLog("Using lucidgloves device driver"); + return std::make_unique(configuration.deviceConfiguration); } } } -VRDeviceConfiguration DeviceProvider::GetDeviceConfiguration(const vr::ETrackedControllerRole role) { - const bool isRightHand = role == vr::TrackedControllerRole_RightHand; - - DriverLog("Getting configuration for: %s", isRightHand ? "Right hand" : "Left hand"); - - const bool isEnabled = vr::VRSettings()->GetBool(c_driverSettingsSection, isRightHand ? "right_enabled" : "left_enabled"); - const bool feedbackEnabled = vr::VRSettings()->GetBool(c_driverSettingsSection, "feedback_enabled"); - const bool indexCurlTrigger = vr::VRSettings()->GetBool(c_knuckleDeviceSettingsSection, "index_curl_as_trigger"); - - const auto communicationProtocol = - static_cast(vr::VRSettings()->GetInt32(c_driverSettingsSection, "communication_protocol")); - const auto encodingProtocol = static_cast(vr::VRSettings()->GetInt32(c_driverSettingsSection, "encoding_protocol")); - const auto deviceDriver = static_cast(vr::VRSettings()->GetInt32(c_driverSettingsSection, "device_driver")); - - const float poseTimeOffset = vr::VRSettings()->GetFloat(c_poseSettingsSection, "pose_time_offset"); - - const float offsetXPos = vr::VRSettings()->GetFloat(c_poseSettingsSection, isRightHand ? "right_x_offset_position" : "left_x_offset_position"); - const float offsetYPos = vr::VRSettings()->GetFloat(c_poseSettingsSection, isRightHand ? "right_y_offset_position" : "left_y_offset_position"); - const float offsetZPos = vr::VRSettings()->GetFloat(c_poseSettingsSection, isRightHand ? "right_z_offset_position" : "left_z_offset_position"); +void DeviceProvider::Cleanup() {} - const float offsetXRot = vr::VRSettings()->GetFloat(c_poseSettingsSection, isRightHand ? "right_x_offset_degrees" : "left_x_offset_degrees"); - const float offsetYRot = vr::VRSettings()->GetFloat(c_poseSettingsSection, isRightHand ? "right_y_offset_degrees" : "left_y_offset_degrees"); - const float offsetZRot = vr::VRSettings()->GetFloat(c_poseSettingsSection, isRightHand ? "right_z_offset_degrees" : "left_z_offset_degrees"); +const char* const* DeviceProvider::GetInterfaceVersions() { + return vr::k_InterfaceVersions; +} - const bool controllerOverrideEnabled = vr::VRSettings()->GetBool(c_poseSettingsSection, "controller_override"); - const int controllerIdOverride = - controllerOverrideEnabled - ? vr::VRSettings()->GetInt32(c_poseSettingsSection, isRightHand ? "controller_override_right" : "controller_override_left") - : -1; - const bool calibrationButton = vr::VRSettings()->GetBool(c_poseSettingsSection, "hardware_calibration_button_enabled"); +void DeviceProvider::HandleSettingsUpdate(const vr::ETrackedControllerRole& role) { + const VRDriverConfiguration newConfiguration = GetDriverConfiguration(role); - const vr::HmdVector3_t offsetVector = {offsetXPos, offsetYPos, offsetZPos}; + if (deviceConfigurations_.at(role) == newConfiguration) { + DriverLog("Settings were updated, but opengloves did not need to update"); + return; + } - // Convert the rotation to a quaternion - const vr::HmdQuaternion_t angleOffsetQuaternion = EulerToQuaternion(DegToRad(offsetZRot), DegToRad(offsetYRot), DegToRad(offsetXRot)); + DriverLog( + "A settings change was detected that affects: %s hand", role == vr::ETrackedControllerRole::TrackedControllerRole_RightHand ? "right" : "left"); - return VRDeviceConfiguration( - role, - isEnabled, - feedbackEnabled, - indexCurlTrigger, - VRPoseConfiguration(offsetVector, angleOffsetQuaternion, poseTimeOffset, controllerOverrideEnabled, controllerIdOverride, calibrationButton), - encodingProtocol, - communicationProtocol, - deviceDriver); -} + // we have something that's updated. -void DeviceProvider::Cleanup() {} + deviceConfigurations_[role] = newConfiguration; -const char* const* DeviceProvider::GetInterfaceVersions() { - return vr::k_InterfaceVersions; + if (devices_.count(role) > 0) { + if (newConfiguration.enabled) { + DriverLog("Settings were updated, and attempting to update device"); + devices_.at(role)->UpdateDeviceConfiguration(newConfiguration.deviceConfiguration); + } else { + DriverLog("Settings were updated, and attempting to deactivate device as it was disabled"); + devices_.at(role)->DisableDevice(); + } + } else { + if (newConfiguration.enabled) { + DriverLog("Settings were updated, and need to initialise new device"); + InitialiseDeviceDriver(role); + } + } } void DeviceProvider::RunFrame() { vr::VREvent_t pEvent; while (vr::VRServerDriverHost()->PollNextEvent(&pEvent, sizeof(pEvent))) { - if (leftHand_ && leftHand_->IsActive()) leftHand_->OnEvent(pEvent); - if (rightHand_ && rightHand_->IsActive()) rightHand_->OnEvent(pEvent); + switch (pEvent.eventType) { + case vr::EVREventType::VREvent_OtherSectionSettingChanged: { + DriverLog("A settings change was detected that might affect our drivers..."); + + HandleSettingsUpdate(vr::ETrackedControllerRole::TrackedControllerRole_RightHand); + HandleSettingsUpdate(vr::ETrackedControllerRole::TrackedControllerRole_LeftHand); + + break; + } + + default: { + for (auto const& ptr : devices_) { + if (ptr.second->IsActive()) ptr.second->OnEvent(pEvent); + } + } + } } } diff --git a/src/Encode/AlphaEncodingManager.cpp b/src/Encode/AlphaEncodingManager.cpp index 080a706c..7f3c8087 100644 --- a/src/Encode/AlphaEncodingManager.cpp +++ b/src/Encode/AlphaEncodingManager.cpp @@ -166,53 +166,53 @@ VRInputData AlphaEncodingManager::Decode(const std::string& input) { VRInputData result; std::array flexion = {-1.0f, -1.0f, -1.0f, -1.0f, -1.0f}; - + // This map contains all the inputs we've got from the packet we received std::map inputMap = ParseInputToMap(input); // curl is 0.0f -> 1.0f inclusive if (inputMap.find(VRCommDataAlphaEncodingKey::FinThumb) != inputMap.end()) - flexion[0] = std::stof(inputMap.at(VRCommDataAlphaEncodingKey::FinThumb)) / maxAnalogValue_; + flexion[0] = std::stof(inputMap.at(VRCommDataAlphaEncodingKey::FinThumb)) / configuration_.maxAnalogValue; if (inputMap.find(VRCommDataAlphaEncodingKey::FinIndex) != inputMap.end()) - flexion[1] = std::stof(inputMap.at(VRCommDataAlphaEncodingKey::FinIndex)) / maxAnalogValue_; + flexion[1] = std::stof(inputMap.at(VRCommDataAlphaEncodingKey::FinIndex)) / configuration_.maxAnalogValue; if (inputMap.find(VRCommDataAlphaEncodingKey::FinMiddle) != inputMap.end()) - flexion[2] = std::stof(inputMap.at(VRCommDataAlphaEncodingKey::FinMiddle)) / maxAnalogValue_; + flexion[2] = std::stof(inputMap.at(VRCommDataAlphaEncodingKey::FinMiddle)) / configuration_.maxAnalogValue; if (inputMap.find(VRCommDataAlphaEncodingKey::FinRing) != inputMap.end()) - flexion[3] = std::stof(inputMap.at(VRCommDataAlphaEncodingKey::FinRing)) / maxAnalogValue_; + flexion[3] = std::stof(inputMap.at(VRCommDataAlphaEncodingKey::FinRing)) / configuration_.maxAnalogValue; if (inputMap.find(VRCommDataAlphaEncodingKey::FinPinky) != inputMap.end()) - flexion[4] = std::stof(inputMap.at(VRCommDataAlphaEncodingKey::FinPinky)) / maxAnalogValue_; + flexion[4] = std::stof(inputMap.at(VRCommDataAlphaEncodingKey::FinPinky)) / configuration_.maxAnalogValue; // fill all the joints int curJoint = (int)VRCommDataAlphaEncodingKey::FinJointThumb0; for (int i = 0; i < 5; i++) { for (int k = 0; k < 4; k++) { VRCommDataAlphaEncodingKey joint = static_cast(curJoint); - result.flexion[i][k] = inputMap.find(joint) != inputMap.end() ? (std::stof(inputMap.at(joint)) / maxAnalogValue_) : flexion[i]; + result.flexion[i][k] = inputMap.find(joint) != inputMap.end() ? (std::stof(inputMap.at(joint)) / configuration_.maxAnalogValue) : flexion[i]; curJoint++; } } // splay is -1.0f -> 1.0f inclusive if (inputMap.find(VRCommDataAlphaEncodingKey::FinSplayThumb) != inputMap.end()) - result.splay[0] = (std::stof(inputMap.at(VRCommDataAlphaEncodingKey::FinSplayThumb)) / maxAnalogValue_ - 0.5f) * 2.0f; + result.splay[0] = (std::stof(inputMap.at(VRCommDataAlphaEncodingKey::FinSplayThumb)) / configuration_.maxAnalogValue - 0.5f) * 2.0f; if (inputMap.find(VRCommDataAlphaEncodingKey::FinSplayIndex) != inputMap.end()) - result.splay[1] = (std::stof(inputMap.at(VRCommDataAlphaEncodingKey::FinSplayIndex)) / maxAnalogValue_ - 0.5f) * 2.0f; + result.splay[1] = (std::stof(inputMap.at(VRCommDataAlphaEncodingKey::FinSplayIndex)) / configuration_.maxAnalogValue - 0.5f) * 2.0f; if (inputMap.find(VRCommDataAlphaEncodingKey::FinSplayMiddle) != inputMap.end()) - result.splay[2] = (std::stof(inputMap.at(VRCommDataAlphaEncodingKey::FinSplayMiddle)) / maxAnalogValue_ - 0.5f) * 2.0f; + result.splay[2] = (std::stof(inputMap.at(VRCommDataAlphaEncodingKey::FinSplayMiddle)) / configuration_.maxAnalogValue - 0.5f) * 2.0f; if (inputMap.find(VRCommDataAlphaEncodingKey::FinSplayRing) != inputMap.end()) - result.splay[3] = (std::stof(inputMap.at(VRCommDataAlphaEncodingKey::FinSplayRing)) / maxAnalogValue_ - 0.5f) * 2.0f; + result.splay[3] = (std::stof(inputMap.at(VRCommDataAlphaEncodingKey::FinSplayRing)) / configuration_.maxAnalogValue - 0.5f) * 2.0f; if (inputMap.find(VRCommDataAlphaEncodingKey::FinSplayPinky) != inputMap.end()) - result.splay[4] = (std::stof(inputMap.at(VRCommDataAlphaEncodingKey::FinSplayPinky)) / maxAnalogValue_ - 0.5f) * 2.0f; + result.splay[4] = (std::stof(inputMap.at(VRCommDataAlphaEncodingKey::FinSplayPinky)) / configuration_.maxAnalogValue - 0.5f) * 2.0f; // joystick axis are -1.0f -> 1.0f inclusive if (inputMap.find(VRCommDataAlphaEncodingKey::JoyX) != inputMap.end()) - result.joyX = 2 * std::stof(inputMap.at(VRCommDataAlphaEncodingKey::JoyX)) / maxAnalogValue_ - 1; + result.joyX = 2 * std::stof(inputMap.at(VRCommDataAlphaEncodingKey::JoyX)) / configuration_.maxAnalogValue - 1; if (inputMap.find(VRCommDataAlphaEncodingKey::JoyY) != inputMap.end()) - result.joyY = 2 * std::stof(inputMap.at(VRCommDataAlphaEncodingKey::JoyY)) / maxAnalogValue_ - 1; + result.joyY = 2 * std::stof(inputMap.at(VRCommDataAlphaEncodingKey::JoyY)) / configuration_.maxAnalogValue - 1; // trigger value is 0.0f -> 1.0f inclusive if (inputMap.find(VRCommDataAlphaEncodingKey::TrgValue) != inputMap.end()) - result.trgValue = std::stof(inputMap.at(VRCommDataAlphaEncodingKey::TrgValue)) / maxAnalogValue_; + result.trgValue = std::stof(inputMap.at(VRCommDataAlphaEncodingKey::TrgValue)) / configuration_.maxAnalogValue; result.joyButton = inputMap.find(VRCommDataAlphaEncodingKey::JoyBtn) != inputMap.end(); result.trgButton = inputMap.find(VRCommDataAlphaEncodingKey::BtnTrg) != inputMap.end(); diff --git a/src/Encode/LegacyEncodingManager.cpp b/src/Encode/LegacyEncodingManager.cpp index 41728448..08d88f71 100644 --- a/src/Encode/LegacyEncodingManager.cpp +++ b/src/Encode/LegacyEncodingManager.cpp @@ -20,8 +20,6 @@ enum class VRCommDataLegacyEncodingPosition : int { Max }; -LegacyEncodingManager::LegacyEncodingManager(const float maxAnalogValue) : EncodingManager(maxAnalogValue) {} - VRInputData LegacyEncodingManager::Decode(const std::string& input) { VRInputData result; @@ -38,11 +36,11 @@ VRInputData LegacyEncodingManager::Decode(const std::string& input) { std::array flexion{}; for (uint8_t flexionI = 0; flexionI < 5; flexionI++) { - for (int k = 0; k < 4; k++) result.flexion[flexionI][k] = tokens[flexionI] / maxAnalogValue_; + for (int k = 0; k < 4; k++) result.flexion[flexionI][k] = tokens[flexionI] / configuration_.maxAnalogValue; } - result.joyX = 2 * tokens[static_cast(VRCommDataLegacyEncodingPosition::JoyX)] / maxAnalogValue_ - 1; - result.joyY = 2 * tokens[static_cast(VRCommDataLegacyEncodingPosition::JoyY)] / maxAnalogValue_ - 1; + result.joyX = 2 * tokens[static_cast(VRCommDataLegacyEncodingPosition::JoyX)] / configuration_.maxAnalogValue - 1; + result.joyY = 2 * tokens[static_cast(VRCommDataLegacyEncodingPosition::JoyY)] / configuration_.maxAnalogValue - 1; result.joyButton = tokens[static_cast(VRCommDataLegacyEncodingPosition::JoyBtn)] == 1; @@ -66,5 +64,8 @@ std::string LegacyEncodingManager::Encode(const VROutput& input) { const VRHapticData& data = input.data.hapticData; return StringFormat("%.2f&%.2f&%.2f&", data.duration, data.frequency, data.amplitude); } + + default: + return ""; } } \ No newline at end of file diff --git a/src/Util/Quaternion.cpp b/src/Util/Quaternion.cpp index 10c4bf55..476bbe6e 100644 --- a/src/Util/Quaternion.cpp +++ b/src/Util/Quaternion.cpp @@ -1,3 +1,5 @@ +#define _USE_MATH_DEFINES + #include "Util/Quaternion.h" #include @@ -5,28 +7,20 @@ double DegToRad(const double degrees) { return degrees * M_PI / 180.0; } +float DegToRad(const float degrees) { + return degrees * M_PI / 180.0; +} + double RadToDeg(const double rad) { return rad * 180.0 / M_PI; } -vr::HmdVector3_t GetPosition(const vr::HmdMatrix34_t& matrix) { - vr::HmdVector3_t vector{}; - - vector.v[0] = matrix.m[0][3]; - vector.v[1] = matrix.m[1][3]; - vector.v[2] = matrix.m[2][3]; - - return vector; +float RadToDeg(const float rad) { + return rad * 180.0 / M_PI; } -vr::HmdVector3_t CombinePosition(const vr::HmdMatrix34_t& matrix, const vr::HmdVector3_t& vec) { - vr::HmdVector3_t vector{}; - - vector.v[0] = matrix.m[0][3] + vec.v[0]; - vector.v[1] = matrix.m[1][3] + vec.v[1]; - vector.v[2] = matrix.m[2][3] + vec.v[2]; - - return vector; +vr::HmdVector3d_t GetPosition(const vr::HmdMatrix34_t& matrix) { + return {matrix.m[0][3], matrix.m[1][3], matrix.m[2][3]}; } vr::HmdQuaternion_t GetRotation(const vr::HmdMatrix34_t& matrix) { @@ -45,26 +39,14 @@ vr::HmdQuaternion_t GetRotation(const vr::HmdMatrix34_t& matrix) { } vr::HmdMatrix33_t GetRotationMatrix(const vr::HmdMatrix34_t& matrix) { - const vr::HmdMatrix33_t result = { + return { {{matrix.m[0][0], matrix.m[0][1], matrix.m[0][2]}, {matrix.m[1][0], matrix.m[1][1], matrix.m[1][2]}, {matrix.m[2][0], matrix.m[2][1], matrix.m[2][2]}}}; - - return result; -} - -vr::HmdVector3_t MultiplyMatrix(const vr::HmdMatrix33_t& matrix, const vr::HmdVector3_t& vector) { - vr::HmdVector3_t result{}; - - result.v[0] = matrix.m[0][0] * vector.v[0] + matrix.m[0][1] * vector.v[1] + matrix.m[0][2] * vector.v[2]; - result.v[1] = matrix.m[1][0] * vector.v[0] + matrix.m[1][1] * vector.v[1] + matrix.m[1][2] * vector.v[2]; - result.v[2] = matrix.m[2][0] * vector.v[0] + matrix.m[2][1] * vector.v[1] + matrix.m[2][2] * vector.v[2]; - - return result; } vr::HmdMatrix33_t QuaternionToMatrix(const vr::HmdQuaternion_t& q) { - const vr::HmdMatrix33_t result = { + return { {{static_cast(1 - 2 * q.y * q.y - 2 * q.z * q.z), static_cast(2 * q.x * q.y - 2 * q.z * q.w), static_cast(2 * q.x * q.z + 2 * q.y * q.w)}, @@ -74,16 +56,53 @@ vr::HmdMatrix33_t QuaternionToMatrix(const vr::HmdQuaternion_t& q) { {static_cast(2 * q.x * q.z - 2 * q.y * q.w), static_cast(2 * q.y * q.z + 2 * q.x * q.w), static_cast(1 - 2 * q.x * q.x - 2 * q.y * q.y)}}}; +} + +vr::HmdQuaternion_t EulerToQuaternion(const double& yaw, const double& pitch, const double& roll) { + const double cy = cos(yaw * 0.5); + const double sy = sin(yaw * 0.5); + const double cp = cos(pitch * 0.5); + const double sp = sin(pitch * 0.5); + const double cr = cos(roll * 0.5); + const double sr = sin(roll * 0.5); + + vr::HmdQuaternion_t q{}; + q.w = cr * cp * cy + sr * sp * sy; + q.x = sr * cp * cy - cr * sp * sy; + q.y = cr * sp * cy + sr * cp * sy; + q.z = cr * cp * sy - sr * sp * cy; + + return q; +} + +vr::HmdVector3d_t QuaternionToEuler(const vr::HmdQuaternion_t& q) { + vr::HmdVector3d_t result{}; + + // roll (x-axis rotation) + const double sinr_cosp = 2 * (q.w * q.x + q.y * q.z); + const double cosr_cosp = 1 - 2 * (q.x * q.x + q.y * q.y); + result.v[2] = std::atan2(sinr_cosp, cosr_cosp); + + // pitch (y-axis rotation) + const double sinp = 2 * (q.w * q.y - q.z * q.x); + if (std::abs(sinp) >= 1) + result.v[1] = std::copysign(M_PI / 2, sinp); // use 90 degrees if out of range + else + result.v[1] = std::asin(sinp); + + // yaw (z-axis rotation) + const double siny_cosp = 2 * (q.w * q.z + q.x * q.y); + const double cosy_cosp = 1 - 2 * (q.y * q.y + q.z * q.z); + result.v[0] = std::atan2(siny_cosp, cosy_cosp); return result; } -vr::HmdQuaternion_t QuatConjugate(const vr::HmdQuaternion_t& q) { - const vr::HmdQuaternion_t quat = {q.w, -q.x, -q.y, -q.z}; - return quat; +vr::HmdQuaternion_t operator-(const vr::HmdQuaternion_t& q) { + return {q.w, -q.x, -q.y, -q.z}; } -vr::HmdQuaternion_t MultiplyQuaternion(const vr::HmdQuaternion_t& q, const vr::HmdQuaternion_t& r) { +vr::HmdQuaternion_t operator*(const vr::HmdQuaternion_t& q, const vr::HmdQuaternion_t& r) { vr::HmdQuaternion_t result{}; result.w = r.w * q.w - r.x * q.x - r.y * q.y - r.z * q.z; @@ -94,7 +113,7 @@ vr::HmdQuaternion_t MultiplyQuaternion(const vr::HmdQuaternion_t& q, const vr::H return result; } -vr::HmdQuaternionf_t MultiplyQuaternion(const vr::HmdQuaternionf_t& q, const vr::HmdQuaternion_t& r) { +vr::HmdQuaternionf_t operator*(const vr::HmdQuaternionf_t& q, const vr::HmdQuaternion_t& r) { vr::HmdQuaternionf_t result{}; result.w = r.w * q.w - r.x * q.x - r.y * q.y - r.z * q.z; @@ -105,42 +124,57 @@ vr::HmdQuaternionf_t MultiplyQuaternion(const vr::HmdQuaternionf_t& q, const vr: return result; } -vr::HmdQuaternion_t EulerToQuaternion(const double& yaw, const double& pitch, const double& roll) { - const double cy = cos(yaw * 0.5); - const double sy = sin(yaw * 0.5); - const double cp = cos(pitch * 0.5); - const double sp = sin(pitch * 0.5); - const double cr = cos(roll * 0.5); - const double sr = sin(roll * 0.5); +vr::HmdVector3_t operator+(const vr::HmdMatrix34_t& matrix, const vr::HmdVector3_t& vec) { + vr::HmdVector3_t vector{}; - vr::HmdQuaternion_t q{}; - q.w = cr * cp * cy + sr * sp * sy; - q.x = sr * cp * cy - cr * sp * sy; - q.y = cr * sp * cy + sr * cp * sy; - q.z = cr * cp * sy - sr * sp * cy; + vector.v[0] = matrix.m[0][3] + vec.v[0]; + vector.v[1] = matrix.m[1][3] + vec.v[1]; + vector.v[2] = matrix.m[2][3] + vec.v[2]; - return q; + return vector; } -vr::HmdVector3_t QuaternionToEuler(const vr::HmdQuaternion_t& q) { - vr::HmdVector3_t result; - const double unit = (q.x * q.x) + (q.y * q.y) + (q.z * q.z) + (q.w * q.w); - - const float test = q.x * q.w - q.y * q.z; +vr::HmdVector3_t operator*(const vr::HmdMatrix33_t& matrix, const vr::HmdVector3_t& vec) { + vr::HmdVector3_t result{}; - if (test > 0.4995f * unit) { - result.v[0] = M_PI / 2; - result.v[1] = (2 * atan2(q.y / unit, q.x / unit)); - result.v[2] = 0; - } else if (test < -0.4995f * unit) { - result.v[0] = -M_PI / 2; - result.v[1] = (-2 * atan2(q.y / unit, q.x / unit)); - result.v[2] = 0; - } else { - result.v[0] = asin(2 * (q.w * q.x - q.y * q.z) / unit); - result.v[1] = atan2((2 / unit * q.w * q.y + 2 / unit * q.z * q.x), (1 - 2 / unit * (q.x * q.x + q.y * q.y))); - result.v[2] = atan2((2 / unit * q.w * q.z + 2 / unit * q.x * q.y), (1 - 2 / unit * (q.z * q.z + q.x * q.x))); - } + result.v[0] = matrix.m[0][0] * vec.v[0] + matrix.m[0][1] * vec.v[1] + matrix.m[0][2] * vec.v[2]; + result.v[1] = matrix.m[1][0] * vec.v[0] + matrix.m[1][1] * vec.v[1] + matrix.m[1][2] * vec.v[2]; + result.v[2] = matrix.m[2][0] * vec.v[0] + matrix.m[2][1] * vec.v[1] + matrix.m[2][2] * vec.v[2]; return result; +} + +vr::HmdVector3_t operator-(const vr::HmdVector3_t& vec, const vr::HmdMatrix34_t& matrix) { + return {vec.v[0] - matrix.m[0][3], vec.v[1] - matrix.m[1][3], vec.v[2] - matrix.m[2][3]}; +} + +vr::HmdVector3d_t operator+(const vr::HmdVector3d_t& vec1, const vr::HmdVector3d_t& vec2) { + return {vec1.v[0] + vec2.v[0], vec1.v[1] + vec2.v[1], vec1.v[2] + vec2.v[2]}; +} +vr::HmdVector3d_t operator-(const vr::HmdVector3d_t& vec1, const vr::HmdVector3d_t& vec2) { + return {vec1.v[0] - vec2.v[0], vec1.v[1] - vec2.v[1], vec1.v[2] - vec2.v[2]}; +} + +vr::HmdVector3d_t operator*(const vr::HmdVector3d_t& vec, const vr::HmdQuaternion_t& q) { + const vr::HmdQuaternion_t qVec = {1.0, vec.v[0], vec.v[1], vec.v[2]}; + + const vr::HmdQuaternion_t qResult = q * qVec * -q; + + return {qResult.x, qResult.y, qResult.z}; +} + +vr::HmdVector3_t operator*(const vr::HmdVector3_t& vec, const vr::HmdQuaternion_t& q) { + const vr::HmdQuaternion_t qVec = {1.0, vec.v[0], vec.v[1], vec.v[2]}; + + const vr::HmdQuaternion_t qResult = q * qVec * -q; + + return {static_cast(qResult.x), static_cast(qResult.y), static_cast(qResult.z)}; +} + +bool operator==(const vr::HmdVector3d_t& v1, const vr::HmdVector3d_t& v2) { + return v1.v[0] == v2.v[0] && v1.v[1] == v2.v[1] && v1.v[2] == v2.v[2]; +} + +bool operator==(const vr::HmdQuaternion_t& q1, const vr::HmdQuaternion_t& q2) { + return q1.w == q2.w && q1.x == q2.x && q1.y == q2.y && q1.z == q2.z; } \ No newline at end of file