I'm trying to create a system similar to Blender's f-curves or Unity's animation curves (google it, I'm not allowed to post more than two links yet). It's basically a 2D spline where time is on the X-axis and the value is Y. Given any X value there's only one Y, so no loops. The user can then add points and modify the tangents for those points. Something like this:
My current implementation uses cubic bezier curves, but I'm kinda stuck on how to calculate the Y value given a certain X (which is the time). After looking around a bit I found two interesting descriptions of it here and here, and also some code for one solution (h**ps://github.com/hfink/pixelnoir/blob/master/player/src/roots.h). The problem is that I need to calculate t by solving the cubic bezier curve for X, which seems like a lot of work (for the CPU).
Is this the way it's usually done? Are there any better ways to represent the spline that avoids solving the equation?
My usecase is simple scaling/rotation/translation animations for 2D sprites to get some nice groovy feeling (like most 2D games released for mobile).
I'll describe the problem a bit more in depth to avoid confusion.
In my implementation the curve is 2D, i.e. the control points are (x,y) pairs. This means that I can freely move around all of them on a 2D plane. I'd say this is the most common case of bezier curves in graphics (think Illustrator, HTML5 canvas, QGraphicsScene, etc). This makes it possible to create the following two curves by just changing one of the control points:
These are drawn with Y on the vertical axis and X on the horizontal.
When evaluating a 2D bezier curve equation you're actually evaluating two equations,
X(u) (I'm using
u instead of
t to avoid confusion further down). So when moving one of the control points (
P2, using wikipedia's names) along the X-axis I'm changing
X derivative) in its corresponding point.
When editing the curve it's usually presented with the
X axis as time and
Y as the actual value. I.e.
X increases by some
dt each tick. So to calculate the
Y value at a certain point in time I need to find which
u to use since
Y is defined as
Y(u). In my case I know that
X(u) = t which means that I need to solve that equation to get
u and then plug that in to
I could switch to a 1D curve, but that doesn't give the same flexibility since the control points in the middle would be scalars. I.e. I wouldn't be able to scale them, just define the start/end derivative in the point.
So the questions are:
- Can I convert this 2D curve to 1D given my contraints?
- Is there any other way increase the flexibility? Maya seems to have "weighted" and "non-weighted" tangents.