diff options
| author | a1xd <[email protected]> | 2021-09-24 02:04:43 -0400 |
|---|---|---|
| committer | GitHub <[email protected]> | 2021-09-24 02:04:43 -0400 |
| commit | 2896b8a09ce42e965705c58593b8738adc454f7f (patch) | |
| tree | 71e4d0cff60b5a1ad11427d78e1f8c7b775e5690 /common/accel-power.hpp | |
| parent | Merge pull request #107 from a1xd/1.5.0-fix (diff) | |
| parent | make note clearer (diff) | |
| download | rawaccel-1.6.0.tar.xz rawaccel-1.6.0.zip | |
v1.6
Diffstat (limited to 'common/accel-power.hpp')
| -rw-r--r-- | common/accel-power.hpp | 161 |
1 files changed, 149 insertions, 12 deletions
diff --git a/common/accel-power.hpp b/common/accel-power.hpp index c8faabb..8e3f417 100644 --- a/common/accel-power.hpp +++ b/common/accel-power.hpp @@ -2,25 +2,162 @@ #include "rawaccel-base.hpp" -#include <math.h> +#include <float.h> namespace rawaccel { - /// <summary> Struct to hold power (non-additive) acceleration implementation. </summary> - struct power { - double pre_scale; - double exponent; - double post_scale; + struct power_base { + vec2d offset; + double scale; + double constant; + + power_base(const accel_args& args) + { + auto n = args.exponent_power; + + if (args.cap_mode != cap_mode::io) { + scale = args.scale; + } + else if (args.gain) { + scale = scale_from_gain_point(args.cap.x, args.cap.y, n); + } + else { + /* + * special case for legacy + io cap mode + * + * offset is ignored because of the circular dependency: + * scale -> constant -> offset + */ + offset = {}; + constant = 0; + scale = scale_from_sens_point(args.cap.x, args.cap.y, n, constant); + return; + } + + offset.x = gain_inverse(args.output_offset, n, scale); + offset.y = args.output_offset; + constant = offset.x * offset.y * n / (n + 1); + } + + double base_fn(double x, const accel_args& args) const + { + if (x <= offset.x) { + return offset.y; + } + else { + return pow(scale * x, args.exponent_power) + constant / x; + } + } + + static double gain(double input, double power, double scale) + { + return (power + 1) * pow(input * scale, power); + } + + static double gain_inverse(double gain, double power, double scale) + { + return pow(gain / (power + 1), 1 / power) / scale; + } + + static double scale_from_gain_point(double input, double gain, double power) + { + return pow(gain / (power + 1), 1 / power) / input; + } + + static double scale_from_sens_point(double input, double sens, double power, double C) + { + return pow(sens - C / input, 1 / power) / input; + } + }; + + template <bool Gain> struct power; + + template <> + struct power<LEGACY> : power_base { + double cap = DBL_MAX; + + power(const accel_args& args) : + power_base(args) + { + + switch (args.cap_mode){ + case cap_mode::io: + cap = args.cap.y; + break; + case cap_mode::in: + if (args.cap.x > 0) cap = base_fn(args.cap.x, args); + break; + case cap_mode::out: + default: + if (args.cap.y > 0) cap = args.cap.y; + break; + } + } + + double operator()(double speed, const accel_args& args) const + { + return minsd(base_fn(speed, args), cap); + } + + }; + + template <> + struct power<GAIN> : power_base { + vec2d cap = { DBL_MAX, DBL_MAX }; + double constant_b; power(const accel_args& args) : - pre_scale(args.scale), - exponent(args.exponent), - post_scale(args.weight) {} + power_base(args) + { + switch (args.cap_mode) { + case cap_mode::io: + cap = args.cap; + break; + case cap_mode::in: + if (args.cap.x > 0) { + + if (args.cap.x <= offset.x) { + cap.x = 0; + cap.y = offset.y; + constant_b = 0; + return; + } + + cap.x = args.cap.x; + cap.y = gain( + args.cap.x, + args.exponent_power, + scale); + } + break; + case cap_mode::out: + default: + if (args.cap.y > 0) { + cap.x = gain_inverse( + args.cap.y, + args.exponent_power, + scale); + cap.y = args.cap.y; + } + break; + } + + constant_b = integration_constant(cap.x, cap.y, base_fn(cap.x, args)); + } + + double operator()(double speed, const accel_args& args) const + { + if (speed < cap.x) { + return base_fn(speed, args); + } + else { + return cap.y + constant_b / speed; + } + } - double operator()(double speed) const + static double integration_constant(double input, double gain, double output) { - // f(x) = (mx)^k - return post_scale * pow(speed * pre_scale, exponent); + return (output - gain) * input; } }; |