OpenGL provides a powerful but primitive set of rendering commands, and all higher-level drawing must be done in terms of these commands. Therefore, you might want to write your own library on top of OpenGL to simplify your programming tasks. Also, you might want to write some routines that allow an OpenGL program to work easily with your windowing system. In fact, several such libraries and routines have already been written to provide specialized features, as follows. Note that the first two libraries are provided with every OpenGL implementation, the third was written for this book and is available using ftp, and the fourth is a separate product that's based on OpenGL.
The OpenGL Utility Library (GLU) contains several routines that use lower-level OpenGL commands to perform such tasks as setting up matrices for specific viewing orientations and projections, performing polygon tessellation, and rendering surfaces. This library is provided as part of your OpenGL implementation. It's described in more detail in Appendix C
and in the OpenGL Reference Manual. The more useful GLU routines are described in the chapters in this guide, where they're relevant to the topic being discussed. GLU routines use the prefix glu.
The OpenGL Extension to the X Window System (GLX) provides a means of creating an OpenGL context and associating it with a drawable window on a machine that uses the X Window System. GLX is provided as an adjunct to OpenGL. It's described in more detail in both Appendix D
and the OpenGL Reference Manual. One of the GLX routines (for swapping framebuffers) is described in "Animation."
GLX routines use the prefix glX.
The OpenGL Programming Guide Auxiliary Library was written specifically for this book to make programming examples simpler and yet more complete. It's the subject of the next section, and it's described in more detail in Appendix E
. Auxiliary library routines use the prefix aux. "How to Obtain the Sample Code"
describes how to obtain the source code for the auxiliary library.
Open Inventor is an object-oriented toolkit based on OpenGL that provides objects and methods for creating interactive three-dimensional graphics applications. Available from Silicon Graphics and written in C++, Open Inventor provides pre-built objects and a built-in event model for user interaction, high-level application components for creating and editing three-dimensional scenes, and the ability to print objects and exchange data in other graphics formats.
As you know, OpenGL contains rendering commands but is designed to be independent of any window system or operating system. Consequently, it contains no commands for opening windows or reading events from the keyboard or mouse. Unfortunately, it's impossible to write a complete graphics program without at least opening a window, and most interesting programs require a bit of user input or other services from the operating system or window system. In many cases, complete programs make the most interesting examples, so this book uses a small auxiliary library to simplify opening windows, detecting input, and so on.
In addition, since OpenGL's drawing commands are limited to those that generate simple geometric primitives (points, lines, and polygons), the auxiliary library includes several routines that create more complicated three-dimensional objects such as a sphere, a torus, and a teapot. This way, snapshots of program output can be interesting to look at. If you have an implementation of OpenGL and this auxiliary library on your system, the examples in this book should run without change when linked with them.
The auxiliary library is intentionally simple, and it would be difficult to build a large application on top of it. It's intended solely to support the examples in this book, but you may find it a useful starting point to begin building real applications. The rest of this section briefly describes the auxiliary library routines so that you can follow the programming examples in the rest of this book. Turn to Appendix E for more details about these routines.
Three routines perform tasks necessary to initialize and open a window:
auxInitWindow() opens a window on the screen. It enables the Escape key to be used to exit the program, and it sets the background color for the window to black.
auxInitPosition() tells auxInitWindow() where to position a window on the screen.
auxInitDisplayMode() tells auxInitWindow() whether to create an RGBA or color-index window. You can also specify a single- or double-buffered window. (If you're working in color-index mode, you'll want to load certain colors into the color map; use auxSetOneColor() to do this.) Finally, you can use this routine to indicate that you want the window to have an associated depth, stencil, and/or accumulation buffer.
You can use these routines to register callback commands that are invoked when specified events occur.
auxReshapeFunc() indicates what action should be taken when the window is resized, moved, or exposed.
auxKeyFunc() and auxMouseFunc() allow you to link a keyboard key or a mouse button with a routine that's invoked when the key or mouse button is pressed or released.
The auxiliary library includes several routines for drawing these three-dimensional objects:
sphere octahedron
cube dodecahedron
torus icosahedron
cylinder teapot
cone
You can draw these objects as wireframes or as solid shaded objects with surface normals defined. For example, the routines for a sphere and a torus are as follows:
void auxWireSphere(GLdouble radius);
void auxSolidSphere(GLdouble radius);
void auxWireTorus(GLdouble innerRadius, GLdouble outerRadius);
void auxSolidTorus(GLdouble innerRadius, GLdouble outerRadius);
All these models are drawn centered at the origin. When drawn with unit scale factors, these models fit into a box with all coordinates from -1 to 1. Use the arguments for these routines to scale the objects.
You can specify a function that's to be executed if no other events are pending - for example, when the event loop would otherwise be idle - with auxIdleFunc(). This routine takes a pointer to the function as its only argument. Pass in zero to disable the execution of the function.
Within your main() routine, call auxMainLoop() and pass it the name of the routine that redraws the objects in your scene. Example 1-2 shows how you might use the auxiliary library to create the simple program shown in Example 1-1 .
Example 1-2 : A Simple OpenGL Program Using the Auxiliary Library: simple.c
#include <GL/gl.h>
#include "aux.h"
int main(int argc, char** argv)
{
auxInitDisplayMode (AUX_SINGLE | AUX_RGBA);
auxInitPosition (0, 0, 500, 500);
auxInitWindow (argv[0]);
glClearColor (0.0, 0.0, 0.0, 0.0);
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 1.0, 1.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
glBegin(GL_POLYGON);
glVertex2f(-0.5, -0.5);
glVertex2f(-0.5, 0.5);
glVertex2f(0.5, 0.5);
glVertex2f(0.5, -0.5);
glEnd();
glFlush();
sleep(10);
}
OpenGL Programming Guide