PDA

View Full Version : Projecting the right view of the world



Exoide
08-17-2009, 01:15 PM
Hi there,

I'm using the default coordinate system as the “top view” of the world now I want to see the “right view” of the world. To get it I did the following


glRotatef(90, 0, 0, -1); // Rotate Z axis
glRotatef(90, 0, -1, 0); // Rotate Y axis

Now I’ve tried to setup a camera perpendicular to this view with this


gluLookAt(10, 0, 0, 0, 0, 0, 0, 1, 0);

But this is wrong.

Can someone explain me what’s wrong there?

Thanks

marshats
08-17-2009, 09:59 PM
If you just want to see a different view, you only need to move the "camera" ie your gluLookAt call is correct by itself.



gluLookAt(10, 0, 0, 0, 0, 0, 0, 1, 0);


When you add the glRotate functions you are rotating the scene so the eye position of 10,0,0 is no longer valid for looking at the "right" side of the scene since you "moved" the scene.

marshats
08-17-2009, 10:10 PM
Note a nice piece of code to help view openGL transformations may be helpful in visualizing the problem; even though it is not quite the same as what you describing you might find it helpful to take a read at

matrixModelView executable (http://www.songho.ca/opengl/gl_transform.html#example1)

The matrixModelView.zip has a windows.exe that allows you to see the effect of various camera settings and model position settings. PS for linux users this runs fine with "wine".

It is good for viewing a scene in relation to the camera but I would still recommend using gluLookAt alone if you just want to view from a different vantage point.

Exoide
08-18-2009, 05:33 AM
Hi Marshats,

Thank you very much for the link it really helps me to clear some doubts I had respect to the matrix view, model view and projection view.

Thank you again :)

Exoide
08-18-2009, 06:04 AM
Hi Marshats,

> When you add the glRotate functions you are rotating the scene so the eye position of 10,0,0 is no longer valid for looking at the "right" side of the scene since you "moved" the scene.

Why the eye position is no longer valid after the rotations?

Here is what I'm doing in the project

I've an orthogonal projection (using the identity matrix for the modelview matrix) and I assume that this is the "top view" of my scene. Now I need to rotate the axis to see the "right view" of the scene that's why I did the rotations


Gl.glRotatef(90, 0, 0, -1);
Gl.glRotatef(90, 0, -1, 0);

Now I've in the front the YZ plane.

In addition I'm using a camera to do the panning in the scene and I need to locate it perpendicular to the YZ plane.

That's why I put the camera in the following location


gluLookAt(10, 0, 0, 0, 0, 0, 0, 1, 0);

10 in the X axis because this axis define the depth now but this is not working.

Can you explain me what's wrong?

marshats
08-18-2009, 06:49 PM
As an explanation of what you were doing the order of operations was the important point. I think you have the order of matrix operations backwards for what you described. Effectively with your original code you were first translating along x-axis (using gluLookAt), then rotating about the y-axis, then finally around the z-axis ie looking at open space since the object out of view. This is not what you wanted, you wanted to look at the "right" side of the object.

A second lesser problem -- If you are trying to do a translation you should use glTranslate, not gluLookAt at all.

Try



glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
glTranslatef (0, 0, -10); // third translate along -z axis (world x-axis!)
glRotatef(90, 0, 0, -1); // second rotate about z-axis (world x-axis!)
glRotatef(90, 0, -1, 0); // first rotate about y-axis


Yes, the order operations goes from "bottom" to "top" as written due to the the way openGL orders its internal matrix multiplications!

Do you see what you expect? If yes, then you could accomplish the same thing with a single "gluLookAt" call as



glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
gluLookAt(10, 0, 0, 0, 0, 0, 0, 0, 1);


This is why gluLookAt is so nice, it helps the programmer out by letting her think about the scene with a "camera" rather than individual translations/rotations.

