#pragma once /** * @file easing_functions.h * @brief Funciones de suavizado (easing) para animaciones * * Colección de funciones matemáticas para interpolar valores de forma suave. * Todas las funciones toman un parámetro t (0.0 - 1.0) y devuelven un valor interpolado. * * Uso típico: * float progress = elapsed_time / total_duration; // 0.0 a 1.0 * float eased = easeOutCubic(progress); * float current_value = start + (end - start) * eased; * * Referencias: * - https://easings.net/ * - Robert Penner's Easing Functions */ #include namespace Easing { /** * @brief Interpolación lineal (sin suavizado) * @param t Progreso normalizado (0.0 - 1.0) * @return Valor interpolado linealmente * * Uso: Movimiento constante, sin aceleración */ inline float linear(float t) { return t; } /** * @brief Aceleración cuadrática (slow start) * @param t Progreso normalizado (0.0 - 1.0) * @return Valor interpolado con aceleración cuadrática * * Uso: Inicio lento que acelera */ inline float easeInQuad(float t) { return t * t; } /** * @brief Desaceleración cuadrática (slow end) * @param t Progreso normalizado (0.0 - 1.0) * @return Valor interpolado con desaceleración cuadrática * * Uso: Llegada suave, objetos que frenan */ inline float easeOutQuad(float t) { return t * (2.0f - t); } /** * @brief Aceleración y desaceleración cuadrática (slow start & end) * @param t Progreso normalizado (0.0 - 1.0) * @return Valor interpolado con aceleración y desaceleración * * Uso: Movimiento suave en ambos extremos */ inline float easeInOutQuad(float t) { return t < 0.5f ? 2.0f * t * t : -1.0f + (4.0f - 2.0f * t) * t; } /** * @brief Aceleración cúbica (slower start) * @param t Progreso normalizado (0.0 - 1.0) * @return Valor interpolado con aceleración cúbica * * Uso: Inicio muy lento, aceleración pronunciada */ inline float easeInCubic(float t) { return t * t * t; } /** * @brief Desaceleración cúbica (slower end) * @param t Progreso normalizado (0.0 - 1.0) * @return Valor interpolado con desaceleración cúbica * * Uso: Frenado suave y natural */ inline float easeOutCubic(float t) { float f = t - 1.0f; return f * f * f + 1.0f; } /** * @brief Aceleración y desaceleración cúbica * @param t Progreso normalizado (0.0 - 1.0) * @return Valor interpolado con curva cúbica * * Uso: Animaciones muy suaves en ambos extremos */ inline float easeInOutCubic(float t) { if (t < 0.5f) { return 4.0f * t * t * t; } else { float f = (2.0f * t - 2.0f); return 0.5f * f * f * f + 1.0f; } } /** * @brief Efecto elástico con rebote al final * @param t Progreso normalizado (0.0 - 1.0) * @return Valor interpolado con rebote elástico * * Uso: Elementos UI que "rebotan" al llegar, notificaciones * ⚠️ Puede sobrepasar el valor 1.0 temporalmente (overshoot) */ inline float easeOutElastic(float t) { if (t == 0.0f) return 0.0f; if (t == 1.0f) return 1.0f; constexpr float p = 0.3f; constexpr float s = p / 4.0f; return powf(2.0f, -10.0f * t) * sinf((t - s) * (2.0f * 3.14159265358979323846f) / p) + 1.0f; } /** * @brief Sobrepaso suave al final (back easing) * @param t Progreso normalizado (0.0 - 1.0) * @return Valor interpolado con sobrepaso * * Uso: Elementos que "se pasan" levemente y vuelven, efecto cartoon * ⚠️ Puede sobrepasar el valor 1.0 temporalmente (overshoot ~10%) */ inline float easeOutBack(float t) { constexpr float c1 = 1.70158f; constexpr float c3 = c1 + 1.0f; return 1.0f + c3 * powf(t - 1.0f, 3.0f) + c1 * powf(t - 1.0f, 2.0f); } /** * @brief Sobrepaso suave al inicio (back easing) * @param t Progreso normalizado (0.0 - 1.0) * @return Valor interpolado con retroceso inicial * * Uso: Elementos que "retroceden" antes de avanzar * ⚠️ Puede generar valores negativos al inicio (undershoot ~10%) */ inline float easeInBack(float t) { constexpr float c1 = 1.70158f; constexpr float c3 = c1 + 1.0f; return c3 * t * t * t - c1 * t * t; } /** * @brief Rebote físico al final (bounce effect) * @param t Progreso normalizado (0.0 - 1.0) * @return Valor interpolado con rebotes * * Uso: Objetos que caen y rebotan, físicas cartoon */ inline float easeOutBounce(float t) { constexpr float n1 = 7.5625f; constexpr float d1 = 2.75f; if (t < 1.0f / d1) { return n1 * t * t; } else if (t < 2.0f / d1) { t -= 1.5f / d1; return n1 * t * t + 0.75f; } else if (t < 2.5f / d1) { t -= 2.25f / d1; return n1 * t * t + 0.9375f; } else { t -= 2.625f / d1; return n1 * t * t + 0.984375f; } } /** * @brief Aceleración exponencial (muy dramática) * @param t Progreso normalizado (0.0 - 1.0) * @return Valor interpolado exponencialmente * * Uso: Efectos dramáticos, zoom in rápido */ inline float easeInExpo(float t) { return t == 0.0f ? 0.0f : powf(2.0f, 10.0f * (t - 1.0f)); } /** * @brief Desaceleración exponencial (muy dramática) * @param t Progreso normalizado (0.0 - 1.0) * @return Valor interpolado exponencialmente * * Uso: Fade outs dramáticos, zoom out rápido */ inline float easeOutExpo(float t) { return t == 1.0f ? 1.0f : 1.0f - powf(2.0f, -10.0f * t); } /** * @brief Curva circular (cuarto de círculo) * @param t Progreso normalizado (0.0 - 1.0) * @return Valor interpolado con curva circular * * Uso: Movimientos muy suaves y naturales */ inline float easeOutCirc(float t) { return sqrtf(1.0f - powf(t - 1.0f, 2.0f)); } } // namespace Easing