Next | Prev | Up | Top | Contents | Index

Polygon Offset Example Program

This section illustrates how to use the polygon offset extension by providing code fragments from an example program hiddenline.c that displays three images:

Figure 8-1 shows the output that the program generates. You are encouraged to run the program yourself to see the difference more clearly than the printed version can show.

Example 8-1 : Polygon Offset Example Program

/**********************************************************************
 * Uses PolygonOffset to draw hidden-line images. PolygonOffset 
 * shifts z values of polygons by an amount proportional to their slope
 * in screen z. This keeps the lines, which are drawn without 
 * displacement, from interacting with their respective polygons, and 
 * and thus eliminates line dropouts.
 */

#include <GL/glx.h>
#include <GL/glu.h>
#include <X11/keysym.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define MAXQUAD 6

typedef float Vertex[3];

typedef Vertex Quad[4];

Quad quads[MAXQUAD] = {    /*data to define six faces of a unit cube */
    0,0,0, 1,0,0, 1,1,0, 0,1,0,
    0,0,1, 1,0,1, 1,1,1, 0,1,1,
    0,0,0, 1,0,0, 1,0,1, 0,0,1,
    0,1,0, 1,1,0, 1,1,1, 0,1,1,
    0,0,0, 0,0,1, 0,1,1, 0,1,0,
    1,0,0, 1,0,1, 1,1,1, 1,1,0
};
#define WIREFRAME       0
#define HIDDEN_LINE     1

/*** function prototypes go here  ***/
static int dimension = 3;

main(int argc, char** argv) {
    Display *dpy;
    XVisualInfo *vi;
    XSetWindowAttributes swa;
    Window win;
    GLXContext cx;

    /*** X Window System setup goes here ***/

    /* check for the polygon offset extension */
    if (!query_extension("GL_EXT_polygon_offset"))
        error(argv[0], "polygon_offset extension is not available");

    /* set up viewing parameters */
    glMatrixMode(GL_PROJECTION);
    gluPerspective(20, 1, 0.1, 20);
    glMatrixMode(GL_MODELVIEW);
    glTranslatef(0, 0, -15);

    /* set other relevant state information */
    glEnable(GL_DEPTH_TEST);
    glPolygonOffsetEXT(1.5, 0.000001);

    /* process events until the user presses ESC */
    while (1) process_input(dpy, win);
}

static void
draw_scene(int mx, int my) {
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glPushMatrix();
    glTranslatef(-1.7, 0.0, 0.0);
    cubes(mx, my, WIREFRAME);
    glPopMatrix();

    glPushMatrix();
    cubes(mx, my, HIDDEN_LINE);
    glPopMatrix();

    glPushMatrix();
    glTranslatef(1.7, 0.0, 0.0);
    glEnable(GL_POLYGON_OFFSET_EXT);
    cubes(mx, my, HIDDEN_LINE);
    glDisable(GL_POLYGON_OFFSET_EXT);
    glPopMatrix();
}

static void
cubes(int mx, int my, int mode) {
    int x, y, z, i;

    /* track the mouse */
    glRotatef(mx / 2.0, 0, 1, 0);
    glRotatef(my / 2.0, 1, 0, 0);

    /* draw the lines as hidden polygons */
    glTranslatef(-0.5, -0.5, -0.5);
    glScalef(1.0/dimension, 1.0/dimension, 1.0/dimension);
    for (z = 0; z < dimension; z++) {
        for (y = 0; y < dimension; y++) {
            for (x = 0; x < dimension; x++) {
                glPushMatrix();
                glTranslatef(x, y, z);
                glScalef(0.8, 0.8, 0.8);
                for (i = 0; i < MAXQUAD; i++)
                    draw_hidden(quads[i], mode);
                glPopMatrix();
            }
        }
    }
}

static void
fill(Quad quad) {
    glBegin(GL_QUADS);
    glVertex3fv(quad[0]);
    glVertex3fv(quad[1]);
    glVertex3fv(quad[2]);
    glVertex3fv(quad[3]);
    glEnd();
}


static void
outline(Quad quad) {
    /* draw an outlined polygon */
    glBegin(GL_LINE_LOOP);
    glVertex3fv(quad[0]);
    glVertex3fv(quad[1]);
    glVertex3fv(quad[2]);
    glVertex3fv(quad[3]);
    glEnd();
}

static void
draw_hidden(Quad quad, int mode) {
    /* draw outline using white, optionally fill interior with black */
    glColor3f(1, 1, 1);
    outline(quad);

    if (mode == HIDDEN_LINE) {
        glColor3f(0, 0, 0);
        fill(quad);
    }
}

static void
process_input(Display *dpy, Window win) {
    XEvent event;
    static int prevx, prevy;
    static int deltax = 90, deltay = 40;

    do {
        char buf[31];
        KeySym keysym;

        XNextEvent(dpy, &event);
        switch(event.type) {
        case Expose:
            break;
        case ConfigureNotify:
            glViewport(0, 0, e+vent.xconfigurewidth, 
                      event.xconfigureheigth);
            break;
        case ButtonPress:
            prevx = event.xbutton.x;
            prevy = event.xbutton.y;
            break;
        case MotionNotify:
            deltax += (event.xbutton.x - prevx); prevx = 
                       event.xbutton.x;
            deltay += (event.xbutton.y - prevy); prevy = 
                       event.xbutton.y;
            break;
        default:
            break;
        }
    } while (XPending(dpy));

    draw_scene(deltax, deltay);
    glXSwapBuffers(dpy, win);
}

Figure 8-1 : Polygon Offset Extension Example


Next | Prev | Up | Top | Contents | Index