Inertia Tensor and World Coordinate conversion

I understand that the inertia tensor is basically a 3x3 matrix. I'm modelling a cube, and the inertia tensor for this shape has values for moment of inertia on the main diagonal of the matrix. All the products of inertia are zero.

However, I understand that this matrix only makes sense in body (i.e., local) coordinates. That is if I have a cube and rotate it, its local coordinate axes rotate with it and the inertia tensor remains constant. However, I need to represent the inertia tensor in world coordinates as well. How can I do that? Do I need to multiply it by the current orientation? I'm using quaternions for orientation, so I can extract a matrix from the quaternion (a 4x4 matrix, and if I get rid of the fact that a 4x4 matrix represents homogeneous coordinates I could convert it into a 3x3. To do this I would simply get rid of the rightmost column and bottommost row of the 4x4 matrix returned from the quaternion).

I hope this is making some sense. I suspect that the values of the inertia tensor in world coordinates will change as the orientation of the cube changes.

Is my logic correct? Formulas would be helpful.

Cheers,

Mark

Yes, you can transform the inertia tensor from one coordinate system to another. This can be done by multiplying the inertia tensor by the inverse of the desired coordinate transformation on the right, and the inverse transpose of the coordinate transformation on the left. (This assumes column-vector math; if using row-vector math, reverse the order.)

In other words,

worldInertiaTensor = transpose(inverse(localToWorld)) *
localInertiaTensor *
inverse(localToWorld);


You can see why this is correct as follows. The way the inertia tensor works is that you multiply it on both sides by a unit vector localAxis to get the object's moment of inertia about that axis. That is,

momentAboutA = transpose(localAxis) * localInertiaTensor * localAxis;


(Here I'm treating localAxis as a column vector, so transposing it gives a row vector.) If we have the axis in world space instead, we have to transform it to local space before putting it into this equation. That involves the inverse of the local-to-world matrix:

momentAboutA = transpose(inverse(localToWorld) * worldAxis) *
localInertiaTensor *
(inverse(localToWorld) * worldAxis);


and rearranging that a little bit gives

momentAboutA = transpose(worldAxis) *
(transpose(inverse(localToWorld)) *
localInertiaTensor *
inverse(localToWorld)) *
worldAxis;


and you can see from this that the term in parentheses in the middle is the world-space inertia tensor, since multiplying it on both sides by worldAxis gives the correct moment of inertia.