I am trying to create a custom animation that has the same animation curve as if I were using a CAMediaTimingFunction
(I am doing the animation in OpenGL, so I am unable to use this). I would also like to stay away from UIKit
in general as I would like it to be as multi-platform as possible.
CAMediaTimingFunction
uses a cubic Bezier function to calculate the animation progress from the time that has elapsed. I have no idea how it does it though.
From what I understand, cubic Bezier functions are defined parametrically and it turns messy when you try to derive a cartesian equation from them.
To be clear: I want a method that takes an x-value input and returns a y-value output along a cubic Bezier curve. The control points would be limited from (0, 0) to (1, 1).
What I was planning on doing is generating a locus of points (say 100) for the bezier curve using the parametric equation in the following function twice for each point (once for x
, once for y
), using 100 values of t
from 0
to 1
static inline CGFloat bezierFunc1D(CGFloat t, CGFloat p0, CGFloat p1, CGFloat p2, CGFloat p3) {
return
(1-t)*(1-t)*(1-t) * p0
+ 3 * (1-t)*(1-t) * t * p1
+ 3 * (1-t) * t*t * p2
+ t*t*t * p3;
}
This is where p0
through to p3
are the control points and t
is the parametric scalar from 0
to 1
. I could optimise this fairly easily by pre-calculating the squared and cubed values of t
.
I was then going to use linear interpolation in order to generate an array of points where the values of x
are linearly seperated (e.g x = 0.01, 0.02... 0.99
) and then use this array to define my animation progress for the time elapsed.
Is this the best way of going about this problem? It seems like a fairly intensive process for quite a simple task, even though it could all be pre-calculated at launch.
I saw on this question the answerer recommended simply eliminating x
and define the function as y
against t
. However, this will give pretty inaccurate results, as a linear Bezier curve from 0.0
to 1.0
will not animate linearly.
Is there a more efficient approach to this?
Does anyone know how Apple achieves this in CAMediaTimingFunction
or is there a library out there that achieves the same result?
Or is there a simpler alternative to using a cubic Bezier function that will give a smooth animation curve on both the in and out stages of the animation?
CGPath
. I'm sorry if I didn't quite make it explicit in the question, but I'd like to stay away from UIKit as much as possible as I'm doing this in OpenGL and would like it to be as multi-platform as possible. Also none of them actually help with getting a linear set of values of a Bezier curve (you cannot read a set of points from aCGPath
, you can only render along it). - Hamishios
out of your tags if you want a multiplatform answer. Incidentally, those answers do read a linear set of values along aCGPath
, using theCGPathCreateCopyByDashingPath
copy function. - rob mayoffCGPathApply
along withCGPathCreateCopyByDashingPath
.. seems quite cumbersome for what I want to do anyway... so thanks but no thanks! - Hamish