Skip to content

Categories:

XNA – Get Rotation Matrix Between Two Vectors

The rotation matrix between two vectors can be found by taking the dot product, taking the arc cosine of that value, determining the cross product of the 2 vectors you are comparing, then finally creating the matrix using the angle and cross vector.

` C# |  copy code |? 01public static Matrix GetRotationMatrix(this Vector3 source, Vector3 target)02{03     float dot = Vector3.Dot(source, target);04     if (!float.IsNaN(dot))05     {06          float angle = (float)Math.Acos(dot);07          if (!float.IsNaN(angle))08          {09               Vector3 cross = Vector3.Cross(source, target);10               cross.Normalize();11               Matrix rotation = Matrix.CreateFromAxisAngle(cross, angle);12               return rotation;13           }14     }15     return Matrix.Identity;16 }`

Posted in XNA.

3 Responses

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.

1. Hi,
I’ve tried to use this method to create the rotation matrix between two vectors so I wrote this to test it:
Vector3 x = new Vector3(1, 0, 0);
Vector3 y = new Vector3(0, 1, 0);
Matrix m = GetRotationMatrix(x, y);
Vector3 res = Vector3.Transform(x, m);

But: y != res ( res = {X:-4,371139E-08 Y:1 Z:0} )
Did I mess up something?
(Sorry for my English)

2. I think the solution is not to check equality but check for a range +/- epsilon.
Anyway thanks for the code.

3. Okay, I understand what you mean by +/- epsilon, and you’re exactly right. using the case of the example you gave, (1,0,0) to (0,1,0), the code returns a matrix, which once applied results in the vector (-0.00000004371139, 1, 0). It struck me as weird at first because the unit test I was using failed, but the reason it failed is due to a rounding issue. Here’s another extension method I added on to Vector3 earlier on which will help deal with this:

public static Vector3 Round(this Vector3 source, int decimals)
{
Vector3 rounded = source;
rounded.X = (float)Math.Round(rounded.X, decimals);
rounded.Y = (float)Math.Round(rounded.Y, decimals);
rounded.Z = (float)Math.Round(rounded.Z, decimals);
return rounded;
}

Some HTML is OK

or, reply to this post via trackback.