274 lines
7.6 KiB
C++
274 lines
7.6 KiB
C++
/**
|
|
* @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 <cmath>
|
|
|
|
#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<float>(M_PI) * 0.5F);
|
|
}
|
|
|
|
inline float sineOut(float t) {
|
|
return std::sin(t * static_cast<float>(M_PI) * 0.5F);
|
|
}
|
|
|
|
inline float sineInOut(float t) {
|
|
return 0.5F * (1.0F - std::cos(static_cast<float>(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<float>(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<float>(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<float>(M_PI)) * std::asin(1.0F / amplitude);
|
|
return amplitude * std::pow(2.0F, -10.0F * t) *
|
|
std::sin((t - s) * (2.0F * static_cast<float>(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<float>(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<float>(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<float>(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
|