[SOLVED] Default eye coordinate position in OpenGL

Started by firemanphil, May 31, 2009, 21:53:55

Previous topic - Next topic

firemanphil

Hi all,

I have a problem understanding the way that OpenGL works when the default projection matrix is used. Please look at the code below. I have used gluLookAt to make it clear that the default camera position is at (0,0,0) looking towards (0,0,-1) with up as (0,1,0). However, when I position a square behind the camera, I can still see it! This also works for any orthographic projection. Am I missing something obvious here?

import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.util.glu.GLU.*;

public class SimpleSquare {
	public static void main(String[] args) throws InterruptedException{
	try {
		Display.setTitle("Simple Square");
		Display.create();
	} catch (LWJGLException e) {
		e.printStackTrace();
	}
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
	gluLookAt( 0, 0, 0,
            0, 0, -1,
            0, 1, 0 );
	// draw the square
	glBegin(GL_LINE_LOOP);
		glVertex3f(-0.5f, -0.5f, 0.5f);
		glVertex3f(-0.5f, 0.5f, 0.5f);
		glVertex3f(0.5f, 0.5f, 0.5f);
		glVertex3f(0.5f, -0.5f, 0.5f);
	glEnd();
	
	// flush any commands that are still hanging about.
	glFlush();
	// update window.
	Display.update();
	
	while(!Display.isCloseRequested()){
		Thread.sleep(100);		
	}
	Display.destroy();
	}
}

Kai

To understand this issue, we have to consider what it means for OpenGL that something "is not visible":
After the vertices of the primitives that you draw got transformed via the modelview and projection matrices, they are within or without an area called the "clipping area" or "clipping box".
If all vertices of the primitive are within that box, they will be drawn, otherwise they will be "clipped" (that is, either not drawn at all or partially drawn).
Now, how does OpenGL decide whether a vertex is within or without that box? Well, that's a basic test of whether the co-ordinates of that transformed vertex are within ([-1, 1], [-1, 1], [-1, 1]). So, the clipping box is always centered at (0, 0, 0) and has a extend of 1 in each direction.
So, let's replay what happens when you setup the OpenGL matrices as you did and how the vertices will be transformed by each step:

0. Original:
      (-0.5, -0.5, 0.5)
      (-0.5, 0.5, 0.5)
      (0.5, 0.5, 0.5)
      (0.5, -0.5, 0.5)

1. modelview:
You are basically flipping the z-value so the modelview-transformed vertices will be
      (-0.5, -0.5, -0.5)
      (-0.5, 0.5, -0.5)
      (0.5, 0.5, -0.5)
      (0.5, -0.5, -0.5)

2. projection:
This is where the modelview-transformed vertices will be fitted into the "clipping box".
Everything in that clipping box then represents the viewing frustum of the camera and hence will be visible in the final scene.
Since per default this is the identity transformation, we still have:
      (-0.5, -0.5, -0.5)
      (-0.5, 0.5, -0.5)
      (0.5, 0.5, -0.5)
      (0.5, -0.5, -0.5)

3. clipping box test
Question: Are all vertices within  ([-1, 1], [-1, 1], [-1, 1])? -> Yes!
So all vertices will be drawn!

Easy solution to that:
Specify the camera's viewing frustum via glOrtho or gluPerspective. What these methods do is to shift and stretch the clipping box so that only vertices with a z-value bigger as the min-z clipping plane will be drawn.

firemanphil

Thanks for your reply.

Hmm, yeah I was aware of the way the projection matrix works, but I thought there was a subsequent part which clips anything behind the current 'eye coordinates'. However, after reading your post I think my idea of a placeable camera is incorrect. The position of a 'camera' is only inferred from the projection matrix itself.

With a perspective transformation the camera position is at the meeting point of the rays from the defined frustum. With the default projection matrix (which is orthographic) the 'camera' could be said to be at +/- infinity as the rays from the enclosing rectangle never meet. This is why however large/small you set znear/zfar in glOrtho, everything is always visible.

So when I call gluLookAt(eyeCoords, directionToLook, upVector) I am not moving some 'camera' but simply rotating/translating my vertices.

Kai

QuoteThis is why however large/small you set znear/zfar in glOrtho, everything is always visible.
I'm afraid this is not true: It will matter how you set znear and zfar. Every vertex with a z-value smaller than znear or greater than zfar will be clipped and thus will not be visible. It is just that with the default projection matrix, those values are -1.0 and +1.0, so if you try to render the lines at z = 1.5 (for instance) and leave the code you posted above as it is, you will not see the lines anymore.

firemanphil

Sorry I didn't explain well enough. However large you set znear and zfar, everything within those bounds is visible, i.e. nothing ever gets clipped for being behind the camera.