My instructor says they can be used interchangeably to affect the projection matrix. He argues that gluLookAt() is preferably used because of its 'relative simplicity due to its ability to define the viewing angle'. Is this true? I've seen code examples using both gluLookAt() and glFrustum() and I'm wondering why would the programmmer mix them.
Like in the cube.c example of the redbook appears:
void display(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 1.0, 1.0);
glLoadIdentity();
gluLookAt(0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
**//why isn't this a call to glFrustum?**
glScalef(1.0, 2.0, 1.0);
glutWireCube(1.0);
glFlush();
}
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0);
//why isn't this a call a call to gluLookAt()?
glMatrixMode(GL_MODELVIEW);
}
Both glFrustum and gluLookAt perform simple matrix multiplication. Check the man pages for equations for those matrices:
gluLookAt
glFrustum
Both of those can be replaced by a glMultMatrix* call.
The most important difference is that glFrustum is used most of the time to establish a perspective projection matrix (used internally by gluPerspective), and gluLookAt is a convenience method for specifying model-view matrices (usually: implementing a camera).
gluLookAt affects the ModelView matrix whereas, glFrustum/gluPerspective affect the Projection matrix. These are entirely two different matrices in the pipeline. gluLookAt is a utility method which is a combination of glRotate and glTranslate calls to move the "camera" to the appropriate point in space and point it to the desired location. Whereas, glFrustum/gluPerspective are methods which define a perspective viewing volume. Check out for more details in the OpenGL Red Book.
Related
When I write the following code, everything works and an ellipsoid is displayed.
void HandModelCreator::drawModel(){
palm();
}
void HandModelCreator::palm(){
glColor4f(0.6, 0.0, 0.0, 0.0);
glScalef(1.0, 0.3, 0.45);
glutSolidSphere (0.4, 20, 20);
}
I am trying to create a hierarchical model & need to use glPushMatrix() and glPopMatrix(). So, I tried the following code, but nothing really worked. No ellipsoid was displayed. Why? What am I doing wrong?
void HandModelCreator::drawModel(){
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();
palm();
glPopMatrix();
}
void HandModelCreator::palm(){
glColor4f(0.6, 0.0, 0.0, 0.0);
glScalef(1.0, 0.3, 0.45);
glutSolidSphere (0.4, 20, 20);
}
Why are you calling glLoadIdentity() before pushing the matrix on the stack? The idea of a stack is, that you push before you make the changes you later want to revert.
Furthermore, I don't think you want glLoadIdentity() there at all, because that resets the whole modelview matrix (i.e. whatever transformation hierachy you had, is then gone):
This is closer to what you actually need:
void HandModelCreator::drawModel(){
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
palm();
glPopMatrix();
}
Before pushing the matrix, you set it to identity (using glLoadIdentity). This will of course cancel all previous transformations accumulated into the modelview matrix and might very well be the reason why you cannot see anything.
I advise you to delve a little deeper into how OpenGL's transformation pipeline and matrix transformations in general work.
I just want to create a perspective where the eye of the camera would be, at, say: (2, 2, -2), looking right at the origin. I'm trying to use a combination of gluLookAt() and glFrustum(), but for some reason, though it is rendering, my objects look very distorted:
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
glFrustum (-1.0, 1.0, -1.0, 1.0, 1.0, 500.0);
...
gluLookAt (-2.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0);
What am I doing wrong?
EDIT: Here is a screenshot. The left side defines a profile curve to be swept around the y-axis. It should be a cylinder in the perspective view, but it's... warped.
EDIT 2: Also, those axis in the perspective view are set up as followed, which I know isn't correct:
// draw the axis
glBegin(GL_LINES);
// x
glVertex3f(500.0, 0.0, 0.0);
glVertex3f(-500.0, 0.0, 0.0);
// y
glVertex3f(0.0, -500.0, 0.0);
glVertex3f(0.0, 500.0, 0.0);
// z
glVertex3f(0.0, 0.0, -500.0);
glVertex3f(0.0, 0.0, 500.0);
glEnd();
EDIT 3: Also, none of the vertices of that shape have an x, y, or z value greater than 1.0..
What am I doing wrong?
I don't thing you're doing wrong anything. The kind of view you want to have in your left pane is usually done using a orthographic projection. The distortion you see is just a perspective distortion; you're not looking perpendicular onto the curve (the curve lies in the XY plane, and you're looking at the XY plane from some angle).
Side note:
The projection matrix only defines the "lens" of OpenGL. It must not be used to place the "camera". Any eyepoint positioning (the view) is defined as part of the modelview transformation. Thus gluLookAt is meant to be used on the modelview matrix.
Your frustum is set up as if the screen is square. If your screen isn't square this will distort the objects badly.
Also, if the objects are close to your camera, the near and far distances can affect the image.
And one more thing, your up axis in gluLookAt is pointing down.
Posting a screenshot would help identify the problem.
Suppose I have a point at (250,125,-20).
After the following transformation,
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(100.0, 50.0, 0.0);
glRotatef(-25.0, 0.0, 1.0, 0.0);
How can I get the value of current coordinates of that point?
Need I write a subroutine to multiply a matrix to a vector?
Are there any built-in solutions?
You can't get the coordinates for a specific vertex (point) after a transformation, however for this particular case you can get the ModelViewMatrix after the translate/rotate is applied.
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(100.0, 50.0, 0.0);
glRotatef(-25.0, 0.0, 1.0, 0.0);
glGetFloatv(GL_MODELVIEW_MATRIX , *your_matrix*);
//print your matrix to check if that is the desired transformation coordinates
There is no magic tape in OpenGL, you will have to write your own framework e.g: for every objects in your world a class where you hold the vertices and what data you find relevant.
When looking at the reshape examples in the redbook, I usually find something like:
void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-1.0, 1.0, -1.0, 1.0, 1.5, 20.0);
glMatrixMode(GL_MODELVIEW);
}
I understand that calling glMatrixMode(GL_PROJECTION); followed by glLoadIdentity(); resets the projection matrix but I don't understand why glMatrixMode(GL_MODELVIEW) is usually called at the end of reshape.
In this particular example glFrustum affects the projection matrix, right? Why is GL_MODELVIEW called later? Would it make a difference if the last call to glMatrixMode(GL_MODELVIEW) is omitted?
Most of your rendering code is going to affect GL_MODELVIEW, because it's what affects object translation and camera position. However, the resizing code works on GL_PROJECTION. The programmer probably assumes the current matrix is the modelview one in most of his code, and when a different one needs to be affected, he/she would change the matrix, update it, and then change the target back to GL_MODELVIEW so the rest of the code doesn't target the wrong matrix.
Generally, OpenGL functions affect whatever matrix is currently being targeted, which is why you change the matrix.
i'm completely don't understanding opengl+glut works....
PLEASE explain why he does that? =(
I have simple code
void display()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glPushMatrix();
ChessboardSurrogate.Draw(6,8,50, 0,0); // draw chessboard(6x8) in (0,0,0) edge per cell 50
glPopMatrix();
glPushMatrix();
//glutSolidCube(100); //!!!!!
glPopMatrix();
glLoadIdentity();
gluLookAt( 0.0, 0.0, -testSet::znear*2,
0.0, 0.0, 0.0,
0.0, 1.0, 0.0);
glMultMatrixf(_data->m); // my transformation matrix
glutSwapBuffers();
}
And i get the expected result. screenshot #1
Then I uncomment glutSolidCube(100). In any case, I even do push/pop current matrix, and later override it by identity matrix.... i think that i would see the same result image with cude... BUT! i see THIS screenshot #2 What the..... &*^##$% Why?
If i add code
glRotatef(angleX,1.0,0.0,0.0);
glRotatef(angleY,0.0,1.0,0.0);
before glutSwapBuffers, than I'll see that the chessboard on the spot .....
screenshot #3
This is probably only half the answer, but why on earth are you setting your matrices AFTER drawing ? What do you expect it to do ?
so :
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
gluLookAt( 0.0, 0.0, -testSet::znear*2,
0.0, 0.0, 0.0,
0.0, 1.0, 0.0);
glMultMatrixf(_data->m); // my transformation matrix
glPushMatrix();
ChessboardSurrogate.Draw(6,8,50, 0,0); // draw chessboard(6x8) in (0,0,0) edge per cell 50
glPopMatrix();
glPushMatrix();
//glutSolidCube(100); //!!!!!
glPopMatrix();
glutSwapBuffers();
moreover, always make sure you're setting the right matrix :
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt()...
Lastly, unless your Draw() method changes the modelview matrix, your Push/PopMatrix is useless and should be avoided (for performance and portability reasons since it's deprecated)