diff --git a/src/mods/UObjectHook.cpp b/src/mods/UObjectHook.cpp index becaef629..88e8e47a4 100644 --- a/src/mods/UObjectHook.cpp +++ b/src/mods/UObjectHook.cpp @@ -430,8 +430,8 @@ void UObjectHook::tick_attachments(Rotator* view_rotation, const float wo return; } - glm::vec3 right_hand_position = vr->get_grip_position(vr->get_right_controller_index()); - glm::quat right_hand_rotation = vr->get_aim_rotation(vr->get_right_controller_index()); + glm::vec3 right_hand_position = vr->get_controller_position_with_offset(VRRuntime::Hand::RIGHT); + glm::quat right_hand_rotation = vr->get_controller_rotation_with_offset(VRRuntime::Hand::RIGHT);// vr->get_aim_rotation(vr->get_right_controller_index()); const float lerp_speed = m_attach_lerp_speed->value() * m_last_delta_time; @@ -452,8 +452,8 @@ void UObjectHook::tick_attachments(Rotator* view_rotation, const float wo const auto original_right_hand_rotation = right_hand_rotation; const auto original_right_hand_position = right_hand_position - hmd_origin; - glm::vec3 left_hand_position = vr->get_grip_position(vr->get_left_controller_index()); - glm::quat left_hand_rotation = vr->get_aim_rotation(vr->get_left_controller_index()); + glm::vec3 left_hand_position = vr->get_controller_position_with_offset(VRRuntime::Hand::LEFT); + glm::quat left_hand_rotation = vr->get_controller_rotation_with_offset(VRRuntime::Hand::LEFT); // vr->get_aim_rotation(vr->get_left_controller_index()); if (m_attach_lerp_enabled->value()) { auto spherical_distance_left = glm::dot(left_hand_rotation, m_last_left_aim_rotation); diff --git a/src/mods/VR.cpp b/src/mods/VR.cpp index 3fca1b6bc..11c401e0a 100644 --- a/src/mods/VR.cpp +++ b/src/mods/VR.cpp @@ -2376,7 +2376,9 @@ void VR::on_draw_sidebar_entry(std::string_view name) { ImGui::SetNextItemOpen(true, ImGuiCond_::ImGuiCond_Once); if (ImGui::TreeNode("Controller")) { m_joystick_deadzone->draw("VR Joystick Deadzone"); - m_controller_pitch_offset->draw("Controller Pitch Offset"); + + // JB: pitch offset is settable in the separate 'offsets' submenu + // m_controller_pitch_offset->draw("Controller Pitch Offset"); m_dpad_shifting->draw("DPad Shifting"); ImGui::SameLine(); @@ -2405,6 +2407,59 @@ void VR::on_draw_sidebar_entry(std::string_view name) { ImGui::TreePop(); } + if (ImGui::TreeNode("Motion Controller Aim Offsets")) { + float left_controller_rotation_offset[] = {m_left_controller_rotation_offset_x->value(), + m_left_controller_rotation_offset_y->value(), m_left_controller_rotation_offset_z->value()}; + if (ImGui::SliderFloat3("Left Rotation", left_controller_rotation_offset, -180.0f, 180.0f)) { + m_left_controller_rotation_offset_x->value() = left_controller_rotation_offset[0]; + m_left_controller_rotation_offset_y->value() = left_controller_rotation_offset[1]; + m_left_controller_rotation_offset_z->value() = left_controller_rotation_offset[2]; + } + if (ImGui::Button("Reset Left Rotation")) { + m_left_controller_rotation_offset_x->value() = 0.0f; + m_left_controller_rotation_offset_y->value() = 0.0f; + m_left_controller_rotation_offset_z->value() = 0.0f; + } + float right_controller_rotation_offset[] = {m_right_controller_rotation_offset_x->value(), + m_right_controller_rotation_offset_y->value(), m_right_controller_rotation_offset_z->value()}; + if (ImGui::SliderFloat3("Right Rotation", right_controller_rotation_offset, -180.0f, 180.0f)) { + m_right_controller_rotation_offset_x->value() = right_controller_rotation_offset[0]; + m_right_controller_rotation_offset_y->value() = right_controller_rotation_offset[1]; + m_right_controller_rotation_offset_z->value() = right_controller_rotation_offset[2]; + } + if (ImGui::Button("Reset Right Rotation")) { + m_right_controller_rotation_offset_x->value() = 0.0f; + m_right_controller_rotation_offset_y->value() = 0.0f; + m_right_controller_rotation_offset_z->value() = 0.0f; + } + ImGui::NewLine(); + float left_controller_position_offset[] = {m_left_controller_position_offset_x->value(), + m_left_controller_position_offset_y->value(), m_left_controller_position_offset_z->value()}; + if (ImGui::SliderFloat3("Left Position", left_controller_position_offset, -1.0f, 1.0f)) { + m_left_controller_position_offset_x->value() = left_controller_position_offset[0]; + m_left_controller_position_offset_y->value() = left_controller_position_offset[1]; + m_left_controller_position_offset_z->value() = left_controller_position_offset[2]; + } + if (ImGui::Button("Reset Left Position")) { + m_left_controller_position_offset_x->value() = 0.0f; + m_left_controller_position_offset_y->value() = 0.0f; + m_left_controller_position_offset_z->value() = 0.0f; + } + float right_controller_position_offset[] = {m_right_controller_position_offset_x->value(), + m_right_controller_position_offset_y->value(), m_right_controller_position_offset_z->value()}; + if (ImGui::SliderFloat3("Right Position", right_controller_position_offset, -1.0f, 1.0f)) { + m_right_controller_position_offset_x->value() = right_controller_position_offset[0]; + m_right_controller_position_offset_y->value() = right_controller_position_offset[1]; + m_right_controller_position_offset_z->value() = right_controller_position_offset[2]; + } + if (ImGui::Button("Reset Right Position")) { + m_right_controller_position_offset_x->value() = 0.0f; + m_right_controller_position_offset_y->value() = 0.0f; + m_right_controller_position_offset_z->value() = 0.0f; + } + ImGui::TreePop(); + } + ImGui::SetNextItemOpen(true, ImGuiCond_::ImGuiCond_Once); if (ImGui::TreeNode("Snap Turn")) { m_snapturn->draw("Enabled"); diff --git a/src/mods/VR.hpp b/src/mods/VR.hpp index b93ab2fa3..4a4c63ae2 100644 --- a/src/mods/VR.hpp +++ b/src/mods/VR.hpp @@ -161,20 +161,42 @@ class VR : public Mod { Matrix4x4f get_transform(uint32_t index, bool grip = true) const; vr::HmdMatrix34_t get_raw_transform(uint32_t index) const; - Vector4f get_grip_position(uint32_t index) const { - return get_position(index, true); - } - Vector4f get_aim_position(uint32_t index) const { return get_position(index, false); } - Matrix4x4f get_grip_rotation(uint32_t index) const { - return get_rotation(index, true); + glm::vec3 get_controller_position_with_offset(VRRuntime::Hand hand) { + float x_offset = (hand == VRRuntime::Hand::LEFT) ? get_left_controller_position_offset_x() : get_right_controller_position_offset_x(); + float y_offset = (hand == VRRuntime::Hand::LEFT) ? get_left_controller_position_offset_y() : get_right_controller_position_offset_y(); + float z_offset = (hand == VRRuntime::Hand::LEFT) ? get_left_controller_position_offset_z() : get_right_controller_position_offset_z(); + // if there's no offsets defined, return the original: + auto const position = get_position((hand == VRRuntime::Hand::LEFT) ? get_left_controller_index() : get_right_controller_index(), false); + if (x_offset == 0 && y_offset == 0 && z_offset == 0) { + return position; + } else { + // if we offset the controller by some specified distance we need a frame of reference - what direction is "x"?. If we use + // the HMD direction then turning your head will make the gun move in the world independently of your hand position. If + // we use the controller's direction then the gun will move around when you rotate it (i.e. it will be on the end of an + // invisible 'stick' that's attached to the rotating controller). As there's no other frame of reference that makes any sense here, + // a stick it is. Whether the stick orientation is the offset or raw orientation is another complication + auto const actual_controller_rotation = get_rotation((hand == VRRuntime::Hand::LEFT) ? get_left_controller_index() : get_right_controller_index(), false); + return position - actual_controller_rotation * glm::vec4{-x_offset, -y_offset, z_offset, 0}; + } } - Matrix4x4f get_aim_rotation(uint32_t index) const { - return get_rotation(index, false); + Matrix4x4f get_controller_rotation_with_offset(VRRuntime::Hand hand) { + float x_offset_degrees = (hand == VRRuntime::Hand::LEFT) ? get_left_controller_rotation_offset_x() : get_right_controller_rotation_offset_x(); + float y_offset_degrees = (hand == VRRuntime::Hand::LEFT) ? get_left_controller_rotation_offset_y() : get_right_controller_rotation_offset_y(); + float z_offset_degrees = (hand == VRRuntime::Hand::LEFT) ? get_left_controller_rotation_offset_z() : get_right_controller_rotation_offset_z(); + // if there's no offsets defined, return the original: + auto const rotation = get_rotation((hand == VRRuntime::Hand::LEFT) ? get_left_controller_index() : get_right_controller_index(), false); + if (x_offset_degrees == 0 && y_offset_degrees == 0 && z_offset_degrees == 0) { + return rotation; + } else { + auto const requested_rotation_offset = + utility::math::ue_rotation_matrix(glm::vec3{y_offset_degrees, z_offset_degrees, -x_offset_degrees}); + return rotation * requested_rotation_offset; + } } Matrix4x4f get_grip_transform(uint32_t hand_index) const; @@ -447,7 +469,55 @@ class VR : public Mod { float get_aim_speed() const { return m_aim_speed->value(); } + + float get_left_controller_rotation_offset_x() const { + return m_left_controller_rotation_offset_x->value(); + } + + float get_left_controller_rotation_offset_y() const { + return m_left_controller_rotation_offset_y->value(); + } + + float get_left_controller_rotation_offset_z() const { + return m_left_controller_rotation_offset_z->value(); + } + + float get_right_controller_rotation_offset_x() const { + return m_right_controller_rotation_offset_x->value(); + } + + float get_right_controller_rotation_offset_y() const { + return m_right_controller_rotation_offset_y->value(); + } + + float get_right_controller_rotation_offset_z() const { + return m_right_controller_rotation_offset_z->value(); + } + float get_left_controller_position_offset_x() const { + return m_left_controller_position_offset_x->value(); + } + + float get_left_controller_position_offset_y() const { + return m_left_controller_position_offset_y->value(); + } + + float get_left_controller_position_offset_z() const { + return m_left_controller_position_offset_z->value(); + } + + float get_right_controller_position_offset_x() const { + return m_right_controller_position_offset_x->value(); + } + + float get_right_controller_position_offset_y() const { + return m_right_controller_position_offset_y->value(); + } + + float get_right_controller_position_offset_z() const { + return m_right_controller_position_offset_z->value(); + } + bool is_aim_multiplayer_support_enabled() const { return m_aim_multiplayer_support->value(); } @@ -814,6 +884,18 @@ class VR : public Mod { const ModSlider::Ptr m_aim_speed{ ModSlider::create(generate_name("AimSpeed"), 0.01f, 25.0f, 15.0f) }; const ModToggle::Ptr m_dpad_shifting{ ModToggle::create(generate_name("DPadShifting"), true) }; const ModCombo::Ptr m_dpad_shifting_method{ ModCombo::create(generate_name("DPadShiftingMethod"), s_dpad_method_names, DPadMethod::RIGHT_TOUCH) }; + const ModSlider::Ptr m_left_controller_rotation_offset_x{ModSlider::create(generate_name("LeftControllerRotationOffsetX"), -180.0f, 180.0f, 0.0f)}; + const ModSlider::Ptr m_left_controller_rotation_offset_y{ModSlider::create(generate_name("LeftControllerRotationOffsetY"), -180.0f, 180.0f, 0.0f)}; + const ModSlider::Ptr m_left_controller_rotation_offset_z{ModSlider::create(generate_name("LeftControllerRotationOffsetZ"), -180.0f, 180.0f, 0.0f)}; + const ModSlider::Ptr m_right_controller_rotation_offset_x{ModSlider::create(generate_name("RightControllerRotationOffsetX"), -180.0f, 180.0f, 0.0f)}; + const ModSlider::Ptr m_right_controller_rotation_offset_y{ModSlider::create(generate_name("RightControllerRotationOffsetY"), -180.0f, 180.0f, 0.0f)}; + const ModSlider::Ptr m_right_controller_rotation_offset_z{ModSlider::create(generate_name("RightControllerRotationOffsetZ"), -180.0f, 180.0f, 0.0f)}; + const ModSlider::Ptr m_left_controller_position_offset_x{ModSlider::create(generate_name("LeftControllerPositionOffsetX"), -1.0f, 1.0f, 0.0f)}; + const ModSlider::Ptr m_left_controller_position_offset_y{ModSlider::create(generate_name("LeftControllerPositionOffsetY"), -1.0f, 1.0f, 0.0f)}; + const ModSlider::Ptr m_left_controller_position_offset_z{ModSlider::create(generate_name("LeftControllerPositionOffsetZ"), -1.0f, 1.0f, 0.0f)}; + const ModSlider::Ptr m_right_controller_position_offset_x{ModSlider::create(generate_name("RightControllerPositionOffsetX"), -1.0f, 1.0f, 0.0f)}; + const ModSlider::Ptr m_right_controller_position_offset_y{ModSlider::create(generate_name("RightControllerPositionOffsetY"), -1.0f, 1.0f, 0.0f)}; + const ModSlider::Ptr m_right_controller_position_offset_z{ModSlider::create(generate_name("RightControllerPositionOffsetZ"), -1.0f, 1.0f, 0.0f)}; struct DPadGestureState { std::recursive_mutex mtx{}; @@ -928,6 +1010,18 @@ class VR : public Mod { *m_aim_modify_player_control_rotation, *m_aim_multiplayer_support, *m_aim_speed, + *m_left_controller_rotation_offset_x, + *m_left_controller_rotation_offset_y, + *m_left_controller_rotation_offset_z, + *m_right_controller_rotation_offset_x, + *m_right_controller_rotation_offset_y, + *m_right_controller_rotation_offset_z, + *m_left_controller_position_offset_x, + *m_left_controller_position_offset_y, + *m_left_controller_position_offset_z, + *m_right_controller_position_offset_x, + *m_right_controller_position_offset_y, + *m_right_controller_position_offset_z, *m_aim_interp, *m_dpad_shifting, *m_dpad_shifting_method, diff --git a/src/mods/vr/IXRTrackingSystemHook.cpp b/src/mods/vr/IXRTrackingSystemHook.cpp index 190a7dcdb..bd47353a4 100644 --- a/src/mods/vr/IXRTrackingSystemHook.cpp +++ b/src/mods/vr/IXRTrackingSystemHook.cpp @@ -1900,7 +1900,9 @@ void IXRTrackingSystemHook::update_view_rotation(sdk::UObject* reference_obj, Ro if (aim_type == VR::AimMethod::RIGHT_CONTROLLER || aim_type == VR::AimMethod::LEFT_CONTROLLER) { const auto controller_index = aim_type == VR::AimMethod::RIGHT_CONTROLLER ? vr->get_right_controller_index() : vr->get_left_controller_index(); - og_controller_rot = glm::quat{vr->get_aim_rotation(controller_index)}; + og_controller_rot = aim_type == VR::AimMethod::RIGHT_CONTROLLER ? + glm::quat{ vr->get_controller_rotation_with_offset(VRRuntime::Hand::RIGHT) } : + glm::quat{ vr->get_controller_rotation_with_offset(VRRuntime::Hand::LEFT) }; // glm::quat{vr->get_aim_rotation(controller_index)}; og_controller_pos = glm::vec3{vr->get_aim_position(controller_index)}; right_controller_forward = og_controller_rot * glm::vec3{0.0f, 0.0f, 1.0f}; } else if (aim_type == VR::AimMethod::TWO_HANDED_RIGHT) { // two handed modes are for imitating rifle aiming