Skip to content
8 changes: 4 additions & 4 deletions src/mods/UObjectHook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -430,8 +430,8 @@ void UObjectHook::tick_attachments(Rotator<float>* 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;

Expand All @@ -452,8 +452,8 @@ void UObjectHook::tick_attachments(Rotator<float>* 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);
Expand Down
57 changes: 56 additions & 1 deletion src/mods/VR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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");
Expand Down
110 changes: 102 additions & 8 deletions src/mods/VR.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
}
Expand Down Expand Up @@ -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{};
Expand Down Expand Up @@ -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,
Expand Down
4 changes: 3 additions & 1 deletion src/mods/vr/IXRTrackingSystemHook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down