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 :
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];
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).