From 1cd72768010b0f08395c1208c3539a65ba6bd34a Mon Sep 17 00:00:00 2001 From: Draena Date: Sun, 30 May 2021 00:31:42 +0200 Subject: [PATCH 1/5] Added mouse acceleration --- src/engine/engine.h | 1 + src/game/game.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/src/engine/engine.h b/src/engine/engine.h index d464c37fd..1826f696b 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -283,6 +283,7 @@ extern bool hasVAO, hasTR, hasTSW, hasPBO, hasFBO, hasAFBO, hasDS, hasTF, hasCBF extern int glversion, glslversion, glcompat; extern char *gfxvendor, *gfxrenderer, *gfxversion; extern int maxdrawbufs, maxdualdrawbufs; +extern int framemillis; enum { DRAWTEX_NONE = 0, DRAWTEX_ENVMAP, DRAWTEX_MINIMAP, DRAWTEX_MODELPREVIEW, DRAWTEX_MAPSHOT, DRAWTEX_HALO }; diff --git a/src/game/game.cpp b/src/game/game.cpp index 3d7d28d3d..a7c61a3be 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -320,6 +320,12 @@ namespace game FVAR(IDF_PERSIST, mousesensitivity, 1e-4f, 1, 10000); FVAR(IDF_PERSIST, zoomsensitivity, 0, 0.65f, 1000); + // Section regarding mouse acceleration + FVAR(IDF_PERSIST, mouseaccelerationexp, FVAR_MIN, 2, FVAR_MAX); + FVAR(IDF_PERSIST, mouseaccelerationfactor, FVAR_MIN, 0, FVAR_MAX); + FVAR(IDF_PERSIST, mouseaccelerationoffset, FVAR_MIN, 0, FVAR_MAX); + FVAR(IDF_PERSIST, mouseaccelerationsenscap, FVAR_MIN, 0, FVAR_MAX); + VARF(IDF_PERSIST, zoomlevel, 0, 4, 10, checkzoom()); VAR(IDF_PERSIST, zoomlevels, 1, 5, 10); VAR(IDF_PERSIST, zoomdefault, -1, -1, 10); // -1 = last used, else defines default level @@ -2431,7 +2437,7 @@ namespace game { #define mousesens(a,b,c) ((float(a)/float(b))*c) if(mouseoverride&2 || (!mouseoverride && hud::hasinput(true))) - { + { cursorx = clamp(cursorx+mousesens(dx, w, mousesensitivity), 0.f, 1.f); cursory = clamp(cursory+mousesens(dy, h, mousesensitivity), 0.f, 1.f); if(!(mouseoverride&1)) return true; @@ -2441,13 +2447,56 @@ namespace game physent *d = (!gs_playing(gamestate) || player1->state >= CS_SPECTATOR) && (focus == player1 || followaim()) ? camera1 : (allowmove(player1) ? player1 : NULL); if(d) { - float scale = (focus == player1 && inzoom() && zoomsensitivity > 0 ? (1.f-((zoomlevel+1)/float(zoomlevels+2)))*zoomsensitivity : 1.f)*sensitivity; + float accelsensitivity = 1; + if(mouseaccelerationfactor) + { + // Then do Quake Live-style power acceleration. + // Note that this behavior REPLACES the usual + // sensitivity, so we apply it but then dividie by + // sensitivity.value so that the later multiplication + // restores it again. + float mouse_deltadist = sqrtf(dx * dx + dy * dy); + float speed = mouse_deltadist / framemillis; + float adjusted_speed_pxms = (speed * 0.001f - mouseaccelerationoffset) * mouseaccelerationfactor; + float inv_sensitivity = 1.0f / sensitivity; + if (adjusted_speed_pxms > 0) + { + if (mouseaccelerationexp > 1.0f) + { + // TODO: How does this interact with sensitivity changes? Is this intended? + // Currently: more sensitivity = less acceleration at same pixel speed. + accelsensitivity += expf((mouseaccelerationexp - 1.0f) * logf(adjusted_speed_pxms)) * inv_sensitivity; + } + else + { + // The limit of the then-branch for m_accelerate_power -> 1. + accelsensitivity += inv_sensitivity; + // Note: QL had just accelsens = 1.0f. + // This is mathematically wrong though. + } + } + else + { + // The limit of the then-branch for adjusted_speed -> 0. + accelsensitivity += 0.0f; + } + if (mouseaccelerationsenscap > 0.0f && accelsensitivity > mouseaccelerationsenscap * inv_sensitivity) + { + // TODO: How does this interact with sensitivity changes? Is this intended? + // Currently: senscap is in absolute sensitivity units, so if senscap < sensitivity, it overrides. + accelsensitivity = mouseaccelerationsenscap * inv_sensitivity; + } + + } + + // end accel + float scale = (focus == player1 && inzoom() && zoomsensitivity > 0 ? (1.f-((zoomlevel+1)/float(zoomlevels+2)))*zoomsensitivity : 1.f)*sensitivity*accelsensitivity; // t d->yaw += mousesens(dx, sensitivityscale, yawsensitivity*scale); d->pitch -= mousesens(dy, sensitivityscale, pitchsensitivity*scale*(mouseinvert ? -1.f : 1.f)); fixrange(d->yaw, d->pitch); } return true; - } + } return false; } From 6611fa392d4a72c5750cae1203464fec8b88c089 Mon Sep 17 00:00:00 2001 From: Draena Date: Sun, 30 May 2021 17:12:42 +0200 Subject: [PATCH 2/5] Correcting and documenting mouse acceleration --- config/usage.cfg | 5 +++++ src/engine/rendergl.cpp | 7 ++----- src/game/game.cpp | 1 - 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/config/usage.cfg b/config/usage.cfg index 2c885595e..1036257d0 100644 --- a/config/usage.cfg +++ b/config/usage.cfg @@ -569,6 +569,11 @@ setdesc "pitchsensitivity" "determines scale factor for pitch (up/down tilt) mov setdesc "sensitivityscale" "determines scale factor for all types of mouse sensitivity" "value" setdesc "mousesensitivity" "determines scale by which to multiply mouse input for cursor position in menus" "value" +setdesc "mouseaccelerationexp" "Values 1 or below are not recommended. 2 is linear and the default. Above 2 begins to amplify exponentially and you will get more acceleration at higher velocities. Great if you want low accel for slow movements, and high accel for fast movements. Good in combination with a sensitivity cap (mouseaccelerationsenscap). Values between 1 and 2 generates logarithmic curves, 1.05 is popular among counter strike players and 1.6 is also very manageable." "value" +setdesc "mouseaccelerationfactor" "Values > 0 will amplify mouse movement proportional to velocity. Small values have great effect. values around 20 have good effect, but this depends on your mouse CPI and polling rate." "value" +setdesc "mouseaccelerationoffset" "Acceleration will not be active until the mouse movement exceeds this speed (counts per millisecond). Negative values are supported, which has the effect of causing higher rates of acceleration to happen at lower velocities." "value" +setdesc "mouseaccelerationsenscap" "Sets an upper limit on the amplified mouse movement. Great for tuning acceleration around lower velocities while still remaining in control of fast motion such as flicking." "value" + //engine settings setdesc "maxfps" "caps the maximum framerate at the given value; note that vsync will cap at monitor refresh if enabled" "value" setdesc "vsync" "toggles vertical synchronization (frame pacing to monitor refresh rate)" "boolean" diff --git a/src/engine/rendergl.cpp b/src/engine/rendergl.cpp index e78933365..8972450bb 100644 --- a/src/engine/rendergl.cpp +++ b/src/engine/rendergl.cpp @@ -2572,11 +2572,8 @@ void gl_drawframe() if(!noview) gl_drawview(); gl_drawhud(noview); - if(frametimer) - { - glFinish(); - framemillis = getclockmillis() - totalmillis; - } + glFinish(); + framemillis = getclockmillis() - totalmillis; } void cleanupgl() diff --git a/src/game/game.cpp b/src/game/game.cpp index a7c61a3be..fc19af1a6 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -2488,7 +2488,6 @@ namespace game } } - // end accel float scale = (focus == player1 && inzoom() && zoomsensitivity > 0 ? (1.f-((zoomlevel+1)/float(zoomlevels+2)))*zoomsensitivity : 1.f)*sensitivity*accelsensitivity; // t d->yaw += mousesens(dx, sensitivityscale, yawsensitivity*scale); From ee56a5c797f1bc7aaa114a2be8f07e3a2a96bb51 Mon Sep 17 00:00:00 2001 From: anengineer1 <52609000+anengineer1@users.noreply.github.com> Date: Sun, 30 May 2021 19:12:52 +0200 Subject: [PATCH 3/5] Solving indexing on mouse accel code --- src/game/game.cpp | 90 +++++++++++++++++++++++------------------------ 1 file changed, 45 insertions(+), 45 deletions(-) diff --git a/src/game/game.cpp b/src/game/game.cpp index fc19af1a6..abb48f707 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -2437,7 +2437,7 @@ namespace game { #define mousesens(a,b,c) ((float(a)/float(b))*c) if(mouseoverride&2 || (!mouseoverride && hud::hasinput(true))) - { + { cursorx = clamp(cursorx+mousesens(dx, w, mousesensitivity), 0.f, 1.f); cursory = clamp(cursory+mousesens(dy, h, mousesensitivity), 0.f, 1.f); if(!(mouseoverride&1)) return true; @@ -2447,55 +2447,55 @@ namespace game physent *d = (!gs_playing(gamestate) || player1->state >= CS_SPECTATOR) && (focus == player1 || followaim()) ? camera1 : (allowmove(player1) ? player1 : NULL); if(d) { - float accelsensitivity = 1; - if(mouseaccelerationfactor) - { - // Then do Quake Live-style power acceleration. - // Note that this behavior REPLACES the usual - // sensitivity, so we apply it but then dividie by - // sensitivity.value so that the later multiplication - // restores it again. - float mouse_deltadist = sqrtf(dx * dx + dy * dy); - float speed = mouse_deltadist / framemillis; - float adjusted_speed_pxms = (speed * 0.001f - mouseaccelerationoffset) * mouseaccelerationfactor; - float inv_sensitivity = 1.0f / sensitivity; - if (adjusted_speed_pxms > 0) - { - if (mouseaccelerationexp > 1.0f) - { - // TODO: How does this interact with sensitivity changes? Is this intended? - // Currently: more sensitivity = less acceleration at same pixel speed. - accelsensitivity += expf((mouseaccelerationexp - 1.0f) * logf(adjusted_speed_pxms)) * inv_sensitivity; - } - else - { - // The limit of the then-branch for m_accelerate_power -> 1. - accelsensitivity += inv_sensitivity; - // Note: QL had just accelsens = 1.0f. - // This is mathematically wrong though. - } - } - else - { - // The limit of the then-branch for adjusted_speed -> 0. - accelsensitivity += 0.0f; - } - if (mouseaccelerationsenscap > 0.0f && accelsensitivity > mouseaccelerationsenscap * inv_sensitivity) - { - // TODO: How does this interact with sensitivity changes? Is this intended? - // Currently: senscap is in absolute sensitivity units, so if senscap < sensitivity, it overrides. - accelsensitivity = mouseaccelerationsenscap * inv_sensitivity; - } - - } - // end accel - float scale = (focus == player1 && inzoom() && zoomsensitivity > 0 ? (1.f-((zoomlevel+1)/float(zoomlevels+2)))*zoomsensitivity : 1.f)*sensitivity*accelsensitivity; // t + float accelsensitivity = 1; + if(mouseaccelerationfactor) + { + // Then do Quake Live-style power acceleration. + // Note that this behavior REPLACES the usual + // sensitivity, so we apply it but then dividie by + // sensitivity.value so that the later multiplication + // restores it again. + float mouse_deltadist = sqrtf(dx * dx + dy * dy); + float speed = mouse_deltadist / framemillis; + float adjusted_speed_pxms = (speed * 0.001f - mouseaccelerationoffset) * mouseaccelerationfactor; + float inv_sensitivity = 1.0f / sensitivity; + if (adjusted_speed_pxms > 0) + { + if (mouseaccelerationexp > 1.0f) + { + // TODO: How does this interact with sensitivity changes? Is this intended? + // Currently: more sensitivity = less acceleration at same pixel speed. + accelsensitivity += expf((mouseaccelerationexp - 1.0f) * logf(adjusted_speed_pxms)) * inv_sensitivity; + } + else + { + // The limit of the then-branch for m_accelerate_power -> 1. + accelsensitivity += inv_sensitivity; + // Note: QL had just accelsens = 1.0f. + // This is mathematically wrong though. + } + } + else + { + // The limit of the then-branch for adjusted_speed -> 0. + accelsensitivity += 0.0f; + } + if (mouseaccelerationsenscap > 0.0f && accelsensitivity > mouseaccelerationsenscap * inv_sensitivity) + { + // TODO: How does this interact with sensitivity changes? Is this intended? + // Currently: senscap is in absolute sensitivity units, so if senscap < sensitivity, it overrides. + accelsensitivity = mouseaccelerationsenscap * inv_sensitivity; + } + + } + // end accel + float scale = (focus == player1 && inzoom() && zoomsensitivity > 0 ? (1.f-((zoomlevel+1)/float(zoomlevels+2)))*zoomsensitivity : 1.f)*sensitivity*accelsensitivity; // t d->yaw += mousesens(dx, sensitivityscale, yawsensitivity*scale); d->pitch -= mousesens(dy, sensitivityscale, pitchsensitivity*scale*(mouseinvert ? -1.f : 1.f)); fixrange(d->yaw, d->pitch); } return true; - } + } return false; } From cea01d3e86ede870eec909f2756f0f82c81f80b5 Mon Sep 17 00:00:00 2001 From: Draena Date: Tue, 1 Jun 2021 16:47:06 +0200 Subject: [PATCH 4/5] Refactor mouse acceleration code --- config/usage.cfg | 8 ++++---- src/game/game.cpp | 38 ++++++++++++++++---------------------- 2 files changed, 20 insertions(+), 26 deletions(-) diff --git a/config/usage.cfg b/config/usage.cfg index 1036257d0..2907db3b0 100644 --- a/config/usage.cfg +++ b/config/usage.cfg @@ -569,10 +569,10 @@ setdesc "pitchsensitivity" "determines scale factor for pitch (up/down tilt) mov setdesc "sensitivityscale" "determines scale factor for all types of mouse sensitivity" "value" setdesc "mousesensitivity" "determines scale by which to multiply mouse input for cursor position in menus" "value" -setdesc "mouseaccelerationexp" "Values 1 or below are not recommended. 2 is linear and the default. Above 2 begins to amplify exponentially and you will get more acceleration at higher velocities. Great if you want low accel for slow movements, and high accel for fast movements. Good in combination with a sensitivity cap (mouseaccelerationsenscap). Values between 1 and 2 generates logarithmic curves, 1.05 is popular among counter strike players and 1.6 is also very manageable." "value" -setdesc "mouseaccelerationfactor" "Values > 0 will amplify mouse movement proportional to velocity. Small values have great effect. values around 20 have good effect, but this depends on your mouse CPI and polling rate." "value" -setdesc "mouseaccelerationoffset" "Acceleration will not be active until the mouse movement exceeds this speed (counts per millisecond). Negative values are supported, which has the effect of causing higher rates of acceleration to happen at lower velocities." "value" -setdesc "mouseaccelerationsenscap" "Sets an upper limit on the amplified mouse movement. Great for tuning acceleration around lower velocities while still remaining in control of fast motion such as flicking." "value" +setdesc "mouseaccelexp" "Values 1 or below are not recommended. 2 is linear and the default. Above 2 begins to amplify exponentially and you will get more acceleration at higher velocities. Great if you want low accel for slow movements, and high accel for fast movements. Good in combination with a sensitivity cap (mouseaccelerationsenscap). Values between 1 and 2 generates logarithmic curves, 1.05 is popular among counter strike players and 1.6 is also very manageable." "value" +setdesc "mouseaccel" "Values > 0 will amplify mouse movement proportional to velocity. Small values have great effect. values around 20 have good effect, but this depends on your mouse CPI and polling rate." "value" +setdesc "mouseacceloffset" "Acceleration will not be active until the mouse movement exceeds this speed (counts per millisecond). Negative values are supported, which has the effect of causing higher rates of acceleration to happen at lower velocities." "value" +setdesc "mouseaccelsenscap" "Sets an upper limit on the amplified mouse movement. Great for tuning acceleration around lower velocities while still remaining in control of fast motion such as flicking." "value" //engine settings setdesc "maxfps" "caps the maximum framerate at the given value; note that vsync will cap at monitor refresh if enabled" "value" diff --git a/src/game/game.cpp b/src/game/game.cpp index abb48f707..f47bc1c54 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -321,10 +321,10 @@ namespace game FVAR(IDF_PERSIST, zoomsensitivity, 0, 0.65f, 1000); // Section regarding mouse acceleration - FVAR(IDF_PERSIST, mouseaccelerationexp, FVAR_MIN, 2, FVAR_MAX); - FVAR(IDF_PERSIST, mouseaccelerationfactor, FVAR_MIN, 0, FVAR_MAX); - FVAR(IDF_PERSIST, mouseaccelerationoffset, FVAR_MIN, 0, FVAR_MAX); - FVAR(IDF_PERSIST, mouseaccelerationsenscap, FVAR_MIN, 0, FVAR_MAX); + FVAR(IDF_PERSIST, mouseaccelexp, FVAR_MIN, 2, FVAR_MAX); + FVAR(IDF_PERSIST, mouseaccel, FVAR_MIN, 0, FVAR_MAX); + FVAR(IDF_PERSIST, mouseacceloffset, FVAR_MIN, 0, FVAR_MAX); + FVAR(IDF_PERSIST, mouseaccelsenscap, FVAR_MIN, 0, FVAR_MAX); VARF(IDF_PERSIST, zoomlevel, 0, 4, 10, checkzoom()); VAR(IDF_PERSIST, zoomlevels, 1, 5, 10); @@ -2448,47 +2448,41 @@ namespace game if(d) { float accelsensitivity = 1; - if(mouseaccelerationfactor) + if(mouseaccel != 0) { // Then do Quake Live-style power acceleration. - // Note that this behavior REPLACES the usual - // sensitivity, so we apply it but then dividie by - // sensitivity.value so that the later multiplication - // restores it again. - float mouse_deltadist = sqrtf(dx * dx + dy * dy); - float speed = mouse_deltadist / framemillis; - float adjusted_speed_pxms = (speed * 0.001f - mouseaccelerationoffset) * mouseaccelerationfactor; - float inv_sensitivity = 1.0f / sensitivity; - if (adjusted_speed_pxms > 0) + // Note that this behavior REPLACES the usual sensitivity, we then have to divide the result by the sensitivity again to no have double the sensitivity + float speed = (sqrtf(dx * dx + dy * dy) / framemillis); + float adjustedspeedpxms = (speed - mouseacceloffset) * 0.001f * mouseaccel; + if(adjustedspeedpxms > 0) { - if (mouseaccelerationexp > 1.0f) + if(mouseaccelexp > 1.0f) { // TODO: How does this interact with sensitivity changes? Is this intended? // Currently: more sensitivity = less acceleration at same pixel speed. - accelsensitivity += expf((mouseaccelerationexp - 1.0f) * logf(adjusted_speed_pxms)) * inv_sensitivity; + accelsensitivity += expf((mouseaccelexp - 1.0f) * logf(adjustedspeedpxms)) / sensitivity; } else { - // The limit of the then-branch for m_accelerate_power -> 1. - accelsensitivity += inv_sensitivity; + // The limit of the then-branch for mauseaccel -> 1. + accelsensitivity += (1 / sensitivity); // Note: QL had just accelsens = 1.0f. // This is mathematically wrong though. } } else { - // The limit of the then-branch for adjusted_speed -> 0. + // The limit of the then-branch for adjustedspeed -> 0. accelsensitivity += 0.0f; } - if (mouseaccelerationsenscap > 0.0f && accelsensitivity > mouseaccelerationsenscap * inv_sensitivity) + if(mouseaccelsenscap > 0.0f && accelsensitivity > mouseaccelsenscap / sensitivity) { // TODO: How does this interact with sensitivity changes? Is this intended? // Currently: senscap is in absolute sensitivity units, so if senscap < sensitivity, it overrides. - accelsensitivity = mouseaccelerationsenscap * inv_sensitivity; + accelsensitivity = mouseaccelsenscap / sensitivity; } } - // end accel float scale = (focus == player1 && inzoom() && zoomsensitivity > 0 ? (1.f-((zoomlevel+1)/float(zoomlevels+2)))*zoomsensitivity : 1.f)*sensitivity*accelsensitivity; // t d->yaw += mousesens(dx, sensitivityscale, yawsensitivity*scale); d->pitch -= mousesens(dy, sensitivityscale, pitchsensitivity*scale*(mouseinvert ? -1.f : 1.f)); From fec5c58c6d1f6d90855de2613db1824495c36877 Mon Sep 17 00:00:00 2001 From: Draena Date: Tue, 4 Jan 2022 16:31:43 +0100 Subject: [PATCH 5/5] using curtime instead of framemillis for mouse acceleration --- src/engine/engine.h | 1 - src/engine/rendergl.cpp | 7 +++++-- src/game/game.cpp | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/engine/engine.h b/src/engine/engine.h index 1826f696b..d464c37fd 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -283,7 +283,6 @@ extern bool hasVAO, hasTR, hasTSW, hasPBO, hasFBO, hasAFBO, hasDS, hasTF, hasCBF extern int glversion, glslversion, glcompat; extern char *gfxvendor, *gfxrenderer, *gfxversion; extern int maxdrawbufs, maxdualdrawbufs; -extern int framemillis; enum { DRAWTEX_NONE = 0, DRAWTEX_ENVMAP, DRAWTEX_MINIMAP, DRAWTEX_MODELPREVIEW, DRAWTEX_MAPSHOT, DRAWTEX_HALO }; diff --git a/src/engine/rendergl.cpp b/src/engine/rendergl.cpp index 8972450bb..e78933365 100644 --- a/src/engine/rendergl.cpp +++ b/src/engine/rendergl.cpp @@ -2572,8 +2572,11 @@ void gl_drawframe() if(!noview) gl_drawview(); gl_drawhud(noview); - glFinish(); - framemillis = getclockmillis() - totalmillis; + if(frametimer) + { + glFinish(); + framemillis = getclockmillis() - totalmillis; + } } void cleanupgl() diff --git a/src/game/game.cpp b/src/game/game.cpp index f47bc1c54..faf21f845 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -2452,7 +2452,7 @@ namespace game { // Then do Quake Live-style power acceleration. // Note that this behavior REPLACES the usual sensitivity, we then have to divide the result by the sensitivity again to no have double the sensitivity - float speed = (sqrtf(dx * dx + dy * dy) / framemillis); + float speed = (sqrtf(dx * dx + dy * dy) / curtime); float adjustedspeedpxms = (speed - mouseacceloffset) * 0.001f * mouseaccel; if(adjustedspeedpxms > 0) {