# Look vector to Rotation Matrix

This topic is 3267 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hi guys. What is the easiest way to take a 3d normalized look vector and turn it into a rotation matrix such that the entity will be looking in the direction of the look vector? Thanks.

##### Share on other sites
Assuming you use OpenGL look at this code:

Matrix4x4& Matrix4x4::LookAt  ( const Vector3<float>& vecPos, const Vector3<float>& vecLookAt, bool Reset ){	Vector3<float> X, Y, Z;		Z = vecPos - vecLookAt; Z.Normalize();	X = cross(Vector3<float>(0.0f, 1.0f, 0.0f), Z);	if ( magnitude(X) < 0.01f)				X = cross(Vector3<float>(0.0f, 0.0f, 1.0f), Z);		if ( magnitude(X) < 0.01f)				X = cross(Vector3<float>(1.0f, 0.0f, 0.0f), Z);			X.Normalize();	assert( magnitude(X) != 0.0f);	Y = cross(Z, X);	Y.Normalize();	if ( Reset == true ) {		_m11 = X.x; _m12 = Y.x; _m13 = Z.x; _m14 = 0.0f;		_m21 = X.y; _m22 = Y.y; _m23 = Z.y; _m24 = 0.0f;		_m31 = X.z; _m32 = Y.z; _m33 = Z.z; _m34 = 0.0f;		_m41 = -dot(vecPos, X); _m42 = -dot(vecPos, Y); _m43 = -dot(vecPos, Z); _m44 = 1.0f;	 				return *this;	}	Matrix4x4 view(X.x, Y.x, Z.x, 0.0f,				 X.y, Y.y, Z.y, 0.0f,				 X.z, Y.z, Z.z, 0.0f,				 -dot(vecPos, X), -dot(vecPos, Y), -dot(vecPos, Z), 1.0f);	 	*this *= view;	return *this;}

##### Share on other sites
Well, think of the identity matrix (column mayor notation):

[1 0 0 0][0 1 0 0][0 0 1 0][0 0 0 1]

