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
This commit is contained in:
Jaime Moreira 2024-06-04 15:48:42 -04:00
parent 0e63bad7d9
commit 24b03b61f8
4 changed files with 85 additions and 10 deletions

View file

@ -598,6 +598,10 @@ Set `0` by default.
for people who hold the controller upright, or use a device with the for people who hold the controller upright, or use a device with the
controller attached to the screen, e.g. Steam Deck. 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 * **gyro_calibration_(x/y/z)**: Offset values on each axis of the gyro
which helps it reach true "zero movement", complete stillness. These which helps it reach true "zero movement", complete stillness. These
values are wrong if you see your in-game view "drift" when leaving values are wrong if you see your in-game view "drift" when leaving

View file

@ -162,6 +162,7 @@ cvar_t *gyro_turning_axis; // yaw or roll
// Gyro sensitivity // Gyro sensitivity
static cvar_t *gyro_yawsensitivity; static cvar_t *gyro_yawsensitivity;
static cvar_t *gyro_pitchsensitivity; static cvar_t *gyro_pitchsensitivity;
static cvar_t *gyro_tightening;
// Gyro is being used in this very moment // Gyro is being used in this very moment
static qboolean gyro_active = false; static qboolean gyro_active = false;
@ -1069,6 +1070,30 @@ IN_ApplyExpo(thumbstick_t stick, float exponent)
return result; 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 * 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_yaw, joystick_pitch;
static float joystick_forwardmove, joystick_sidemove; static float joystick_forwardmove, joystick_sidemove;
static thumbstick_t left_stick = {0}, right_stick = {0}; static thumbstick_t left_stick = {0}, right_stick = {0};
thumbstick_t gyro_in = {0};
if (m_filter->value) if (m_filter->value)
{ {
@ -1378,16 +1404,21 @@ IN_Move(usercmd_t *cmd)
* cl_sidespeed->value * 2.0f * joystick_sidemove; * cl_sidespeed->value * 2.0f * joystick_sidemove;
} }
if (gyro_yaw) if (gyro_yaw || gyro_pitch)
{ {
cl.viewangles[YAW] += m_yaw->value * gyro_yawsensitivity->value gyro_in = IN_TightenInput(gyro_yaw, gyro_pitch);
* cl_yawspeed->value * gyro_yaw * gyroViewFactor;
} }
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.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 // 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_yawsensitivity = Cvar_Get("gyro_yawsensitivity", "1.0", CVAR_ARCHIVE);
gyro_pitchsensitivity = Cvar_Get("gyro_pitchsensitivity", "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_turning_axis = Cvar_Get("gyro_turning_axis", "0", CVAR_ARCHIVE);
gyro_mode = Cvar_Get("gyro_mode", "2", CVAR_ARCHIVE); gyro_mode = Cvar_Get("gyro_mode", "2", CVAR_ARCHIVE);

View file

@ -165,6 +165,7 @@ cvar_t *gyro_turning_axis; // yaw or roll
// Gyro sensitivity // Gyro sensitivity
static cvar_t *gyro_yawsensitivity; static cvar_t *gyro_yawsensitivity;
static cvar_t *gyro_pitchsensitivity; static cvar_t *gyro_pitchsensitivity;
static cvar_t *gyro_tightening;
// Gyro is being used in this very moment // Gyro is being used in this very moment
static qboolean gyro_active = false; static qboolean gyro_active = false;
@ -1058,6 +1059,26 @@ IN_ApplyExpo(thumbstick_t stick, float exponent)
return result; 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 * 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_yaw, joystick_pitch;
static float joystick_forwardmove, joystick_sidemove; static float joystick_forwardmove, joystick_sidemove;
static thumbstick_t left_stick = {0}, right_stick = {0}; static thumbstick_t left_stick = {0}, right_stick = {0};
thumbstick_t gyro_in = {0};
if (m_filter->value) if (m_filter->value)
{ {
@ -1367,16 +1389,21 @@ IN_Move(usercmd_t *cmd)
* cl_sidespeed->value * 2.0f * joystick_sidemove; * cl_sidespeed->value * 2.0f * joystick_sidemove;
} }
if (gyro_yaw) if (gyro_yaw || gyro_pitch)
{ {
cl.viewangles[YAW] += m_yaw->value * gyro_yawsensitivity->value gyro_in = IN_TightenInput(gyro_yaw, gyro_pitch);
* cl_yawspeed->value * gyro_yaw * gyroViewFactor;
} }
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.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 // 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_yawsensitivity = Cvar_Get("gyro_yawsensitivity", "1.0", CVAR_ARCHIVE);
gyro_pitchsensitivity = Cvar_Get("gyro_pitchsensitivity", "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_turning_axis = Cvar_Get("gyro_turning_axis", "0", CVAR_ARCHIVE);
gyro_mode = Cvar_Get("gyro_mode", "2", CVAR_ARCHIVE); gyro_mode = Cvar_Get("gyro_mode", "2", CVAR_ARCHIVE);

View file

@ -1780,6 +1780,7 @@ static menuslider_s s_gyro_yawsensitivity_slider;
static menuslider_s s_gyro_pitchsensitivity_slider; static menuslider_s s_gyro_pitchsensitivity_slider;
static menulist_s s_gyro_invertyaw_box; static menulist_s s_gyro_invertyaw_box;
static menulist_s s_gyro_invertpitch_box; static menulist_s s_gyro_invertpitch_box;
static menuslider_s s_gyro_tightening_slider;
static menuseparator_s s_calibrating_text[2]; static menuseparator_s s_calibrating_text[2];
static menuaction_s s_calibrate_gyro; static menuaction_s s_calibrate_gyro;
@ -1917,6 +1918,15 @@ Gyro_MenuInit(void)
s_gyro_invertpitch_box.itemnames = yesno_names; s_gyro_invertpitch_box.itemnames = yesno_names;
s_gyro_invertpitch_box.curvalue = (Cvar_VariableValue("gyro_pitchsensitivity") < 0); 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.type = MTYPE_SEPARATOR;
s_calibrating_text[0].generic.x = 48 * scale + 32; s_calibrating_text[0].generic.x = 48 * scale + 32;
s_calibrating_text[0].generic.y = (y += 20); 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_pitchsensitivity_slider);
Menu_AddItem(&s_gyro_menu, (void *)&s_gyro_invertyaw_box); 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_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[0]);
Menu_AddItem(&s_gyro_menu, (void *)&s_calibrating_text[1]); Menu_AddItem(&s_gyro_menu, (void *)&s_calibrating_text[1]);
Menu_AddItem(&s_gyro_menu, (void *)&s_calibrate_gyro); Menu_AddItem(&s_gyro_menu, (void *)&s_calibrate_gyro);