# Matrix interpolation method for Skeleton?

## Recommended Posts

Zouflain    548
I'm writing a skeletal animation class and it's come down to interpolating keyframes. Currently each joint is a 4x4 matrix storing both rotation and translation. The problem I'm having is that I have no idea how to interpolate matrices, and the explanations on google pre-assume a very technical understanding (if the explanation is even accessible, as most are locked documents and/or books). I've never been able to wade through the intricacies of matrices as it's all counter intuitive. I find quaternions far more sensible, and they're based on imaginary numbers! Linear and cosine interpolation aren't foreign subjects to me, and they're easy to do on N dimensional vectors. The trouble is trying to find an equivalent for matrices. Quaternion SLERP is a cake walk by comparison. All I really want is a function that takes two matrices (mA and mB) in addition to some delta (lets say mu) between 0 and 1, and spits out a matrix that lies between the two. The only other consideration I have is that the interpolation has to look smooth for the animation (hence why I'm not just using a scalar and calling it a day). I would prefer to keep the interpolation method matrix related - if I have to use quaternions, I might as well rewrite the entire engine and obliterate every mention of a matrix from the code. Thanks for any help on the matter.

##### Share on other sites
Eric_Brown    127
There are a few things that quaternions just do better than matrices - and interpolation is one of them. To the point, if inserting quaternions requires you to consider rewriting a lot of your animation code, you may want to consider the rewrite.

As an alternative you may want to specify the keyframes using quaternions, and then once you have the interpolated result, immediately convert from a quaternion to a matrix.

What is the initial form of the keyframe data? It surely isn't a matrix, is it? Most animation packages export animation curves as euler angles, or quaternions.

##### Share on other sites
Zouflain    548
The animation package is whatever I want - I wrote the file format, and converting between matrices or euler angles to quaternions during the export/conversion phase is fairly trivial. Writing the converter itself... not so much, but the math for storing it as quaternions is simple enough.

I chose to use matrices because, so far as I remember, when I was learning quaternions most responders repeatedly insisted that matrices were a better method and more of a standard in animation. Now that I'm actually animating, I'm getting the opposite. The irony is painful.

Anyway, if matrices are indeed the inferior method, I'll need to brush up on skeletons as quaternions.

Quick question regarding quaternion interpolation (SLERP) though: the input for quaternion slerp is some delta mu. Can I use a second delta mu2 = (1-cos(mu*PI))/2 as an input to the SLERP function to further smooth out the interpolation?It's still a value between 0 and 1, so I can't see why not, but I thought I'd ask. Cosine interpolation seems as though it would be preferable to straight linear interpolation, and if it can be done this way, requires just one line of code to implement.

##### Share on other sites
Steve132    433
so, this is really mathy, but heres a way to do it that a not a lot of people are familiar with:

So, your modelview matrices are actually going to be of the form

R T
0 1

Where R is a 3x3 rotation matrix and T is a 3x1 translation vector. You can do standard linear interpolation on the translation parts because you can interpolate 3D points trivially.

The hard part is linear interpolation of the orthonormal rotation matrices R0 and R1 correctly. Specifically, every interpolated matrix Ri between R0 and R1 has to be orthonormal as well, so we have to come up with a scheme that makes sure that the interpolation is valid.

To do that, see the following page:
http://en.wikipedia.org/wiki/Axis_angle#Exponential_map_from_so.283.29_to_SO.283.29

The exponential map from so(3) to SO(3), and the associated logarithmic map will allow you to convert from an Orthonormal matrix to an axis angle rotation which can be interpolated.

So, the algorithm is,

take your R0, R1 and interpolation parameter t,

L0=log(R0); //apply "logarithmic mapping" formula from that page
L1=log(R1);
Li=L0*t+(1-t)*L1; //interpolate L1
Ri=exp(Li); //apply exponential mapping formula from that page

##### Share on other sites
arithma    226
You can also transform the rotation matrix into a quaternion, interpolate it, and transform it back to a matrix. I am sure this has performance merit to it as well. The conversion from matrix to quaternion and vice versa is well documented online.

##### Share on other sites
hplus0603    11347
In general, you want to interpolate in SRT space -- Scale, Translation and Rotation is each stored as a float3, quat and float3. The reason for this is that you can compose more than two animations this way. Once interpolated, you normalize the quaternion, and then generate the output matrix from the three separate components.

If all you have is matrices, you can decompose into SRT through fairly simple math, as long as there is no skew involved. However, it's much faster to make the animation tool output this in the first place.

If you don't want to do that, you *can* interpolate matrices linearly -- each element is just the linear combination of each input element times that element's weight. You will get some volume collapse during fast movement, quite similar to how keyframe (morph blend) animation works, because that's basically what you end up doing at that point. If you want to solve that problem, in turn, then you need to re-orthonormalize the upper-left of the matrix -- normalize each column (assuming column vectors on the right, OpenGL style), remove any non-orthogonal component from each column, and then re-normalize the columns again.

Yes, this is fairly math-y -- because that's what the operation is. You're working with a time-varying basis transform. There's a reason they don't teach that in middle school :-)

Hopefully, the words in this explanation will give you something to Google for, if nothing else.