Given a vector, A, which represents a point, and a unit vector, B, which represents the looking direction, how would I rotate A so that B is the axis that's looked down on? Let's say the looking-axis is originally (0,0,1) and I want it to become B by rotating A accordingly. So it needs to rotate by (0,0,1) - B.


You can directly construct a look-at matrix without using trigometry (but using vector math). First, you need an up-vector to specify which direction should be up from the camera's point of view. This would typically be (0, 1, 0) or (0, 0, 1), depending on your choice of coordinates.

Then, you can calculate the orthonormal basis for your camera:

float3 right = normalize(cross(dir, up));
float3 upTrue = normalize(cross(right, dir));

Beware! If dir is parallel or antiparallel to up, this will break.

Then, you can construct the (left-handed) camera-to-world matrix by shoving right, upTrue, and dir into the first three rows (if using row vectors) or columns (if using column vectors) of a 4x4 matrix. Put the camera position into the fourth row/column.

Then calculate the inverse of this 4x4 matrix to get the world-to-camera matrix. If you just need the rotation part, use a 3x3 matrix, and you can take the transpose instead of doing a full inverse.

This matrix can then be used as a view matrix in a 3D graphics engine, or you can transform a point yourself by multiplying with this matrix.

| improve this answer | |
  • \$\begingroup\$ Thanks. Can you clarify a bit on how I would construct a 3x3 matrix using column vectors? \$\endgroup\$ – slartibartfast Jun 7 '12 at 5:30
  • \$\begingroup\$ @myrkos What do you need to know? Are you familiar with matrices in general? \$\endgroup\$ – Nathan Reed Jun 7 '12 at 6:08
  • \$\begingroup\$ I am, but I'm still a bit new to them. I'm a but confused where I would put the right,upTrue, and dir. On the top of each column? \$\endgroup\$ – slartibartfast Jun 7 '12 at 6:11
  • \$\begingroup\$ Each vector has three components; you copy those entries into the first, second, and third row components of each column of the matrix. The first column would contain the xyz values of right, from top to bottom, and so on. \$\endgroup\$ – Nathan Reed Jun 7 '12 at 16:38
  • \$\begingroup\$ Oh, oh, sorry. I read float3 as some sort of float number rather than a 3D vector. Thanks! \$\endgroup\$ – slartibartfast Jun 7 '12 at 17:19

Given direction as d and point as p

d = normalize(d);
double yaw = Math.Atan2(d.X, d.Y);
double pitch = Math.Atan2(d.Z, Math.Sqrt((d.X * d.X) + (d.Y * d.Y)));
p.rotateXYZ(pitch, yaw, 0); //Roll == 0

Well, this should do :)

| improve this answer | |
  • \$\begingroup\$ You could also use Math.Asin(d.z) for the pitch, since you already normalized d; that's slightly simpler/faster. (Although, the Atan2 calls will work even when d is unnormalized.) \$\endgroup\$ – Nathan Reed Jun 7 '12 at 4:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.