Search code examples
cocoaopenglperspectivedepth-buffer

Strange behaviour with gluPerspective and gluLookAt


For a project I need to implemente a NSOpenGLView. I found some resources (tutorials, apple documentation...) to be able to start, but when I try to use gluPerspective and GluLookAt, I have some strange behaviours (vertex of my cube are troncated, and faces are drawn above each other as if there wasn't a Depth buffer). Here is the implementation of my OpenGLView (NSOpenGLView class).

Nota 1 : I need my application to be compatible with OSX 10.6, it's mean that I have to use OpenGL 2.1.

Nota 2 : I can't use Interface Builder. I need to initialize an NSOpenGLView programmatically.

UPDATE : gluPerspective zNear and zFar, and gluLookAt eye parameters has been modified to correct the problem of troncated vertex. But the problem of faces that don't draw correctly is still present. Here are images to illustrate :

Capture01 Capture02

UPDATE 2 : Finally I found the answer by reading the question titled "OpenGL GL_DEPTH_TEST not working". The solution is : If you want to create an NSOpenGLView without Interface Builder, you'll have to set the pixelFormat programmatically. I correct my code for those who encounter the same problem.

OpenGLView.m

#import "OpenGLView.h"

@interface OpenGLView ()
{
    NSTimer *updateTimer;
    float cubeRotationAngle;
}
@end

@implementation OpenGLView

-(id)initWithFrame:(NSRect)contentRect pixelFormat:(NSOpenGLPixelFormat *)format
{
    if(self = [super initWithFrame:(NSRect)contentRect  pixelFormat:format])
    {
        [self setFrame:contentRect];

        updateTimer = [[NSTimer scheduledTimerWithTimeInterval:1.0/30.0 target:self selector:@selector(redraw) userInfo:nil repeats:YES] retain];
    [[NSRunLoop currentRunLoop] addTimer:updateTimer forMode:NSRunLoopCommonModes];
    }

    return self;
}

- (void)prepareOpenGL
{
    [[self openGLContext] makeCurrentContext];
}

- (void)drawRect:(NSRect)rect
{
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0, 1.0, 1.0, 10.0);
    glEnable(GL_DEPTH_TEST);

    glClearColor(1, 1, 1, 1);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    GLdouble eyeX = 2.0;
    GLdouble eyeY = 2.0;
    GLdouble eyeZ = 2.0;

    GLdouble targetX = 0.0;
    GLdouble targetY = 0.0;
    GLdouble targetZ = 0.0;

    GLdouble verticalVectorX = 0.0;
    GLdouble verticalVectorY = 0.0;
    GLdouble verticalVectorZ = 1.0;

    gluLookAt(eyeX, eyeY, eyeZ, targetX, targetY, targetZ, verticalVectorX, verticalVectorY, verticalVectorZ);

    cubeRotationAngle = cubeRotationAngle + 0.5;
    glRotatef(cubeRotationAngle, 2.0, 0.5, 0.5);

    float size = 0.4;

    glBegin(GL_QUADS);
    {
        //Blue face
        glColor3f(0, 0, 1);
        glVertex3f(-1*size,  1*size, -1*size);
        glVertex3f( 1*size,  1*size, -1*size);
        glVertex3f( 1*size, -1*size, -1*size);
        glVertex3f(-1*size, -1*size, -1*size);

        //Red face
        glColor3f(1, 0, 0);
        glVertex3f(-1*size, -1*size, -1*size);
        glVertex3f( 1*size, -1*size, -1*size);
        glVertex3f( 1*size, -1*size,  1*size);
        glVertex3f(-1*size, -1*size,  1*size);

        //Green face
        glColor3f(0, 1, 0);
        glVertex3f(-1*size,  1*size,  1*size);
        glVertex3f( 1*size,  1*size,  1*size);
        glVertex3f( 1*size, -1*size,  1*size);
        glVertex3f(-1*size, -1*size,  1*size);

        //Yellow face
        glColor3f(1, 1, 0);
        glVertex3f(-1*size,  1*size,  1*size);
        glVertex3f(-1*size,  1*size, -1*size);
        glVertex3f(-1*size, -1*size, -1*size);
        glVertex3f(-1*size, -1*size,  1*size);

        //Pink face 
        glColor3f(1, 0, 1);
        glVertex3f(-1*size,  1*size,  1*size);
        glVertex3f( 1*size,  1*size,  1*size);
        glVertex3f( 1*size,  1*size, -1*size);
        glVertex3f(-1*size,  1*size, -1*size);

        //light blue face
        glColor3f(0, 1, 1);
        glVertex3f( 1*size,  1*size, -1*size);
        glVertex3f( 1*size,  1*size,  1*size);
        glVertex3f( 1*size, -1*size,  1*size);
        glVertex3f( 1*size, -1*size, -1*size);
    }
    glEnd();
    glPopMatrix();

    glFlush();
}

- (void)redraw
{
    [self setNeedsDisplay:YES];
}

Then you have to instantiate the OpenGLView like this :

NSOpenGLPixelFormatAttribute attrs[] = {NSOpenGLPFADepthSize, 32, 0};

NSOpenGLPixelFormat *format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attrs];

openGLView = [[OpenGLView alloc] initWithFrame:NSMakeRect(20, 20, 760, 560) pixelFormat:format];

Solution

  • Your gluPerspective call is invalid, and as a result, will just generate an error and leave the current matrix untouched. Both the near and far parameters must be positive, and they also must not be equal to each other (so your commented values are as invalid).

    Those values define the signed distance of the near and far clipping planes from the projection center, so negative values would refer to the spece behind of the camera, which would not make the slightest sense (and would also run in a couple of clipping-related issues for primitives which intersect the camera plane).