views:

61

answers:

3

I want to display something in an NSOpenGLView, but since there is a total of zero bytes of documentation on it, and the sample code is as big and complex as the documentation should be, I can't get any wise out of it. This is my code so far, and my ANOpenGLView is an NSOpenGLView in a NIB subclassed as ANOpenGLView:

@implementation ANOpenGLView
@synthesize animationTimer;

// MEM
- (void)dealloc {
  [animationTimer release];

  [super dealloc];
}

// INIT
- (id)initWithFrame:(NSRect)frameRect {
  if (self = [super initWithFrame:frameRect]) {
    NSOpenGLPixelFormatAttribute pixelFormatAttributes[] = {
      NSOpenGLPFADoubleBuffer,
      NSOpenGLPFADepthSize, 32,
      0
    };
    NSOpenGLPixelFormat *format = [[NSOpenGLPixelFormat alloc] initWithAttributes:pixelFormatAttributes];

    [self setOpenGLContext:[[[NSOpenGLContext alloc] initWithFormat:format shareContext:nil] autorelease]];
  }

  return self;
}

- (void)awakeFromNib {

  /* 60 FPS */
  animationTimer = [[NSTimer timerWithTimeInterval:(1.0f/60.0f) target:self selector:@selector(redraw:) userInfo:nil repeats:YES] retain];
  [[NSRunLoop currentRunLoop] addTimer:animationTimer forMode:NSDefaultRunLoopMode];
}

// DRAW
- (void)redraw:(NSTimer*)theTimer {
  [self drawRect:[self bounds]];
}

- (void)drawRect:(NSRect)dirtyRect {
  NSLog(@"Redraw");

  [[self openGLContext] clearDrawable];
  [[self openGLContext] setView:self];
  [[self openGLContext] makeCurrentContext];
  glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
  glDisable(GL_DEPTH_TEST);
  glClear(GL_COLOR_BUFFER_BIT);
  glLoadIdentity();

  glViewport(0, 0, [self frame].size.width, [self frame].size.height);  
  glMatrixMode(GL_PROJECTION); glLoadIdentity();
  glMatrixMode(GL_MODELVIEW); glLoadIdentity();

  glTranslatef(-1.5f, 0.0f, -6.0f);
  glBegin( GL_TRIANGLES );
  glColor3f(1.0f, 0.0f, 0.0f);
  glVertex2f(0.0f, 1.0f);
  glColor3f(0.0f, 1.0f, 0.0f);
  glVertex2f(-1.0f, -1.0f);
  glColor3f(0.0f, 0.0f, 1.0f);
  glVertex2f(1.0f, -1.0f);
  glEnd();

  [[self openGLContext] flushBuffer];
  [NSOpenGLContext clearCurrentContext];
}

@end

How can I get the triangle to show up? The only thing I get is a blank, white screen.


P.S. I want to draw in 2D.


EDIT I have updated my code, and this is what I have now: screenshot

+1  A: 

I'm not sure that it's the only problem, but:

  1. You haven't defined the pixel format
  2. You haven't set up the matrices in the code
  3. You haven't set up the viewport

Here http://www.cocoadev.com/index.pl?NSOpenGLView is a short example, it's almost what you need, but there is perspective matrix set up while you need orthogonal to render in 2D space (function glOrtho). World & View can be identity in this case.

Since 2D is your target, you won't deal with this matrices too much, just set them once.

Gobra
I'm a little farther atm: everything on my screen is screwed up and the menubar is cut in pieces spread over the screen. But hey! It's better than white! =D
Time Machine
You have set PROJECTION matrix to identity, but it must be glOrtho(0, width, height, 0, 0, 1). I have googled an article about 2D in OpenGL, take a look: http://basic4gl.wikispaces.com/2D+Drawing+in+OpenGL
Gobra
A: 

Edit: @Peter is right, Still a great resource, just not applicable to this question.

Jeff Lamarche's openGL posts are a great introduction and they include a project template that handles most of the setup for you.

http://iphonedevelopment.blogspot.com/2009/05/opengl-es-from-ground-up-table-of.html

kubi
That's about OpenGL ES. It has nothing to do with NSOpenGLView and I question how applicable it is to OpenGL non-ES.
Peter Hosey
A: 

For one thing, you've requested a double buffered context but you never swap them, so you're probably always drawing into the unseen back buffer. Add a call to glSwapAPPLE() after you flush.

I'm also a bit unsure about all your direct [self openGLContext] calls. Normally NSOpenGLView ought to handle this stuff for you, but in this case you're bypassing the set up of the view by calling drawRect directly from your timer, so things might be a bit messed up.

Have you tried just calling [self setNeedsDisplay:YES] from your timer method and letting the normal view setup occur? I would expect the redrawing still to be fast enough that way and it would make life easier...

walkytalky