21 November 2017

Math – Align a rotation matrix with a normal

Angle and axis

I found this method when I needed to rotate a vehicle to be positioned on the terrain. I had the positions of the wheels, and used those to calculate the vehicle's normal. Then I found the following method to calculate the angle and rotation axis:

var axis = new Vector3(0, 1, 0); //Up vector
float angle = Vector3.DotProduct(normal, axis).Acos(); //I do like extension methods.
var transformation = new Matrix();

if (angle.Absolute() > 0.001f) {
  axis = Vector3.CrossProduct(normal, axis).Normalized();
  transformation.Rotate(angle, axis); //See below.
}

Rotate the matrix

Then the glRotatef function is used to use these values, but that's from the old fixed pipeline OpenGL, and I was using the new OpenGL with shaders and all that. I then found this function that applies the rotation to a matrix:

float rad = angle.ToRadians();
float c = rad.Cos();
float s = rad.Sin();
float t = 1 - c;

float x = axis.X;
float y = axis.Y;
float z = axis.Z;

var rotation = new Matrix();
rotation.M[0, 0] = c + x * x * t;
rotation.M[0, 1] = y * x * t + z * s;
rotation.M[0, 2] = z * x * t - y * s;

rotation.M[1, 0] = x * y * t - z * s;
rotation.M[1, 1] = c + y * y * t;
rotation.M[1, 2] = z * y * t + x * s;

rotation.M[2, 0] = x * z * t + y * s;
rotation.M[2, 1] = y * z * t - x * s;
rotation.M[2, 2] = z * z * t + c;

SetMatrix((this * rotation).M); //This just overwrites the 16 values of this matrix.

See also

Using quaternions to create a rotation matrix

No comments:

Post a Comment