Skip to main content
gamedev.net
🔒 Locked

gluLookAt?

Started by supagu Mar 3, 2004 at 5:36 AM 5 replies 1.3k views
Original Post
supagu
supagu
gluLookAt? does it just do a transpose? and... is a transpose only done on the 3x3 rotation part of a matrix that includes position?
HellRaiZer
HellRaiZer
What do you mean with "transpose"? If you mean what i think, then, no.

gluLookAt() builds a 4x4 matrix, from the position, view, and upvector you give it, and then it calls glMultMatrixf() with that matrix as parameter. Then it glTranslatef() to the "negative" eye position. (Why they didn''t made those two in one glMultMatrixf() call i don''t know. Ask micro$oft!).

I have ripped gluLookAt out of GLu32.dll some time ago, trying to find out what was going on in there. I don''t have the source right now (really it isn''t something terrible, just some cross products and the matrix assemly). In general, what gluLookAt() does is:

* Calc direction vector (view - eye)
* Calc the real up vector (cross between direction and the given upvector (right vector) and then cross between direction and the right vector).
* Fill matrix columns with the transformation (i don''t remember that, that''s why i mentioned the code)
* Call glMultMatrixf() with the above matrix
* Call glTranslatef(-eyex, -eyey, -eyez).

That''s all.

If you want the code i can post, when i get home.

Hope this helped.

HellRaiZer
HellRaiZer
supagu
supagu
yeah code would be good.

Trienco
Trienco

float viewmatrix[16]={
Transform[0], Transform[4], Transform[8], 0,
Transform[1], Transform[5], Transform[9], 0,
Transform[2], Transform[6], Transform[10], 0,
-(Transform[0]*Transform[12] + Transform[1]*Transform[13] + Transform[2]*Transform[14]),
-(Transform[4]*Transform[12] + Transform[5]*Transform[13] + Transform[6]*Transform[14]),
-(Transform[8]*Transform[12] + Transform[9]*Transform[13] + Transform[10]*Transform[14]), 1};
glLoadMatrixf(viewmatrix);


