# How to get the rotation matrix to transform between two 3d cartesian coordinate systems?

I'd like to know how to get the rotation matrix for the transformation from one cartesian coordinate system (X, Y, Z) to another one (X', Y', Z').

Both systems are defined with three orthogonal vectors as one would expect. No scaling or translation occurs. I'm using OpenSceneGraph and it offers a Matrix convenience class, if it makes finding the matrix easier:

One easy way is to think of both coordinate systems as transforms from the unit vectors (1,0,0) (0,1,0) and (0,0,1). You start off in this coordinate space (I will call it '1')whose transform matrix is the identity matrix:

    [1,0,0]
I = [0,1,0]
[0,0,1]


then your first coordinate space (I will call it '2') has the transform matrix:

    [Xx,Xy,Xz]
A = [Yx,Yy,Yz]
[Zx,Zy,Zz]


and your second coordinate space (I will call it '3') has the transform matrix:

    [Xx',Xy',Xz']
B = [Yx',Yy',Yz']
[Zx',Zy',Zz']


For your points to be in the first coordinate system, then you have transformed them from 1 to 2. If you want to go from 2 to 3 then you can undo the transform from 1 to 2 then do the transform from 1 to 3. You can reverse the transform by inverting 2's transform matrix.

A point v in 2 can be transformed to a point v' in 3 with this equation: v' = B(A^-1)v where (A^-1) is the inverse of A.

Note this also handles scaling even though you don't need it. This approach will work with translation as well, though you would need a 4x4 matrix instead of a 3x3.

• Hey, thank you for the great answer. I wanted to clarify a couple of things though. v'=(A^-1)v takes me from CS2->CS1. Then v'' = Bv' would take me from CS1->CS3, or you can compactly write CS2->CS3 as v'=B(A^-1)v as you did. Also in my case, CS2 == CS1, so all I'd have to do to get to CS3 is v'=Bv ... is that correct?
– Pris
Mar 24, 2012 at 15:10
• That is indeed correct. You can multiply matrices to combine their transformations, so if you have lots of points its more efficient to multiply B(A^-1) once and used that. Mar 24, 2012 at 17:42
• Can I ask a further question about this problem... I understand the answer given but can't work out how calculate the transforms [A] or [B] for my situation. I have one vector shown in the two coordinate systems '2' and '3', so how can I calculate the transforms [A] and [B]. eg. v = [0.5; 5; 3] and v' = [1; 5.408; 2] Any clues
– user26395
Feb 16, 2013 at 18:46
• That is a difficult question. If you have only one vector, you can find the rotation from the x-axis then scale the magnitude to match (see gamedev.stackexchange.com/questions/6137/…), but in general, this is a difficult problem, especially when you have sources of error. Feb 17, 2013 at 19:10

I worked on a project that had lots of transformation to do. I found lots of links on the subject, but they used math that I couldn't comprehend because the symbology was alien. I finally found this paper, which revealed the contents of the matrix to use. The short answer is that the matrix is composed of the dot product of the different axis that you're trying to convert to and from.

In order to save some pain for the next developer I posted some C# in GitHub that has a working sample. The program was derived from one that I found on Code Project, which was written to demonstrate using quaternions but which I found to be useful as a ready-to-go program that would let me rotate and display a surface.

If you want to see what's under the hood here is the essential code. This doesn't show the actual transformation, that's in the code, but the secret sauce of how to do it is located here.

Vector3d X1 = XAxisWorld;            // This is vector (1,0,0)
Vector3d X2 = YAxisWorld;            // This is vector (0,1,0)
Vector3d X3 = ZAxisWorld;            // This is vector (0,0,1)

// These vectors are the local X,Y,Z of the rotated object
Vector3d X1Prime = XAxisLocal;
Vector3d X2Prime = YAxisLocal;
Vector3d X3Prime = ZAxisLocal;
// This matrix will transform points from the rotated axis to the world
LocalToWorldTransform = new Matrix3x3()
{
M11 = (float)Vector3d.DotProduct(X1, X1Prime),
M12 = (float)Vector3d.DotProduct(X1, X2Prime),
M13 = (float)Vector3d.DotProduct(X1, X3Prime),
M21 = (float)Vector3d.DotProduct(X2, X1Prime),
M22 = (float)Vector3d.DotProduct(X2, X2Prime),
M23 = (float)Vector3d.DotProduct(X2, X3Prime),
M31 = (float)Vector3d.DotProduct(X3, X1Prime),
M32 = (float)Vector3d.DotProduct(X3, X2Prime),
M33 = (float)Vector3d.DotProduct(X3, X3Prime),
};
// This matrix will transform points from the world back to the rotated axis
WorldToLocalTransform = new Matrix3x3()
{
M11 = (float)Vector3d.DotProduct(X1Prime, X1),
M12 = (float)Vector3d.DotProduct(X1Prime, X2),
M13 = (float)Vector3d.DotProduct(X1Prime, X3),
M21 = (float)Vector3d.DotProduct(X2Prime, X1),
M22 = (float)Vector3d.DotProduct(X2Prime, X2),
M23 = (float)Vector3d.DotProduct(X2Prime, X3),
M31 = (float)Vector3d.DotProduct(X3Prime, X1),
M32 = (float)Vector3d.DotProduct(X3Prime, X2),
M33 = (float)Vector3d.DotProduct(X3Prime, X3),
};


The text is copied from an archived version of the page originally presented as the answer and that had rot.