From e160691feca6bb53be3b585a762c2a3e3750956d Mon Sep 17 00:00:00 2001 From: starfrost013 Date: Wed, 29 May 2024 15:41:12 +0100 Subject: [PATCH 1/8] Fix potential memory corruption issue where cl_numparticles is 0 and CL_ClearParticles is called. --- src/client/cl_particles.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/client/cl_particles.c b/src/client/cl_particles.c index f7d2996d..c2d4ecca 100644 --- a/src/client/cl_particles.c +++ b/src/client/cl_particles.c @@ -33,6 +33,9 @@ int cl_numparticles = MAX_PARTICLES; void CL_ClearParticles(void) { + if (cl_numparticles == 0) + return; + int i; free_particles = &particles[0]; From c68ffec274e6dbb05a11bda7120bafb0a57671d5 Mon Sep 17 00:00:00 2001 From: Jaime Moreira Date: Tue, 4 Jun 2024 14:53:25 -0400 Subject: [PATCH 2/8] GL1 multitexture bugfix With "hand 2" and no "alias" models in player sight, sometimes only lightmap was visible. Now forcing disabled multitexture when needed. Another bugfix: "gl_showbbox 1" no longer produces OpenGL errors. --- src/client/refresh/gl1/gl1_main.c | 1 + src/client/refresh/gl1/gl1_mesh.c | 10 ++++------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/client/refresh/gl1/gl1_main.c b/src/client/refresh/gl1/gl1_main.c index b9f21f39..309e8c2a 100644 --- a/src/client/refresh/gl1/gl1_main.c +++ b/src/client/refresh/gl1/gl1_main.c @@ -409,6 +409,7 @@ R_DrawEntitiesOnList(void) } glDepthMask(1); /* back to writing */ + R_EnableMultitexture(false); } void diff --git a/src/client/refresh/gl1/gl1_mesh.c b/src/client/refresh/gl1/gl1_mesh.c index 1c3f5d13..e4ab4f8c 100644 --- a/src/client/refresh/gl1/gl1_mesh.c +++ b/src/client/refresh/gl1/gl1_mesh.c @@ -825,14 +825,12 @@ R_DrawAliasModel(entity_t *currententity, const model_t *currentmodel) glDisable(GL_CULL_FACE); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); glDisable(GL_TEXTURE_2D); - glBegin(GL_TRIANGLE_STRIP); - for (i = 0; i < 8; i++) - { - glVertex3fv(bbox[i]); - } + glEnableClientState(GL_VERTEX_ARRAY); + glVertexPointer(3, GL_FLOAT, 0, bbox); + glDrawArrays(GL_TRIANGLE_STRIP, 0, 8); + glDisableClientState(GL_VERTEX_ARRAY); - glEnd(); glEnable(GL_TEXTURE_2D); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glEnable(GL_CULL_FACE); From 6869d7dddda19d44c99ace752682db00e162338a Mon Sep 17 00:00:00 2001 From: Jaime Moreira Date: Tue, 4 Jun 2024 14:59:05 -0400 Subject: [PATCH 3/8] GL1 multitexture combine removed Applied too many OpenGL calls for an effect that could not be told apart from normal GL_MODULATE; explains its absence from Q3A code. Also, removed calls to glPixelStorei when no dynamic lights present. --- src/client/refresh/gl1/gl1_image.c | 39 +++------------------------ src/client/refresh/gl1/gl1_main.c | 27 ++----------------- src/client/refresh/gl1/gl1_surf.c | 15 ++++++++--- src/client/refresh/gl1/header/local.h | 1 - src/client/refresh/gl1/header/qgl.h | 7 ----- 5 files changed, 16 insertions(+), 73 deletions(-) diff --git a/src/client/refresh/gl1/gl1_image.c b/src/client/refresh/gl1/gl1_image.c index 83061cd2..1be62d1e 100644 --- a/src/client/refresh/gl1/gl1_image.c +++ b/src/client/refresh/gl1/gl1_image.c @@ -234,47 +234,14 @@ R_EnableMultitexture(qboolean enable) { glEnable(GL_TEXTURE_2D); - if (gl_config.mtexcombine) + if (gl_lightmap->value) { - R_TexEnv(GL_COMBINE); - - if (gl_lightmap->value) - { - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE); - } - else - { - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_PREVIOUS); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA, GL_PREVIOUS); - } - - R_SelectTexture(GL_TEXTURE0); - R_TexEnv(GL_COMBINE); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_REPLACE); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_TEXTURE); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_TEXTURE); - return; + R_TexEnv(GL_REPLACE); } else { - if (gl_lightmap->value) - { - R_TexEnv(GL_REPLACE); - } - else - { - R_TexEnv(GL_MODULATE); - } + R_TexEnv(GL_MODULATE); } - } else // disable multitexturing { diff --git a/src/client/refresh/gl1/gl1_main.c b/src/client/refresh/gl1/gl1_main.c index 309e8c2a..3709cc16 100644 --- a/src/client/refresh/gl1/gl1_main.c +++ b/src/client/refresh/gl1/gl1_main.c @@ -1220,7 +1220,7 @@ R_Register(void) gl1_palettedtexture = ri.Cvar_Get("r_palettedtextures", "0", CVAR_ARCHIVE); gl1_pointparameters = ri.Cvar_Get("gl1_pointparameters", "1", CVAR_ARCHIVE); - gl1_multitexture = ri.Cvar_Get("gl1_multitexture", "2", CVAR_ARCHIVE); + gl1_multitexture = ri.Cvar_Get("gl1_multitexture", "1", CVAR_ARCHIVE); gl1_biglightmaps = ri.Cvar_Get("gl1_biglightmaps", "1", CVAR_ARCHIVE); gl_drawbuffer = ri.Cvar_Get("gl_drawbuffer", "GL_BACK", 0); @@ -1586,7 +1586,7 @@ RI_Init(void) // ---- /* Multitexturing */ - gl_config.multitexture = gl_config.mtexcombine = false; + gl_config.multitexture = false; R_Printf(PRINT_ALL, " - Multitexturing: "); @@ -1621,29 +1621,6 @@ RI_Init(void) // ---- - /* Multi texturing combine */ - R_Printf(PRINT_ALL, " - Multitexturing combine: "); - - if ( ( strstr(gl_config.extensions_string, "GL_ARB_texture_env_combine") - || strstr(gl_config.extensions_string, "GL_EXT_texture_env_combine") ) ) - { - if (gl_config.multitexture && gl1_multitexture->value > 1) - { - gl_config.mtexcombine = true; - R_Printf(PRINT_ALL, "Okay\n"); - } - else - { - R_Printf(PRINT_ALL, "Disabled\n"); - } - } - else - { - R_Printf(PRINT_ALL, "Failed\n"); - } - - // ---- - /* Big lightmaps */ R_Printf(PRINT_ALL, " - Big lightmaps: "); diff --git a/src/client/refresh/gl1/gl1_surf.c b/src/client/refresh/gl1/gl1_surf.c index d0a2fd72..41d47805 100644 --- a/src/client/refresh/gl1/gl1_surf.c +++ b/src/client/refresh/gl1/gl1_surf.c @@ -746,7 +746,7 @@ static void R_RegenAllLightmaps() { int i, map, smax, tmax, top, bottom, left, right, bt, bb, bl, br; - qboolean affected_lightmap; + qboolean affected_lightmap, pixelstore_set = false; msurface_t *surf; byte *base; @@ -755,8 +755,6 @@ R_RegenAllLightmaps() return; } - glPixelStorei(GL_UNPACK_ROW_LENGTH, gl_state.block_width); - for (i = 1; i < gl_state.max_lightmaps; i++) { if (!gl_lms.lightmap_surfaces[i] || !gl_lms.lightmap_buffer[i]) @@ -816,6 +814,12 @@ R_RegenAllLightmaps() continue; } + if (!pixelstore_set) + { + glPixelStorei(GL_UNPACK_ROW_LENGTH, gl_state.block_width); + pixelstore_set = true; + } + base = gl_lms.lightmap_buffer[i]; base += (bt * gl_state.block_width + bl) * LIGHTMAP_BYTES; @@ -825,7 +829,10 @@ R_RegenAllLightmaps() GL_LIGHTMAP_FORMAT, GL_UNSIGNED_BYTE, base); } - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + if (pixelstore_set) + { + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + } } static void diff --git a/src/client/refresh/gl1/header/local.h b/src/client/refresh/gl1/header/local.h index 03cfe3d4..7422f633 100644 --- a/src/client/refresh/gl1/header/local.h +++ b/src/client/refresh/gl1/header/local.h @@ -365,7 +365,6 @@ typedef struct qboolean palettedtexture; qboolean pointparameters; qboolean multitexture; - qboolean mtexcombine; // ---- diff --git a/src/client/refresh/gl1/header/qgl.h b/src/client/refresh/gl1/header/qgl.h index d3bcc510..7e30662d 100644 --- a/src/client/refresh/gl1/header/qgl.h +++ b/src/client/refresh/gl1/header/qgl.h @@ -57,14 +57,7 @@ #define GL_TEXTURE1 0x84C1 #define GL_MULTISAMPLE 0x809D #define GL_COMBINE 0x8570 -#define GL_COMBINE_RGB 0x8571 -#define GL_COMBINE_ALPHA 0x8572 -#define GL_SOURCE0_RGB 0x8580 -#define GL_SOURCE1_RGB 0x8581 -#define GL_SOURCE0_ALPHA 0x8588 -#define GL_SOURCE1_ALPHA 0x8589 #define GL_RGB_SCALE 0x8573 -#define GL_PREVIOUS 0x8578 #endif #ifndef GL_EXT_shared_texture_palette From d2b0ebd5222e56adfd51542ca455eb2b76fe9e23 Mon Sep 17 00:00:00 2001 From: Jaime Moreira Date: Tue, 4 Jun 2024 15:10:41 -0400 Subject: [PATCH 4/8] Correct OpenGL boolean flags. --- src/client/refresh/gl1/gl1_light.c | 4 ++-- src/client/refresh/gl1/gl1_main.c | 10 +++++----- src/client/refresh/gl1/gl1_surf.c | 4 ++-- src/client/refresh/gl3/gl3_main.c | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/client/refresh/gl1/gl1_light.c b/src/client/refresh/gl1/gl1_light.c index 472261ee..88b46106 100644 --- a/src/client/refresh/gl1/gl1_light.c +++ b/src/client/refresh/gl1/gl1_light.c @@ -98,7 +98,7 @@ R_RenderDlights(void) /* because the count hasn't advanced yet for this frame */ r_dlightframecount = r_framecount + 1; - glDepthMask(0); + glDepthMask(GL_FALSE); glDisable(GL_TEXTURE_2D); glShadeModel(GL_SMOOTH); glEnable(GL_BLEND); @@ -115,7 +115,7 @@ R_RenderDlights(void) glDisable(GL_BLEND); glEnable(GL_TEXTURE_2D); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDepthMask(1); + glDepthMask(GL_TRUE); } void diff --git a/src/client/refresh/gl1/gl1_main.c b/src/client/refresh/gl1/gl1_main.c index 3709cc16..1afef160 100644 --- a/src/client/refresh/gl1/gl1_main.c +++ b/src/client/refresh/gl1/gl1_main.c @@ -365,7 +365,7 @@ R_DrawEntitiesOnList(void) /* draw transparent entities we could sort these if it ever becomes a problem... */ - glDepthMask(0); + glDepthMask(GL_FALSE); for (i = 0; i < r_newrefdef.num_entities; i++) { @@ -408,7 +408,7 @@ R_DrawEntitiesOnList(void) } } - glDepthMask(1); /* back to writing */ + glDepthMask(GL_TRUE); /* back to writing */ R_EnableMultitexture(false); } @@ -505,7 +505,7 @@ R_DrawParticles2(int num_particles, const particle_t particles[], glDisable(GL_BLEND); glColor4f(1, 1, 1, 1); - glDepthMask(1); /* back to normal Z buffering */ + glDepthMask(GL_TRUE); /* back to normal Z buffering */ R_TexEnv(GL_REPLACE); YQ2_VLAFREE(vtx); @@ -809,7 +809,7 @@ R_Clear(void) // Check whether the stencil buffer needs clearing, and do so if need be. GLbitfield stencilFlags = 0; if (gl_state.stereo_mode >= STEREO_MODE_ROW_INTERLEAVED && gl_state.stereo_mode <= STEREO_MODE_PIXEL_INTERLEAVED) { - glClearStencil(0); + glClearStencil(GL_FALSE); stencilFlags |= GL_STENCIL_BUFFER_BIT; } @@ -870,7 +870,7 @@ R_Clear(void) /* stencilbuffer shadows */ if (gl_shadows->value && gl_state.stencil && gl1_stencilshadow->value) { - glClearStencil(1); + glClearStencil(GL_TRUE); glClear(GL_STENCIL_BUFFER_BIT); } } diff --git a/src/client/refresh/gl1/gl1_surf.c b/src/client/refresh/gl1/gl1_surf.c index 41d47805..76d90d8a 100644 --- a/src/client/refresh/gl1/gl1_surf.c +++ b/src/client/refresh/gl1/gl1_surf.c @@ -245,7 +245,7 @@ R_BlendLightmaps(const model_t *currentmodel) } /* don't bother writing Z */ - glDepthMask(0); + glDepthMask(GL_FALSE); /* set the appropriate blending mode unless we're only looking at the lightmaps. */ @@ -406,7 +406,7 @@ R_BlendLightmaps(const model_t *currentmodel) /* restore state */ glDisable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDepthMask(1); + glDepthMask(GL_TRUE); } static void diff --git a/src/client/refresh/gl3/gl3_main.c b/src/client/refresh/gl3/gl3_main.c index 977e59f0..73399244 100644 --- a/src/client/refresh/gl3/gl3_main.c +++ b/src/client/refresh/gl3/gl3_main.c @@ -1131,7 +1131,7 @@ GL3_DrawEntitiesOnList(void) /* draw transparent entities we could sort these if it ever becomes a problem... */ - glDepthMask(0); + glDepthMask(GL_FALSE); for (i = 0; i < gl3_newrefdef.num_entities; i++) { @@ -1176,7 +1176,7 @@ GL3_DrawEntitiesOnList(void) GL3_DrawAliasShadows(); - glDepthMask(1); /* back to writing */ + glDepthMask(GL_TRUE); /* back to writing */ } From 0e63bad7d9f28ac619ad3ae71708d3bee9b0197d Mon Sep 17 00:00:00 2001 From: Jaime Moreira Date: Tue, 4 Jun 2024 15:18:37 -0400 Subject: [PATCH 5/8] Sliders and gamepad buttons refactor Same logic with less code. --- src/client/input/sdl2.c | 11 +++-------- src/client/input/sdl3.c | 11 +++-------- src/client/menu/qmenu.c | 36 ++++++++++++------------------------ 3 files changed, 18 insertions(+), 40 deletions(-) diff --git a/src/client/input/sdl2.c b/src/client/input/sdl2.c index 16e53043..0e0dd9a4 100644 --- a/src/client/input/sdl2.c +++ b/src/client/input/sdl2.c @@ -726,14 +726,9 @@ IN_Update(void) qboolean down = (event.type == SDL_CONTROLLERBUTTONDOWN); unsigned char btn = event.cbutton.button; - // Handle Back Button first, to override its original key - if (btn == sdl_back_button) - { - Key_Event(K_JOY_BACK, down, true); - break; - } - - Key_Event(K_BTN_A + btn, down, true); + // Handle Back Button, to override its original key + Key_Event( (btn == sdl_back_button)? K_JOY_BACK : K_BTN_A + btn, + down, true ); break; } diff --git a/src/client/input/sdl3.c b/src/client/input/sdl3.c index 96a85a02..33c62dc8 100644 --- a/src/client/input/sdl3.c +++ b/src/client/input/sdl3.c @@ -717,14 +717,9 @@ IN_Update(void) qboolean down = (event.type == SDL_EVENT_GAMEPAD_BUTTON_DOWN); unsigned char btn = event.gbutton.button; - // Handle Back Button first, to override its original key - if (btn == sdl_back_button) - { - Key_Event(K_JOY_BACK, down, true); - break; - } - - Key_Event(K_BTN_A + btn, down, true); + // Handle Back Button, to override its original key + Key_Event( (btn == sdl_back_button)? K_JOY_BACK : K_BTN_A + btn, + down, true ); break; } diff --git a/src/client/menu/qmenu.c b/src/client/menu/qmenu.c index e4724346..f0e55815 100644 --- a/src/client/menu/qmenu.c +++ b/src/client/menu/qmenu.c @@ -613,14 +613,10 @@ Separator_Draw(menuseparator_s *s) void Slider_DoSlide(menuslider_s *s, int dir) { + const float step = (s->slidestep)? s->slidestep : 0.1f; float value = Cvar_VariableValue(s->cvar); - float step = 0.1f; float sign = 1.0f; - if (s->slidestep) - { - step = s->slidestep; - } if (s->abs && value < 0) // absolute value treatment { value = -value; @@ -641,48 +637,40 @@ Slider_DoSlide(menuslider_s *s, int dir) void Slider_Draw(menuslider_s *s) { + const float scale = SCR_GetMenuScale(); + const int x = s->generic.parent->x + s->generic.x; + const int y = s->generic.parent->y + s->generic.y; + const int x_rcol = x + (RCOLUMN_OFFSET * scale); int i; char buffer[5]; - const char * format; - float scale = SCR_GetMenuScale(); - int x = s->generic.parent->x + s->generic.x; - int y = s->generic.parent->y + s->generic.y; float value = Cvar_VariableValue(s->cvar); if (s->abs && value < 0) // absolute value { value = -value; } - float range = (ClampCvar(s->minvalue, s->maxvalue, value) - s->minvalue) / + const float range = (ClampCvar(s->minvalue, s->maxvalue, value) - s->minvalue) / (s->maxvalue - s->minvalue); Menu_DrawStringR2LDark(x + (LCOLUMN_OFFSET * scale), y, s->generic.name); - Draw_CharScaled(x + (RCOLUMN_OFFSET * scale), + Draw_CharScaled(x_rcol, y * scale, 128, scale); for (i = 0; i < SLIDER_RANGE * scale; i++) { - Draw_CharScaled(x + (RCOLUMN_OFFSET * scale) + (i * 8) + 8, + Draw_CharScaled(x_rcol + (i * 8) + 8, y * scale, 129, scale); } - Draw_CharScaled(x + (RCOLUMN_OFFSET * scale) + (i * 8) + 8, + Draw_CharScaled(x_rcol + (i * 8) + 8, y * scale, 130, scale); - Draw_CharScaled(x + ((int)((RCOLUMN_OFFSET * scale) + (SLIDER_RANGE * scale - 1) * 8 * range)) + 8, + Draw_CharScaled(x_rcol + (int)((SLIDER_RANGE * scale - 1) * 8 * range) + 8, y * scale, 131, scale); - if (!s->printformat) - { - format = "%.1f"; - } - else - { - format = s->printformat; - } - snprintf(buffer, 5, format, value); - Menu_DrawString(x + (RCOLUMN_OFFSET * scale) + ((SLIDER_RANGE + 2) * scale * 8), + snprintf(buffer, 5, (s->printformat)? s->printformat : "%.1f", value); + Menu_DrawString(x_rcol + ((SLIDER_RANGE + 2) * scale * 8), y, buffer); } From 24b03b61f8a91c7d60182844849fc2cb758f8a9e Mon Sep 17 00:00:00 2001 From: Jaime Moreira Date: Tue, 4 Jun 2024 15:48:42 -0400 Subject: [PATCH 6/8] 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); From c4271848dfaa19176525ccfd171620cfba11a4a5 Mon Sep 17 00:00:00 2001 From: Jaime Moreira Date: Tue, 4 Jun 2024 16:21:10 -0400 Subject: [PATCH 7/8] gl1_multitexture doc update --- doc/040_cvarlist.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/doc/040_cvarlist.md b/doc/040_cvarlist.md index 8bd22978..c31c9c81 100644 --- a/doc/040_cvarlist.md +++ b/doc/040_cvarlist.md @@ -468,11 +468,10 @@ Set `0` by default. value, at least `1.0` - default is `2.0`. Applied when textures are loaded, so it needs a `vid_restart`. -* **gl1_multitexture**: Enables (`1`) the blending of color and light - textures on a single drawing pass; disabling this (`0`) does one pass - for color and another for light. Default is `2`, which also enables - texture combine mode (`GL_ARB_texture_env_combine`) when supported. - Requires a `vid_restart` when changed. +* **gl1_multitexture**: Enables (`1`, default) the blending of color and + light textures on a single drawing pass; disabling this (`0`) does one + pass for color and another for light. Requires a `vid_restart` when + changed. * **gl1_overbrightbits**: Enables overbright bits, brightness scaling of lightmaps and models. Higher values make shadows less dark. Possible From c842ab806ff92b76e0faacd8ee7f8ee239109690 Mon Sep 17 00:00:00 2001 From: Jaime Moreira Date: Thu, 6 Jun 2024 18:23:26 -0400 Subject: [PATCH 8/8] Remove fruitless glBindTexture() calls ...when there are no SURF_DRAWTURB surfaces to draw. --- src/client/refresh/gl1/gl1_surf.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/client/refresh/gl1/gl1_surf.c b/src/client/refresh/gl1/gl1_surf.c index 76d90d8a..5283d3fb 100644 --- a/src/client/refresh/gl1/gl1_surf.c +++ b/src/client/refresh/gl1/gl1_surf.c @@ -903,12 +903,11 @@ R_DrawTextureChains(entity_t *currententity) continue; } - R_Bind(image->texnum); // no danger of resetting in R_RenderBrushPoly - for (s = image->texturechain; s; s = s->texturechain) { if (s->flags & SURF_DRAWTURB) { + R_Bind(image->texnum); R_RenderBrushPoly(currententity, s); } }