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.
| 01 | public 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 | } |
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)
I think the solution is not to check equality but check for a range +/- epsilon.
Anyway thanks for the code.
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;
}