I am trying to create a simple program that will display the Utah Teapot at the origin and view it with the camera, however the teapot does not render at all until the camera is extremely close (so that they almost coincide). At first, I thought I may have had the wrong polygon faces rendered, but when I changed it from CCW to CW, this problem was not corrected. I've added a function that moves the camera down the z axis in the -z direction each time z is pressed. Nothing is rendered until the camera is extremely close to the origin. The camera then passes through and the scene is not rendered again. I've tried with various lightings and camera positions and nothing helps. I no longer know what to change. Any help is appreciated. The problematic code is below.
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#include <GLUT/glut.h>
void display(void);
void reshape(int x, int y);
void init(void);
void keyboard(unsigned char, int, int);
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(800, 600);
glutInitWindowPosition(0, 0);
glutCreateWindow("Test");
init();
glutDisplayFunc(display);
glutReshapeFunc(reshape);
glutKeyboardFunc(keyboard);
glutMainLoop();
return 0;
}
void init(void)
{
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
}
float camx = 0.0, camy = 0.0, camz = 5.0;
void display(void)
{
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
gluPerspective(30.0, 1.3, 0.1, 200.0);
glLoadIdentity();
gluLookAt(camx, camy, camz, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glFrontFace(GL_CCW);
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glColor3f(1.0, 0.0, 0.0);
glutSolidTeapot(1.0);
glFlush();
}
void reshape (int w, int h)
{
glViewport(0, 0, (GLsizei) w, (GLsizei) h);
}
void keyboard(unsigned char key, int x, int y)
{
if (key == 'z') {
camz -= .3;
glutPostRedisplay();
}
}
gluPerspective
, gluLookAt
and glLoadIdentity
all target the currently active matrix as specified by glMatrixMode
, so this block of code is nonsensical.
glMatrixMode (GL_PROJECTION);
glLoadIdentity();
// ^^^ write an identity projection
gluPerspective(30.0, 1.3, 0.1, 200.0);
// ^^^ overwrites identity with your desired projection matrix
glLoadIdentity();
// ^^^ overwrites identity your desired projection matrix with identity
gluLookAt(camx, camy, camz, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
// ^^^ overwrites your identity with a view transform that
// shouldn't be in the projection matrix
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// ^^^ Loads identity into the modelview matrix
The end result is that your project matrix contains a view matrix and your view matrix is empty (identity). Because you don't have a projection matrix, you're essentially defaulting to an orthographic projection of -1 to 1 in all three dimensions (otherwise known as normalized device coordinates).
Try this instead:
// Specify that you're targeting the projection matrix
glMatrixMode (GL_PROJECTION);
// set the projection
gluPerspective(30.0, 1.3, 0.1, 200.0);
// specify that you're targeting the modelview matrix
glMatrixMode(GL_MODELVIEW);
// set the camera.
gluLookAt(camx, camy, camz, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0);
I'm fairly certain that glLoadIdentity
isn't necessary at all because both gluPerspective
and gluLookAt
completely populate the active matrix.