From: Rudolf Polzer Date: Thu, 12 Mar 2020 00:12:01 +0000 (-0400) Subject: Fix handling of sensitivity.value, and split m_accel into m_accel + m_accel_power_str... X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=53d6fb3c919349e2a1074844feabb11fd98099cd;p=xonotic%2Fdarkplaces.git Fix handling of sensitivity.value, and split m_accel into m_accel + m_accel_power_strength. This eliminates the need for the ability to switch between the two methods of acceleration. Also, explain a lot more. --- diff --git a/cl_input.c b/cl_input.c index 4aa4eb4f..06a2b811 100644 --- a/cl_input.c +++ b/cl_input.c @@ -399,15 +399,14 @@ cvar_t in_pitch_min = {CVAR_CLIENT, "in_pitch_min", "-90", "how far you can aim cvar_t in_pitch_max = {CVAR_CLIENT, "in_pitch_max", "90", "how far you can aim downward (quake used 80)"}; cvar_t m_filter = {CVAR_CLIENT | CVAR_SAVE, "m_filter","0", "smoothes mouse movement, less responsive but smoother aiming"}; -cvar_t m_accelerate = {CVAR_CLIENT | CVAR_SAVE, "m_accelerate","1", "mouse acceleration factor (try 2 when m_accelerate_type is 0 and 0.01 when m_accelerate_type is 1)"}; -cvar_t m_accelerate_minspeed = {CVAR_CLIENT | CVAR_SAVE, "m_accelerate_minspeed","5000", "(when m_accelerate is 0) below this speed, no acceleration is done"}; -cvar_t m_accelerate_maxspeed = {CVAR_CLIENT | CVAR_SAVE, "m_accelerate_maxspeed","10000", "(when m_accelerate is 0) above this speed, full acceleration is done"}; -cvar_t m_accelerate_filter = {CVAR_CLIENT | CVAR_SAVE, "m_accelerate_filter","0.1", "(when m_accelerate is 0) mouse acceleration factor filtering"}; -// Quake live implementation of mouse acceleration -cvar_t m_accelerate_type = {CVAR_CLIENT | CVAR_SAVE, "m_accelerate_type","0", "0 for the darkplaces default implementation of mouse acceleration, 1 for the quakelive implementation"}; -cvar_t m_accelerate_offset = {CVAR_CLIENT | CVAR_SAVE, "m_accelerate_offset","0", "(when m_accelerate_type is 1) below this speed, no acceleration is done"}; -cvar_t m_accelerate_power = {CVAR_CLIENT | CVAR_SAVE, "m_accelerate_power","2", "(when m_accelerate_type is 1) 2 means linear dependence with the speed, higher values means exponential dependency"}; -cvar_t m_accelerate_senscap = {CVAR_CLIENT | CVAR_SAVE, "m_accelerate_senscap", "0", "(when m_accelerate_type is 1) the sensitivity won't go above this value, 0 means no cap"}; +cvar_t m_accelerate = {CVAR_CLIENT | CVAR_SAVE, "m_accelerate","1", "linear mouse acceleration factor"}; +cvar_t m_accelerate_minspeed = {CVAR_CLIENT | CVAR_SAVE, "m_accelerate_minspeed","5000", "below this speed in px/s, no acceleration is done, with a linear slope between"}; +cvar_t m_accelerate_maxspeed = {CVAR_CLIENT | CVAR_SAVE, "m_accelerate_maxspeed","10000", "above this speed in px/s, full acceleration is done, with a linear slope between"}; +cvar_t m_accelerate_filter = {CVAR_CLIENT | CVAR_SAVE, "m_accelerate_filter","0.1", "linear mouse acceleration factor filtering lowpass constant in seconds"}; +cvar_t m_accelerate_power_offset = {CVAR_CLIENT | CVAR_SAVE, "m_accelerate_power_offset","0", "below this speed in px/ms, no power acceleration is done"}; +cvar_t m_accelerate_power = {CVAR_CLIENT | CVAR_SAVE, "m_accelerate_power","2", "acceleration power (must be above 1 to be useful)"}; +cvar_t m_accelerate_power_senscap = {CVAR_CLIENT | CVAR_SAVE, "m_accelerate_power_senscap", "0", "maximum acceleration factor generated by power acceleration; use 0 for unbounded"}; +cvar_t m_accelerate_power_strength = {CVAR_CLIENT | CVAR_SAVE, "m_accelerate_power_strength", "0", "strength of the mouse acceleration effect"}; cvar_t cl_netfps = {CVAR_CLIENT | CVAR_SAVE, "cl_netfps","72", "how many input packets to send to server each second"}; cvar_t cl_netrepeatinput = {CVAR_CLIENT | CVAR_SAVE, "cl_netrepeatinput", "1", "how many packets in a row can be lost without movement issues when using cl_movement (technically how many input messages to repeat in each packet that have not yet been acknowledged by the server), only affects DP7 and later servers (Quake uses 0, QuakeWorld uses 2, and just for comparison Quake3 uses 1)"}; @@ -548,15 +547,17 @@ void CL_Input (void) // apply m_accelerate if it is on if(m_accelerate.value > 0) { + float mouse_deltadist = sqrtf(in_mouse_x * in_mouse_x + in_mouse_y * in_mouse_y); + float speed = mouse_deltadist / cl.realframetime; - if (! m_accelerate_type.value) // Default Darkplaces acceleration - { - - - static float averagespeed = 0; - float speed, f, mi, ma; - - speed = sqrt(in_mouse_x * in_mouse_x + in_mouse_y * in_mouse_y) / cl.realframetime; + // Note: this check is technically unnecessary, as everything in here cancels out if it is zero. + if (m_accelerate.value != 1.0f) + { + // First do linear slope acceleration which was ripped "in + // spirit" from many classic mouse driver implementations. + // If m_accelerate.value == 1, this code does nothing at all. + static float averagespeed = 0; + float f, mi, ma; if(m_accelerate_filter.value > 0) f = bound(0, cl.realframetime / m_accelerate_filter.value, 1); else @@ -568,62 +569,59 @@ void CL_Input (void) if(averagespeed <= mi) { - f = 1; + f = 1; } else if(averagespeed >= ma) { - f = m_accelerate.value; + f = m_accelerate.value; } else { - f = averagespeed; + f = averagespeed; f = (f - mi) / (ma - mi) * (m_accelerate.value - 1) + 1; } - in_mouse_x *= f; in_mouse_y *= f; - } - else if (m_accelerate_type.value == 1) // quakelive acceleration - { - - if (cl.realframetime) + // Note: this check is technically unnecessary, as everything in here cancels out if it is zero. + if (m_accelerate_power_strength.value != 0.0f) + { + // 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 accelsens = sensitivity.value; + float adjusted_speed_pxms = (speed * 0.001f - m_accelerate_power_offset.value) * m_accelerate_power_strength.value; + if (adjusted_speed_pxms > 0) { - float accelsens = sensitivity.value; - float speed = (sqrt (in_mouse_x * in_mouse_x + in_mouse_y * in_mouse_y)) / - (cl.realframetime * 1000); - speed -= m_accelerate_offset.value; - - if (speed > 0) + if (m_accelerate_power.value > 1.0f) { - speed *= m_accelerate.value; - - if (m_accelerate_power.value > 1) - { - accelsens += exp((m_accelerate_power.value - 1) * log(speed)); - } - else - { - accelsens = 1; - } + accelsens += expf((m_accelerate_power.value - 1.0f) * logf(adjusted_speed_pxms)); } - - if (m_accelerate_senscap.value > 0 && accelsens > m_accelerate_senscap.value) + else { - accelsens = m_accelerate_senscap.value; + // The limit of the then-branch for m_accel_power -> 1. + accelsens += 1.0f; + // Note: QL had just accelsens = 1.0f. + // This is mathematically wrong though. } - - in_mouse_x *= accelsens; - in_mouse_y *= accelsens; - } else { - float mouse_deltadist = sqrt(in_mouse_x * in_mouse_x + in_mouse_y * in_mouse_y); - in_mouse_x *= (mouse_deltadist*m_accelerate.value + sensitivity.value); - in_mouse_y *= (mouse_deltadist*m_accelerate.value + sensitivity.value); + // The limit of the then-branch for adjusted_speed -> 0. + // accelsens += 0.0f; } + if (m_accelerate_power_senscap.value > 0.0f && accelsens > m_accelerate_power_senscap.value) + { + accelsens = m_accelerate_power_senscap.value; + } + // Divide by the standard linear sensitivity again. + accelsens /= sensitivity.value; + + in_mouse_x *= accelsens; + in_mouse_y *= accelsens; } } @@ -2262,10 +2260,10 @@ void CL_InitInput (void) Cvar_RegisterVariable(&m_accelerate_minspeed); Cvar_RegisterVariable(&m_accelerate_maxspeed); Cvar_RegisterVariable(&m_accelerate_filter); - Cvar_RegisterVariable(&m_accelerate_type); - Cvar_RegisterVariable(&m_accelerate_offset); Cvar_RegisterVariable(&m_accelerate_power); - Cvar_RegisterVariable(&m_accelerate_senscap); + Cvar_RegisterVariable(&m_accelerate_power_offset); + Cvar_RegisterVariable(&m_accelerate_power_senscap); + Cvar_RegisterVariable(&m_accelerate_power_strength); Cvar_RegisterVariable(&cl_netfps); Cvar_RegisterVariable(&cl_netrepeatinput);