diff --git a/include/gamepad/joystick_modifier.hpp b/include/gamepad/joystick_modifier.hpp index c3c6259..6ccc509 100644 --- a/include/gamepad/joystick_modifier.hpp +++ b/include/gamepad/joystick_modifier.hpp @@ -43,6 +43,16 @@ class ExpoCurve : public AbstractTransformation { float m_y_curve; }; +class Fisheye : public AbstractTransformation { + public: + Fisheye(float radius) + : m_radius(radius) {} + + std::pair get_value(std::pair) override; + private: + float m_radius; +}; + class Transformation final { friend class TransformationBuilder; public: diff --git a/src/gamepad/joystick_modifier.cpp b/src/gamepad/joystick_modifier.cpp index 1741acf..be8258f 100644 --- a/src/gamepad/joystick_modifier.cpp +++ b/src/gamepad/joystick_modifier.cpp @@ -27,6 +27,22 @@ std::pair ExpoCurve::get_value(std::pair value) { return {x, y}; } +std::pair Fisheye::get_value(std::pair value) { + float x = value.first; + float y = value.second; + float x_abs = abs(x); + float y_abs = abs(y); + float j = std::sqrt(m_radius * m_radius - 127 * 127); + if (x_abs >= j && y_abs >= j) { + float theta = std::atan2(y_abs, x_abs); + x_abs *= std::acos(abs(std::remainder(theta, 90))); + y_abs *= std::acos(abs(std::remainder(theta, 90))); + } + x = std::copysign(std::min(127.0f, x_abs), x); + y = std::copysign(std::min(127.0f, y_abs), y); + return {x, y}; +} + std::pair Transformation::get_value(std::pair value) { std::pair ret_value {}; return std::accumulate(m_all_transforms.begin(), m_all_transforms.end(), ret_value,