# OpenGL 3D Camera

And here I am again, looking for help with my OpenGL camera once again. This is starting to get embarrassing. Anyway, here's the deal: I think my OpenGL First Person free roaming camera is starting to work correctly. I can draw objects, see them, and my coordinate system is set up as expected. Great. I solved the gimbal lock issue by fixing the UP vector to be the Y unit vector and restricted the camera's rotation to no more than PI/2 and -PI/2 up/down. All of this is used to build the modelview matrix, which I invert and set at the beginning of every frame. Sweet. It can move in all directions and seems to work just fine.

That is until I try to change the projection settings. For whatever reason, no matter what I do, my clipping plane is always around +50.0 Z, regardless of the OpenGL calls I attempt. If I move the camera around and move it into certain positions, rotating the camera causes my objects to disappear and reappear. They tend to appear on the edges of the screen, and disappear near the center. In order to facilitate a better answer, allow me to state my assumptions:

• glFrustum only needs to be called ONCE. OpenGL maintains the Projection Matrix and AUTOMATICALLY multiplies the Modelview and Projection Matrices during rendering.
• The math on the gluPerspective page and glFrustum pages is correct, despite the gluPerspective matrix listing seemingly containing 19 elements when OpenGL only uses 16 of those.
• I'm assuming that the INVERSION of my camera's Modelview Matrix is somehow screwing with my Projection frustum. I have to bet it's something to do with how the rotation is being calculated.

Has anyone seen this kind of behavior before? Where should I look to start tracking down the problem? Am I doing this completely wrong?

Here is the step-by-step code:

 
// -[[ When my application is ready, this code is run only once ]]-

glMatrixMode(GL_PROJECTION);

fieldOfVision = 60.0f;
aspect = 1.5f;
near = 0.1f;
far = 100.0f;

ymin = -ymax;
xmin = ymin * aspect;
xmax = ymax * aspect;

glFrustum(xmin, xmax, ymin, ymax, near, far);

glEnable(GL_DEPTH_TEST);

// -[[ That should setup the viewing volume such that the field of view is 120.0 degrees, the near plane is at 0.1 and the far plane is at 100.0.  For whatever reason, my clipping plane is ALWAYS around 50.0, even if I set the far plane to 1000.0.  Additionally, I can move around objects using this camera and cause them to clip out by rotating the camera. Does this code snippet need to be run more than once?  I was pretty sure that OpenGL takes care of storing the Projection Matrix for the pipeline. ]]-

// -[[ The next chunk of code is performed at every frame. ]]-

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);

// Pos, forward, and up are 3D vectors and forward and up are normalized before the modelview matrix is processed.

side = crossProduct(forward, up);

GLfloat m[] =
{
side.x, side.y, side.z, 0,
up.x, up.y, up.z, 0,
-forward.x, -forward.y, -forward.z, 0
pos.x, pos.y, pos.z, 1
};

m = matrixInvert(m);

// Multing onto the Modelview Identity
glMultMatrix(m);

foreach object
{
glPushMatrix();
object.translate();
object.rotate();
object.scale();
object.draw();
glPopMatrix();
}

glPushMatrix();
renderInterface();
glPopMatrix();

GLenum err = glGetError();
if (err != GL_NO_ERROR)
{
reportError();
}

glFlush();

// -[[ End per-frame drawing.  It looks right to me, but please let me know what I am doing wrong!  Thank you very much for your time and consideration! ]]-
</code>

• There seems to be a matrix order problem. Can you describe in which orders you do your model view operations? You might be translating before rotating, which would rotate your camera around some other point in the world. – void May 18 '11 at 5:37
• Translation/rotation order shouldn't be an issue if I am using a single matrix for my transform, should it? I thought matrices were used to solve that issue. Additionally, the camera seems to move and rotate correctly, except for the frustum. Is it possible that translation/rotation order doesn't effect modelview but effects the projection matrix? That seems very strange to me. I'm uncertain how to answer your comment, because the camera can be moved and/or rotated at any time and it's modelview matrix is calculated each frame. – Grimless May 18 '11 at 6:26
• No you will still have to order things correctly, since rotating before or after a translation will have completely different results. Do you set your matrices correctly in the different matrix slots? – void May 18 '11 at 6:29
• Matrix slots? As in Projection and Modelview? I think so, but obviously I've got something wrong here. My modelview matrix calculations are based on the gluLookAt page. The resulting matrix looks something like M = (s[0] s[1] s[2] 0 u[0] u[1] u[2] 0 -f[0] -f[1] -f[2] 0 p.x p.y p.z 1) where s=side u=up and f=forward and p=position. Once that is built, it is inverted and then glMultMatrix'd onto the identity Modelview. If necessary, I can do a full psuedocode dump as an edit. – Grimless May 18 '11 at 6:54
• Please show us the code where you calculate s, u and f. Additionally it is always helpful to dump the values for each step up to the matrix and post it here, including the final matrix passed to the glMultMatrix/glLoadMatrix func. Also post the code where you pass the result matrix to OpenGL. – Maik Semder May 18 '11 at 8:32

Do you set the correct current matrix prior to update the projection matrix (using glMatrixMode())? Please provide a snippet of your code where you set the projection / modelview matrices.

It should look something like this:

// Setup projection - needs to be done only if the projection
// params change, but doesn't hurt to do on every frame
glMatrixMode(GL_PROJECTION);
gluPerspective(...);

// Setup view transform matrix (the view part from model-view)
glMatrixMode(GL_MODELVIEW);
gluLookAt(...);

// Draw scene
for each object:

// Setup model transform matrix (the model part of model-view)
glMatrixMode(GL_MODELVIEW);
glPushMatrix();

glTranslate(); // finally, translate object into position
glRotate(); // then rotate object
glScale(); // first scale object

[draw object]

// optionally draw sub-objects (if you have a scene graph / transform hierchy)

glPopMatrix();