If all this is confusing take a look at the redbook online (http://www.glprogramming.com/red/chapter03.html) -- especially the sections near Figure 3-4 entitled "Thinking about Transformations" and "Grand, Fixed Coordinate System"

Exoide
08-20-2009, 07:35 AM
Hi Marshats,

I've read the chapter you told me and I understood everything but now I've a doubt about the first block of code you put in the last post


glTranslatef (0, 0, -10); // third translate along -z axis (world x-axis!)

I think the displacement must be realized in the X axis and not in the Z axis because X is the axis that define the depth after the rotations.

Could you verify this and answer me to clear the doubt please?

In fact that's what you're doing in the second block of code


gluLookAt(10, 0, 0, 0, 0, 0, 0, 0, 1);

Here you're doing the displacement in the X axis.

Thank you very much again for your help ;)

marshats
08-20-2009, 08:09 PM
No -- X is _not_ the axis that defines the depth after the rotations. You have to be more specific. Which X-axis are you referring to? The fixed-x axis or the object's x-axis? If you said the objects X-axis you would be correct because that is the same as the fixed z-axis after rotations! -- all very confusing. Hang in there, its like a puzzle once you see it things become easy!

Imagine a fixed coordinate system that does NOT change when you apply rotations/translations/etc: x=right, y=up, z=out-of-monitor. As you apply the rotations your object rotates but the fixed coordinate system still is x=right, y=up, z=out-of-monitor at every step. In the following code I make this distinction more apparent by referring to the fixed-x,y,z coordinate system differently from the object-x,y,z coordinate system.



3: glTranslatef (0, 0, -10); // third translate along fixed z-axis (=object x-axis!)
2: glRotatef(90, 0, 0, -1); // second rotate about fixed z-axis (=object x-axis!)
1: glRotatef(90, 0, -1, 0); // first rotate about fixed y-axis (initially same as object y-axis)


The object starts with the face (U) you want to view on the right.
Step 1: glRotatef(90, 0, -1, 0) rotates the object so U is now facing you in the xy-plane (x=right, y=up still!) but the "view look at up direction" is (0,1,0)
Step 2: glRotatef(90, 0, 0, -1) rotates the object around the z-axis (the z-axis still pointing out of the monitor!) so U is still facing you in the xy-plane (x=right,y=up) while achieving the desired "view look up direction" (0,0,1).
Step 3: glTranslatef (0, 0, -10) moves the object away from you into the monitor (z=out-of_monitor), hence the -10 in the _z_ direction.

I wrote the following code to verify what I said. The result is rather boring -- it starts out viewing that object before any rotations or gluLookAt are applied showing U on the right. If you press a key then you will see the effect of applying the translate/rotate pair -- U moved to the center which is now on the z-axis (out-of-monitor). If you press another key the view stays the same even though the modelview is changed to use gluLookat.


#include <stdio.h>
#include <stdlib.h>
#include <GL/glut.h>

int useLookAt = 0;

void Keyboard (unsigned char key, int q, int s)
{
switch (key) {

case 27: exit(0);
break;

default : ++useLookAt %= 3;
}

glutPostRedisplay();
}

// modified from code by maxN in post #262420
void Triad (char xlab, char ylab, char zlab)
{
static const float XUP[3] = {1,0,0},
YUP[3] = {0,1,0},
ZUP[3] = {0,0,1},
ORG[3] = {0,0,0};
static float siz = 1.5;
static GLfloat color[3] = {1,1,0};

glLineWidth (2.0);
glColor3fv (color);

glPushMatrix ();

glScalef (siz, siz, siz);

glBegin (GL_LINES);
glVertex3fv (ORG); glVertex3fv (XUP);
glVertex3fv (ORG); glVertex3fv (YUP);
glVertex3fv (ORG); glVertex3fv (ZUP);
glEnd ();

glRasterPos3f (1.1, 0.0, 0.0);
glutBitmapCharacter (GLUT_BITMAP_HELVETICA_18, xlab);

glRasterPos3f (0.0, 1.1, 0.0);
glutBitmapCharacter (GLUT_BITMAP_HELVETICA_18, ylab);

glRasterPos3f (0.0, 0.0, 1.1);
glutBitmapCharacter (GLUT_BITMAP_HELVETICA_18, zlab);

glRasterPos3f (1.1, 1.1, 1.1);
glutBitmapCharacter (GLUT_BITMAP_HELVETICA_18, 48+useLookAt);

glPopMatrix ();
}

