I have just finished a bezier timing algorithm, and I’ll give a small description here.
I will be using the bezier values a linear stepping value in a loop… layman’s terms: a counter that counts up evenly, 0,1,2,3 or 0,2,4,6, etc.
There are methods to do this in the iPhone SDK but I already wrote half of the code, and it wasn’t much effort to complete. Plus, I looked up the CAMediaTimingFunction class, and it seemed too complicated just for what I wanted (just an in-and-out structure).
So all I did is this: create a 100-element array.
.. and it gets a bit complicated, so here’s the code to build the array:
float t; int i; CGPoint bpoints[1000]; CGPoint bypoints[100]; for (i = 0; i < 1000; i++) { t = i / 1000.0f; bpoints[i].x = (1-t)*(1-t)*(1-t)* 0 + 3*(1-t)*(1-t)*t*0.5 + 3*(1-t)*t*t* 0.5 + t*t*t*1.0; bpoints[i].y = (1-t)*(1-t)*(1-t)* 0 + 3*(1-t)*(1-t)*t*0.05 + 3*(1-t)*t*t* 0.95 + t*t*t*1.0; } for ( transitionTimeStep =0; transitionTimeStep < 100; transitionTimeStep++) { float closest = 1.1; int closestI = -1; // Find the index in bpoints where .x is the closest to the transitionTimestep percent for (int x = 0; x < 1000; x++) { if ( fabs( bpoints[x].x - ( transitionTimeStep /100.0f)) < closest) { closest = fabs( bpoints[x].x - ( transitionTimeStep /100.0f)); closestI = x; } } bypoints[transitionTimeStep] = bpoints[closestI].y; }
The first loop creates a high-resolution set of points on a quadratic bezier curve (see Wikipedia’s page for Bezier curves) where the 4 points are between 0.0 and 1.0. The points (0,1,2,3) have the following x,y coordinates:
- 0,0
- 0.5, 0.05
- 0.5, 0.95
- 1.0, 1.0
If a person even multiplied these values by 100 and then used a program like Adobe Illustrator, the curve would look something vaguely like a capitol letter S. Rather, it’s actually more like a forward-slash / and little curves at the top and bottom .
So I collect the high-resolution points of the line, and then loop through my time-step array. For every element in the time-step array, I examine every x-coordinate value of the bpoints array. If the value is closest to the current time-step index value, then I save the bpoints array y-coordinate value.
Yes, this seems very complicated now, but when I was doing it, it seemed very easy. I guess sometimes I just get on a roll and create complicated stuff.
Also, I know there are better ways to do this, but I only want a look-up table and when I see it in live operation before typing this post, it works beautifully.
An important note! The bpoint array is VERY important. It is not good to simply create an exact-resolution array and fill it with values. I did that at first, and found that there were too many indexes being dropped, that when the timing animation was run, there was a lot of choppy movement, like if the smooth slope of the curve was suddenly turned into a staircase of jagged edges.
So, creating the higher-resolution array first and then scanning it for the closest x value was the logical solution. Perhaps I could have done it with a 200 element array, but I didn’t try it.
The process only takes a split-second, and it’s only done once at the beginning of the program.
That’s all, take care everyone.