Creating a New OpenGL Project

I’ve typically proceeded by creating a new project and its files from scratch, copying only a few larger and more tedious chunks (list of vertices, code I’ve already typed into a previous project, and the like). Along the way I’ve made some modifications to my typical project, and I think it’s now ready for public debut.

For my OpenGL studies, I always start with the basic Mac OS X app template, so leave the boxes for “Create document-based application” and “Use Core Data for storage” unchecked. Next, I add the OpenGL and GLUT frameworks. To do this, right-click the Linked Frameworks group, select Add→ and then Existing Frameworks… to bring up the dialog box listing the available frameworks.

Next up is creating a subclass of NSOpenGLView. Create a new file, select the NSView template, and click Next. That brings up the dialog box to let you choose the name and location for the new file. I usually pick a name like BitmapView. Be sure that the box for “Also create BitmapView.h” is checked, and click Finished or hit return to create the files. This should bring up the .h file to edit.

Now change the superclass from NSView to NSOpenGLView and add any instance variables that the class will need. These might include things like xRotation and yRotation to control the orientation of the viewpoint or an NSTimer for controlling animation. Also add any IBActions, so you’ll be ready to work in Interface Builder, which is your next stop.

Under the resources group, double-click the MainMenu.xib to start IB (Interface Builder). Select the you app’s window, click cmd-1 to bring up the attributes inspector, and uncheck One Shot (You’ll get a warning when you try to save if you forget this).

Now drag an OpenGL View onto the window, move it into place and adjust its size. Set its resizing behavior if you want to. Type cmd-6 to change the inspector view and set the view’s class to your new subclass. Now it’s time to set up the attributes for the view.

Type cmd-1 to bring up the attributes pane of the inspector. This is where you will determine the capabilities of your OpenGL view, largely by choosing the types and bit-depths of the view’s buffers.

  • Color: the default buffer will be fine. The float buffers don’t work, at least on my machine.
  • Depth: defaults to none, but you need to include one to do depth testing.
    The minimum of 16 bits has given adequate performance for everything I’ve done so far.
  • Stencil: Either off (the default) or 8 bits. Useful for drawing shadows and other effects.
  • Accum: Accumulation buffers are used to accumulate composite images. Chapter 6 uses the accumulation buffer to create a motion blur for a “moving” sphere.
  • Aux. Buffers: for anything else you might think of.

I’ve also started to split apart the various initializations and setup code, so it’s not all one big blur. For programs that do animation, I have a setupTimer method, and for all programs I have a setupGL method. These are called from a commonInit method that I call from both initWithFrame and initWithCoder, because I haven’t figured out which one of the init methods will get called.

– (void)setupTimer

As noted in the comments, you need to set the selector to the name of the method that updates your scene, and then set the class name that sets the signature.

- (void)setupTimer {
    SEL theSelector = @selector(moveObjects); 
    // replace "moveObjects" with the method you want the timer to call
    NSMethodSignature *aSignature;
    NSInvocation *anInvocation;

    NSLog(@"theSelector loaded");
    aSignature = [WorldView instanceMethodSignatureForSelector: theSelector]; 
    // replace "WorldView" with the appropriate class name
    anInvocation = [NSInvocation invocationWithMethodSignature:aSignature];
    [anInvocation setSelector:theSelector];
    [anInvocation setTarget: self];
    NSLog(@"aSignature created");

    // The time interval is in seconds, so 0.025 is 40 Hz
    timer = [NSTimer scheduledTimerWithTimeInterval: 0.025
                                         invocation: anInvocation
                                            repeats: YES];
    [timer retain];
}

– (void)setupGL

This routine is for setting up things like the background color, drawing settings (the example shows typical settings), lighting, fog parameters, etc.

- (void)setupGL {
    // Green background
    glClearColor(0.0f, 1.0f, 0.0f, 1.0f);

    // Object drawing settings
    glCullFace(GL_BACK);
    glEnable(GL_DEPTH_TEST);
    glFrontFace(GL_CCW);
    glEnable(GL_CULL_FACE);

    // Set up light parameters...
    // Set up fog parameters...
}

– (void)commonInit

If you don’t set the swap interval as shown at the start of this routine, your program will fall immediately into the debugger. From what I’ve been able to figure out, the swap interval controls how many vertical retraces of the screen should occur before a buffer swap takes place. A value of 1 works, but the default of zero doesn’t. You could use two, which would limit drawing to half of your monitor’s refresh rate, but I don’t see the point of that. I set it here because it seems more system-related than a part of you OpenGL setup process. The rest of the method simply calls the other setup methods.

- (void)commonInit {
    GLint swapInterval = 1;
    [[self openGLContext] setValues: &swapInterval
                       forParameter: NSOpenGLCPSwapInterval];

    [self setupTimer];
    [self setupGL];
}

– (void)logGLErrorQuietly

This isn’t part of initialization or set up, but I always add this error logging routine so I can conveniently check for OpenGL errors. Set the Boolean input to YES if you don’t want to see any message if there are no errors. It’s usually the last method in the file.

- (void)logGLErrorQuietly:(BOOL)quietly {
	GLenum errorFlag = glGetError();
	if (errorFlag == GL_NO_ERROR) {
		if (!quietly) {
			NSLog(@"No OpenGL errors found");
		}
		return;
	}
	do {
		NSLog(@"OpenGL Error: %s", gluErrorString(errorFlag));
		errorFlag = glGetError();
	} while (errorFlag != GL_NO_ERROR);
}
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