Wrapping Up Chapter 2

To wrap up SuperBible’s chapter 2, here’s what I figured out about the last two programs, GLRect and Bouncing Square.

GLRect

This program draws a rectangle on the screen, and is based on the book’s GLRect on pages 53–55. I got it working with minor issues. I tried using the default initWithFrame method provided by the template NSView file, and discovered that it never ran. That’s why Gliss used initWithCoder: it’s the one that actually gets called.

The other topic of interest is that this program uses glOrtho to set up an orthographic projection instead of a perspective projection as was used in Gliss.

Bouncing Square

The third program in chapter 2 is an animation. The book’s version uses GLUT to set up the timing, but my version uses an NSTimer, as is standard in Cocoa programs.

I based this program on an old OpenGL program I had on my hard drive, Green Triangle. It displays a green triangle on a black screen, which fades in and out slowly. You can place one vertex of the triangle by clicking or drag-clicking in the window. Fun! I don’t remember where I got it (or how much modification I did to it), so if anyone recognizes it, let me know.

In Green Triangle, the timer gets set up in initWithFrame (this gets called, but initWithCoder doesn’t!), and it calls pulseColor at 20 Hz. pulseColor calculates the new color intensity and then sets the needsDisplay flag. Green Triangle also uses mouseDown and mouseDragged, but Bouncing Square won’t interact with the user that way.

I discovered one Mac-specific change to the book’s program: instead of using glutSwapBuffers(), I had to use glSwapAPPLE().

The last part of the chapter talks about checking for OpenGL errors, so I wrote a method to test gglGetError() in a loop until it turned out GL_NO_ERROR. It’s in Bouncing Square’s BouncingSquareView.m. Here’s the method:

- (void)logGLError {
  GLenum errorFlag = glGetError();
  if (errorFlag == GL_NO_ERROR) {
    NSLog(@"No OpenGL errors found");
    return;
  }
  do {
    NSLog(@"OpenGL Error: %s", gluErrorString(errorFlag));
    errorFlag = glGetError();
  } while (errorFlag != GL_NO_ERROR);
}

Since none of my programs (so far) generate OpenGL errors, this hasn’t been properly tested. I did write a second method that tested how to log OpenGL errors:

- (void)testGLErrorLogging {
  NSLog(@"starting %s", __PRETTY_FUNCTION__);
  NSLog(@"%s", gluErrorString(GL_INVALID_ENUM));
  NSLog(@"%s", gluErrorString(GL_INVALID_VALUE));
  NSLog(@"%s", gluErrorString(GL_INVALID_OPERATION));
  NSLog(@"%s", gluErrorString(GL_STACK_OVERFLOW));
  NSLog(@"%s", gluErrorString(GL_STACK_UNDERFLOW));
  NSLog(@"%s", gluErrorString(GL_OUT_OF_MEMORY));
  NSLog(@"%s", gluErrorString(GL_TABLE_TOO_LARGE));
  NSLog(@"ending %s", __PRETTY_FUNCTION__);
}

This does run, and prints the appropriate error messages to the log, so I have some confidence that logGLError will work as advertised.

So the burning question I’m left with is about initializing NSOpenGLViews: what determines which initializer gets run, initWithCoder: or initWithFrame? I may try looking in IB to see what in the nib might be determining this. Anybody out there know the answer?

Advertisements
This entry was posted in OpenGL. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s