From 673accd630be88fde4b6b748608a9c3bc42ea60f Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Tue, 21 Feb 2023 21:46:42 -0600 Subject: input_common: Implement dedicated motion from mouse --- src/input_common/drivers/mouse.cpp | 94 +++++++++++++++++++++++++++++++------- src/input_common/drivers/mouse.h | 5 +- src/input_common/input_mapping.cpp | 10 ++-- 3 files changed, 85 insertions(+), 24 deletions(-) diff --git a/src/input_common/drivers/mouse.cpp b/src/input_common/drivers/mouse.cpp index da50e0a24..8b7f9aee9 100644 --- a/src/input_common/drivers/mouse.cpp +++ b/src/input_common/drivers/mouse.cpp @@ -10,17 +10,25 @@ #include "input_common/drivers/mouse.h" namespace InputCommon { +constexpr int update_time = 10; +constexpr float default_stick_sensitivity = 0.022f; +constexpr float default_motion_sensitivity = 0.008f; constexpr int mouse_axis_x = 0; constexpr int mouse_axis_y = 1; constexpr int wheel_axis_x = 2; constexpr int wheel_axis_y = 3; -constexpr int motion_wheel_y = 4; constexpr PadIdentifier identifier = { .guid = Common::UUID{}, .port = 0, .pad = 0, }; +constexpr PadIdentifier motion_identifier = { + .guid = Common::UUID{}, + .port = 0, + .pad = 1, +}; + constexpr PadIdentifier real_mouse_identifier = { .guid = Common::UUID{}, .port = 1, @@ -37,47 +45,87 @@ Mouse::Mouse(std::string input_engine_) : InputEngine(std::move(input_engine_)) PreSetController(identifier); PreSetController(real_mouse_identifier); PreSetController(touch_identifier); + PreSetController(motion_identifier); // Initialize all mouse axis PreSetAxis(identifier, mouse_axis_x); PreSetAxis(identifier, mouse_axis_y); PreSetAxis(identifier, wheel_axis_x); PreSetAxis(identifier, wheel_axis_y); - PreSetAxis(identifier, motion_wheel_y); PreSetAxis(real_mouse_identifier, mouse_axis_x); PreSetAxis(real_mouse_identifier, mouse_axis_y); PreSetAxis(touch_identifier, mouse_axis_x); PreSetAxis(touch_identifier, mouse_axis_y); + + // Initialize variables + mouse_origin = {}; + last_mouse_position = {}; + wheel_position = {}; + last_mouse_change = {}; + last_motion_change = {}; + update_thread = std::jthread([this](std::stop_token stop_token) { UpdateThread(stop_token); }); } void Mouse::UpdateThread(std::stop_token stop_token) { Common::SetCurrentThreadName("Mouse"); - constexpr int update_time = 10; - while (!stop_token.stop_requested()) { - if (Settings::values.mouse_panning) { - // Slow movement by 4% - last_mouse_change *= 0.96f; - const float sensitivity = - Settings::values.mouse_panning_sensitivity.GetValue() * 0.022f; - SetAxis(identifier, mouse_axis_x, last_mouse_change.x * sensitivity); - SetAxis(identifier, mouse_axis_y, -last_mouse_change.y * sensitivity); - } - SetAxis(identifier, motion_wheel_y, 0.0f); + while (!stop_token.stop_requested()) { + UpdateStickInput(); + UpdateMotionInput(); - if (mouse_panning_timout++ > 20) { + if (mouse_panning_timeout++ > 20) { StopPanning(); } std::this_thread::sleep_for(std::chrono::milliseconds(update_time)); } } +void Mouse::UpdateStickInput() { + if (!Settings::values.mouse_panning) { + return; + } + + const float sensitivity = + Settings::values.mouse_panning_sensitivity.GetValue() * default_stick_sensitivity; + + // Slow movement by 4% + last_mouse_change *= 0.96f; + SetAxis(identifier, mouse_axis_x, last_mouse_change.x * sensitivity); + SetAxis(identifier, mouse_axis_y, -last_mouse_change.y * sensitivity); +} + +void Mouse::UpdateMotionInput() { + const float sensitivity = + Settings::values.mouse_panning_sensitivity.GetValue() * default_motion_sensitivity; + + // Slow movement by 7% + if (Settings::values.mouse_panning) { + last_motion_change *= 0.93f; + } else { + last_motion_change.z *= 0.93f; + } + + const BasicMotion motion_data{ + .gyro_x = last_motion_change.x * sensitivity, + .gyro_y = last_motion_change.y * sensitivity, + .gyro_z = last_motion_change.z * sensitivity, + .accel_x = 0, + .accel_y = 0, + .accel_z = 0, + .delta_timestamp = update_time * 1000, + }; + + SetMotion(motion_identifier, 0, motion_data); +} + void Mouse::Move(int x, int y, int center_x, int center_y) { if (Settings::values.mouse_panning) { + mouse_panning_timeout = 0; + auto mouse_change = (Common::MakeVec(x, y) - Common::MakeVec(center_x, center_y)).Cast(); - mouse_panning_timout = 0; + Common::Vec3 motion_change{-mouse_change.y, -mouse_change.x, last_motion_change.z}; const auto move_distance = mouse_change.Length(); if (move_distance == 0) { @@ -93,6 +141,7 @@ void Mouse::Move(int x, int y, int center_x, int center_y) { // Average mouse movements last_mouse_change = (last_mouse_change * 0.91f) + (mouse_change * 0.09f); + last_motion_change = (last_motion_change * 0.69f) + (motion_change * 0.31f); const auto last_move_distance = last_mouse_change.Length(); @@ -116,6 +165,12 @@ void Mouse::Move(int x, int y, int center_x, int center_y) { const float sensitivity = Settings::values.mouse_panning_sensitivity.GetValue() * 0.0012f; SetAxis(identifier, mouse_axis_x, static_cast(mouse_move.x) * sensitivity); SetAxis(identifier, mouse_axis_y, static_cast(-mouse_move.y) * sensitivity); + + last_motion_change = { + static_cast(-mouse_move.y) / 50.0f, + static_cast(-mouse_move.x) / 50.0f, + last_motion_change.z, + }; } } @@ -157,15 +212,19 @@ void Mouse::ReleaseButton(MouseButton button) { SetAxis(identifier, mouse_axis_x, 0); SetAxis(identifier, mouse_axis_y, 0); } + + last_motion_change.x = 0; + last_motion_change.y = 0; + button_pressed = false; } void Mouse::MouseWheelChange(int x, int y) { wheel_position.x += x; wheel_position.y += y; + last_motion_change.z += static_cast(y) / 100.0f; SetAxis(identifier, wheel_axis_x, static_cast(wheel_position.x)); SetAxis(identifier, wheel_axis_y, static_cast(wheel_position.y)); - SetAxis(identifier, motion_wheel_y, static_cast(y) / 100.0f); } void Mouse::ReleaseAllButtons() { @@ -234,6 +293,9 @@ Common::Input::ButtonNames Mouse::GetUIName(const Common::ParamPackage& params) if (params.Has("axis_x") && params.Has("axis_y") && params.Has("axis_z")) { return Common::Input::ButtonNames::Engine; } + if (params.Has("motion")) { + return Common::Input::ButtonNames::Engine; + } return Common::Input::ButtonNames::Invalid; } diff --git a/src/input_common/drivers/mouse.h b/src/input_common/drivers/mouse.h index f3b65bdd1..b872c7a0f 100644 --- a/src/input_common/drivers/mouse.h +++ b/src/input_common/drivers/mouse.h @@ -96,6 +96,8 @@ public: private: void UpdateThread(std::stop_token stop_token); + void UpdateStickInput(); + void UpdateMotionInput(); void StopPanning(); Common::Input::ButtonNames GetUIButtonName(const Common::ParamPackage& params) const; @@ -103,9 +105,10 @@ private: Common::Vec2 mouse_origin; Common::Vec2 last_mouse_position; Common::Vec2 last_mouse_change; + Common::Vec3 last_motion_change; Common::Vec2 wheel_position; bool button_pressed; - int mouse_panning_timout{}; + int mouse_panning_timeout{}; std::jthread update_thread; }; diff --git a/src/input_common/input_mapping.cpp b/src/input_common/input_mapping.cpp index 6990a86b9..2ff480ff9 100644 --- a/src/input_common/input_mapping.cpp +++ b/src/input_common/input_mapping.cpp @@ -142,14 +142,10 @@ void MappingFactory::RegisterMotion(const MappingData& data) { new_input.Set("port", static_cast(data.pad.port)); new_input.Set("pad", static_cast(data.pad.pad)); - // If engine is mouse map the mouse position as 3 axis motion + // If engine is mouse map it automatically to mouse motion if (data.engine == "mouse") { - new_input.Set("axis_x", 1); - new_input.Set("invert_x", "-"); - new_input.Set("axis_y", 0); - new_input.Set("axis_z", 4); - new_input.Set("range", 1.0f); - new_input.Set("deadzone", 0.0f); + new_input.Set("motion", 0); + new_input.Set("pad", 1); input_queue.Push(new_input); return; } -- cgit v1.2.3 From 739a81055f8f33ab0987ee730370a0535a1bdf05 Mon Sep 17 00:00:00 2001 From: Narr the Reg Date: Tue, 21 Feb 2023 21:47:47 -0600 Subject: core: hid: Restore motion state on refresh and clamp motion values --- src/core/hid/emulated_controller.cpp | 12 +++++++++++- src/core/hid/motion_input.cpp | 14 ++++++++++++++ src/core/hid/motion_input.h | 6 +++++- 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index 6d5a3dead..a29c9a6f8 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -363,7 +363,17 @@ void EmulatedController::ReloadInput() { SetMotion(callback, index); }, }); - motion_devices[index]->ForceUpdate(); + + // Restore motion state + auto& emulated_motion = controller.motion_values[index].emulated; + auto& motion = controller.motion_state[index]; + emulated_motion.ResetRotations(); + emulated_motion.ResetQuaternion(); + motion.accel = emulated_motion.GetAcceleration(); + motion.gyro = emulated_motion.GetGyroscope(); + motion.rotation = emulated_motion.GetRotations(); + motion.orientation = emulated_motion.GetOrientation(); + motion.is_at_rest = !emulated_motion.IsMoving(motion_sensitivity); } for (std::size_t index = 0; index < camera_devices.size(); ++index) { diff --git a/src/core/hid/motion_input.cpp b/src/core/hid/motion_input.cpp index eef6edf4b..0dd66c1cc 100644 --- a/src/core/hid/motion_input.cpp +++ b/src/core/hid/motion_input.cpp @@ -10,6 +10,8 @@ MotionInput::MotionInput() { // Initialize PID constants with default values SetPID(0.3f, 0.005f, 0.0f); SetGyroThreshold(ThresholdStandard); + ResetQuaternion(); + ResetRotations(); } void MotionInput::SetPID(f32 new_kp, f32 new_ki, f32 new_kd) { @@ -20,11 +22,19 @@ void MotionInput::SetPID(f32 new_kp, f32 new_ki, f32 new_kd) { void MotionInput::SetAcceleration(const Common::Vec3f& acceleration) { accel = acceleration; + + accel.x = std::clamp(accel.x, -AccelMaxValue, AccelMaxValue); + accel.y = std::clamp(accel.y, -AccelMaxValue, AccelMaxValue); + accel.z = std::clamp(accel.z, -AccelMaxValue, AccelMaxValue); } void MotionInput::SetGyroscope(const Common::Vec3f& gyroscope) { gyro = gyroscope - gyro_bias; + gyro.x = std::clamp(gyro.x, -GyroMaxValue, GyroMaxValue); + gyro.y = std::clamp(gyro.y, -GyroMaxValue, GyroMaxValue); + gyro.z = std::clamp(gyro.z, -GyroMaxValue, GyroMaxValue); + // Auto adjust drift to minimize drift if (!IsMoving(IsAtRestRelaxed)) { gyro_bias = (gyro_bias * 0.9999f) + (gyroscope * 0.0001f); @@ -61,6 +71,10 @@ void MotionInput::ResetRotations() { rotations = {}; } +void MotionInput::ResetQuaternion() { + quat = {{0.0f, 0.0f, -1.0f}, 0.0f}; +} + bool MotionInput::IsMoving(f32 sensitivity) const { return gyro.Length() >= sensitivity || accel.Length() <= 0.9f || accel.Length() >= 1.1f; } diff --git a/src/core/hid/motion_input.h b/src/core/hid/motion_input.h index 9180bb9aa..e2c1bbf95 100644 --- a/src/core/hid/motion_input.h +++ b/src/core/hid/motion_input.h @@ -20,6 +20,9 @@ public: static constexpr float IsAtRestStandard = 0.01f; static constexpr float IsAtRestThight = 0.005f; + static constexpr float GyroMaxValue = 5.0f; + static constexpr float AccelMaxValue = 7.0f; + explicit MotionInput(); MotionInput(const MotionInput&) = default; @@ -40,6 +43,7 @@ public: void EnableReset(bool reset); void ResetRotations(); + void ResetQuaternion(); void UpdateRotation(u64 elapsed_time); void UpdateOrientation(u64 elapsed_time); @@ -69,7 +73,7 @@ private: Common::Vec3f derivative_error; // Quaternion containing the device orientation - Common::Quaternion quat{{0.0f, 0.0f, -1.0f}, 0.0f}; + Common::Quaternion quat; // Number of full rotations in each axis Common::Vec3f rotations; -- cgit v1.2.3