void Render_Scene (void)
{
static GLfloat color[3] = {1,1,0};

glClear (GL_COLOR_BUFFER_BIT);


glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();

switch (useLookAt) {
case 0: // do nothing but zoom out to view triad without rotations
glTranslatef (0, 0, -10);
printf ("glTranslatef (0, 0, -10);\n");
break;
case 1:
glTranslatef (0, 0, -10); // third translate along fixed z-axis (object x-axis!)
glRotatef(90, 0, 0, -1); // second rotate about fixed z-axis (object x-axis!)
glRotatef(90, 0, -1, 0); // first rotate about fixed y-axis
printf ("glTranslatef (0, 0, -10); glRotatef(90, 0, 0, -1); glRotatef(90, 0, -1, 0)\n");
break;
default:
gluLookAt(10, 0, 0, 0, 0, 0, 0, 0, 1);
printf ("gluLookAt(10, 0, 0, 0, 0, 0, 0, 0, 1)\n");
break;
}

Triad ('u', 'v', 'w'); // draw the coordinate axis of object
//distinguish fixed coordinates (x,y,z) from object coordinates(u,v,w)

glutSwapBuffers();
}

int main (int argc, char **argv)
{
glutInit (&amp;argc, argv);
glutInitDisplayMode (GLUT_DOUBLE);

glutCreateWindow ("OpenGL matrix operations");
glutDisplayFunc (Render_Scene);
glutKeyboardFunc ( Keyboard );

glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
gluPerspective (60, 1.33, 1, 10);

glutMainLoop ();

return 1;
}

Exoide
08-26-2009, 07:12 AM
Hi Marshat,

I didn't write you before because I took some vacations and I didn't check the forum.

You were right from the start!

My fault was that once I read the chapter you sent me I started to mix both fixed coordinate system and objects coordinate system so in your code when I started from bottom to top I represented well both rotations in fixed coordinate system but once I tried to imagine the glTranslate() I visualized it using the object coordinate system so it goes wrong and it had no sense to me because the result was not the expected.

Like I told you before I understood well how both coordinate system works but personally I do prefer the object coordinate system because I can visualize it easier (and the code remain the same) so I parse the functions from top to bottom.

so the code


3:glTranslatef (0, 0, -10); // third translate along fixed z-axis (=object x-axis!)
2:glRotatef(90, 0, 0, -1); // second rotate about fixed z-axis (=object x-axis!)
1:glRotatef(90, 0, -1, 0);

is equivalent to this code thought in object coordinate system



1:glRotatef(90, 0, 0, -1); // rotate about object z-axis
2:glRotatef(90, 0, -1, 0); // rotate about object y-axis
3:glTranslatef (-10, 0, 0); // translate along object x-axis


because I do the translation once the axis are rotated.

Now two questions,

1- gluLookAt() always work with the fixed coordinate system? I mean if I do some rotations and translations before calling gluLookAt() then it uses the result of them or it always uses the identity matrix (the default position and orientation of the coordinate system)?

2- Do you know some tutorial to learn how gluLookAt() works? Because I've a vague idea about how it works. For example if you change the statement gluLookAt(10, 0, 0, 0, 0, 0, 0, 0, 1); with this gluLookAt(0, 10, 0, 0, 0, 0, 1, 0, 0); I don't know where I'm pointing to.

Here is what I think is happening

glRotatef(90, 0, 0, 1);
glRotatef(90, 1, 0, 0);
glTranslatef(0, 10, 0);

