Sign in to follow this  

Maya animation curves

Recommended Posts

I'm trying to recreate the interpolation of maya's animation curves, and so far I've only had problems. For those of you who are not familiar with maya-curves they are implemented as a modified version of cubic 2 dimensional bezier curves. Or well rather some version of hermite curve(?). Internally they are saved as points with 2 tangents, an incoming and one outgoing. When calculating the interpolation between 2 points (p1 and p2) the outgoing tangent of p1 and the incoming tangent of p2 is used. I'm only going to use non-weighted tangents, which should simplify the process a lot. Here's a snippet from the maya-manual:
Animation curves may have either weighted or non-weighted tangents. With non-weighted tangents, tangents are implemented as vectors and P2 and P3 are internally adjusted to account for the time difference between P1 and P4. When evaluating a time within a segment, the following algortithms are used: For non-weighted tangents: where x is the start of the segment compute the parameter t as time - x with t (and the bezier y parameters a, b, c, d) compute the value as: v = (t^3 * a) + (t^2 + b) + (t * c) + d
You can find the complete document here. I believe my problem is this part "and the bezier y parameters a, b, c, d". How do I calculate a, b, c and d from the points? here's what I have at the moment:
struct KeyFrame
	float ix, iy; // incoming tangent-vector
	float ox, oy; // outgoing tangent-vector
	float x; // point x
	float y; // point y

// Grab the keyframes we are interpolating between
KeyFrame cur = getKeyFrame(animCurve, currKey);
KeyFrame nxt = getKeyFrame(animCurve, currKey+1);
float dist = (nxt.x - cur.x) / 3.0f;

// This is actually the x-coords of the points (seems to be working)
float a = nxt.y;
float b = nxt.y - nxt.iy * (dist / nxt.ix); // scale tangent to x=1/3
float c = cur.y + cur.oy * (dist / cur.ox); // scale tangent to x=1/3
float d = cur.y;

// Calculate the interpolated value
float t = 0.5f;
float v = (t*t*t*a) + (t*t+b) + (t*c) + d;
// I really doubt the "t*t+b" is correct, but the manual says so.
// I think "t*t*b" is more likely. Anyway, neither of them seems to
// work, so I suppose I'm doing something wrong when calculating the
// four coefficients.

Share this post

Link to post
Share on other sites
goto the devkit/animEngine example. They have code there that recreates the maya animation curve evaluation exactly as it is in maya.

As for your code problems, possibly the bezier interpolation is failing because bezier interpolation is :

float it = 1.0f-t;
float v = t*t*t*a + 3*t*t*it*b + 3*t*it*it*c + it*it*it*d;

In addition, your time value is always set to 0.5. This will always return the same mid position between keys. ? I think you may also be using the wrong tangents with the points? it's kinda a bit difficult to tell from your code.

I think though, you may be overcomplicating this stuff somewhat. All you need is a single 1D hermite curve, the time values don't really come into this too much. A hermite curve better fits the bill here simply because you have 2 points, and 2 tangents as you input data. A bezier curve is *not* ideal...

// i'll assume that in_t is the input time to evaluate the curve at
// i'll also assume that cur.x < in_t and next.x > in_t

// no idea why you are dividing by 3?
float dist = nxt.x - cur.x;

// scale the t value to 0 to 1 range between cur & next
float t = (in_t-dist) /dist;

// calculate the hermite blending values using our time value
float h1 = 2*t*t*t - 3*t*t + 1;
float h2 = -2*t*t*t + 3*t*t;
float h3 = t*t*t - 2*t*t + t;
float h4 = t*t*t - t*t;

// Calculate the interpolated value
float v = h1*cur.y + // P1 - 1st point
h2*nxt.y + // P2 - 2nd point
h3*cur.oy + // R1 - tangent leaving P1
h4*nxt.iy; // R2 - tangent arraving at P2

you might find a couple of useful maya bits and bobs here

Share this post

Link to post
Share on other sites
Thank you very much for the reply. I will try your method when I get back home. The site you provided along with the animEngine will surely help! I can't believe I didn't notice the animEngine sample.

As you might have noticed I don't really have any knowledge of curves, and in my frustration yesterday I attempted a trial-n-error without any success. I should've tried to understand the math instead.

Anyway, thank you again for the help!

Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this