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.