diff options
Diffstat (limited to 'common/accel-classic.hpp')
| -rw-r--r-- | common/accel-classic.hpp | 121 |
1 files changed, 93 insertions, 28 deletions
diff --git a/common/accel-classic.hpp b/common/accel-classic.hpp index 1df888a..c7d6519 100644 --- a/common/accel-classic.hpp +++ b/common/accel-classic.hpp @@ -1,36 +1,101 @@ #pragma once #include <math.h> +#include <float.h> -#include "accel-base.hpp" +#include "rawaccel-settings.h" namespace rawaccel { - /// <summary> Struct to hold "classic" (linear raised to power) acceleration implementation. </summary> - struct classic_impl { - double accel; - double power; - double power_inc; - double offset; - double multiplicative_const; - - classic_impl(const accel_args& args) : - accel(args.accel), power(args.exponent - 1), offset(args.offset) { - multiplicative_const = pow(accel, power); - power_inc = power + 1; - } - - inline double operator()(double speed) const { - //f(x) = (mx)^(k-1) - double base_speed = speed + offset; - return multiplicative_const * pow(speed, power_inc) / base_speed; - } - - inline double legacy_offset(double speed) const { - return pow(accel * speed, power); - } - }; - - using accel_classic = additive_accel<classic_impl>; - + /// <summary> Struct to hold "classic" (linear raised to power) acceleration implementation. </summary> + struct classic_base { + double offset; + double power; + double accel_raised; + + classic_base(const accel_args& args) : + offset(args.offset), + power(args.power), + accel_raised(pow(args.accel_classic, power - 1)) {} + + double base_fn(double x) const { + return accel_raised * pow(x - offset, power) / x; + } + }; + + struct classic_legacy : classic_base { + double sens_cap = DBL_MAX; + double sign = 1; + + classic_legacy(const accel_args& args) : + classic_base(args) + { + if (args.cap > 0) { + sens_cap = args.cap - 1; + + if (sens_cap < 0) { + sens_cap = -sens_cap; + sign = -sign; + } + } + } + + inline double operator()(double x) const { + if (x <= offset) return 1; + return sign * minsd(base_fn(x), sens_cap) + 1; + } + }; + + struct classic : classic_base { + vec2d gain_cap = { DBL_MAX, DBL_MAX }; + double constant = 0; + double sign = 1; + + classic(const accel_args& args) : + classic_base(args) + { + if (args.cap > 0) { + gain_cap.y = args.cap - 1; + + if (gain_cap.y < 0) { + gain_cap.y = -gain_cap.y; + sign = -sign; + } + + gain_cap.x = gain_inverse(gain_cap.y, args.accel_classic, power, offset); + constant = (base_fn(gain_cap.x) - gain_cap.y) * gain_cap.x; + } + } + + double operator()(double x) const { + double output; + + if (x <= offset) return 1; + + if (x < gain_cap.x) { + output = base_fn(x); + } + else { + output = constant / x + gain_cap.y; + } + + return sign * output + 1; + } + + static double gain(double x, double accel, double power, double offset) + { + return power * pow(accel * (x - offset), power - 1); + } + + static double gain_inverse(double y, double accel, double power, double offset) + { + return (accel * offset + pow(y / power, 1 / (power - 1))) / accel; + } + + static double gain_accel(double x, double y, double power, double offset) + { + return -pow(y / power, 1 / (power - 1)) / (offset - x); + } + }; + } |