now lets just pretend Transform is your "cameras" or viewers matrix. if not, thats where all the crossproducts come from (finding the "right" vector and calculating the correct "up" vector -> r = f x u; u = f x r

also: glulookat does pretty much nothing but take your vectors and construct a "view" matrix. HOW it is doing that is completely up to the implementation and looking at how microsoft did it wont tell you how other implementations do it. mesa is usually a good place to check how you CAN do it. you can also have a look at the lookat functions of d3d, they explain what they do inside those functions.
f@dzhttp://festini.device-zero.de
Boni
Boni

(thought i'd give my confusing explanation)

supagu: in a sense you're right. it does do a transpose on the rotation matrix, and an inverse on the position.
--

The goal of gluLookAt is to bring your objects from 'World Space' to 'Camera Space'. You specify the orientation of the camera and its position. The orientation is like so:
          ^
|
| up
|
(center) ------> X = up cross Z
/
/
/
(eye)

(center) and (eye) are points. and Z = (eye) - (center).
You then recompute the up vector, call it Y, as Y = Z cross X.
You have to normalize all the vectors so that you form an orthogonal matrix. You will see the importance of this (and the reason for taking the transpose) below.

The position of the camera is simply the position of the eye.

With these vectors X,Y,Z, we have a 'basis' for the 'Camera Space' to represent the rotation (orientation) of the camera. So, we can build a matrix to represent this.
Let X=(x1,x2,x3), Y=(y1,y2,y3), Z=(z1,z2,z3), and eye=(p1,p2,p3)
Then the rotation matrix
     (x1  y1  z1)            (p1)
R = (x2 y2 z2) and T = (p2)
(x3 y3 z3) (p3)

Notice how the X,Y,Z vectors are 'columns' in the R matrix.
--

Conceptually, you could think of positioning a camera, like how you position an object (actually, there's a difference, but i'll get to that.) When you position an object, you first rotate (about the origin), then translate it to its position in the world. In matrix form, this would correspond to: TR, where R is the rotation matrix, and T the translation matrix. When you multiply this out (in 4x4 form) you get:
       (x1  y1  z1  p1)
(x2 y2 z2 p2)
TR = (x3 y3 z3 p3)
(0 0 0 1 )

The difference, however, is that in placing a camera, you want all other objects in the world in the point of view of the camera. This is done by taking the inverse of the matrix above:
    inv(TR) = inv(R)inv(T) 

This will give you the matrix which transforms points from 'World Space', to 'Camera Space', which is what you want.

Now, if R is an orthogonal matrix (as we made it to be above), the inverse of R equals the transpose of R:
    inv(R) = transpose(R)   ; when R is orthogonal 

and the inverse of T is simply the matrix scaled by -1:
    inv(T) = -T. 

--

So, we now have inv(R) and inv(T):
         (x1  x2  x3  0)             (1  0  0  -p1)
(y1 y2 y3 0) (0 1 0 -p2)
inv(R) = (z1 z2 z3 0) inv(T) = (0 0 1 -p3)
(0 0 0 1) (0 0 0 1 )

and combining this, we have:
        inv(TR) = inv(R)inv(T)
= (x1 x2 x3 -(p1x1 + p2x2 + p3x3) )
(y1 y2 y3 -(p1y1 + p2y2 + p3y3) )
(z1 z2 z3 -(p1z1 + p2z2 + p3z3) )
(0 0 0 1 )

You could verify that this is indeed the inverse, by multiplying it by TR above.
--

But, in code, you may see the rotation and translation calls separated. So, you would have:
   glMultMatrixd(  inv(R)   );
glTranslated( inv(T) ); // umm ... the components.

--
Here's the mesa source: (am i allowed to post this????)
(i've added a few comments)

void GLAPIENTRY
gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez,
GLdouble centerx, GLdouble centery, GLdouble centerz,
GLdouble upx, GLdouble upy, GLdouble upz)
{
GLdouble m[16];
GLdouble x[3], y[3], z[3];
GLdouble mag;

/* Make rotation matrix */

/* Z vector */
z[0] = eyex - centerx;
z[1] = eyey - centery;
z[2] = eyez - centerz;
// Normalize (to form orthogonal matrix)

mag = sqrt(z[0] * z[0] + z[1] * z[1] + z[2] * z[2]);
if (mag) { /* mpichler, 19950515 */
z[0] /= mag;
z[1] /= mag;
z[2] /= mag;
}

/* Y vector */
y[0] = upx;
y[1] = upy;
y[2] = upz;

/* X vector = Y cross Z */
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];

/* Recompute Y = Z cross X */
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];

/* mpichler, 19950515 */
/* cross product gives area of parallelogram, which is < 1.0 for
* non-perpendicular unit-length vectors; so normalize x, y here
*/


// Normalize (to form orthogonal matrix)

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

// Normalize (to form orthogonal matrix)

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

// Build the rotation (orientation) matrix. Notice how x, y, z

// are put as rows (because it is the inverse.)

#define M(row,col) m[col*4+row]
M(0, 0) = x[0]; // row 0

M(0, 1) = x[1];
M(0, 2) = x[2];
M(0, 3) = 0.0;
M(1, 0) = y[0]; // row 1

M(1, 1) = y[1];
M(1, 2) = y[2];
M(1, 3) = 0.0;
M(2, 0) = z[0]; // row 2

M(2, 1) = z[1];
M(2, 2) = z[2];
M(2, 3) = 0.0;
M(3, 0) = 0.0;
M(3, 1) = 0.0;
M(3, 2) = 0.0;
M(3, 3) = 1.0;
#undef M
glMultMatrixd(m);

/* Translate Eye to Origin */
// Note that this is the inverse of the position.

glTranslated(-eyex, -eyey, -eyez);
}


-----------

hope it helps.

[edited by - boni on March 4, 2004 5:25:18 PM]
supagu
supagu
hrmm trying to write my own gllook at for my camera class, so i havea bit more control...

void Camera::LookAt()
{
// Vector3 lookAt = position + view;

Matrix4 look;

//Vector3 up(0,1,0);
//Vector3 right = view.CrossProduct( up );
//up = view.CrossProduct( right );

look[ 0] = right[X];
look[ 4] = right[Y];
look[ 8] = right[Z];

look[ 1] = up[X];
look[ 5] = up[Y];
look[ 9] = up[Z];

look[ 2] = view[X];
look[ 6] = view[Y];
look[10] = view[Z];

//look.Translate( -position[X], -position[Y], -position[Z]);

look[12] = -position[X];
look[13] = -position[Y];
look[14] = -position[Z];

look.Set(); //this uses glLoadMatrixf(m);



/*
// Give openGL our camera position, then camera view, then camera up vector
gluLookAt( position[X], position[Y], position[Z],
lookAt[X], lookAt[Y], lookAt[Z],
up[X], up[Y], up[Z] );*/
}

i get some funkey camera movement when i move from 0,0,0
if im at 0,0,0 and rotate around its fine, but when i move the position seems to have some strange effects :-/
Trienco
Trienco
quote:
Original post by supagu
//look.Translate( -position[X], -position[Y], -position[Z]);

look[12] = -position[X];
look[13] = -position[Y];
look[14] = -position[Z];

i get some funkey camera movement when i move from 0,0,0
if im at 0,0,0 and rotate around its fine, but when i move the position seems to have some strange effects :-/


*cough* what gave you the impression, that translation would just be setting the negative position? its a movement along local axes, so you cant just negate the global position (unless your local axes happen to be the global axes which is not the case as soon as you rotate).

f@dzhttp://festini.device-zero.de

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.