diff options
Diffstat (limited to 'common')
| -rw-r--r-- | common/accel-classic.hpp | 14 | ||||
| -rw-r--r-- | common/accel-natural.hpp | 2 | ||||
| -rw-r--r-- | common/accel-power.hpp | 225 | ||||
| -rw-r--r-- | common/rawaccel-base.hpp | 5 | ||||
| -rw-r--r-- | common/rawaccel-validate.hpp | 15 |
5 files changed, 102 insertions, 159 deletions
diff --git a/common/accel-classic.hpp b/common/accel-classic.hpp index c230bb4..ca0651c 100644 --- a/common/accel-classic.hpp +++ b/common/accel-classic.hpp @@ -11,13 +11,13 @@ namespace rawaccel { struct classic_base { double base_fn(double x, double accel_raised, const accel_args& args) const { - return accel_raised * pow(x - args.offset, args.exponent_classic) / x; + return accel_raised * pow(x - args.input_offset, args.exponent_classic) / x; } static double base_accel(double x, double y, const accel_args& args) { auto power = args.exponent_classic; - return pow(x * y * pow(x - args.offset, -power), 1 / (power - 1)); + return pow(x * y * pow(x - args.input_offset, -power), 1 / (power - 1)); } }; @@ -70,7 +70,7 @@ namespace rawaccel { double operator()(double x, const accel_args& args) const { - if (x <= args.offset) return 1; + if (x <= args.input_offset) return 1; return sign * minsd(base_fn(x, accel_raised, args), cap) + 1; } @@ -96,7 +96,7 @@ namespace rawaccel { } { - double a = gain_accel(cap.x, cap.y, args.exponent_classic, args.offset); + double a = gain_accel(cap.x, cap.y, args.exponent_classic, args.input_offset); accel_raised = pow(a, args.exponent_classic - 1); } constant = (base_fn(cap.x, accel_raised, args) - cap.y) * cap.x; @@ -105,7 +105,7 @@ namespace rawaccel { accel_raised = pow(args.acceleration, args.exponent_classic - 1); if (args.cap.x > 0) { cap.x = args.cap.x; - cap.y = gain(cap.x, args.acceleration, args.exponent_classic, args.offset); + cap.y = gain(cap.x, args.acceleration, args.exponent_classic, args.input_offset); constant = (base_fn(cap.x, accel_raised, args) - cap.y) * cap.x; } break; @@ -121,7 +121,7 @@ namespace rawaccel { sign = -sign; } - cap.x = gain_inverse(cap.y, args.acceleration, args.exponent_classic, args.offset); + cap.x = gain_inverse(cap.y, args.acceleration, args.exponent_classic, args.input_offset); constant = (base_fn(cap.x, accel_raised, args) - cap.y) * cap.x; } break; @@ -132,7 +132,7 @@ namespace rawaccel { { double output; - if (x <= args.offset) return 1; + if (x <= args.input_offset) return 1; if (x < cap.x) { output = base_fn(x, accel_raised, args); diff --git a/common/accel-natural.hpp b/common/accel-natural.hpp index 6f30a38..9d615a9 100644 --- a/common/accel-natural.hpp +++ b/common/accel-natural.hpp @@ -11,7 +11,7 @@ namespace rawaccel { double limit; natural_base(const accel_args& args) : - offset(args.offset), + offset(args.input_offset), limit(args.limit - 1) { accel = args.decay_rate / fabs(limit); diff --git a/common/accel-power.hpp b/common/accel-power.hpp index 014acae..ffbadb0 100644 --- a/common/accel-power.hpp +++ b/common/accel-power.hpp @@ -7,10 +7,66 @@ namespace rawaccel { struct power_base { - static double base_fn(double x, double scale, const accel_args& args) + vec2d offset; + double scale; + double constant; + + power_base(const accel_args& args) + { + auto n = args.exponent_power; + + if (args.cap_mode != classic_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 { - // f(x) = w(mx)^k - return pow(scale * x, args.exponent_power); + 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; } }; @@ -19,88 +75,44 @@ namespace rawaccel { template <> struct power<LEGACY> : power_base { double cap = DBL_MAX; - double scale = 0; - power(const accel_args& args) + power(const accel_args& args) : + power_base(args) { - // Note that cap types may overwrite scale below. - scale = args.scale; switch (args.cap_mode){ - case classic_cap_mode::in: - if (args.cap.x > 0) - { - cap = base_fn( - args.cap.x, - args.scale, - args); - } - break; case classic_cap_mode::io: - if (args.cap.x > 0 && - args.cap.y > 1) - { - cap = args.cap.y; - scale = scale_from_sens_point( - args.cap.y, - args.cap.x, - args.exponent_power); - } + cap = args.cap.y; + break; + case classic_cap_mode::in: + if (args.cap.x > 0) cap = base_fn(args.cap.x, args); break; case classic_cap_mode::out: default: - if (args.cap.y > 1) - { - cap = args.cap.y; - } + if (args.cap.y > 0) cap = args.cap.y; break; } - /* - if (args.cap.x > 0) { - cap.x = args.cap.x; - cap.y = base_fn(cap.x, args); - } - */ } double operator()(double speed, const accel_args& args) const { - if (args.powerStartFromOne) { - return minsd(maxsd(base_fn(speed, scale, args), 1), cap); - } - else { - return minsd(base_fn(speed, scale, args), cap); - } + return minsd(base_fn(speed, args), cap); } - double static scale_from_sens_point(double sens, double input, double power) - { - return pow(sens, 1 / power) / input; - } }; template <> struct power<GAIN> : power_base { vec2d cap = { DBL_MAX, DBL_MAX }; - double constant = 0; - double scale = 0; - vec2d startFromOne{ 0, 0 }; + double constant_b; - power(const accel_args& args) + power(const accel_args& args) : + power_base(args) { - /* - if (args.cap.x > 0) { - cap.x = args.cap.x; - double output = base_fn(cap.x, args); - cap.y = output * (args.exponent_power + 1); - constant = -args.exponent_power * output * args.cap.x; - } - */ - - // Note that cap types may overwrite this below. - scale = args.scale; - switch (args.cap_mode) { + case classic_cap_mode::io: + cap = args.cap; + break; case classic_cap_mode::in: if (args.cap.x > 0) { cap.x = args.cap.x; @@ -110,111 +122,32 @@ namespace rawaccel { scale); } break; - case classic_cap_mode::io: - if (args.cap.x > 0 && - args.cap.y > 1) { - cap.x = args.cap.x; - cap.y = args.cap.y; - scale = scale_from_gain_point( - args.cap.x, - args.cap.y, - args.exponent_power); - } - break; case classic_cap_mode::out: default: - if (args.cap.y > 1) { - cap.y = args.cap.y; + if (args.cap.y > 0) { cap.x = gain_inverse( args.cap.y, args.exponent_power, scale); + cap.y = args.cap.y; } break; } - if (args.powerStartFromOne) - { - startFromOne.x = gain_inverse( - 1, - args.exponent_power, - scale); - startFromOne.y = -1 * integration_constant(startFromOne.x, - 1, - base_fn(startFromOne.x, scale, args)); - } - - if (cap.x < DBL_MAX && cap.y < DBL_MAX) - { - if (args.powerStartFromOne) { - constant = integration_constant( - cap.x, - cap.y, - startFromOneOutput( - startFromOne, - cap.x, - scale, - args)); - } - else { - constant = integration_constant( - cap.x, - cap.y, - base_fn(cap.x, scale, args)); - } - } - + 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) { - if (args.powerStartFromOne) { - return startFromOneOutput( - startFromOne, - speed, - scale, - args); - } - else { - return base_fn(speed, scale, args); - } + return base_fn(speed, args); } else { - return cap.y + constant / speed; - } - } - - double static startFromOneOutput( - const vec2d& startFromOne, - double speed, - double scale, - const accel_args& args) - { - if (speed > startFromOne.x) { - return base_fn(speed, scale, args) + startFromOne.y / speed; - } - else - { - return 1; + return cap.y + constant_b / speed; } } - double static gain_inverse(double gain, double power, double scale) - { - return pow(gain / (power + 1), 1 / power) / scale; - } - double static gain(double input, double power, double scale) - { - return (power + 1) * pow(input * scale, power); - } - - double static scale_from_gain_point(double input, double gain, double power) - { - return pow(gain / (power + 1), 1 / power) / input; - } - - double static integration_constant(double input, double gain, double output) + static double integration_constant(double input, double gain, double output) { return (output - gain) * input; } diff --git a/common/rawaccel-base.hpp b/common/rawaccel-base.hpp index 08d42c6..cee1a3e 100644 --- a/common/rawaccel-base.hpp +++ b/common/rawaccel-base.hpp @@ -42,7 +42,8 @@ namespace rawaccel { accel_mode mode = accel_mode::noaccel; bool gain = 1; - double offset = 0; + double input_offset = 0; + double output_offset = 0; double acceleration = 0.005; double decay_rate = 0.1; double growth_rate = 1; @@ -53,7 +54,7 @@ namespace rawaccel { double limit = 1.5; double midpoint = 5; double smooth = 0.5; - bool powerStartFromOne = true; + vec2d cap = { 15, 1.5 }; classic_cap_mode cap_mode = classic_cap_mode::out; diff --git a/common/rawaccel-validate.hpp b/common/rawaccel-validate.hpp index a88d514..23deb5f 100644 --- a/common/rawaccel-validate.hpp +++ b/common/rawaccel-validate.hpp @@ -50,16 +50,20 @@ namespace rawaccel { error("data size > max"); } - if (args.offset < 0) { + if (args.input_offset < 0) { error("offset can not be negative"); } - else if (args.mode == accel_mode::jump && args.offset == 0) { + else if (args.mode == accel_mode::jump && args.input_offset == 0) { error("offset can not be 0"); } + if (args.output_offset < 0) { + error("offset can not be negative"); + } + bool jump_or_io_cap = (args.mode == accel_mode::jump || - (args.mode == accel_mode::classic && + ((args.mode == accel_mode::classic || args.mode == accel_mode::power) && args.cap_mode == classic_cap_mode::io)); if (args.cap.x < 0) { @@ -76,6 +80,11 @@ namespace rawaccel { error("cap (output) can not be 0"); } + if (args.cap.x > 0 && args.cap.x < args.input_offset || + args.cap.y > 0 && args.cap.y < args.output_offset) { + error("cap < offset"); + } + if (args.growth_rate <= 0 || args.decay_rate <= 0 || args.acceleration <= 0) { |