From 89b3dcaf822bf750b87f5e48c8498dd2d6e1515b Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Tue, 29 Apr 2014 05:31:50 +1000 Subject: f-curve easing: Adjustments to Robert Penner elastic easing Compensate for the clamped amplitude by blending the elastic effect. Allows for a subtle elastic effect which wasn't possible before. --- source/blender/blenlib/intern/easing.c | 61 ++++++++++++++++++++++++++++------ 1 file changed, 51 insertions(+), 10 deletions(-) (limited to 'source/blender/blenlib/intern/easing.c') diff --git a/source/blender/blenlib/intern/easing.c b/source/blender/blenlib/intern/easing.c index 7233a26cb4d..6b702fe85dc 100644 --- a/source/blender/blenlib/intern/easing.c +++ b/source/blender/blenlib/intern/easing.c @@ -38,6 +38,8 @@ #include "BLI_strict_flags.h" +/* blend if (amplitude < fabsf(change) */ +#define USE_ELASTIC_BLEND float BLI_easing_back_ease_in(float time, float begin, float change, float duration, float overshoot) { @@ -141,76 +143,115 @@ float BLI_easing_cubic_ease_in_out(float time, float begin, float change, float return change / 2 * (time * time * time + 2) + begin; } +#ifdef USE_ELASTIC_BLEND +/** + * When the amplitude is less then the change, we need to blend + * \a f when we're close to the crossing point (int time), else we get an ugly sharp falloff. + */ +static float elastic_blend(float time, float change, float amplitude, float period, float f) +{ + if (change) { + /* Looks like a magic number, + * but this is a part of the sine curve we need to blend from */ + const float t = fabsf(period) / (32 * (float)M_PI); + if (amplitude) { + f *= amplitude / fabsf(change); + } + else { + f = 0.0f; + } + + if (fabsf(time) < t) { + float l = fabsf(time) / t; + f = (f * l) + (1.0f - l); + } + } + + return f; +} +#endif + float BLI_easing_elastic_ease_in(float time, float begin, float change, float duration, float amplitude, float period) { float s; + float f = 1.0f; if (time == 0.0f) return begin; if ((time /= duration) == 1.0f) return begin + change; - + time -= 1.0f; if (!period) period = duration * 0.3f; - if (!amplitude || amplitude < fabsf(change)) { +#ifdef USE_ELASTIC_BLEND + f = elastic_blend(time, change, amplitude, period, f); +#endif amplitude = change; s = period / 4; } else s = period / (2 * (float)M_PI) * asinf(change / amplitude); - time -= 1.0f; - return -(amplitude * powf(2, 10 * time) * sinf((time * duration - s) * (2 * (float)M_PI) / period)) + begin; + return (-f * (amplitude * powf(2, 10 * time) * sinf((time * duration - s) * (2 * (float)M_PI) / period))) + begin; } float BLI_easing_elastic_ease_out(float time, float begin, float change, float duration, float amplitude, float period) { float s; + float f = 1.0f; if (time == 0.0f) return begin; if ((time /= duration) == 1.0f) return begin + change; + time = -time; if (!period) period = duration * 0.3f; if (!amplitude || amplitude < fabsf(change)) { +#ifdef USE_ELASTIC_BLEND + f = elastic_blend(time, change, amplitude, period, f); +#endif amplitude = change; s = period / 4; } else s = period / (2 * (float)M_PI) * asinf(change / amplitude); - time = -time; - return (amplitude * powf(2, 10 * time) * sinf((time * duration - s) * (2 * (float)M_PI) / period) + change + begin); + return (f * (amplitude * powf(2, 10 * time) * sinf((time * duration - s) * (2 * (float)M_PI) / period))) + change + begin; } float BLI_easing_elastic_ease_in_out(float time, float begin, float change, float duration, float amplitude, float period) { float s; + float f = 1.0f; if (time == 0.0f) return begin; if ((time /= duration / 2) == 2.0f) return begin + change; + time -= 1.0f; if (!period) period = duration * (0.3f * 1.5f); if (!amplitude || amplitude < fabsf(change)) { +#ifdef USE_ELASTIC_BLEND + f = elastic_blend(time, change, amplitude, period, f); +#endif amplitude = change; s = period / 4; } else s = period / (2 * (float)M_PI) * asinf(change / amplitude); - time -= 1.0f; - if (time < 0.0f) { - return -0.5f * (amplitude * powf(2, 10 * time) * sinf((time * duration - s) * (2 * (float)M_PI) / period)) + begin; + f *= -0.5f; + return (f * (amplitude * powf(2, 10 * time) * sinf((time * duration - s) * (2 * (float)M_PI) / period))) + begin; } else { time = -time; - return (0.5f * amplitude * powf(2, 10 * time) * sinf((time * duration - s) * (2 * (float)M_PI) / period)) + change + begin; + f *= 0.5f; + return (f * (amplitude * powf(2, 10 * time) * sinf((time * duration - s) * (2 * (float)M_PI) / period))) + change + begin; } } -- cgit v1.2.3