Is it correct?

Once again thank you very much for your time.

marshats
08-29-2009, 05:20 PM
Hello, you asked two questions:

1- gluLookAt() always work with the fixed coordinate system? I mean if I do some rotations and translations before calling gluLookAt() then it uses the result of them or it always uses the identity matrix (the default position and orientation of the coordinate system)?

In its essence, gluLookAt is equivalent to a glMultMatrixf(M) then a glTranslated(-eyex,-eyey,-eyez) operation. (see link to detailed gluLookAt function description) (http://pyopengl.sourceforge.net/documentation/manual/gluLookAt.3G.html). Hence, gluLookAt uses the result of the previous operations on the current matrix set by glMatrixMode. That is why you usually see people use it once at the very beginning before you start locating objects in the scene. Something like



void Render_Scene (void)
{
glClear (GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);

glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
gluLookAt(10, 0, 0, 0, 0, 0, 0, 0, 1);

//now start locating objects in scene using glRotate,
//glTranslate, glScale, etc while thinking about the
//fixed cooridinate system ... in your original case
//a box located at 0,0,0
}



I get the feeling you are trying to use gluLookAt in an way it was not designed to be useful for. Try thinking of it as simply a way of positioning a camera in relation to your scene. Place your camera with gluLookAt then place your objects in the scene in the global fixed coordinate system. gluLookAt is a view transformation not an individual object transformation. To quote the famous OpenGL Redbook page 131 Version 2 -- "Note: You can have only one active viewing transformation. You cannot try to combine the effects of two viewing transformations, any more than a camera can have two tripods. If you want to change the position of the camera, make sure you call glLoadIdentity() to wipe away the effects of any current viewing transformation."

2- Do you know some tutorial to learn how gluLookAt() works? Because I've a vague idea about how it works. For example if you change the statement gluLookAt(10, 0, 0, 0, 0, 0, 0, 0, 1); with this gluLookAt(0, 10, 0, 0, 0, 0, 1, 0, 0); I don't know where I'm pointing to.

As for a tutorial I suggest buying the OpenGL Redbook. It is the best resource I have found -- you already have a online link to it in an older revision. Did you read the entire chapter 3? It has a nice section on gluLookAt itself.

To try to answer your more detailed question ... Defining left-right as the fixed x-axis, top-bottom as the fixed y-axis and the front-back as the fixed z-axis. Picture a generic scene as

http://www.juniata.edu/faculty/rhodes/graphics/images/camera2.gif from image location (http://www.juniata.edu/faculty/rhodes/graphics/images/camera2.gif)

Which is equivalent to the following code:



void Render_Scene (void)
{
glClear (GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);

glMatrixMode (GL_MODELVIEW);
glLoadIdentity ();
gluLookAt(eye_x, eye_y, eye_y, at_x, at_y, at_z, up_x, up_y, up_z);

//locate the box in fixed coordinates at (at_x,at_y,at_z)
glPushMatrix();
glTranslatef (at_x, at_y, at_z);
glutSolidCube(1);
glPopMatrix();
}


So in your case gluLookAt( 0,10,0, 0,0,0, 1,0,0 ), your camera is on the fixed y-axis (0,10,0). The camera is pointed "down" at the fixed axis origin (0,0,0) and assuming your object is located at the origin also you will see it's "top". The up direction of the "photograph taken by the camera", i.e. what you see rendered on your monitor, will be parallel to the fixed x-axis (1,0,0).

To be honest, I don't think about the individual rotations/translations of gluLookAt because that ruins its usefulness in my opinion. If you really really want to know what gluLookAt is doing under the hood, take a look at the source code for Meas3D:MesaLib-7.5.* (http://sourceforge.net/projects/mesa3d/files/) in the /Mesa-7.5/src/glu/sgi/libutil/project.c file and locate the the following code snippet



void GLAPIENTRY
gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez, GLdouble centerx,
GLdouble centery, GLdouble centerz, GLdouble upx, GLdouble upy,
GLdouble upz)
{
float forward[3], side[3], up[3];
GLfloat m[4][4];

forward[0] = centerx - eyex;
forward[1] = centery - eyey;
forward[2] = centerz - eyez;

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

normalize(forward);

/* Side = forward x up */
cross(forward, up, side);
normalize(side);

/* Recompute up as: up = side x forward */
cross(side, forward, up);

__gluMakeIdentityf(&amp;m[0][0]);
m[0][0] = side[0];
m[1][0] = side[1];
m[2][0] = side[2];

m[0][1] = up[0];
m[1][1] = up[1];
m[2][1] = up[2];

m[0][2] = -forward[0];
m[1][2] = -forward[1];
m[2][2] = -forward[2];

glMultMatrixf(&amp;m[0][0]);
glTranslated(-eyex, -eyey, -eyez);
}

