Выбрать главу

 glutKeyboardFunc(keyboard); /* set keyboard handler */

 glutMainLoop();

 return 0;

}

void init(void) {

 glClearColor(0.0, 0.0, 0.0, 0.0);

 glMatrixMode(GL_PROJECTION);

 glLoadIdentity();

 glOrtho(-15.0, 15.0, –15.0, 15.0, –15.0, 15.0);

}

void display(void) {

 glClear(GL_COLOR_BUFFER_BIT);

 glBegin(GL_QUADS);

 glColor3f(0.0, 0.0, 1.0); /* center square */

 glVertex3f(-3.0, –3.0, 0.0);

 glVertex3f(3.0, –3.0, 0.0);

 glVertex3f(3.0, 3.0, 0.0);

 glVertex3f(-3.0, 3.0, 0.0);

 glEnd();

 glBegin(GL_TRIANGLES);

 glColor3f(1.0, 0.0, 0.0); /* now draw the four triangles */

 glVertex3f(0.0, 6.5, 0.0);

 glColor3f(0.0, 0.0, 0.9f);

 glVertex3f(-3.0, 3.0, 0.0);

 glVertex3f(3.0, 3.0, 0.0);

 glColor3f(0.0, 0.0, 0.9f);

 glVertex3f(-3.0, –3.0, 0.0);

 glVertex3f(-3.0, 3.0, 0.0);

 glColor3f(1.0, 0.0, 0.0);

 glVertex3f(-6.5, 0.0, 0.0);

 glColor3f(1.0, 0.0, 0.0);

 glVertex3f(0.0, –6.5, 0.0);

 glColor3f(0.0, 0.0, 0.9f);

 glVertex3f(3.0, –3.0, 0.0);

 glVertex3f(-3.0, –3.0, 0.0);

 glColor3f(1.0, 0.0, 0.0);

 glVertex3f(6.5, 0.0, 0.0);

 glColor3f(0.0, 0.0, 0.9f);

 glVertex3f(3.0, 3.0, 0.0);

 glVertex3f(3.0, –3.0, 0.0);

 glEnd();

 glutSwapBuffers();

}

void keyboard(unsigned char key, int x, int y) {

 /* this is the keyboard event handler the x and y parameters are the mouse coordintes when the key was struck */

 switch (key) {

 case 'u':

 case 'U':

  glRotatef(3.0, 1.0, 0.0, 0.0); /* rotate up */

  break;

 case 'd':

 case 'D':

  glRotatef(-3.0, 1.0, 0.0, 0.0); /* rotate down */

  break;

 case 'l':

 case 'L':

  glRotatef(3.0, 0.0, 1.0, 0.0); /* rotate left */

  break;

 case 'r':

 case 'R':

  glRotatef(-3.0, 0.0, 1.0, 0.0); /* rotate right */

 }

 display(); /* repaint the window */

}

/**********************************************************************/

Note that I use the glRotate function to rotate the view when the u, d, l, or r keys are pressed; don't worry, we haven't gone over this yet. I'll cover it in the next section, for now I put it in to illustrate the 3D nature of our shape. You may want to play around with this demo before continuing on to the next section. What else can you draw? What happens to the shading in the demo if you call glShadeModel(GL_FLAT)? Once you feel comfortable working with 3D space, we can move on to the next section…

III. Perspective, Animation, and Depth Testing

OK, enough teasing! Now that you know how to draw polygons in OpenGL, you can do anything! Lets move on to some more advanced tricks to make really impressive graphical applications.

First off, a while back I promised you perspective…well, here it is. In case you're wondering, perspective means that objects recede, or get smaller with distance. In OpenGL the only thing required to use perspective is to set up the clipping volume for that operation. This can sometimes be tricky, since instead of a cube, a perspective clipping volume is actually sort of a truncated pyramid, called a frustum. The typical OGL function to do this is glFrustum, shown here:

void glFrustum(double left, double right, double bottom, double top, double near, double far);

In this case, near and far are the distances to the front and back clipping planes. This function may look simple at first, but it gets tricky once you start dealing with windows that can be resized, etc. A far better solution is gluPerspective:

void gluPerspective(double fovy, double aspect, double near, double far);

The last two arguments remain the same as above, but what are aspect and fovy? FOVY is the Field Of View, and it specifies the angle which represents how much the viewer can see…somewhat like changing to a wide-angle lens in photography. Aspect is the aspect ratio of width/height in the window. Now I know what you're thinking: "Are you nuts? Fovy? Aspect? I'm supposed to understand this?" But don't worry; you'll see in the example program in this section why gluPerspective sets up a viewing volume so easily. Also note that the function's name begins with glu, not gl. This is an indicator that gluPerspective is not a part of the regular OpenGL library, but rather an extension which remains a part of the GL standard. Just remember that when using any function beginning with glu, you must #include <gl\glu.h>, and link with the appropriate library.

Well, if you followed that, you now have a nice perspective view to draw into. Now lets make the renderings themselves more interesting by adding motion. If you've ever seen any kind of documentary on cartoons and so forth, you're familiar with the concept of animation. You just take many slightly different static drawings and switch them very fast in front of the viewer to produce a motion effect. This is the easy part; we're already drawing several frames a second into our window. The hard part is moving our pictures so they make sense in relation to each other. In practice this involves a little math. For example, if you have an object at point x, you can move said object over 4 units if you add 4 to all the x coordinates of the vertices that make up the object (whew!). Likewise, if you know how to rotate each individual vertex around a circle (using the cosine and sine to determine the x and y coordinites), you can rotate the entire object in this manner. The problem with these types of operations is they're slow…it's easier to compute all the coordinate positions at once using a matrix. Matrices are kind of like tables that can encapsulate these types of operations. I'm not going to go into detail about it here, since OpenGL contains built in support for handling matrices. The problem is they don't always do what you want; a transformation matrix, when applied, will transform the *entire* scene, not just the object you wanted to move! There are some neat tricks you can use involving the matrix stack to put any combination of transforms into a matrix, but space will not permit me to discuss that here :(. In the meantime we can use matrices to move our objects at times when we want the entire scene to move as a unit.

Here are the functions in OpenGL which deal with matrices:

void glLoadIdentity(void);

You've seen this one before…this function loads the "identity" matrix into the current matrix. This has the effect of resetting everything back to its original position, i.e. an object drawn centered at (0,0,0) will appear in the center of the screen.

void glTranslatef(float x, float y, float z);

This function translates (moves) the entire scene forward, left and up the specified amounts. Use negative values to translate in the other direction.