Sign in to follow this  
Deliverance

LookAt rotation matrix computation

Recommended Posts

Depending on the type of coordinate system and vectors you're using, take a look at the documentation for D3DXMatrixLookAtLH (left-handed, row vectors), D3DXMatrixLookAtRH (right-handed, row vectors), and gluLookAt (right-handed, column vectors). They all contain some matrix diagrams showing you how to construct the matrix. If you're looking more for why's than how's, then ask away. Note that I didn't reference anything for left-handed, row vector configurations, because then you're just asking for trouble [smile]

Share this post


Link to post
Share on other sites
Thanks Zipster, but I have a few more questions.
I'm crating a camera class, and I use Euler angles. Since I want a FPS-like camera I use only 2 angles: angle around X axis and angle around Y axes.
I need to have a function that passed in EyePos and ViewPoint would return a matrix with rotation and translation, that will orient/translate the scene correctly. I can use the gluLookAt function or the code to actually create the matrix, but there are problems. Whenever I look down th positive or negative Y axis(something like this:
gluLookAt(eye.x, eye.y, eye.z, eye.x, eye.y+1/eye.y-1, eye.z, 0, 1, 0))
problems occur. I'm using an Up vector that points dirrectly up ((0,1,0) that is) and because of this the 3 vectors will not create a 3D orthogonal system, because the up vector will be the same or opposite with the view vector.
How can I go arround this? How can I solve this and not use quaternions?

Share this post


Link to post
Share on other sites
That's one reason why I don't use LookAt-style methods for creating my view transformations, because you have to pick some magic up vector and hope your view is never parallel to it.

Instead of constructing the view matrix directly, what I usually do is construct it from three Euler angle rotations for yaw, pitch, and roll. Since you're not using roll, this boils down to a single matrix multiplication, which you can expand explicitly to avoid the matrix multiplication. It's better than using LookAt functions since you already have Euler angles to begin with. So take a Y-axis rotation matrix RY (yaw) and an X-axis rotation matrix RX (pitch) and expand out RXRY (for column vectors) or RYRX (for row vectors).

Share this post


Link to post
Share on other sites
The up vector you select is niether magical, nor arbitrary... it defines the upward direction of the view space in the world space. If the view vector (also in world space) is (0,1,0), then obviously "up" should not be the same vector.

Share this post


Link to post
Share on other sites
Exactly, and then you have a degenerate case to deal with [smile] Especially so in an FPS, where the player looking straight up or straight down is quite common. So I'll concede it's not as much arbitrary or magical as it is problematic in those cases.

Share this post


Link to post
Share on other sites
If you use the up vector from the last frame, you're quite unlikely to bump into the degenerate case. That is unless you can spin 90 degrees in a single frame, which I find unlikely in any game. And if it did happen, you could then use the forward vector from the prior frame to construct the matrix.

Share this post


Link to post
Share on other sites

void Matrix4x4::BuildLookAtMatrix(float posx,float posy,float posz,float eyex,float eyey, float eyez,float upx,float upy, float upz)
{
float x[3], y[3], z[3];
float mag;

z[0] = eyex - posx;
z[1] = eyey - posy;
z[2] = eyez - posz;
mag = sqrt( z[0]*z[0] + z[1]*z[1] + z[2]*z[2] );
if (mag>.0001)
{
mag = 1/mag;
z[0] *= mag;
z[1] *= mag;
z[2] *= mag;
}

y[0] = upx;
y[1] = upy;
y[2] = upz;

x[0] = y[1]*z[2] - y[2]*z[1];
x[1] = -y[0]*z[2] + y[2]*z[0];
x[2] = y[0]*z[1] - y[1]*z[0];


y[0] = z[1]*x[2] - z[2]*x[1];
y[1] = -z[0]*x[2] + z[2]*x[0];
y[2] = z[0]*x[1] - z[1]*x[0];

mag = sqrt( x[0]*x[0] + x[1]*x[1] + x[2]*x[2] );
if (mag > .0001)
{
mag = 1/mag;
x[0] *= mag;
x[1] *= mag;
x[2] *= mag;
}

mag = sqrt( y[0]*y[0] + y[1]*y[1] + y[2]*y[2] );
if (mag > .0001)
{
mag = 1/mag;
y[0] *= mag;
y[1] *= mag;
y[2] *= mag;
}

#define M(row,col) mat[row][col]
M(0,0) = x[0]; M(0,1) = x[1]; M(0,2) = x[2]; M(0,3) = -x[0]*eyex + -x[1]*eyey + -x[2]*eyez;
M(1,0) = y[0]; M(1,1) = y[1]; M(1,2) = y[2]; M(1,3) = -y[0]*eyex + -y[1]*eyey + -y[2]*eyez;
M(2,0) = z[0]; M(2,1) = z[1]; M(2,2) = z[2]; M(2,3) = -z[0]*eyex + -z[1]*eyey + -z[2]*eyez;
M(3,0) = 0.0; M(3,1) = 0.0; M(3,2) = 0.0; M(3,3) = 1.0;
#undef M
}


Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this