Search code examples
openglcameraclipping

Objects are not rendering except when very close (almost intersecting with camera) in OpenGL


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();
    }
}

Solution

  • 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.