marshats
08-30-2009, 12:16 AM
Earlier today I answered your questions but ran out of time to draw a diagram that would help the words. I suggest you read that post first, then come back to this. Since this will help visualize (with the help of Blender) your particular test case.

Assuming you have a cube at the origin of the fixed coordinate system. This assumption is only one of convenience, your object doesn't have to be at the origin but I have to put it it somewhere in the camera's center view as defined by you as (at_x,at_y,at_z)=(0,0,0). If I assumed the object somewhere else you may not see it since it might be out of the camera's view.

The following shows a camera in relation to the object corresponding to your code question:


gluLookAt(0, 10, 0, 0, 0, 0, 1, 0, 0);
// means:
// camera eye = (0,10,0)
// look at = (0,0,0) ie the center of the scene
// camera up direction = (1,0,0)


The most confusing thing for me sometimes is the meaning of the "up direction". Notice the camera's "up" arrow pointing to the right in the diagram parallel to the fixed x-axis (1,0,0).

http://24.130.61.216/temporary/view.png

So the "photograph" you will see looking thru the "camera" after openGL renders to your screen will be

http://24.130.61.216/temporary/opengl-view.png

Notice carefully the colors of the axes between the two pictures -- they help you visualize the orientation of the camera relative to the cube object. See how the up direction in the "photograph" corresponds to the x-axis of the fixed coordinate system.

Exoide
08-31-2009, 12:01 PM
Hi Marshats!

Thanks to the last two posts I understood how gluLookAt() works. Now I don't have any doubt about it.

Thank you again for your constant help.

:)

marshats
08-31-2009, 07:45 PM
:) Happy to help.

Now that you understand gluLookAt, you might find some value looking at the source code in the section entitled Points of View (http://users.encs.concordia.ca/~grogono/Graphics/examples.html). Especially the Display() function. This is a nice bit of GLUT based openGL code that I ran across showing how useful gluLookAt can be. I learn a lot from studying other's code when available.

Note I had to make a slight change to the code to make it not run "too fast" on a good modern GPU in Linux. Not that you have to do this but just for the record to throttle the speed to a viewable level, I had to change

Line 512: from

"glutIdleFunc(drive);"

to

"glutTimerFunc(30, drive, -1);"

Line 294: from

"void drive () {"

to

"void drive (int data) {"
" glutTimerFunc(30, drive, -1);"

Also some old C++ code needed a slight tweak to be ANSI:
needed to replace "clock" variable everywhere with "gClock"
replaced "#include <iostream.h>" with "#include <iostream>"
changed line 26-29 to
enum view_name { // Constants for different views
DISTANT, INSIDE, OUTSIDE, DRIVER, HOUSE,
OTHER, BESIDE, BALLOON, HELICOPTER, AUTO
};
view_name view = DISTANT;

Sounds like a lot of changes but it is not that much really to see a cool use of gluLookAt in action.

Exoide
09-03-2009, 09:57 AM
Hi Marshats!

Thank you once again for your time and dedication.