From 24b03b61f8a91c7d60182844849fc2cb758f8a9e Mon Sep 17 00:00:00 2001 From: Jaime Moreira Date: Tue, 4 Jun 2024 15:48:42 -0400 Subject: [PATCH] Gyro tightening A practical way to avoid a noisy gyro signal, or shaky hands. Unlike a deadzone, inputs below the threshold are "squeezed towards zero", so they are not completely ignored. Source: http://gyrowiki.jibbsmart.com/blog:good-gyro-controls-part-1:the-gyro-is-a-mouse#toc9 --- doc/040_cvarlist.md | 4 ++++ src/client/input/sdl2.c | 42 ++++++++++++++++++++++++++++++++++++----- src/client/input/sdl3.c | 38 ++++++++++++++++++++++++++++++++----- src/client/menu/menu.c | 11 +++++++++++ 4 files changed, 85 insertions(+), 10 deletions(-) diff --git a/doc/040_cvarlist.md b/doc/040_cvarlist.md index eb7bc7d1..8bd22978 100644 --- a/doc/040_cvarlist.md +++ b/doc/040_cvarlist.md @@ -598,6 +598,10 @@ Set `0` by default. for people who hold the controller upright, or use a device with the controller attached to the screen, e.g. Steam Deck. +* **gyro_tightening**: Threshold of rotation in degrees per second, + where gyro inputs below it will be dampened. Meant to counter a + noisy gyro and involuntary hand movements. Default `3.5`. + * **gyro_calibration_(x/y/z)**: Offset values on each axis of the gyro which helps it reach true "zero movement", complete stillness. These values are wrong if you see your in-game view "drift" when leaving diff --git a/src/client/input/sdl2.c b/src/client/input/sdl2.c index 0e0dd9a4..520c134a 100644 --- a/src/client/input/sdl2.c +++ b/src/client/input/sdl2.c @@ -162,6 +162,7 @@ cvar_t *gyro_turning_axis; // yaw or roll // Gyro sensitivity static cvar_t *gyro_yawsensitivity; static cvar_t *gyro_pitchsensitivity; +static cvar_t *gyro_tightening; // Gyro is being used in this very moment static qboolean gyro_active = false; @@ -1069,6 +1070,30 @@ IN_ApplyExpo(thumbstick_t stick, float exponent) return result; } +/* + * Minimize gyro movement when under a small threshold. + * http://gyrowiki.jibbsmart.com/blog:good-gyro-controls-part-1:the-gyro-is-a-mouse#toc9 + */ +static thumbstick_t +IN_TightenInput(float yaw, float pitch) +{ + thumbstick_t input = { yaw, pitch }; + const float magnitude = IN_StickMagnitude(input); +#ifdef NATIVE_SDL_GYRO + const float threshold = (M_PI / 180.0f) * gyro_tightening->value; +#else + const float threshold = (2560.0f / 180.0f) * gyro_tightening->value; +#endif + + if (magnitude < threshold) + { + const float scale = magnitude / threshold; + input.x *= scale; + input.y *= scale; + } + return input; +} + /* * Delete flick stick's buffer of angle samples for smoothing */ @@ -1198,6 +1223,7 @@ IN_Move(usercmd_t *cmd) static float joystick_yaw, joystick_pitch; static float joystick_forwardmove, joystick_sidemove; static thumbstick_t left_stick = {0}, right_stick = {0}; + thumbstick_t gyro_in = {0}; if (m_filter->value) { @@ -1378,16 +1404,21 @@ IN_Move(usercmd_t *cmd) * cl_sidespeed->value * 2.0f * joystick_sidemove; } - if (gyro_yaw) + if (gyro_yaw || gyro_pitch) { - cl.viewangles[YAW] += m_yaw->value * gyro_yawsensitivity->value - * cl_yawspeed->value * gyro_yaw * gyroViewFactor; + gyro_in = IN_TightenInput(gyro_yaw, gyro_pitch); } - if (gyro_pitch) + if (gyro_in.x) + { + cl.viewangles[YAW] += m_yaw->value * gyro_yawsensitivity->value + * cl_yawspeed->value * gyro_in.x * gyroViewFactor; + } + + if (gyro_in.y) { cl.viewangles[PITCH] -= m_pitch->value * gyro_pitchsensitivity->value - * cl_pitchspeed->value * gyro_pitch * gyroViewFactor; + * cl_pitchspeed->value * gyro_in.y * gyroViewFactor; } // Flick Stick: flick in progress, changing the yaw angle to the target progressively @@ -2286,6 +2317,7 @@ IN_Init(void) gyro_yawsensitivity = Cvar_Get("gyro_yawsensitivity", "1.0", CVAR_ARCHIVE); gyro_pitchsensitivity = Cvar_Get("gyro_pitchsensitivity", "1.0", CVAR_ARCHIVE); + gyro_tightening = Cvar_Get("gyro_tightening", "3.5", CVAR_ARCHIVE); gyro_turning_axis = Cvar_Get("gyro_turning_axis", "0", CVAR_ARCHIVE); gyro_mode = Cvar_Get("gyro_mode", "2", CVAR_ARCHIVE); diff --git a/src/client/input/sdl3.c b/src/client/input/sdl3.c index 33c62dc8..5972c708 100644 --- a/src/client/input/sdl3.c +++ b/src/client/input/sdl3.c @@ -165,6 +165,7 @@ cvar_t *gyro_turning_axis; // yaw or roll // Gyro sensitivity static cvar_t *gyro_yawsensitivity; static cvar_t *gyro_pitchsensitivity; +static cvar_t *gyro_tightening; // Gyro is being used in this very moment static qboolean gyro_active = false; @@ -1058,6 +1059,26 @@ IN_ApplyExpo(thumbstick_t stick, float exponent) return result; } +/* + * Minimize gyro movement when under a small threshold. + * http://gyrowiki.jibbsmart.com/blog:good-gyro-controls-part-1:the-gyro-is-a-mouse#toc9 + */ +static thumbstick_t +IN_TightenInput(float yaw, float pitch) +{ + thumbstick_t input = { yaw, pitch }; + const float magnitude = IN_StickMagnitude(input); + const float threshold = (M_PI / 180.0f) * gyro_tightening->value; + + if (magnitude < threshold) + { + const float scale = magnitude / threshold; + input.x *= scale; + input.y *= scale; + } + return input; +} + /* * Delete flick stick's buffer of angle samples for smoothing */ @@ -1187,6 +1208,7 @@ IN_Move(usercmd_t *cmd) static float joystick_yaw, joystick_pitch; static float joystick_forwardmove, joystick_sidemove; static thumbstick_t left_stick = {0}, right_stick = {0}; + thumbstick_t gyro_in = {0}; if (m_filter->value) { @@ -1367,16 +1389,21 @@ IN_Move(usercmd_t *cmd) * cl_sidespeed->value * 2.0f * joystick_sidemove; } - if (gyro_yaw) + if (gyro_yaw || gyro_pitch) { - cl.viewangles[YAW] += m_yaw->value * gyro_yawsensitivity->value - * cl_yawspeed->value * gyro_yaw * gyroViewFactor; + gyro_in = IN_TightenInput(gyro_yaw, gyro_pitch); } - if (gyro_pitch) + if (gyro_in.x) + { + cl.viewangles[YAW] += m_yaw->value * gyro_yawsensitivity->value + * cl_yawspeed->value * gyro_in.x * gyroViewFactor; + } + + if (gyro_in.y) { cl.viewangles[PITCH] -= m_pitch->value * gyro_pitchsensitivity->value - * cl_pitchspeed->value * gyro_pitch * gyroViewFactor; + * cl_pitchspeed->value * gyro_in.y * gyroViewFactor; } // Flick Stick: flick in progress, changing the yaw angle to the target progressively @@ -2278,6 +2305,7 @@ IN_Init(void) gyro_yawsensitivity = Cvar_Get("gyro_yawsensitivity", "1.0", CVAR_ARCHIVE); gyro_pitchsensitivity = Cvar_Get("gyro_pitchsensitivity", "1.0", CVAR_ARCHIVE); + gyro_tightening = Cvar_Get("gyro_tightening", "3.5", CVAR_ARCHIVE); gyro_turning_axis = Cvar_Get("gyro_turning_axis", "0", CVAR_ARCHIVE); gyro_mode = Cvar_Get("gyro_mode", "2", CVAR_ARCHIVE); diff --git a/src/client/menu/menu.c b/src/client/menu/menu.c index 0c77615a..c5baadf2 100644 --- a/src/client/menu/menu.c +++ b/src/client/menu/menu.c @@ -1780,6 +1780,7 @@ static menuslider_s s_gyro_yawsensitivity_slider; static menuslider_s s_gyro_pitchsensitivity_slider; static menulist_s s_gyro_invertyaw_box; static menulist_s s_gyro_invertpitch_box; +static menuslider_s s_gyro_tightening_slider; static menuseparator_s s_calibrating_text[2]; static menuaction_s s_calibrate_gyro; @@ -1917,6 +1918,15 @@ Gyro_MenuInit(void) s_gyro_invertpitch_box.itemnames = yesno_names; s_gyro_invertpitch_box.curvalue = (Cvar_VariableValue("gyro_pitchsensitivity") < 0); + s_gyro_tightening_slider.generic.type = MTYPE_SLIDER; + s_gyro_tightening_slider.generic.x = 0; + s_gyro_tightening_slider.generic.y = (y += 20); + s_gyro_tightening_slider.generic.name = "tightening thresh"; + s_gyro_tightening_slider.cvar = "gyro_tightening"; + s_gyro_tightening_slider.minvalue = 0.0f; + s_gyro_tightening_slider.maxvalue = 12.0f; + s_gyro_tightening_slider.slidestep = 0.5f; + s_calibrating_text[0].generic.type = MTYPE_SEPARATOR; s_calibrating_text[0].generic.x = 48 * scale + 32; s_calibrating_text[0].generic.y = (y += 20); @@ -1939,6 +1949,7 @@ Gyro_MenuInit(void) Menu_AddItem(&s_gyro_menu, (void *)&s_gyro_pitchsensitivity_slider); Menu_AddItem(&s_gyro_menu, (void *)&s_gyro_invertyaw_box); Menu_AddItem(&s_gyro_menu, (void *)&s_gyro_invertpitch_box); + Menu_AddItem(&s_gyro_menu, (void *)&s_gyro_tightening_slider); Menu_AddItem(&s_gyro_menu, (void *)&s_calibrating_text[0]); Menu_AddItem(&s_gyro_menu, (void *)&s_calibrating_text[1]); Menu_AddItem(&s_gyro_menu, (void *)&s_calibrate_gyro);