Issue combining matrix components

Started by
2 comments, last by Telanor 9 years, 12 months ago
Previously I was multiplying 2 matrices together to do my bone transformations, but now I've broken the matrices down into scale, rotation, translation components. My goal is to work with the component parts so I can perform proper lerping and then combine the final result into a matrix to send off to the GPU. I'm having a problem combining things in this form though.

This is what I did previously: C = A * B. Where those are all matrices. That worked fine. Now what I'm doing is:

C.rotation = A.rotation * B.rotation;
C.translation = A.translation + B.translation;
C.scale = A.scale * B.scale;

Rotation is a quaternion, translation and scale are vector3s. When I combine these 3 components of C into a matrix again: Matrix.Scaling(Scale) * Matrix.RotationQuaternion(Rotation) * Matrix.Translation(Translation) the result is wrong, and my model looks like a collapsed blob.

I'm not sure if this matters, but the original info coming from the model file is a matrix, so I have to decompose the matrix into the 3 component parts on load, which I then store and use for these calculations.

Anyone know what I'm doing wrong here?
Advertisement

Unfortunately, you can't make a simple combination of the components as the order of application is important.

Consider: multiplying 2 matrices together, each comprised of scale-rotation-translation components. That matrix multiplication becomes the following series of operations:


scale1 * rotation1 * translation1 * scale2 * rotation2 * translation2

In your implementation, you simply add the two translations. However, the second translation (translation2) does not simply follow on translation1. Translation2 is preceded by rotation2. Rotation2 changes the orientation of the axes before translation2 is applied. So translation2 applies to a different orientation than translation1.

As a very simple example, consider the situation where an object has a translation (1, 0, 0), a move 1 unit along the x-axis. The next operation is a rotation by pi/2 about the y-axis. The next operation is a translation of (1, 0, 0). Your implementation would place the object at (2, 0, 0). However, the rotation of pi/2 changes the object's axes and the second translation actually moves the object perpendicular to its original movement to a location (1, 0, 1) or (1, 0, -1) depending on the direction of the rotation.

Your approach of maintaining separate quats and vectors for each keyframe is a good one if your intent is to lerp/slerp between keyframes, combine animations, etc. If so, you may want to take a look at my article on an animation controller for a skinned mesh. Not all of the discussion may apply to your situation, but the bottom line is that you can lerp/slerp the animation components, but you'll still have to apply them in SRT order. That is, do your lerp/slerps on the animation keyframe components; calculate a matrix combining the SRT results; and multiply the bone offset matrices by the animation matrices, etc.

Please don't PM me with questions. Post them in the forums for everyone's benefit, and I can embarrass myself publicly.

You don't forget how to play when you grow old; you grow old when you forget how to play.

It is just a matter of interpretation. Keeping the components isolated for bone animation to use slerp for the rotation is common. The interpretation of the 3 components should be: I have a bone at position X(=translation) which point in the direction of Y (=rotation) of size Z(=scale). This way you need to combine the matricies like this


// Order: first scale, then rotate, then move, applying from right to left:
final = translation * rotation * scale;

If you need the inverse, you need to reverse the order too:


// Order: first scale, then rotate, then move, applying from right to left:
inv(final) 
= inv(translation * rotation * scale) 
= inv(scale) * inv(rotation) * inv(translation)  

Ah ok, so basically I need to keep them separate for the interpolation and then after that's done, build the matrix and then do the hierarchy multiplication. I've got it working now, thanks for the help guys.

This topic is closed to new replies.

Advertisement