Wednesday, November 24, 2010

F-Curves, Keyframes, and Other 2.5 Animation Bits and Pieces

In continuation of some of my earlier FAQ posts (#1 and #2), I'll be discussing a bit about various aspects of the 2.5 Animation System here, especially related to keyframes and F-Curves.

Changing Interpolation method doesn't work
Since the earliest days of Animato (2.5 Animation System), interpolation has been a per-keyframe property instead of being a property for the entire curve. The interpolation method used applies from each keyframe onwards. To illustrate this, here's a little diagram of how this works:
Disclaimer: the curve is for illustrative purposes only - that is, the angles/lengths of the handles shown do not exactly correspond to such curve shapes present.

This means that it is now possible to easily have sections that are linearly or constantly interpolated, but without the overhead of having to add/tweak extra handles to make sure that this holds. After so many years, we can finally put the proponents of this functionality to rest!

However, it needs to be said that the "downside" of this approach is that to make an entire curve use a single type of interpolation, you'll need to select all the keyframes in that curve to do so. See this for tips on how this can easily be done.

What interpolation will be used for new keyframes?
This really depends where the keyframe will be added:
1) The value of the "New F-Curve Defaults" -> "Interpolation" setting in the User Preferences (under Editing) is used when keyframes are added to new F-Curves (i.e. F-Curves without any existing keyframes)
2) The interpolation value of the existing keyframe is used when keyframes will replace an existing keyframe (i.e. on same frame).
3) Otherwise, the prevailing interpolation value (see figure above) will be used

Looking at this another way:
1) If you want to all your keyframes to have constant interpolation while you are doing your blocking, set the "New F-Curve Defaults" -> "Interpolation" in the User Preferences to "Constant".
3a) While continuing to do your blocking, all newly added keyframes will also have constant interpolation, as the preceding keyframe also had constant interpolation
2) Replacing the keyframes for a pose will still maintain the interpolation of the keyframes. So, if for some reason you'd already changed a pose's keyframes to Linear, then the newly replaced keyframes will be Linear still.
-) After blocking, you change the interpolation for all keyframes to "Linear" or "Bezier" for example
3b) If you add any extra keyframes now between existing keyframes (i.e. adding breakdowns), they will take the interpolation of the preceeding keyframe ("Linear" or "Bezier").

How does interpolation work? Or How are F-Curves evaluated?
There was a forum thread asking this question a few days ago. I can only really wonder what the original poster was really curious about this for, though I have suspicions that it might be another case of trying to get some importer/exporter working, as is usually the case when people ask about these things as I've found over the years.

Anyways, getting back on topic. You can look at F-Curve evaluation in 2 ways:
1) The "math" way - An "F-Curve" is a curve representing some "function" (you could say that "F-Curve" stands for "Function Curve", or at least that's what I've sometimes heard them called) of the form
y = f(x)
where y is the final value found by "evaluating" the function f at point x.

2) Visually - Imagine that the function (i.e. the F-Curve) referred to above, is a long piece of rope, that is held in place/space by a series of pegs/power-poles (i.e. keyframes). Now imagine that you're sitting in a little car running on a road beside these power poles, that is parked in front of the first such power pole. As the car starts to drive forward, it's horizontal distance from the start of the road (i.e. x-value) increases, and as a result, the segment of the rope directly above the car changes. In this situation, the (y)-"value" of the F-Curve would be the distance between you and the segment of rope directly above you.

Moving to a different x-value (i.e. horizontal distance along the road) will give you a different segment of the F-Curve, and so a (potentially) different y-value. When you are directly beside one of the poles (i.e. a keyframe) the value of the rope will be the value of the keyframe, as the rope is lodged/attached to the top of the poles. Elsewhere along the curve though, the rope will sag or be taut, depending on the poles either side of the segment, and how the curve is attached to those poles.

For argument's sake, let's also say that the shape of the curve between two posts depends also on what the top of the earlier occurring post looks like. That is, whether it has a platform extending out, or whether it loops the rope tight or lets it hang loose. This is kindof like interpolation setting for the segment of the F-Curve between the two keyframes that occurs on the first keyframes.

So to recap, the interpolation setting on a keyframe defines how to figure out what the F-Curve does between two keyframes. Knowing the type of interpolation, for a segment, we can calculate the value of the F-Curve at any point between the keyframes by performing the necessary calculations (linear blending for "linear", and calculating the Bezier curve equations for "bezier", or just taking the initial keyframe value for "constant"). When we are on a keyframe though, we just take the value there :)

How does extrapolation come into this?
Extrapolation is about what we do when we try to find the value of the F-Curve on a frame where keyframes don't extend to - i.e. before the first keyframe or after the last one.

In 2.5, there are only 2 extrapolation types:
1) Constant - take whatever value the first/last keyframe had, and use that as appropriate for all frames to +/- infinity
2) Linear - take the slope of the last segments of the curve (from both ends) and extend those to all frames not covered by keyframes

In 2.4x and older versions of Blender, there were also a few other types of extrapolation (cyclic, etc.). However, as mentioned in FAQ #2, these have now been removed as they fit better within the F-Modifiers framework.

And what about F-Modifiers? How do they fit in with all of this?
Ah cherrups, don't you tire of hearing bedtime stories yet? Manana manana I'll tell you the rest of this story...

The short answer to this question though, is that they occur on top of all this, but really, it's better that I leave this for another day...


  1. hey aligorith, this is all really helpful, thanks for all the docs! I know in the dope sheet you can set and view whether a key is a breakdown/extreme/key etc. You can also set how a key is interpolated, but there is no way of seeing how keys are interpolated without using the graph editor. Are there any plans to draw the diamonds as different symbols (for example a square for stepped, a circle for bezier and a diamond for linear, some other symbol for a mixed subgroup etc) so at a glance I can see what my curves are doing. Would be great as a way to move between pose to pose blocking through easing in and out to final graph tweaking! thanks, Josh

  2. Would sure be nice if there were more that three different interpolation types available...

  3. Hi! I worked with 3DMax for a while (that has all the things Josh and Dan say), but fine-tuning always appears to happen in the curve editor... or at least that's what I've seen pros do (I'm just a hobbyist).

    I'm really enjoying these technical posts and FAQs! Thanks a lot Aligorith!!!

  4. Hi all,

    Doh! I was going to mention in passing those new "keyframe types" (breakdown, etc.) here too but forgot.

    Regarding showing different indicators for different interpolation/handles, this is indeed something that I have thought about before. However, as I found, it can be quite difficult finding enough easily distinguishable appearances which will still be easily usable by all members of our wide userbase (taking into account colour perception, eyesight, and understadability).

    Furthermore, until recently, this wasn't really an option either, as only in 2.5 have we finally moved towards a fully OpenGL representation. Previously using the fixed icons, adding new representations was much more difficult.

    Having said this, perhaps we can expect to see some more on this topic later... :)