GLU.gluLookAt in Java OpenGL bindings seems to do nothing

8k views Asked by At

I've already checked the other questions on this topic and their solutions haven't worked for me. I'm at a bit of a loss. I have the following functions in my GLEventListener implementation.

public void init(GLAutoDrawable gl) {
    GL2 gl2 = gl.getGL().getGL2();

    gl2.glMatrixMode(GL2.GL_PROJECTION);
    gl2.glLoadIdentity();
    GLU glu = GLU.createGLU(gl2);
    glu.gluPerspective(45.0f, 1, 0.1f,100.0f);
    gl2.glMatrixMode(GL2.GL_MODELVIEW);
    gl2.glLoadIdentity();
    gl2.glViewport(0, 0, width, height);
    gl2.glEnable(GL.GL_DEPTH_TEST);
}

private void render(GLAutoDrawable drawable) {

    GL2 gl = drawable.getGL().getGL2();
    GLU glu = GLU.createGLU(gl);

    gl.glClear(GL.GL_COLOR_BUFFER_BIT);
    gl.glMatrixMode(GL2.GL_MODELVIEW);
    gl.glLoadIdentity();
    glu.gluLookAt(5,  0, 20, 
                  0, 30,  0, 
                  0,  1,  0);

    gl2.glPushMatrix();
    gl2.glClear( GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT );                
    gl2.glLoadIdentity();
    gl2.glTranslatef(x, y, z);        
    gl2.glBegin( GL2.GL_QUADS );
        gl2.glColor3f( 1, 0, 0 );

        //24 glVertex3f calls & some colour changes go here.
        gl2.glVertex3f(...)

    gl2.glEnd();
    gl2.glPopMatrix();

    gl.glFlush();
}

It doesn't matter what values I put into the gluLookAt() matrix, the view doesn't change. I still end up looking at the same face of a cube.

Any ideas?

Thanks

1

There are 1 answers

3
Bob Cross On BEST ANSWER

EDIT: Responding to the edit in the original question. Leaving the original text below because people seem to find it to be useful.

I think your problem is in your cube drawing code. Check the commentary below: the glLoadIdentity call is doing exactly what you would expect - forcing the cube to be there in front of you:

gl2.glPushMatrix();     
gl2.glClear( GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT );
/** Try removing the following glLoadIdentity call below.
  * That call was blowing out the MODELVIEW matrix - it's removing your 
  * gluLookAt call and returning to the identity.
  * As a result, the cube will always be right there in front of you.
  */
// gl2.glLoadIdentity();
gl2.glTranslatef(x, y, z);
gl2.glBegin( GL2.GL_QUADS );
gl2.glColor3f( 1, 0, 0 ); //24 glVertex3f calls & some colour changes go here.
gl2.glVertex3f(...)
gl2.glEnd();
gl2.glPopMatrix(); 

Here's a very quick explanation about what the related calls will do. See the documentation for more information:

gl2.glPushMatrix(); // This preserves current MODEL_VIEW matrix so you can get back here.
                    // Think of it as a checkpoint save in a game.
                    // Most of your objects will be wrapped in push and pop.
gl2.glLoadIdentity(); // This erases the MODEL_VIEW and replaces it with an identity.
                      // This un-does your previous gluLookAt call.  You will rarely use
                      // this inside an object (but it's not impossible).
                      // Does not apply here so don't use.
gl2.glTranslatef(x, y, z); // This is what puts your object out in space for you to find
                           // as opposed to putting it at the origin.  Most objects will
                           // have a translate (and likely a rotate as well).
                           // Note that the order of operations matters:
                           // translate and then rotate != rotate and then translate.
// QUAD strip code with vertices and colors - you're okay with these.
gl2.glPopMatrix(); // This brings back the MODEL_VIEW that you originally saved by pushing
                   // it.

The great thing about the matrix code in OpenGL is that once you get a portfolio of example code that you understand, you'll always have it as a reference. When I switched from IrisGL to OpenGL back in the day, it took me a little while to port my utilities over and then I never looked back.

ORIGINAL: You need to add your cube drawing code - if you are putting the cube in the vicinity of (0, 30, 0), it's highly likely that the code is doing what you asked it to.

Checking the OpenGL FAQ, there's a specific question and answer that is likely relevant to what you're doing: 8.080 Why doesn't gluLookAt work? I'm going to quote the whole answer as there really isn't a good break but please visit the OpenGL FAQ, the answer is likely there:

This is usually caused by incorrect transformations.

Assuming you are using gluPerspective() on the Projection matrix stack with zNear and zFar as the third and fourth parameters, you need to set gluLookAt on the ModelView matrix stack, and pass parameters so your geometry falls between zNear and zFar.

It's usually best to experiment with a simple piece of code when you're trying to understand viewing transformations. Let's say you are trying to look at a unit sphere centered on the origin. You'll want to set up your transformations as follows:

 glMatrixMode(GL_PROJECTION);
 glLoadIdentity(); 
 gluPerspective(50.0, 1.0, 3.0, 7.0); 
 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity(); 
 gluLookAt(0.0, 0.0, 5.0,
           0.0, 0.0, 0.0,
           0.0, 1.0, 0.0);

It's important to note how the Projection and ModelView transforms work together.

In this example, the Projection transform sets up a 50.0-degree field of view, with an aspect ratio of 1.0. The zNear clipping plane is 3.0 units in front of the eye, and the zFar clipping plane is 7.0 units in front of the eye. This leaves a Z volume distance of 4.0 units, ample room for a unit sphere.

The ModelView transform sets the eye position at (0.0, 0.0, 5.0), and the look-at point is the origin in the center of our unit sphere. Note that the eye position is 5.0 units away from the look at point. This is important, because a distance of 5.0 units in front of the eye is in the middle of the Z volume that the Projection transform defines. If the gluLookAt() call had placed the eye at (0.0, 0.0, 1.0), it would produce a distance of 1.0 to the origin. This isn't long enough to include the sphere in the view volume, and it would be clipped by the zNear clipping plane.

Similarly, if you place the eye at (0.0, 0.0, 10.0), the distance of 10.0 to the look at point will result in the unit sphere being 10.0 units away from the eye and far behind the zFar clipping plane placed at 7.0 units.

If this has confused you, read up on transformations in the OpenGL red book or OpenGL Specification. After you understand object coordinate space, eye coordinate space, and clip coordinate space, the above should become clear. Also, experiment with small test programs. If you're having trouble getting the correct transforms in your main application project, it can be educational to write a small piece of code that tries to reproduce the problem with simpler geometry.