I'm trying to decompose a homogeneous coordinates transform matrix which is the result of these transformations matrices (applied in their writing order): non-uniform Scale -> Rotate -> Translate I haven't any problem in extracting the translation coordinates from the resulting 4x4 transfor matrix (the first three values of the last column) but I couldn't find a way to extract the rotation and scaling matrices.
I found the following matrix decomposition algorithm on the web:
- Compute the scaling factors as the magnitudes of the first three basis vectors (columns or rows) of the matrix
- Divide the first three basis vectors by these values (thus normalizing them)
- The upper-left 3x3 part of the matrix now represents the rotation (you can use this as is, or convert it to quaternion form)
- The translation is the fourth basis vector of the matrix (in homogeneous coordinates - it'll be the first three elements that you're interested in)
Here comes my java implementation
public void decompose(Vec3 translation, Vec4 rotationAxisAndAngle, Vec3 scale) {
translation = this.getTranslation();
Vec3 c0 = new Vec3(values[ 0], values[ 1], values[ 2]);
Vec3 c1 = new Vec3(values[ 4], values[ 5], values[ 6]);
Vec3 c2 = new Vec3(values[ 8], values[ 9], values[10]);
scale.x = Vec3.len(c0.x, c0.y, c0.z);
scale.y = Vec3.len(c1.x, c1.y, c1.z);
scale.z = Vec3.len(c2.x, c2.y, c2.z);
Matrix4 mat = new Matrix4();
mat.values[ 0] = c0.x / scale.x; mat.values[ 4] = c1.x / scale.y; mat.values[ 8] = c2.x / scale.z; mat.values[12] = 0;
mat.values[ 1] = c0.y / scale.x; mat.values[ 5] = c1.y / scale.y; mat.values[ 9] = c2.y / scale.z; mat.values[13] = 0;
mat.values[ 2] = c0.z / scale.x; mat.values[ 6] = c1.z / scale.y; mat.values[10] = c2.z / scale.z; mat.values[14] = 0;
mat.values[ 3] = 0; mat.values[ 7] = 0; mat.values[11] = 0; mat.values[15] = 1;
rotationAxisAndAngle = mat.toAxisAngle();
System.out.println("<Transform translation=\"" + translation.x + " " + translation.y + " " + translation.z + "\">");
System.out.println("<Transform rotation=\"" + rotationAxisAndAngle.x + " " + rotationAxisAndAngle.y + " " + rotationAxisAndAngle.z + " " + rotationAxisAndAngle.w + "\">");
System.out.println("<Transform scale=\"" + scale.x + " " + scale.y + " " + scale.z + "\">");
}
But the axis angle and the scale factor which it retrieves are incorrect.
What's wrong with it?