X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=src%2Fswfc-interpolation.c;fp=src%2Fswfc-interpolation.c;h=17759e73311be7db75271ba46dcb915c0b5fbfb4;hb=3ef17c4cee41231e1eed731c08381d3ddf0c8d1a;hp=0000000000000000000000000000000000000000;hpb=d1920e49f268abad90e5aabed8b65f6ea048a681;p=swftools.git diff --git a/src/swfc-interpolation.c b/src/swfc-interpolation.c new file mode 100644 index 0000000..17759e7 --- /dev/null +++ b/src/swfc-interpolation.c @@ -0,0 +1,301 @@ +/* swfc- Compiles swf code (.sc) files into .swf files. + + Part of the swftools package. + + Copyright (c) 2007 Huub Schaeks + Copyright (c) 2007 Matthias Kramm + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include +#include +#include +#include "interpolation.h" + +static inline float poly(float fraction, float start, float delta, int degree) +{ + return delta * pow(fraction, degree) + start; +} + +float linear(float fraction, float start, float delta) +{ + return poly(fraction, start, delta, 1); +} + +float quadIn(float fraction, float start, float delta) +{ + return poly(fraction, start, delta, 2); +} + +float quadOut(float fraction, float start, float delta) +{ + return quadIn(1 - fraction, start + delta, -delta); +} + +float quadInOut(float fraction, float start, float delta) +{ + if (fraction < 0.5) + return quadIn(2 * fraction, start, delta / 2); + return quadOut(2 * fraction - 1, start + delta / 2, delta / 2); +} + +float cubicIn(float fraction, float start, float delta) +{ + return poly(fraction, start, delta, 3); +} + +float cubicOut(float fraction, float start, float delta) +{ + return cubicIn(1 - fraction, start + delta, -delta); +} + +float cubicInOut(float fraction, float start, float delta) +{ + if (fraction < 0.5) + return cubicIn(2 * fraction, start, delta / 2); + return cubicOut(2 * fraction - 1, start + delta / 2, delta / 2); +} + +float quartIn(float fraction, float start, float delta) +{ + return poly(fraction, start, delta, 4); +} + +float quartOut(float fraction, float start, float delta) +{ + return quartIn(1 - fraction, start + delta, -delta); +} + +float quartInOut(float fraction, float start, float delta) +{ + if (fraction < 0.5) + return quartIn(2 * fraction, start, delta / 2); + return quartOut(2 * fraction - 1, start + delta / 2, delta / 2); +} + +float quintIn(float fraction, float start, float delta) +{ + return poly(fraction, start, delta, 5); +} + +float quintOut(float fraction, float start, float delta) +{ + return quintIn(1 - fraction, start + delta, -delta); +} + +float quintInOut(float fraction, float start, float delta) +{ + if (fraction < 0.5) + return quintIn(2 * fraction, start, delta / 2); + return quintOut(2 * fraction - 1, start + delta / 2, delta / 2); +} + +float circleIn(float fraction, float start, float delta) +{ + return delta * (1 - sqrt(1 - fraction * fraction)) + start; +} + +float circleOut(float fraction, float start, float delta) +{ + return circleIn(1 - fraction, start + delta, -delta); +} + +float circleInOut(float fraction, float start, float delta) +{ + if (fraction < 0.5) + return circleIn(2 * fraction, start, delta / 2); + return circleOut(2 * fraction - 1, start + delta / 2, delta / 2); +} + +float exponentialIn(float fraction, float start, float delta) +{ + if (fraction == 0) + return start; + return delta * pow(2, 10 * (fraction - 1)) + start; +} + +float exponentialOut(float fraction, float start, float delta) +{ + return exponentialIn(1 - fraction, start + delta, -delta); +} + +float exponentialInOut(float fraction, float start, float delta) +{ + if (fraction < 0.5) + return exponentialIn(2 * fraction, start, delta / 2); + return exponentialOut(2 * fraction - 1, start + delta / 2, delta / 2); +} + +float sineIn(float fraction, float start, float delta) +{ + return delta * (1 - cos(fraction * PI/2)) + start; +} + +float sineOut(float fraction, float start, float delta) +{ + return sineIn(1 - fraction, start + delta, -delta); +} + +float sineInOut(float fraction, float start, float delta) +{ + if (fraction < 0.5) + return sineIn(2 * fraction, start, delta / 2); + return sineOut(2 * fraction - 1, start + delta / 2, delta / 2); +} + +float elasticIn(float fraction, float start, float delta, float amplitude, int bounces, float damping) +{ + if (fraction == 0 || delta == 0) + return start; + if (fraction == 1) + return start + delta; + if (amplitude < fabs(delta)) + amplitude = delta; + float period = 1 / (bounces + 0.25); +// float s = asin(delta / amplitude) - 2 * PI / period; + return amplitude * pow(2, damping * (fraction - 1)) * sin(fraction * (2 * PI) / period /*+ fraction * s*/) + start; +} + +float elasticOut(float fraction, float start, float delta, float amplitude, int bounces, float damping) +{ + return elasticIn(1 - fraction, start + delta, -delta, amplitude, bounces, damping); +} + +float elasticInOut(float fraction, float start, float delta, float amplitude, int bounces, float damping) +{ + if (fraction < 0.5) + return elasticIn(2 * fraction, start, delta / 2, amplitude, bounces, damping); + return elasticOut(2 * fraction - 1, start + delta / 2, delta / 2, amplitude, bounces, damping); +} + +float backIn(float fraction, float start, float delta, float speed) +{ + return delta * fraction * fraction * ((speed + 1) * fraction - speed) + start; +} + +float backOut(float fraction, float start, float delta, float speed) +{ + return backIn(1 - fraction, start + delta, -delta, speed); +} + +float backInOut(float fraction, float start, float delta, float speed) +{ + if (fraction < 0.5) + return backIn(2 * fraction, start, delta / 2, speed); + return backOut(2 * fraction - 1, start + delta / 2, delta / 2, speed); +} + +/* when applied to movement bounceIn the object 'hits the floor' bounces times + * (after leaving the floor first) before gently reaching the final position at the top of the final bounce + * Each bounce takes growth times a long as the previous, except for the last one which lasts only half + * that time. The heights of the intermediate bounces are determined by the damping parameter. + * Set damping to 0 for an undamped movement.*/ + +float bounceIn(float fraction, float start, float delta, int bounces, float growth, float damping) +{ + if (fraction == 0 || delta == 0) + return start; + if (fraction == 1) + return start + delta; + float w0; + if (growth == 1.0) + w0 = 1 / (bounces + 0.5); + else + { + float gN = pow(growth, bounces); + w0 = 1 / ((gN - 1) / (growth - 1) + gN / 2 ); + } + float bounceStart = 0; + int i; + float w = w0; + for (i = 0; i <= bounces; i++) + { + float bounceEnd = bounceStart + w; + if (fraction >= bounceStart && fraction < bounceEnd) + { + float half = (bounceEnd + bounceStart) / 2; + float top = delta / pow(2, damping * ((bounces - i))); + fraction -= half; + fraction /= (w / 2); + return (1 - fraction * fraction) * top + start; + } + bounceStart = bounceEnd; + w = w * growth; + } +} + +/* bounceOut is a time-reversed bounceIn; therefore each bounce takes 1/growth times as long as + * the previous, which I think fits the idea when applied to movement */ + +float bounceOut(float fraction, float start, float delta, int bounces, float growth, float damping) +{ + return bounceIn(1 - fraction, start + delta, -delta, bounces, growth, damping); +} + +/* since bounceIn and bounceOut are combined, if growth > 1 then the bounce-times will increase in + * the first half and decrease in the second half */ + +float bounceInOut(float fraction, float start, float delta, int bounces, float growth, float damping) +{ + if (fraction < 0.5) + return bounceIn(2 * fraction, start, delta / 2, bounces, growth, damping); + return bounceOut(2 * fraction - 1, start + delta / 2, delta / 2, bounces, growth, damping); +} +/* fastBounce(In/Out) doesn't end or start in a horizontal slope (= gentle end or start) as + * bounce(In/Out) do which means fastBounceInOut doesn't have the 'delay' in the middle */ +float fastBounceIn(float fraction, float start, float delta, int bounces, float growth, float damping) +{ + if (fraction == 0 || delta == 0) + return start; + if (fraction == 1) + return start + delta; + float w0; + if (growth == 1.0) + w0 = 1 / (bounces + 0.25); /* in general (bounces + 1 / (2 * f)) */ + else + { + float gN = pow(growth, bounces); + w0 = 1 / ((gN - 1) / (growth - 1) + gN / 4 /* in general: gN / (2 * f) */ ); + } + float bounceStart = 0; + int i; + float w = w0; + for (i = 0; i <= bounces; i++) + { + float bounceEnd = bounceStart + w; + if (fraction >= bounceStart && fraction < bounceEnd) + { + float half = (bounceEnd + bounceStart) / 2; + float top = delta / 0.75/* in general: (1 - (1 / f) * (1 / f)) */ / pow(2, damping * ((bounces - i))); + fraction -= half; + fraction /= (w / 2); + return (1 - fraction * fraction) * top + start; + } + bounceStart = bounceEnd; + w = w * growth; + } +} + +float fastBounceOut(float fraction, float start, float delta, int bounces, float growth, float damping) +{ + return fastBounceIn(1 - fraction, start + delta, -delta, bounces, growth, damping); +} + +float fastBounceInOut(float fraction, float start, float delta, int bounces, float growth, float damping) +{ + if (fraction < 0.5) + return fastBounceIn(2 * fraction, start, delta / 2, bounces, growth, damping); + return fastBounceOut(2 * fraction - 1, start + delta / 2, delta / 2, bounces, growth, damping); +}