/** * @file easing_functions.hpp * @brief Colección de funciones de suavizado (easing) para animaciones * * Todas las funciones toman un parámetro t (0.0 a 1.0) que representa * el progreso de la animación y retornan el valor suavizado. * * Convenciones: * - In: Aceleración (slow -> fast) * - Out: Desaceleración (fast -> slow) * - InOut: Aceleración + Desaceleración (slow -> fast -> slow) */ #ifndef EASING_FUNCTIONS_HPP #define EASING_FUNCTIONS_HPP #include #ifndef M_PI #define M_PI 3.14159265358979323846 #endif namespace Easing { // ============================================================================ // LINEAR // ============================================================================ inline float linear(float t) { return t; } // ============================================================================ // QUAD (Cuadrática: t^2) // ============================================================================ inline float quadIn(float t) { return t * t; } inline float quadOut(float t) { return t * (2.0F - t); } inline float quadInOut(float t) { if (t < 0.5F) { return 2.0F * t * t; } return -1.0F + (4.0F - 2.0F * t) * t; } // ============================================================================ // CUBIC (Cúbica: t^3) // ============================================================================ inline float cubicIn(float t) { return t * t * t; } inline float cubicOut(float t) { const float f = t - 1.0F; return f * f * f + 1.0F; } inline float cubicInOut(float t) { if (t < 0.5F) { return 4.0F * t * t * t; } const float f = (2.0F * t - 2.0F); return 0.5F * f * f * f + 1.0F; } // ============================================================================ // QUART (Cuártica: t^4) // ============================================================================ inline float quartIn(float t) { return t * t * t * t; } inline float quartOut(float t) { const float f = t - 1.0F; return 1.0F - f * f * f * f; } inline float quartInOut(float t) { if (t < 0.5F) { return 8.0F * t * t * t * t; } const float f = t - 1.0F; return 1.0F - 8.0F * f * f * f * f; } // ============================================================================ // QUINT (Quíntica: t^5) // ============================================================================ inline float quintIn(float t) { return t * t * t * t * t; } inline float quintOut(float t) { const float f = t - 1.0F; return f * f * f * f * f + 1.0F; } inline float quintInOut(float t) { if (t < 0.5F) { return 16.0F * t * t * t * t * t; } const float f = (2.0F * t - 2.0F); return 0.5F * f * f * f * f * f + 1.0F; } // ============================================================================ // SINE (Sinusoidal) // ============================================================================ inline float sineIn(float t) { return 1.0F - std::cos(t * static_cast(M_PI) * 0.5F); } inline float sineOut(float t) { return std::sin(t * static_cast(M_PI) * 0.5F); } inline float sineInOut(float t) { return 0.5F * (1.0F - std::cos(static_cast(M_PI) * t)); } // ============================================================================ // EXPO (Exponencial) // ============================================================================ inline float expoIn(float t) { if (t == 0.0F) return 0.0F; return std::pow(2.0F, 10.0F * (t - 1.0F)); } inline float expoOut(float t) { if (t == 1.0F) return 1.0F; return 1.0F - std::pow(2.0F, -10.0F * t); } inline float expoInOut(float t) { if (t == 0.0F || t == 1.0F) return t; if (t < 0.5F) { return 0.5F * std::pow(2.0F, (20.0F * t) - 10.0F); } return 0.5F * (2.0F - std::pow(2.0F, -20.0F * t + 10.0F)); } // ============================================================================ // CIRC (Circular) // ============================================================================ inline float circIn(float t) { return 1.0F - std::sqrt(1.0F - t * t); } inline float circOut(float t) { const float f = t - 1.0F; return std::sqrt(1.0F - f * f); } inline float circInOut(float t) { if (t < 0.5F) { return 0.5F * (1.0F - std::sqrt(1.0F - 4.0F * t * t)); } const float f = 2.0F * t - 2.0F; return 0.5F * (std::sqrt(1.0F - f * f) + 1.0F); } // ============================================================================ // BACK (Overshoot - retrocede antes de avanzar) // ============================================================================ inline float backIn(float t, float overshoot = 1.70158F) { return t * t * ((overshoot + 1.0F) * t - overshoot); } inline float backOut(float t, float overshoot = 1.70158F) { const float f = t - 1.0F; return f * f * ((overshoot + 1.0F) * f + overshoot) + 1.0F; } inline float backInOut(float t, float overshoot = 1.70158F) { const float s = overshoot * 1.525F; if (t < 0.5F) { const float f = 2.0F * t; return 0.5F * (f * f * ((s + 1.0F) * f - s)); } const float f = 2.0F * t - 2.0F; return 0.5F * (f * f * ((s + 1.0F) * f + s) + 2.0F); } // ============================================================================ // ELASTIC (Oscilación elástica - efecto de resorte) // ============================================================================ inline float elasticIn(float t, float amplitude = 1.0F, float period = 0.3F) { if (t == 0.0F || t == 1.0F) return t; const float s = period / (2.0F * static_cast(M_PI)) * std::asin(1.0F / amplitude); const float f = t - 1.0F; return -(amplitude * std::pow(2.0F, 10.0F * f) * std::sin((f - s) * (2.0F * static_cast(M_PI)) / period)); } inline float elasticOut(float t, float amplitude = 1.0F, float period = 0.3F) { if (t == 0.0F || t == 1.0F) return t; const float s = period / (2.0F * static_cast(M_PI)) * std::asin(1.0F / amplitude); return amplitude * std::pow(2.0F, -10.0F * t) * std::sin((t - s) * (2.0F * static_cast(M_PI)) / period) + 1.0F; } inline float elasticInOut(float t, float amplitude = 1.0F, float period = 0.3F) { if (t == 0.0F || t == 1.0F) return t; const float s = period / (2.0F * static_cast(M_PI)) * std::asin(1.0F / amplitude); if (t < 0.5F) { const float f = 2.0F * t - 1.0F; return -0.5F * (amplitude * std::pow(2.0F, 10.0F * f) * std::sin((f - s) * (2.0F * static_cast(M_PI)) / period)); } const float f = 2.0F * t - 1.0F; return 0.5F * amplitude * std::pow(2.0F, -10.0F * f) * std::sin((f - s) * (2.0F * static_cast(M_PI)) / period) + 1.0F; } // ============================================================================ // BOUNCE (Rebote - simula física de rebote) // ============================================================================ inline float bounceOut(float t) { const float n1 = 7.5625F; const float d1 = 2.75F; if (t < 1.0F / d1) { return n1 * t * t; } if (t < 2.0F / d1) { const float f = t - 1.5F / d1; return n1 * f * f + 0.75F; } if (t < 2.5F / d1) { const float f = t - 2.25F / d1; return n1 * f * f + 0.9375F; } const float f = t - 2.625F / d1; return n1 * f * f + 0.984375F; } inline float bounceIn(float t) { return 1.0F - bounceOut(1.0F - t); } inline float bounceInOut(float t) { if (t < 0.5F) { return 0.5F * bounceIn(2.0F * t); } return 0.5F * bounceOut(2.0F * t - 1.0F) + 0.5F; } } // namespace Easing #endif // EASING_FUNCTIONS_HPP