diff --git a/.gitmodules b/.gitmodules index 269287b7..d342de21 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "libraries/openvr"] path = libraries/openvr - url = https://github.com/ValveSoftware/openvr.git \ No newline at end of file + url = https://github.com/ValveSoftware/openvr.git +[submodule "libraries/tinygltf"] + path = libraries/tinygltf + url = https://github.com/syoyo/tinygltf.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ddb365b..007ffc13 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,7 @@ set_property(GLOBAL PROPERTY USE_FOLDERS ON) # Deps set(OPENVR_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/libraries/openvr/headers") +set(TINYGLTF_INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/libraries/tinygltf") set(SIZEOF_VOIDP ${CMAKE_SIZEOF_VOID_P}) @@ -35,7 +36,7 @@ file(GLOB_RECURSE SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp") add_library("${OPENGLOVE_PROJECT}" SHARED "${HEADERS}" "${SOURCES}") -target_include_directories("${OPENGLOVE_PROJECT}" PUBLIC "${OPENVR_INCLUDE_DIR}") +target_include_directories("${OPENGLOVE_PROJECT}" PUBLIC "${OPENVR_INCLUDE_DIR}" "${TINYGLTF_INCLUDE_DIR}") target_include_directories("${OPENGLOVE_PROJECT}" PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include/") target_link_libraries("${OPENGLOVE_PROJECT}" PUBLIC "${OPENVR_LIB}" setupapi wsock32 ws2_32 bthprops) diff --git a/include/Bones.h b/include/Bones.h index cc36b6bf..3d923cae 100644 --- a/include/Bones.h +++ b/include/Bones.h @@ -1,56 +1,83 @@ #pragma once -#include + #include +#include -const int NUM_BONES = 31; -extern vr::VRBoneTransform_t rightOpenPose[NUM_BONES]; -extern vr::VRBoneTransform_t rightFistPose[NUM_BONES]; +#include "openvr_driver.h" + +enum class HandSkeletonBone : vr::BoneIndex_t { + eBone_Root = 0, + eBone_Wrist, + eBone_Thumb0, + eBone_Thumb1, + eBone_Thumb2, + eBone_Thumb3, + eBone_IndexFinger0, + eBone_IndexFinger1, + eBone_IndexFinger2, + eBone_IndexFinger3, + eBone_IndexFinger4, + eBone_MiddleFinger0, + eBone_MiddleFinger1, + eBone_MiddleFinger2, + eBone_MiddleFinger3, + eBone_MiddleFinger4, + eBone_RingFinger0, + eBone_RingFinger1, + eBone_RingFinger2, + eBone_RingFinger3, + eBone_RingFinger4, + eBone_PinkyFinger0, + eBone_PinkyFinger1, + eBone_PinkyFinger2, + eBone_PinkyFinger3, + eBone_PinkyFinger4, + eBone_Aux_Thumb, + eBone_Aux_IndexFinger, + eBone_Aux_MiddleFinger, + eBone_Aux_RingFinger, + eBone_Aux_PinkyFinger, + eBone_Count +}; +const short NUM_BONES = (short)HandSkeletonBone::eBone_Count; + +extern vr::VRBoneTransform_t rightOpenPose[NUM_BONES]; extern vr::VRBoneTransform_t leftOpenPose[NUM_BONES]; -extern vr::VRBoneTransform_t leftFistPose[NUM_BONES]; - -enum HandSkeletonBone : vr::BoneIndex_t { - eBone_Root = 0, - eBone_Wrist, - eBone_Thumb0, - eBone_Thumb1, - eBone_Thumb2, - eBone_Thumb3, - eBone_IndexFinger0, - eBone_IndexFinger1, - eBone_IndexFinger2, - eBone_IndexFinger3, - eBone_IndexFinger4, - eBone_MiddleFinger0, - eBone_MiddleFinger1, - eBone_MiddleFinger2, - eBone_MiddleFinger3, - eBone_MiddleFinger4, - eBone_RingFinger0, - eBone_RingFinger1, - eBone_RingFinger2, - eBone_RingFinger3, - eBone_RingFinger4, - eBone_PinkyFinger0, - eBone_PinkyFinger1, - eBone_PinkyFinger2, - eBone_PinkyFinger3, - eBone_PinkyFinger4, - eBone_Aux_Thumb, - eBone_Aux_IndexFinger, - eBone_Aux_MiddleFinger, - eBone_Aux_RingFinger, - eBone_Aux_PinkyFinger, - eBone_Count + +struct Transform_t { + Transform_t(); + std::array rotation; + std::array translation; }; -void ComputeHand(vr::VRBoneTransform_t* skeleton, const std::array& flexion, bool isRightHand); -void ComputeBoneFlexion(vr::VRBoneTransform_t* bone_transform, float transform, int index, const bool isRightHand); +struct AnimationData_t { + AnimationData_t(); + Transform_t startTransform; + float startTime; + Transform_t endTransform; + float endTime; +}; + +class IModelManager { + public: + virtual bool Load() = 0; + + virtual AnimationData_t GetAnimationDataByBoneIndex(const HandSkeletonBone& boneIndex, float f) const = 0; + virtual Transform_t GetTransformByBoneIndex(const HandSkeletonBone& boneIndex) const = 0; +}; + +class BoneAnimator { + public: + BoneAnimator(const std::string& fileName); + void ComputeSkeletonTransforms(vr::VRBoneTransform_t* skeleton, const std::array& flexion, const bool rightHand); + void TransformLeftBone(vr::VRBoneTransform_t& bone, const HandSkeletonBone& boneIndex); + + private: + vr::VRBoneTransform_t GetTransformForBone(const HandSkeletonBone& boneIndex, const float f, const bool rightHand); -vr::HmdQuaternionf_t CalculateOrientation(const float transform, const int boneIndex, const vr::VRBoneTransform_t* openPose, const vr::VRBoneTransform_t* fistPose); -vr::HmdVector4_t CalculatePosition(const float transform, const int boneIndex, const vr::VRBoneTransform_t* openPose, const vr::VRBoneTransform_t* fistPose); -int FingerFromBone(vr::BoneIndex_t bone); -/** -*Linear interpolation between a and b. -**/ -float Lerp(const float a, const float b, const float f); \ No newline at end of file + std::string m_fileName; + std::unique_ptr m_modelManager; + bool m_loaded; + std::vector m_keyframes; +}; \ No newline at end of file diff --git a/include/Communication/BTSerialCommunicationManager.h b/include/Communication/BTSerialCommunicationManager.h index b75e7789..bfde2704 100644 --- a/include/Communication/BTSerialCommunicationManager.h +++ b/include/Communication/BTSerialCommunicationManager.h @@ -16,8 +16,6 @@ #include "DeviceConfiguration.h" #include "DriverLog.h" -static const char* c_btserialCommunicationSettingsSection = "communication_btserial"; - class BTSerialCommunicationManager : public ICommunicationManager { public: BTSerialCommunicationManager(const VRBTSerialConfiguration_t& configuration, std::unique_ptr encodingManager); diff --git a/include/Communication/SerialCommunicationManager.h b/include/Communication/SerialCommunicationManager.h index e1d0722f..29d10556 100644 --- a/include/Communication/SerialCommunicationManager.h +++ b/include/Communication/SerialCommunicationManager.h @@ -11,8 +11,6 @@ #include "CommunicationManager.h" #include "DeviceConfiguration.h" -static const char* c_serialCommunicationSettingsSection = "communication_serial"; - class SerialCommunicationManager : public ICommunicationManager { public: SerialCommunicationManager(const VRSerialConfiguration_t& configuration, std::unique_ptr encodingManager) diff --git a/include/DeviceConfiguration.h b/include/DeviceConfiguration.h index cecee1a5..c9b70e4a 100644 --- a/include/DeviceConfiguration.h +++ b/include/DeviceConfiguration.h @@ -1,12 +1,17 @@ #pragma once +#include "openvr_driver.h" + #include "Communication/CommunicationManager.h" #include "DeviceDriver/DeviceDriver.h" #include "Encode/EncodingManager.h" -#include "openvr_driver.h" -static const char* c_driverSettingsSection = "driver_openglove"; -static const char* c_poseSettingsSection = "pose_settings"; +extern const char* c_poseSettingsSection; +extern const char* c_driverSettingsSection; +extern const char* c_serialCommunicationSettingsSection; +extern const char* c_btserialCommunicationSettingsSection; +extern const char* c_knuckleDeviceSettingsSection; +extern const char* c_lucidGloveDeviceSettingsSection; enum class VRCommunicationProtocol { SERIAL = 0, diff --git a/include/DeviceDriver/KnuckleDriver.h b/include/DeviceDriver/KnuckleDriver.h index f83ac63b..27d3edc8 100644 --- a/include/DeviceDriver/KnuckleDriver.h +++ b/include/DeviceDriver/KnuckleDriver.h @@ -1,6 +1,6 @@ #pragma once -#pragma once -#include + +#include "openvr_driver.h" #include #include @@ -13,11 +13,9 @@ #include "Encode/LegacyEncodingManager.h" #include "ForceFeedback.h" -static const char* c_knuckleDeviceSettingsSection = "device_knuckles"; - class KnuckleDeviceDriver : public IDeviceDriver { public: - KnuckleDeviceDriver(VRDeviceConfiguration_t configuration, std::unique_ptr communicationManager, std::string serialNumber); + KnuckleDeviceDriver(VRDeviceConfiguration_t configuration, std::unique_ptr communicationManager, std::string serialNumber, std::shared_ptr boneAnimator); vr::EVRInitError Activate(uint32_t unObjectId); void Deactivate(); @@ -51,4 +49,5 @@ class KnuckleDeviceDriver : public IDeviceDriver { std::unique_ptr m_controllerPose; std::unique_ptr m_ffbProvider; + std::shared_ptr m_boneAnimator; }; diff --git a/include/DeviceDriver/LucidGloveDriver.h b/include/DeviceDriver/LucidGloveDriver.h index a86ec093..730cf027 100644 --- a/include/DeviceDriver/LucidGloveDriver.h +++ b/include/DeviceDriver/LucidGloveDriver.h @@ -1,60 +1,50 @@ #pragma once -#include +#include "openvr_driver.h" + #include #include -#include "Communication/CommunicationManager.h" -#include "Encode/LegacyEncodingManager.h" -#include "DeviceDriver/DeviceDriver.h" - #include "Bones.h" - +#include "Communication/CommunicationManager.h" #include "ControllerPose.h" #include "DeviceConfiguration.h" +#include "DeviceDriver/DeviceDriver.h" +#include "Encode/LegacyEncodingManager.h" -static const char* c_lucidGloveDeviceSettingsSection = "device_lucidgloves"; - -/** -This class controls the behavior of the controller. This is where you -tell OpenVR what your controller has (buttons, joystick, trackpad, etc.). -This is also where you inform OpenVR when the state of your controller -changes (for example, a button is pressed). - -For the methods, take a look at the comment blocks for the ITrackedDeviceServerDriver -class too. Those comment blocks have some good information. - -**/ class LucidGloveDeviceDriver : public IDeviceDriver { -public: - LucidGloveDeviceDriver(VRDeviceConfiguration_t configuration, std::unique_ptr communicationManager, std::string serialNumber); + public: + LucidGloveDeviceDriver(VRDeviceConfiguration_t configuration, std::unique_ptr communicationManager, std::string serialNumber, + std::shared_ptr boneAnimator); + + vr::EVRInitError Activate(uint32_t unObjectId); + void Deactivate(); - vr::EVRInitError Activate(uint32_t unObjectId); - void Deactivate(); + void EnterStandby(); + void* GetComponent(const char* pchComponentNameAndVersion); + void DebugRequest(const char* pchRequest, char* pchResponseBuffer, uint32_t unResponseBufferSize); + vr::DriverPose_t GetPose(); + void RunFrame(); - void EnterStandby(); - void* GetComponent(const char* pchComponentNameAndVersion); - void DebugRequest(const char* pchRequest, char* pchResponseBuffer, uint32_t unResponseBufferSize); - vr::DriverPose_t GetPose(); - void RunFrame(); + std::string GetSerialNumber(); - std::string GetSerialNumber(); + bool IsActive(); - bool IsActive(); -private: - void StartDevice(); - bool IsRightHand() const; + private: + void StartDevice(); + bool IsRightHand() const; - bool m_hasActivated; - uint32_t m_driverId; + bool m_hasActivated; + uint32_t m_driverId; - vr::VRInputComponentHandle_t m_skeletalComponentHandle{}; - vr::VRInputComponentHandle_t m_inputComponentHandles[15]{}; + vr::VRInputComponentHandle_t m_skeletalComponentHandle{}; + vr::VRInputComponentHandle_t m_inputComponentHandles[15]{}; - vr::VRBoneTransform_t m_handTransforms[NUM_BONES]; + vr::VRBoneTransform_t m_handTransforms[NUM_BONES]; - VRDeviceConfiguration_t m_configuration; - std::unique_ptr m_communicationManager; - std::string m_serialNumber; + VRDeviceConfiguration_t m_configuration; + std::unique_ptr m_communicationManager; + std::string m_serialNumber; - std::unique_ptr m_controllerPose; + std::unique_ptr m_controllerPose; + std::shared_ptr m_boneAnimator; }; diff --git a/include/DeviceProvider.h b/include/DeviceProvider.h index 9c682ca2..f634b9ae 100644 --- a/include/DeviceProvider.h +++ b/include/DeviceProvider.h @@ -3,10 +3,11 @@ #undef _WINSOCKAPI_ #define _WINSOCKAPI_ -#include +#include "openvr_driver.h" #include +#include "Bones.h" #include "Communication/CommunicationManager.h" #include "DeviceConfiguration.h" #include "DeviceDriver/DeviceDriver.h" @@ -66,5 +67,5 @@ class DeviceProvider : public vr::IServerTrackedDeviceProvider { **/ VRDeviceConfiguration_t GetDeviceConfiguration(vr::ETrackedControllerRole role); - std::unique_ptr InstantiateDeviceDriver(VRDeviceConfiguration_t configuration); + std::unique_ptr InstantiateDeviceDriver(VRDeviceConfiguration_t configuration, std::shared_ptr boneAnimator); }; \ No newline at end of file diff --git a/include/DriverLog.h b/include/DriverLog.h index 97eb487c..9cb20e4c 100644 --- a/include/DriverLog.h +++ b/include/DriverLog.h @@ -6,7 +6,8 @@ #pragma once #include -#include + +#include "openvr_driver.h" extern void DriverLog(const char* pchFormat, ...); diff --git a/include/Util/Windows.h b/include/Util/Windows.h new file mode 100644 index 00000000..5881399e --- /dev/null +++ b/include/Util/Windows.h @@ -0,0 +1,6 @@ +#pragma once + +#include + +extern std::string GetDriverPath(); +extern std::string GetLastErrorAsString(); \ No newline at end of file diff --git a/libraries/asio b/libraries/asio deleted file mode 160000 index 57577c6d..00000000 --- a/libraries/asio +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 57577c6db46a4e2de5351af2b185bf52696699a9 diff --git a/libraries/tinygltf b/libraries/tinygltf new file mode 160000 index 00000000..514167b4 --- /dev/null +++ b/libraries/tinygltf @@ -0,0 +1 @@ +Subproject commit 514167b475ef6d684c93c7f1f232ccf2c8701b34 diff --git a/openglove/resources/anims/glove_anim.glb b/openglove/resources/anims/glove_anim.glb new file mode 100644 index 00000000..b7ac6451 Binary files /dev/null and b/openglove/resources/anims/glove_anim.glb differ diff --git a/src/Bones.cpp b/src/Bones.cpp index 7410c139..84850f3b 100644 --- a/src/Bones.cpp +++ b/src/Bones.cpp @@ -1,8 +1,281 @@ -#include -#include +#include "Bones.h" -// these poses come from Valve's Index Controllers so share the same root bone to wrist -// geometry assumptions. +#include "DriverLog.h" + +#define TINYGLTF_IMPLEMENTATION +#define TINYGLTF_NO_STB_IMAGE +#define TINYGLTF_NO_STB_IMAGE_WRITE +#include "tiny_gltf.h" + +static const std::array emptyRotation = {0.0f, 0.0f, 0.0f, 0.0f}; +static const std::array emptyTranslation = {0.0f, 0.0f, 0.0f}; + +Transform_t::Transform_t() : rotation(emptyRotation), translation(emptyTranslation) {} +AnimationData_t::AnimationData_t() : startTime(0.0f), endTime(0.0f) {} + +static float Lerp(const float& a, const float& b, const float& f) { return a + f * (b - a); } + +enum class FingerIndex : int { Thumb = 0, IndexFinger, MiddleFinger, RingFinger, PinkyFinger, Unknown = -1 }; + +static FingerIndex GetFingerFromBoneIndex(HandSkeletonBone bone) { + switch (bone) { + case HandSkeletonBone::eBone_Thumb0: + case HandSkeletonBone::eBone_Thumb1: + case HandSkeletonBone::eBone_Thumb2: + case HandSkeletonBone::eBone_Thumb3: + case HandSkeletonBone::eBone_Aux_Thumb: + return FingerIndex::Thumb; + case HandSkeletonBone::eBone_IndexFinger0: + case HandSkeletonBone::eBone_IndexFinger1: + case HandSkeletonBone::eBone_IndexFinger2: + case HandSkeletonBone::eBone_IndexFinger3: + case HandSkeletonBone::eBone_IndexFinger4: + case HandSkeletonBone::eBone_Aux_IndexFinger: + return FingerIndex::IndexFinger; + case HandSkeletonBone::eBone_MiddleFinger0: + case HandSkeletonBone::eBone_MiddleFinger1: + case HandSkeletonBone::eBone_MiddleFinger2: + case HandSkeletonBone::eBone_MiddleFinger3: + case HandSkeletonBone::eBone_MiddleFinger4: + case HandSkeletonBone::eBone_Aux_MiddleFinger: + return FingerIndex::MiddleFinger; + case HandSkeletonBone::eBone_RingFinger0: + case HandSkeletonBone::eBone_RingFinger1: + case HandSkeletonBone::eBone_RingFinger2: + case HandSkeletonBone::eBone_RingFinger3: + case HandSkeletonBone::eBone_RingFinger4: + case HandSkeletonBone::eBone_Aux_RingFinger: + return FingerIndex::RingFinger; + case HandSkeletonBone::eBone_PinkyFinger0: + case HandSkeletonBone::eBone_PinkyFinger1: + case HandSkeletonBone::eBone_PinkyFinger2: + case HandSkeletonBone::eBone_PinkyFinger3: + case HandSkeletonBone::eBone_PinkyFinger4: + case HandSkeletonBone::eBone_Aux_PinkyFinger: + return FingerIndex::PinkyFinger; + + default: + return FingerIndex::Unknown; + } +} + +class GLTFModelManager : public IModelManager { + private: + tinygltf::Model m_model; + std::string m_fileName; + std::vector m_initialTransforms; + std::vector m_keyframeTimes; + std::vector> m_keyframeTransforms; + + public: + GLTFModelManager(const std::string& fileName) : m_fileName(fileName) {} + + bool Load() { + tinygltf::TinyGLTF loader; + std::string err; + std::string warn; + + bool ret = loader.LoadBinaryFromFile(&m_model, &err, &warn, m_fileName); + + if (!warn.empty()) { + DriverLog("Warning parsing gltf file: %s", warn.c_str()); + return false; + } + + if (!err.empty()) { + DriverLog("Error parsing gltf file: %s", err.c_str()); + return false; + } + + if (!ret) { + DriverLog("Failed to parse gltf"); + return false; + } + + m_initialTransforms = std::vector(m_model.nodes.size()-1); + m_keyframeTransforms = std::vector>(m_model.nodes.size()-1); + + LoadInitialTransforms(); + LoadKeyframeTimes(); + LoadKeyframeTransforms(); + + return true; + } + + AnimationData_t GetAnimationDataByBoneIndex(const HandSkeletonBone& boneIndex, float f) const { + const size_t lowerKeyframeIndex = std::lower_bound(m_keyframeTimes.begin(), m_keyframeTimes.end(), std::clamp(f, 0.0001f, 1.0f)) - m_keyframeTimes.begin() - 1; + const size_t upperKeyframeIndex = (lowerKeyframeIndex < m_keyframeTimes.size() - 1) ? (lowerKeyframeIndex + 1) : lowerKeyframeIndex; + + AnimationData_t result; + result.startTransform = m_keyframeTransforms[(size_t)boneIndex][lowerKeyframeIndex]; + result.startTime = m_keyframeTimes[lowerKeyframeIndex]; + result.endTransform = m_keyframeTransforms[(size_t)boneIndex][upperKeyframeIndex]; + result.endTime = m_keyframeTimes[upperKeyframeIndex]; + return result; + } + + Transform_t GetTransformByBoneIndex(const HandSkeletonBone& boneIndex) const { return m_initialTransforms[(size_t)boneIndex]; } + + private: + void LoadInitialTransforms() { + for (size_t nodeIndex = 1; nodeIndex < m_model.nodes.size(); nodeIndex++) { + tinygltf::Node node = m_model.nodes[nodeIndex]; + + Transform_t transform; + if (node.rotation.size() >= 4) { + transform.rotation[0] = (float)node.rotation[0]; + transform.rotation[1] = (float)node.rotation[1]; + transform.rotation[2] = (float)node.rotation[2]; + transform.rotation[3] = (float)node.rotation[3]; + } + if (node.translation.size() >= 3) { + transform.translation[0] = (float)node.translation[0]; + transform.translation[1] = (float)node.translation[1]; + transform.translation[2] = (float)node.translation[2]; + } + + //first node is never needed + m_initialTransforms[nodeIndex - 1] = transform; + } + } + + void LoadKeyframeTimes() { + tinygltf::Accessor accessor = m_model.accessors[0]; + m_keyframeTimes.resize(accessor.count); + + tinygltf::BufferView bufferView = m_model.bufferViews[accessor.bufferView]; + const std::vector& bufData = m_model.buffers[0].data; + memcpy(&m_keyframeTimes[0], bufData.data() + bufferView.byteOffset + accessor.byteOffset, accessor.count * sizeof(float)); + } + + template + std::vector> GetVecN(const tinygltf::Accessor& accessor) const { + tinygltf::BufferView bufferView = m_model.bufferViews[accessor.bufferView]; + const std::vector& bufData = m_model.buffers[0].data; + + std::vector> res(accessor.count); + memcpy(&res[0], bufData.data() + bufferView.byteOffset + accessor.byteOffset, accessor.count * sizeof(float) * N); + + return res; + } + + void LoadKeyframeTransforms() { + for (size_t nodeIndex = 1; nodeIndex < m_model.nodes.size(); nodeIndex++) { + const tinygltf::Animation& animation = m_model.animations[0]; + + // first node is never needed + std::vector& transforms = m_keyframeTransforms[nodeIndex - 1]; + + transforms.resize(m_keyframeTimes.size()); + + for (auto& channel : animation.channels) { + if (channel.target_node != nodeIndex) continue; + + const tinygltf::Accessor& accessor = m_model.accessors[animation.samplers[channel.sampler].output]; + switch (accessor.type) { + // rotation via quaternion + case TINYGLTF_TYPE_VEC4: { + std::vector> keyframes = GetVecN<4>(accessor); + for (size_t i = 0; i < keyframes.size(); i++) transforms[i].rotation = keyframes[i]; + break; + } + // translation + case TINYGLTF_TYPE_VEC3: { + std::vector> keyframes = GetVecN<3>(accessor); + for (size_t i = 0; i < keyframes.size(); i++) transforms[i].translation = keyframes[i]; + break; + } + } + } + } + } +}; + +BoneAnimator::BoneAnimator(const std::string& fileName) : m_fileName(fileName) { + m_modelManager = std::make_unique(fileName); + m_loaded = m_modelManager->Load(); +} + +void BoneAnimator::ComputeSkeletonTransforms(vr::VRBoneTransform_t* skeleton, const std::array& flexion, const bool rightHand) { + if (!m_loaded) return; + + for (size_t i = 0; i < NUM_BONES; i++) { + FingerIndex finger = GetFingerFromBoneIndex((HandSkeletonBone)i); + if (finger != FingerIndex::Unknown) skeleton[i] = GetTransformForBone((HandSkeletonBone)i, flexion[static_cast(finger)], rightHand); + } +} + +vr::VRBoneTransform_t BoneAnimator::GetTransformForBone(const HandSkeletonBone& boneIndex, const float f, const bool rightHand) { + vr::VRBoneTransform_t result{}; + + Transform_t nodeTransform = m_modelManager->GetTransformByBoneIndex(boneIndex); + result.orientation.x = nodeTransform.rotation[0]; + result.orientation.y = nodeTransform.rotation[1]; + result.orientation.z = nodeTransform.rotation[2]; + result.orientation.w = nodeTransform.rotation[3]; + result.position.v[0] = nodeTransform.translation[0]; + result.position.v[1] = nodeTransform.translation[1]; + result.position.v[2] = nodeTransform.translation[2]; + + AnimationData_t animationData = m_modelManager->GetAnimationDataByBoneIndex(boneIndex, f); + + const float interp = std::clamp((f - animationData.startTime) / (animationData.endTime - animationData.startTime), 0.0f, 1.0f); + + if (animationData.startTransform.rotation != emptyRotation) { + result.orientation.x = Lerp(animationData.startTransform.rotation[0], animationData.endTransform.rotation[0], interp); + result.orientation.y = Lerp(animationData.startTransform.rotation[1], animationData.endTransform.rotation[1], interp); + result.orientation.z = Lerp(animationData.startTransform.rotation[2], animationData.endTransform.rotation[2], interp); + result.orientation.w = Lerp(animationData.startTransform.rotation[3], animationData.endTransform.rotation[3], interp); + } + + if (animationData.startTransform.translation != emptyTranslation) { + result.position.v[0] = Lerp(animationData.startTransform.translation[0], animationData.endTransform.translation[0], interp); + result.position.v[1] = Lerp(animationData.startTransform.translation[1], animationData.endTransform.translation[1], interp); + result.position.v[2] = Lerp(animationData.startTransform.translation[2], animationData.endTransform.translation[2], interp); + } + result.position.v[3] = 1.0f; + + if (!rightHand) TransformLeftBone(result, boneIndex); + return result; +}; + +void BoneAnimator::TransformLeftBone(vr::VRBoneTransform_t& bone, const HandSkeletonBone& boneIndex) { + switch (boneIndex) { + case HandSkeletonBone::eBone_Root: { + return; + } + case HandSkeletonBone::eBone_Thumb0: + case HandSkeletonBone::eBone_IndexFinger0: + case HandSkeletonBone::eBone_MiddleFinger0: + case HandSkeletonBone::eBone_RingFinger0: + case HandSkeletonBone::eBone_PinkyFinger0: { + vr::HmdQuaternionf_t quat = bone.orientation; + bone.orientation.w = -quat.x; + bone.orientation.x = quat.w; + bone.orientation.y = -quat.z; + bone.orientation.z = quat.y; + break; + } + case HandSkeletonBone::eBone_Wrist: + case HandSkeletonBone::eBone_Aux_IndexFinger: + case HandSkeletonBone::eBone_Aux_Thumb: + case HandSkeletonBone::eBone_Aux_MiddleFinger: + case HandSkeletonBone::eBone_Aux_RingFinger: + case HandSkeletonBone::eBone_Aux_PinkyFinger: { + bone.orientation.y *= -1; + bone.orientation.z *= -1; + break; + } + default: { + bone.position.v[1] *= -1; + bone.position.v[2] *= -1; + } + } + + bone.position.v[0] *= -1; +} + +// Initial values for the right/left poses vr::VRBoneTransform_t rightOpenPose[NUM_BONES] = { {{0.000000f, 0.000000f, 0.000000f, 1.000000f}, {1.000000f, -0.000000f, -0.000000f, 0.000000f}}, {{0.034038f, 0.036503f, 0.164722f, 1.000000f}, {-0.055147f, -0.078608f, 0.920279f, -0.379296f}}, @@ -37,40 +310,6 @@ vr::VRBoneTransform_t rightOpenPose[NUM_BONES] = { {{0.031806f, -0.087214f, 0.121015f, 1.000000f}, {-0.003659f, 0.758407f, 0.639342f, 0.126678f}}, }; -vr::VRBoneTransform_t rightFistPose[NUM_BONES] = { - {{0.000000f, 0.000000f, 0.000000f, 1.000000f}, {1.000000f, -0.000000f, -0.000000f, 0.000000f}}, - {{0.034038f, 0.036503f, 0.164722f, 1.000000f}, {-0.055147f, -0.078608f, 0.920279f, -0.379296f}}, - {{0.016305f, 0.027529f, 0.017800f, 1.000000f}, {0.483332f, -0.225703f, 0.836342f, -0.126413f}}, - {{-0.040406f, -0.000000f, 0.000000f, 1.000000f}, {0.894335f, -0.013302f, -0.082902f, 0.439448f}}, - {{-0.032517f, -0.000000f, -0.000000f, 1.000000f}, {0.842428f, 0.000655f, 0.001244f, 0.538807f}}, - {{-0.030464f, 0.000000f, 0.000000f, 1.000000f}, {1.000000f, -0.000000f, -0.000000f, 0.000000f}}, - {{-0.003802f, 0.021514f, 0.012803f, 1.000000f}, {0.395174f, -0.617314f, 0.449185f, 0.510874f}}, - {{-0.074204f, 0.005002f, -0.000234f, 1.000000f}, {0.737291f, -0.032006f, -0.115013f, 0.664944f}}, - {{-0.043287f, 0.000000f, 0.000000f, 1.000000f}, {0.611381f, 0.003287f, 0.003823f, 0.791321f}}, - {{-0.028275f, -0.000000f, -0.000000f, 1.000000f}, {0.745388f, -0.000684f, -0.000945f, 0.666629f}}, - {{-0.022821f, -0.000000f, 0.000000f, 1.000000f}, {1.000000f, -0.000000f, 0.000000f, -0.000000f}}, - {{-0.005787f, 0.006806f, 0.016534f, 1.000000f}, {0.522315f, -0.514203f, 0.483700f, 0.478348f}}, - {{-0.070953f, -0.000779f, -0.000997f, 1.000000f}, {0.723653f, -0.097901f, 0.048546f, 0.681458f}}, - {{-0.043108f, -0.000000f, -0.000000f, 1.000000f}, {0.637464f, -0.002366f, -0.002831f, 0.770472f}}, - {{-0.033266f, -0.000000f, -0.000000f, 1.000000f}, {0.658008f, 0.002610f, 0.003196f, 0.753000f}}, - {{-0.025892f, 0.000000f, -0.000000f, 1.000000f}, {0.999195f, -0.000000f, 0.000000f, 0.040126f}}, - {{-0.004123f, -0.006858f, 0.016563f, 1.000000f}, {0.523374f, -0.489609f, 0.463997f, 0.520644f}}, - {{-0.065876f, -0.001786f, -0.000693f, 1.000000f}, {0.759970f, -0.055609f, 0.011571f, 0.647471f}}, - {{-0.040331f, -0.000000f, -0.000000f, 1.000000f}, {0.664315f, 0.001595f, 0.001967f, 0.747449f}}, - {{-0.028489f, 0.000000f, 0.000000f, 1.000000f}, {0.626957f, -0.002784f, -0.003234f, 0.779042f}}, - {{-0.022430f, 0.000000f, -0.000000f, 1.000000f}, {1.000000f, 0.000000f, 0.000000f, 0.000000f}}, - {{-0.001131f, -0.019295f, 0.015429f, 1.000000f}, {0.477833f, -0.479766f, 0.379935f, 0.630198f}}, - {{-0.062878f, -0.002844f, -0.000332f, 1.000000f}, {0.827001f, 0.034282f, 0.003440f, 0.561144f}}, - {{-0.029874f, -0.000000f, -0.000000f, 1.000000f}, {0.702185f, -0.006716f, -0.009289f, 0.711903f}}, - {{-0.017979f, -0.000000f, -0.000000f, 1.000000f}, {0.676853f, 0.007956f, 0.009917f, 0.736009f}}, - {{-0.018018f, -0.000000f, 0.000000f, 1.000000f}, {1.000000f, 0.000000f, 0.000000f, 0.000000f}}, - {{-0.019716f, 0.002802f, 0.093937f, 1.000000f}, {0.377286f, -0.540831f, -0.150446f, 0.736562f}}, - {{-0.000171f, 0.016473f, 0.096515f, 1.000000f}, {-0.006456f, 0.022747f, 0.932927f, 0.359287f}}, - {{-0.000448f, 0.001536f, 0.116543f, 1.000000f}, {-0.039357f, 0.105143f, 0.928833f, 0.353079f}}, - {{-0.003949f, -0.014869f, 0.130608f, 1.000000f}, {-0.055071f, 0.068695f, 0.944016f, 0.317933f}}, - {{-0.003263f, -0.034685f, 0.139926f, 1.000000f}, {0.019690f, -0.100741f, 0.957331f, 0.270149f}}, -}; - vr::VRBoneTransform_t leftOpenPose[NUM_BONES] = { {{0.000000f, 0.000000f, 0.000000f, 1.000000f}, {1.000000f, -0.000000f, -0.000000f, 0.000000f}}, {{-0.034038f, 0.036503f, 0.164722f, 1.000000f}, {-0.055147f, -0.078608f, -0.920279f, 0.379296f}}, @@ -103,125 +342,4 @@ vr::VRBoneTransform_t leftOpenPose[NUM_BONES] = { {{-0.039354f, -0.075674f, 0.047048f, 1.000000f}, {-0.187047f, 0.678062f, -0.659285f, -0.265683f}}, {{-0.038340f, -0.090987f, 0.082579f, 1.000000f}, {-0.183037f, 0.736793f, -0.634757f, -0.143936f}}, {{-0.031806f, -0.087214f, 0.121015f, 1.000000f}, {-0.003659f, 0.758407f, -0.639342f, -0.126678f}}, -}; - -vr::VRBoneTransform_t leftFistPose[NUM_BONES] = { - {{0.000000f, 0.000000f, 0.000000f, 1.000000f}, {1.000000f, -0.000000f, -0.000000f, 0.000000f}}, - {{-0.034038f, 0.036503f, 0.164722f, 1.000000f}, {-0.055147f, -0.078608f, -0.920279f, 0.379296f}}, - {{-0.016305f, 0.027529f, 0.017800f, 1.000000f}, {0.225703f, 0.483332f, 0.126413f, 0.836342f}}, - {{0.040406f, 0.000000f, -0.000000f, 1.000000f}, {0.894335f, -0.013302f, -0.082902f, 0.439448f}}, - {{0.032517f, 0.000000f, 0.000000f, 1.000000f}, {0.842428f, 0.000655f, 0.001244f, 0.538807f}}, - {{0.030464f, -0.000000f, -0.000000f, 1.000000f}, {1.000000f, -0.000000f, -0.000000f, 0.000000f}}, - {{0.003802f, 0.021514f, 0.012803f, 1.000000f}, {0.617314f, 0.395175f, -0.510874f, 0.449185f}}, - {{0.074204f, -0.005002f, 0.000234f, 1.000000f}, {0.737291f, -0.032006f, -0.115013f, 0.664944f}}, - {{0.043287f, -0.000000f, -0.000000f, 1.000000f}, {0.611381f, 0.003287f, 0.003823f, 0.791321f}}, - {{0.028275f, 0.000000f, 0.000000f, 1.000000f}, {0.745388f, -0.000684f, -0.000945f, 0.666629f}}, - {{0.022821f, 0.000000f, -0.000000f, 1.000000f}, {1.000000f, -0.000000f, 0.000000f, -0.000000f}}, - {{0.005787f, 0.006806f, 0.016534f, 1.000000f}, {0.514203f, 0.522315f, -0.478348f, 0.483700f}}, - {{0.070953f, 0.000779f, 0.000997f, 1.000000f}, {0.723653f, -0.097901f, 0.048546f, 0.681458f}}, - {{0.043108f, 0.000000f, 0.000000f, 1.000000f}, {0.637464f, -0.002366f, -0.002831f, 0.770472f}}, - {{0.033266f, 0.000000f, 0.000000f, 1.000000f}, {0.658008f, 0.002610f, 0.003196f, 0.753000f}}, - {{0.025892f, -0.000000f, 0.000000f, 1.000000f}, {0.999195f, -0.000000f, 0.000000f, 0.040126f}}, - {{0.004123f, -0.006858f, 0.016563f, 1.000000f}, {0.489609f, 0.523374f, -0.520644f, 0.463997f}}, - {{0.065876f, 0.001786f, 0.000693f, 1.000000f}, {0.759970f, -0.055609f, 0.011571f, 0.647471f}}, - {{0.040331f, 0.000000f, 0.000000f, 1.000000f}, {0.664315f, 0.001595f, 0.001967f, 0.747449f}}, - {{0.028489f, -0.000000f, -0.000000f, 1.000000f}, {0.626957f, -0.002784f, -0.003234f, 0.779042f}}, - {{0.022430f, -0.000000f, 0.000000f, 1.000000f}, {1.000000f, 0.000000f, 0.000000f, 0.000000f}}, - {{0.001131f, -0.019295f, 0.015429f, 1.000000f}, {0.479766f, 0.477833f, -0.630198f, 0.379934f}}, - {{0.062878f, 0.002844f, 0.000332f, 1.000000f}, {0.827001f, 0.034282f, 0.003440f, 0.561144f}}, - {{0.029874f, 0.000000f, 0.000000f, 1.000000f}, {0.702185f, -0.006716f, -0.009289f, 0.711903f}}, - {{0.017979f, 0.000000f, 0.000000f, 1.000000f}, {0.676853f, 0.007956f, 0.009917f, 0.736009f}}, - {{0.018018f, 0.000000f, -0.000000f, 1.000000f}, {1.000000f, 0.000000f, 0.000000f, 0.000000f}}, - {{0.019716f, 0.002802f, 0.093937f, 1.000000f}, {0.377286f, -0.540831f, 0.150446f, -0.736562f}}, - {{0.000171f, 0.016473f, 0.096515f, 1.000000f}, {-0.006456f, 0.022747f, -0.932927f, -0.359287f}}, - {{0.000448f, 0.001536f, 0.116543f, 1.000000f}, {-0.039357f, 0.105143f, -0.928833f, -0.353079f}}, - {{0.003949f, -0.014869f, 0.130608f, 1.000000f}, {-0.055071f, 0.068695f, -0.944016f, -0.317933f}}, - {{0.003263f, -0.034685f, 0.139926f, 1.000000f}, {0.019690f, -0.100741f, -0.957331f, -0.270149f}}, -}; - -vr::HmdQuaternionf_t CalculateOrientation(const float transform, const int boneIndex, const vr::VRBoneTransform_t* openPose, const vr::VRBoneTransform_t* fistPose) { - const vr::HmdQuaternionf_t openPoseOrientation = openPose[boneIndex].orientation; - const vr::HmdQuaternionf_t fistPoseOrientation = fistPose[boneIndex].orientation; - - vr::HmdQuaternionf_t result; - result.w = Lerp(openPoseOrientation.w, fistPoseOrientation.w, transform); - result.x = Lerp(openPoseOrientation.x, fistPoseOrientation.x, transform); - result.y = Lerp(openPoseOrientation.y, fistPoseOrientation.y, transform); - result.z = Lerp(openPoseOrientation.z, fistPoseOrientation.z, transform); - - return result; -} -vr::HmdVector4_t CalculatePosition(const float transform, const int boneIndex, const vr::VRBoneTransform_t* openPose, const vr::VRBoneTransform_t* fistPose) { - const vr::HmdVector4_t openPosePosition = openPose[boneIndex].position; - const vr::HmdVector4_t fistPosePosition = fistPose[boneIndex].position; - - vr::HmdVector4_t result; - result.v[0] = Lerp(openPosePosition.v[0], fistPosePosition.v[0], transform); - result.v[1] = Lerp(openPosePosition.v[1], fistPosePosition.v[1], transform); - result.v[2] = Lerp(openPosePosition.v[2], fistPosePosition.v[2], transform); - result.v[3] = Lerp(openPosePosition.v[3], fistPosePosition.v[3], transform); - - return result; -} - -void ComputeHand(vr::VRBoneTransform_t* skeleton, const std::array& flexion, const bool isRightHand) { - for (int i = 0; i < NUM_BONES; i++) { - int fingerNum = FingerFromBone(i); - if (fingerNum != -1) { - ComputeBoneFlexion(&skeleton[i], flexion[fingerNum], i, isRightHand); - } - } -} - -// Transform should be between 0-1 -void ComputeBoneFlexion(vr::VRBoneTransform_t* boneTransform, float transform, int index, const bool isRightHand) { - vr::VRBoneTransform_t* fist_pose = isRightHand ? rightFistPose : leftFistPose; - vr::VRBoneTransform_t* open_pose = isRightHand ? rightOpenPose : leftOpenPose; - - boneTransform->orientation = CalculateOrientation(transform, index, open_pose, fist_pose); - boneTransform->position = CalculatePosition(transform, index, open_pose, fist_pose); -} - -float Lerp(const float a, const float b, const float f) { return a + f * (b - a); } - -int FingerFromBone(vr::BoneIndex_t bone) { - switch (bone) { - case eBone_Thumb0: - case eBone_Thumb1: - case eBone_Thumb2: - case eBone_Thumb3: - case eBone_Aux_Thumb: - return 0; - case eBone_IndexFinger0: - case eBone_IndexFinger1: - case eBone_IndexFinger2: - case eBone_IndexFinger3: - case eBone_IndexFinger4: - case eBone_Aux_IndexFinger: - return 1; - case eBone_MiddleFinger0: - case eBone_MiddleFinger1: - case eBone_MiddleFinger2: - case eBone_MiddleFinger3: - case eBone_MiddleFinger4: - case eBone_Aux_MiddleFinger: - return 2; - case eBone_RingFinger0: - case eBone_RingFinger1: - case eBone_RingFinger2: - case eBone_RingFinger3: - case eBone_RingFinger4: - case eBone_Aux_RingFinger: - return 3; - case eBone_PinkyFinger0: - case eBone_PinkyFinger1: - case eBone_PinkyFinger2: - case eBone_PinkyFinger3: - case eBone_PinkyFinger4: - case eBone_Aux_PinkyFinger: - return 4; - - default: - return -1; - } -} \ No newline at end of file +}; \ No newline at end of file diff --git a/src/Communication/BTSerialCommunicationManager.cpp b/src/Communication/BTSerialCommunicationManager.cpp index 9f59a1a1..4641173f 100644 --- a/src/Communication/BTSerialCommunicationManager.cpp +++ b/src/Communication/BTSerialCommunicationManager.cpp @@ -1,27 +1,11 @@ -#include -#include - -static const uint32_t c_listenerWaitTime = 1000; - -// Adapted from Finally Functional's SerialBT implementation - -static std::string GetLastErrorAsString() { - DWORD errorMessageID = ::GetLastError(); - if (errorMessageID == 0) { - return std::string(); - } - - LPSTR messageBuffer = nullptr; +#include "Communication/BTSerialCommunicationManager.h" - size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorMessageID, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL); +#include - std::string message(messageBuffer, size); +#include "Util/Windows.h" - LocalFree(messageBuffer); +static const uint32_t c_listenerWaitTime = 1000; - return message; -} BTSerialCommunicationManager::BTSerialCommunicationManager(const VRBTSerialConfiguration_t& configuration, std::unique_ptr encodingManager) : m_btSerialConfiguration(configuration), diff --git a/src/Communication/SerialCommunicationManager.cpp b/src/Communication/SerialCommunicationManager.cpp index 75834df8..1e17e7ef 100644 --- a/src/Communication/SerialCommunicationManager.cpp +++ b/src/Communication/SerialCommunicationManager.cpp @@ -1,28 +1,11 @@ -#include - -#include +#include "Communication/SerialCommunicationManager.h" #include "DriverLog.h" +#include "Util/Windows.h" -static const uint32_t c_listenerWaitTime = 1000; - -static std::string GetLastErrorAsString() { - DWORD errorMessageID = ::GetLastError(); - if (errorMessageID == 0) { - return std::string(); - } - - LPSTR messageBuffer = nullptr; - - size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorMessageID, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL); - - std::string message(messageBuffer, size); - - LocalFree(messageBuffer); +#include - return message; -} +static const uint32_t c_listenerWaitTime = 1000; bool SerialCommunicationManager::Connect() { // We're not yet connected diff --git a/src/DeviceConfiguration.cpp b/src/DeviceConfiguration.cpp new file mode 100644 index 00000000..2555cc68 --- /dev/null +++ b/src/DeviceConfiguration.cpp @@ -0,0 +1,8 @@ +#include "DeviceConfiguration.h" + +const char* c_poseSettingsSection = "pose_settings"; +const char* c_driverSettingsSection = "driver_openglove"; +const char* c_serialCommunicationSettingsSection = "communication_serial"; +const char* c_btserialCommunicationSettingsSection = "communication_btserial"; +const char* c_knuckleDeviceSettingsSection = "device_knuckles"; +const char* c_lucidGloveDeviceSettingsSection = "device_lucidgloves"; \ No newline at end of file diff --git a/src/DeviceDriver/KnuckleDriver.cpp b/src/DeviceDriver/KnuckleDriver.cpp index 6c3e13b5..942f30bb 100644 --- a/src/DeviceDriver/KnuckleDriver.cpp +++ b/src/DeviceDriver/KnuckleDriver.cpp @@ -32,10 +32,12 @@ enum ComponentIndex : int { FINGER_PINKY }; -KnuckleDeviceDriver::KnuckleDeviceDriver(VRDeviceConfiguration_t configuration, std::unique_ptr communicationManager, std::string serialNumber) +KnuckleDeviceDriver::KnuckleDeviceDriver(VRDeviceConfiguration_t configuration, std::unique_ptr communicationManager, std::string serialNumber, + std::shared_ptr boneAnimator) : m_configuration(configuration), m_communicationManager(std::move(communicationManager)), m_serialNumber(std::move(serialNumber)), + m_boneAnimator(std::move(boneAnimator)), m_driverId(-1), m_hasActivated(false) { // copy a default bone transform to our hand transform for use in finger positioning later @@ -166,9 +168,9 @@ vr::EVRInitError KnuckleDeviceDriver::Activate(uint32_t unObjectId) { vr::VRScalarUnits_NormalizedOneSided); vr::VRDriverInput()->CreateHapticComponent(props, "/output/haptic", &m_haptic); - vr::EVRInputError error = vr::VRDriverInput()->CreateSkeletonComponent( - props, isRightHand ? "/input/skeleton/right" : "/input/skeleton/left", isRightHand ? "/skeleton/hand/right" : "/skeleton/hand/left", "/pose/raw", - vr::VRSkeletalTracking_Partial, isRightHand ? rightOpenPose : leftOpenPose, NUM_BONES, &m_skeletalComponentHandle); + vr::EVRInputError error = vr::VRDriverInput()->CreateSkeletonComponent(props, isRightHand ? "/input/skeleton/right" : "/input/skeleton/left", + isRightHand ? "/skeleton/hand/right" : "/skeleton/hand/left", "/pose/raw", + vr::VRSkeletalTracking_Partial, m_handTransforms, NUM_BONES, &m_skeletalComponentHandle); if (error != vr::VRInputError_None) { DebugDriverLog("CreateSkeletonComponent failed. Error: %s\n", error); @@ -191,17 +193,15 @@ void KnuckleDeviceDriver::StartDevice() { m_configuration.role); m_ffbProvider->Start(); - { - // OpenVR needs an initial skeleton for when the device is activated - ComputeHand(m_handTransforms, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, IsRightHand()); - - vr::VRDriverInput()->UpdateSkeletonComponent(m_skeletalComponentHandle, vr::VRSkeletalMotionRange_WithoutController, m_handTransforms, NUM_BONES); - vr::VRDriverInput()->UpdateSkeletonComponent(m_skeletalComponentHandle, vr::VRSkeletalMotionRange_WithController, m_handTransforms, NUM_BONES); - } + vr::VRDriverInput()->UpdateSkeletonComponent(m_skeletalComponentHandle, vr::VRSkeletalMotionRange_WithoutController, IsRightHand() ? rightOpenPose : leftOpenPose, + NUM_BONES); + vr::VRDriverInput()->UpdateSkeletonComponent(m_skeletalComponentHandle, vr::VRSkeletalMotionRange_WithController, IsRightHand() ? rightOpenPose : leftOpenPose, + NUM_BONES); m_communicationManager->BeginListener([&](VRCommData_t datas) { try { - ComputeHand(m_handTransforms, datas.flexion, IsRightHand()); + m_boneAnimator->ComputeSkeletonTransforms(m_handTransforms, datas.flexion, IsRightHand()); + vr::VRDriverInput()->UpdateSkeletonComponent(m_skeletalComponentHandle, vr::VRSkeletalMotionRange_WithoutController, m_handTransforms, NUM_BONES); vr::VRDriverInput()->UpdateSkeletonComponent(m_skeletalComponentHandle, vr::VRSkeletalMotionRange_WithController, m_handTransforms, NUM_BONES); diff --git a/src/DeviceDriver/LucidGloveDriver.cpp b/src/DeviceDriver/LucidGloveDriver.cpp index 64088519..d0b015f8 100644 --- a/src/DeviceDriver/LucidGloveDriver.cpp +++ b/src/DeviceDriver/LucidGloveDriver.cpp @@ -27,8 +27,13 @@ enum ComponentIndex : int { }; LucidGloveDeviceDriver::LucidGloveDeviceDriver(VRDeviceConfiguration_t configuration, std::unique_ptr communicationManager, - std::string serialNumber) - : m_configuration(configuration), m_communicationManager(std::move(communicationManager)), m_serialNumber(serialNumber), m_driverId(-1), m_hasActivated(false) { + std::string serialNumber, std::shared_ptr boneAnimator) + : m_configuration(configuration), + m_communicationManager(std::move(communicationManager)), + m_boneAnimator(std::move(boneAnimator)), + m_serialNumber(serialNumber), + m_driverId(-1), + m_hasActivated(false) { // copy a default bone transform to our hand transform for use in finger positioning later std::copy(std::begin(m_configuration.role == vr::TrackedControllerRole_RightHand ? rightOpenPose : leftOpenPose), std::end(m_configuration.role == vr::TrackedControllerRole_RightHand ? rightOpenPose : leftOpenPose), std::begin(m_handTransforms)); @@ -107,17 +112,13 @@ vr::EVRInitError LucidGloveDeviceDriver::Activate(uint32_t unObjectId) { } void LucidGloveDeviceDriver::StartDevice() { - { - // OpenVR needs an initial skeleton for when the device is activated - ComputeHand(m_handTransforms, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, IsRightHand()); - - vr::VRDriverInput()->UpdateSkeletonComponent(m_skeletalComponentHandle, vr::VRSkeletalMotionRange_WithoutController, m_handTransforms, NUM_BONES); - vr::VRDriverInput()->UpdateSkeletonComponent(m_skeletalComponentHandle, vr::VRSkeletalMotionRange_WithController, m_handTransforms, NUM_BONES); - } + vr::VRDriverInput()->UpdateSkeletonComponent(m_skeletalComponentHandle, vr::VRSkeletalMotionRange_WithoutController, m_handTransforms, NUM_BONES); + vr::VRDriverInput()->UpdateSkeletonComponent(m_skeletalComponentHandle, vr::VRSkeletalMotionRange_WithController, m_handTransforms, NUM_BONES); m_communicationManager->BeginListener([&](VRCommData_t datas) { try { - ComputeHand(m_handTransforms, {0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, IsRightHand()); + m_boneAnimator->ComputeSkeletonTransforms(m_handTransforms, datas.flexion, IsRightHand()); + vr::VRDriverInput()->UpdateSkeletonComponent(m_skeletalComponentHandle, vr::VRSkeletalMotionRange_WithoutController, m_handTransforms, NUM_BONES); vr::VRDriverInput()->UpdateSkeletonComponent(m_skeletalComponentHandle, vr::VRSkeletalMotionRange_WithController, m_handTransforms, NUM_BONES); @@ -147,7 +148,7 @@ void LucidGloveDeviceDriver::StartDevice() { } } catch (const std::exception&) { - DebugDriverLog("Exception caught while parsing comm data"); + DriverLog("Exception caught while parsing comm data"); } }); } diff --git a/src/DeviceProvider.cpp b/src/DeviceProvider.cpp index 98356c0a..5be67284 100644 --- a/src/DeviceProvider.cpp +++ b/src/DeviceProvider.cpp @@ -2,6 +2,7 @@ #include #include +#include #include "Communication/BTSerialCommunicationManager.h" #include "Communication/SerialCommunicationManager.h" @@ -11,31 +12,9 @@ #include "Encode/AlphaEncodingManager.h" #include "Encode/LegacyEncodingManager.h" #include "Quaternion.h" +#include "Util/Windows.h" -EXTERN_C IMAGE_DOS_HEADER __ImageBase; - -std::string GetDriverPath() { - char path[MAX_PATH]; - HMODULE hm = NULL; - - if (GetModuleHandleEx( - GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, - (LPCSTR)&__ImageBase, &hm) == 0) { - int ret = GetLastError(); - fprintf(stderr, "GetModuleHandle failed, error = %d\n", ret); - // Return or however you want to handle an error. - } - if (GetModuleFileName(hm, path, sizeof(path)) == 0) { - int ret = GetLastError(); - fprintf(stderr, "GetModuleFileName failed, error = %d\n", ret); - // Return or however you want to handle an error. - } - - std::string::size_type pos = std::string(path).find_last_of("\\/"); - return std::string(path).substr(0, pos); -} - -bool CreateBackgroundProcess() { +static bool CreateBackgroundProcess() { STARTUPINFOA si; PROCESS_INFORMATION pi; ZeroMemory(&si, sizeof(si)); @@ -68,29 +47,30 @@ vr::EVRInitError DeviceProvider::Init(vr::IVRDriverContext* pDriverContext) { DriverLog("Could not create background process"); return vr::VRInitError_Init_FileNotFound; } + + VRDeviceConfiguration_t leftConfiguration = GetDeviceConfiguration(vr::TrackedControllerRole_LeftHand); + VRDeviceConfiguration_t rightConfiguration = GetDeviceConfiguration(vr::TrackedControllerRole_RightHand); - VRDeviceConfiguration_t leftConfiguration = - GetDeviceConfiguration(vr::TrackedControllerRole_LeftHand); - VRDeviceConfiguration_t rightConfiguration = - GetDeviceConfiguration(vr::TrackedControllerRole_RightHand); + std::string driverPath = GetDriverPath(); + + const std::string unwanted = "\\bin\\win64"; + driverPath.erase(driverPath.find(unwanted), unwanted.length()); + + std::shared_ptr boneAnimator = std::make_shared(driverPath + "\\resources\\anims\\glove_anim.glb"); if (leftConfiguration.enabled) { - m_leftHand = InstantiateDeviceDriver(leftConfiguration); - vr::VRServerDriverHost()->TrackedDeviceAdded( - m_leftHand->GetSerialNumber().c_str(), vr::TrackedDeviceClass_Controller, m_leftHand.get()); + m_leftHand = InstantiateDeviceDriver(leftConfiguration, boneAnimator); + vr::VRServerDriverHost()->TrackedDeviceAdded(m_leftHand->GetSerialNumber().c_str(), vr::TrackedDeviceClass_Controller, m_leftHand.get()); } if (rightConfiguration.enabled) { - m_rightHand = InstantiateDeviceDriver(rightConfiguration); - vr::VRServerDriverHost()->TrackedDeviceAdded(m_rightHand->GetSerialNumber().c_str(), - vr::TrackedDeviceClass_Controller, - m_rightHand.get()); + m_rightHand = InstantiateDeviceDriver(rightConfiguration, boneAnimator); + vr::VRServerDriverHost()->TrackedDeviceAdded(m_rightHand->GetSerialNumber().c_str(), vr::TrackedDeviceClass_Controller, m_rightHand.get()); } return vr::VRInitError_None; } -std::unique_ptr DeviceProvider::InstantiateDeviceDriver( - VRDeviceConfiguration_t configuration) { +std::unique_ptr DeviceProvider::InstantiateDeviceDriver(VRDeviceConfiguration_t configuration, std::shared_ptr boneAnimator) { std::unique_ptr communicationManager; std::unique_ptr encodingManager; @@ -104,8 +84,7 @@ std::unique_ptr DeviceProvider::InstantiateDeviceDriver( break; } case VREncodingProtocol::ALPHA: { - const float maxAnalogValue = - vr::VRSettings()->GetFloat(c_alphaEncodingSettingsSection, "max_analog_value"); // + const float maxAnalogValue = vr::VRSettings()->GetFloat(c_alphaEncodingSettingsSection, "max_analog_value"); encodingManager = std::make_unique(maxAnalogValue); break; } @@ -115,100 +94,72 @@ std::unique_ptr DeviceProvider::InstantiateDeviceDriver( case VRCommunicationProtocol::BTSERIAL: { DriverLog("Communication set to BTSerial"); char name[248]; - vr::VRSettings()->GetString(c_btserialCommunicationSettingsSection, - isRightHand ? "right_name" : "left_name", name, sizeof(name)); + vr::VRSettings()->GetString(c_btserialCommunicationSettingsSection, isRightHand ? "right_name" : "left_name", name, sizeof(name)); VRBTSerialConfiguration_t btSerialSettings(name); - communicationManager = std::make_unique( - btSerialSettings, std::move(encodingManager)); + communicationManager = std::make_unique(btSerialSettings, std::move(encodingManager)); 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)); + vr::VRSettings()->GetString(c_serialCommunicationSettingsSection, isRightHand ? "right_port" : "left_port", port, sizeof(port)); const int baudRate = vr::VRSettings()->GetInt32(c_serialCommunicationSettingsSection, "baud_rate"); VRSerialConfiguration_t serialSettings(port, baudRate); - communicationManager = - std::make_unique(serialSettings, std::move(encodingManager)); + communicationManager = std::make_unique(serialSettings, std::move(encodingManager)); break; } switch (configuration.deviceDriver) { case VRDeviceDriver::EMULATED_KNUCKLES: { char serialNumber[32]; - vr::VRSettings()->GetString(c_knuckleDeviceSettingsSection, - isRightHand ? "right_serial_number" : "left_serial_number", - serialNumber, sizeof(serialNumber)); + vr::VRSettings()->GetString(c_knuckleDeviceSettingsSection, isRightHand ? "right_serial_number" : "left_serial_number", serialNumber, sizeof(serialNumber)); - return std::make_unique(configuration, std::move(communicationManager), - serialNumber); + return std::make_unique(configuration, std::move(communicationManager), serialNumber, std::move(boneAnimator)); } 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)); + vr::VRSettings()->GetString(c_lucidGloveDeviceSettingsSection, isRightHand ? "right_serial_number" : "left_serial_number", serialNumber, sizeof(serialNumber)); - return std::make_unique( - configuration, std::move(communicationManager), serialNumber); + return std::make_unique(configuration, std::move(communicationManager), serialNumber, std::move(boneAnimator)); } } } VRDeviceConfiguration_t DeviceProvider::GetDeviceConfiguration(vr::ETrackedControllerRole role) { const bool isRightHand = role == vr::TrackedControllerRole_RightHand; - const bool isEnabled = vr::VRSettings()->GetBool(c_driverSettingsSection, - isRightHand ? "right_enabled" : "left_enabled"); + const bool isEnabled = vr::VRSettings()->GetBool(c_driverSettingsSection, isRightHand ? "right_enabled" : "left_enabled"); - const auto communicationProtocol = (VRCommunicationProtocol)vr::VRSettings()->GetInt32( - c_driverSettingsSection, "communication_protocol"); - const auto encodingProtocol = - (VREncodingProtocol)vr::VRSettings()->GetInt32(c_driverSettingsSection, "encoding_protocol"); - const auto deviceDriver = - (VRDeviceDriver)vr::VRSettings()->GetInt32(c_driverSettingsSection, "device_driver"); + const auto communicationProtocol = (VRCommunicationProtocol)vr::VRSettings()->GetInt32(c_driverSettingsSection, "communication_protocol"); + const auto encodingProtocol = (VREncodingProtocol)vr::VRSettings()->GetInt32(c_driverSettingsSection, "encoding_protocol"); + const auto deviceDriver = (VRDeviceDriver)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"); - - 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 bool controllerOverrideEnabled = - vr::VRSettings()->GetBool(c_poseSettingsSection, "controller_override"); + 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 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 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; + controllerOverrideEnabled ? vr::VRSettings()->GetInt32(c_poseSettingsSection, isRightHand ? "controller_override_right" : "controller_override_left") : -1; const vr::HmdVector3_t offsetVector = {offsetXPos, offsetYPos, offsetZPos}; // Convert the rotation to a quaternion - const vr::HmdQuaternion_t angleOffsetQuaternion = - EulerToQuaternion(DegToRad(offsetXRot), DegToRad(offsetYRot), DegToRad(offsetZRot)); - - return VRDeviceConfiguration_t( - role, isEnabled, - VRPoseConfiguration_t(offsetVector, angleOffsetQuaternion, poseTimeOffset, - controllerOverrideEnabled, controllerIdOverride), - encodingProtocol, communicationProtocol, deviceDriver); + const vr::HmdQuaternion_t angleOffsetQuaternion = EulerToQuaternion(DegToRad(offsetXRot), DegToRad(offsetYRot), DegToRad(offsetZRot)); + + return VRDeviceConfiguration_t(role, isEnabled, + VRPoseConfiguration_t(offsetVector, angleOffsetQuaternion, poseTimeOffset, controllerOverrideEnabled, controllerIdOverride), + encodingProtocol, communicationProtocol, deviceDriver); } void DeviceProvider::Cleanup() {} diff --git a/src/Util/Windows.cpp b/src/Util/Windows.cpp new file mode 100644 index 00000000..38848c19 --- /dev/null +++ b/src/Util/Windows.cpp @@ -0,0 +1,42 @@ +#include "Util/Windows.h" +#include +#include "DriverLog.h" + +EXTERN_C IMAGE_DOS_HEADER __ImageBase; + +std::string GetLastErrorAsString() { + DWORD errorMessageID = ::GetLastError(); + if (errorMessageID == 0) { + return std::string(); + } + + LPSTR messageBuffer = nullptr; + + size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errorMessageID, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL); + + std::string message(messageBuffer, size); + + LocalFree(messageBuffer); + + return message; +} + +std::string GetDriverPath() { + char path[MAX_PATH]; + HMODULE hm = NULL; + + if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, (LPCSTR)&__ImageBase, &hm) == 0) { + DriverLog("GetModuleHandle failed, error: %c", GetLastErrorAsString().c_str()); + return std::string(); + } + + if (GetModuleFileName(hm, path, sizeof(path)) == 0) { + DriverLog("GetModuleFileName failed, error: %c", GetLastErrorAsString().c_str()); + return std::string(); + } + + std::string pathString = std::string(path); + return pathString.substr(0, pathString.find_last_of("\\/")); +} +