you can think of each column as a direction vector, such that column 1 is the "right" vector, column 2 is the "forward" vector and column 3 is the "up" vector (if you're using Y as up, just swap Y for Z)

Now, you have the forward vector 'f', your normalized direction vector, so replace it into your matrix:
[1 fx 0 0][0 fy 0 0][0 fz 1 0][0 0  0 1]

you know which way is up in your game world (0,0,1) this vector we will call U, so do a cross product with your forward vector and your up vector to get the right vector 'r':

r = normalize ( f x U)

now you have your right vector:

[rx fx 0 0][ry fy 0 0][rz fz 1 0][0  0  0 1]

Finally once you have both right and forward vectors you can calculate your object space up vector 'u', same as before using cross product:

u = normalize ( r x f)

and there you have it:

[rx fx ux 0][ry fy uy 0][rz fz uz 0][0  0  0  1]

This is what gluLookAt does.

(the cross product gives you a perpendicular vector to the plane in which the 2 vectors reside)

[Edited by - Kwizatz on December 7, 2009 1:49:15 PM]

##### Share on other sites
I have tried creating a row major version for DirectX/XNA as follows:

        public static Quaternion GetOrientation(Vector3 v_Position, Vector3 v_Direction, Vector3 up)        {            Vector3 zAxis = Vector3.Normalize(v_Direction);            Vector3 xAxis = Vector3.Cross(up, zAxis);            if (xAxis.Length() < 0.01f)            {                xAxis = Vector3.Cross(Vector3.UnitZ, zAxis);            }            xAxis.Normalize();            Vector3 yAxis = Vector3.Normalize(Vector3.Cross(zAxis, xAxis));            Matrix m = Matrix.Identity;            // Row Major            m.M11 = xAxis.X;            m.M12 = xAxis.Y;            m.M13 = xAxis.Z;            m.M21 = yAxis.X;            m.M22 = yAxis.Y;            m.M23 = yAxis.Z;            m.M31 = zAxis.X;            m.M32 = zAxis.Y;            m.M33 = zAxis.Z;            m.M41 = -Vector3.Dot(v_Position, xAxis);            m.M42 = -Vector3.Dot(v_Position, yAxis);            m.M43 = -Vector3.Dot(v_Position, zAxis);            return Quaternion.CreateFromRotationMatrix(m);        }

It appears to work with no problems but I wanted to check a few things with you guys.

Could you explain what the M41, M42, M43 are in this case? Do they need to be changed from column major to row major?

If -ve Z goes into the screen the look direction remains positive, correct?

Thanks.

##### Share on other sites
Quote:
 Original post by Spa8nkyCould you explain what the M41, M42, M43 are in this case? Do they need to be changed from column major to row major?Thanks.

They should be position, if you don't need to set a position, set them to 0, gluLookAt just assigns the negated provided position as-is to this row/column, I have no idea why Deliverance is doing a dot product, but what it does is project the position onto the local axis after rotation.

Since you're extracting a Quaternion, I would think those values are ignored anyway (Quaternions contain no position information)

Quote:
 Original post by Spa8nkyIf -ve Z goes into the screen the look direction remains positive, correct?

I didn't understand that last part.

##### Share on other sites
Thanks Kwizatz, that makes sense now.

I probably should explain the last part:

If I have a textured quadrangle rendered in DirectX/XNA with no rotation (Quaternion.Identity), is the normal of the quadrangle (0,0,1) or (0,0,-1)?

##### Share on other sites
Quote:
 Original post by Spa8nkyThanks Kwizatz, that makes sense now.I probably should explain the last part:If I have a textured quadrangle rendered in DirectX/XNA with no rotation (Quaternion.Identity), is the normal of the quadrangle (0,0,1) or (0,0,-1)?

Depends on the vertex order... not sure if I understood still, but anyway, I really don't know about D3D, but OpenGL's camera 'forward' vector is 0,0,-1 (by default the camera looks down the Z axis), which is why it is negated if you look up the man page for gluLookAt, as you can see here (note: that page uses row mayor notation).

##### Share on other sites
Ok, no problem, it works fine apart from the following:

If I have a quadrangle facing backwards, its up vector is (0,1,0). This is a problem when I want the quadrangle to face up from default of facing backwards.

Now in the code I attempt to solve this problem with:

            if (xAxis.Length() < 0.01f)            {                // Pick another unit axis                xAxis = Vector3.Cross(Vector3.UnitX, zAxis);            }

However, although this works and the quad will face up, the texture on the quad will face (0,0,1). Is this to be expected?

If I use:

xAxis = Vector3.Cross(Vector3.UnitZ, zAxis);

then the quadrangle will still face up but the texture will now point towards UnitZ.

Thanks again.

##### Share on other sites
Quote:
 Original post by Spa8nkyOk, no problem, it works fine apart from the following...

Hmmm... you could try swapping the operands from the cross products, depending on their order the normal will face one way or the other (forward or backward) so maybe you're getting one or more of the vectors flipped.

##### Share on other sites
The matrix i prrovided contains a rotation matrix and a translation matrix. They are combined by multiplying matrices like this:

ViewMatrix = Translation^(-1) * Rotation (rotation is applied first)
(1, 0, 0, 0,                          (X.x, Y.x, Z.x, 0.0f, 0, 1, 0, 0,                       *   X.y, Y.y, Z.y, 0.0f,  0, 0, 1.0f, 0.0f,                           X.z, Y.z, Z.z, 0.0f,   -vecPos.x  -vecPos.y, -vecPos.z,   1.0f)    0    0    0,   1.0f)

1. 1
Rutin
43
2. 2
3. 3
4. 4
5. 5

• 9
• 27
• 20
• 9
• 20
• ### Forum Statistics

• Total Topics
633398
• Total Posts
3011661
• ### Who's Online (See full list)

There are no registered users currently online

×