A 2D keyframe animation system
Windows
--------------
The program consists of 2 windows:
(1) KeyFrameWindow class to define keyframe and rendering animation
(2) SpeedCurveWindow class to define speed curve they both extends
Ortho2DWindow base class
Catmull-Rom splines is used to interpolate both curves. In both cases
extra virtual keyframes are added at the very beginning and the very
end.
The interface allow user to manipulate both speed and interpolate
curves as follows :
(i) Insert keyframe at the beginning
(ii) Insert keyframe at the End
(iii) Insert keyframe in the middle of nearest 2 interpolate points for
fine control.
(iv) Editing of existing keyframe
(v) Removal of keyframe
(vi) Clear the whole curve OR reset to default
For (iii), we find the closest point P to line distance for each line
form by 2 keyframes A, B. In the case closest point Q (from P) in the
line AB is not within segment of A, B it is reject. Link list is
used to store keyframes, this allow efficient add/remove keyframes
operation.
Adaptive subdivision
-------------------------
Instead of using subdivision by checking the length between 2 points in
curve and subdivide again if length too long. I use a faster approach
by consider length of each curve segment, let say we have keyframe K0,
K1, K2, K3, K4.
The number of segment for curve [K1, K2] is
(length(K0, K1) + 4*length(K1, K2) + length(K2, K3))/6.
similarly for [K2, K3] it is
(length(K1, K2) + 4*length(K2, K3) + length(K3, K4))/6.
where
length(Ki, K(i+1)) is the distance between point Ki, K(i+1) in SCREEN
coordinates. The reason to take into account the length in previous
segment and next segment is to handle case that K1 very close to K2 but
K0 and K3 are far away - thus a loop is formed. Therefore we need more
subdivision to faithfully represent the curve and can't just take
screen coordinate between K1 and K2 as criteria.
Check for speed curve monotonic
increasing
--------------------------------------------------
For speed cuve, special procedure is empolyed to gurantee monotonic
increasing speed function. By default 4 keyframes are added. The first
and last are virtual keyframe that allow user to modify (subject to
monotonic increasing constraint). The second and second to last are
fixed to make sure correct begin and end conditions.
For each keyframe when user insert/modify, we check if the neighbouring
4 segments are monotonic increasing. This is done by
(i) First check edit/new keyframe x, y coordinate are monotonic
increasing with respect to neighbouring keyframes.
(ii) The above condition is not a sufficient condition since curve may
have local max/min in the segment.
So I find the cubic equations of BSpline curve form by 4 keyframes.
Then the derivative of it so it becomes quadratic equation. After
solving u in both x and y dimension, there are at most 4 real roots. If
both all of them are NOT within [0, 1] or no real root exists this mean
the speed curve is monotonic increasing. Otherwise the operation
is not allow.
In case of remove, it is also possible that after a keyframe remove the
3 segments around it break monotonic increasing requirement. In this
case remove is deny until user modify keyframes to a better position.
Computing time to distance in speed
curve
---------------------------------------------
The speed curve is a cubic functions for each segments. So a cubic
equation solver from a public open source code is employed for this
task. (cubic.c and quadra.c). After the distance is solved it is used
to search for 2 sample points found in adaptive subdivision above with
distance fall in between. The correct u is interpolate from this 2
sample points.
For the search, we cache the value of last search as starting point.
Since the function is invoke with increasing time value so the expected
time to search is constant.
Rendering
-----------
We render interpolate keyframe as teapot and virtual keyframe as
square. For efficient during animation we use display list for both
curve and teapot so there is no need to recompute curve coordinate
every frame during animation.
For line drawing, we turn on OpenGL line antialiasing using Blend mode
and line smooth. This enchance quality of output.
Features
-----------
We draw a vertical time line in speed curve window which move with
keyframe during animation. This help visualize the corresponding
between them. In addition user can DRAG the timeline under time axis
using left mouse button to see the position of interolate keyframe
(draw in blue).
The inteface also displays the time [0, 1], distance [0, 1] and number
of segment use in speed curve window.
For keyframe window it displays the total length and number of segments
of curve. The total length is computed by summing individual line
segments.
Speed of animation
----------------------
The program allow user to control speed of animation through a spin
button. The method is just subdivide the timeline more/less so the
object can travel slower/faster.
Load/Save
-----------
After user define both keyframe and speed curve, he/she can save the
definition (together with speed of animation). So next time when
program restart the user can reload the definition and run the
animation easily.
Download program
Have fun !