home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************
- Copyright 1995 by Silicon Graphics Incorporated, Mountain View, California.
-
- All Rights Reserved
-
- Permission to use, copy, modify, and distribute this software and its
- documentation for any purpose and without fee is hereby granted,
- provided that the above copyright notice appear in all copies and that
- both that copyright notice and this permission notice appear in
- supporting documentation, and that the name of Silicon Graphics not be
- used in advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
-
- SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
- CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
- USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- PERFORMANCE OF THIS SOFTWARE.
-
- ****************************************************************************/
-
- /*
- * Roger Corron
- * May 1997
- *
- * Use a pbuffer to provide backing store. This requires the following
- * extensions:
- *
- * SGI_make_current_read
- * SGIX_fbconfig
- * SGIX_pbuffer
- *
- * This example draws cubes with hidden lines removed. An optional delay
- * of one clock clock tick per cube face make the difference between
- * normal drawing and pbuffer exposure handling more obvious.
- *
- * Depress the 'd' key to toggle drawing delay. It is initially on.
- * Depress the 'h' keyy to toggle hidden line removal. It is initially
- * off.
- * Depress the escape key to exit.
- */
-
- #include <GL/gl.h>
- #include <GL/glu.h>
- #include <GL/glx.h>
- #include <X11/keysym.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
-
- #define MAXQUAD 6
-
- typedef GLfloat Vertex[4];
- typedef Vertex Quad[4];
-
- /* data to define the six faces of a cube */
- static Quad quads[MAXQUAD] = {
- 0,0,0,1, 1,0,0,1, 1,1,0,1, 0,1,0,1,
- 0,0,1,1, 1,0,1,1, 1,1,1,1, 0,1,1,1,
- 0,0,0,1, 1,0,0,1, 1,0,1,1, 0,0,1,1,
- 0,1,0,1, 1,1,0,1, 1,1,1,1, 0,1,1,1,
- 0,0,0,1, 0,0,1,1, 0,1,1,1, 0,1,0,1,
- 1,0,0,1, 1,0,1,1, 1,1,1,1, 1,1,0,1
- };
-
- static void fill(Quad quad);
- static void outline(Quad quad);
- static void drawhidden(Quad quad);
- static void process_input(Display *dpy, Window win);
-
- static int dimension = 5;
- static GLboolean offset = GL_TRUE;
- static GLboolean hidden = GL_FALSE;
-
- static int attributeList[] = { GLX_RGBA,
- GLX_DEPTH_SIZE, 1,
- GLX_RED_SIZE, 1,
- GLX_GREEN_SIZE, 1,
- GLX_BLUE_SIZE, 1,
- None };
-
- static int pbuffer_fb_attributes[] =
- { GLX_DRAWABLE_TYPE_SGIX, GLX_PBUFFER_BIT_SGIX | GLX_WINDOW_BIT_SGIX,
- GLX_RENDER_TYPE_SGIX, GLX_RGBA_BIT_SGIX,
- GLX_DOUBLEBUFFER, False,
- GLX_RED_SIZE, 1,
- GLX_GREEN_SIZE, 1,
- GLX_BLUE_SIZE, 1,
- GLX_DEPTH_SIZE, 1,
- GLX_X_VISUAL_TYPE_EXT, GLX_TRUE_COLOR_EXT,
- None };
-
- static int pbuffer_attributes[] =
- {GLX_PRESERVED_CONTENTS_SGIX, True,
- None };
-
- static GLXContext cx, win_cx;
- static GLXPbufferSGIX pbuffer;
- static Display *dpy;
- static Window win;
- static int width = 500 , height = 500;
- static Bool delay = True;
-
- int main(int argc, char** argv) {
- XVisualInfo *vi;
- XSetWindowAttributes swa;
- int list_length;
- int visual_red_size, FBconfig_red_size;
- GLXFBConfigSGIX *configs, pbuffer_cfg;
- int i;
- Bool status;
-
- dpy = XOpenDisplay(0);
-
- if (!(vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeList))) {
- fprintf(stderr, "backingstore: no suitable RGB visual available\n");
- exit(EXIT_FAILURE);
- }
-
- win_cx = glXCreateContext(dpy, vi, 0, GL_TRUE);
-
- swa.colormap = XCreateColormap(dpy, RootWindow(dpy, vi->screen),
- vi->visual, AllocNone);
-
- swa.border_pixel = 0;
- swa.event_mask = ExposureMask | StructureNotifyMask | KeyPressMask |
- ButtonPressMask | ButtonReleaseMask | ButtonMotionMask ;
- win = XCreateWindow(dpy, RootWindow(dpy, vi->screen), 0, 0, width, height,
- 0, vi->depth, InputOutput, vi->visual,
- CWBorderPixel|CWColormap|CWEventMask, &swa);
- XStoreName(dpy, win, "Backing Store");
- XMapWindow(dpy, win);
-
- glXMakeCurrent(dpy, win, win_cx);
-
- /* check for required capabilities. We need pbuffers, fbconfig, and
- make_current_read for backing store, and polygon offset for hidden
- line removal.
- */
-
- if (!strstr(glGetString(GL_EXTENSIONS), "polygon_offset")) {
- fprintf(stderr,
- "backingstore: PolygonOffset extension not available. Abort\n");
- exit(EXIT_FAILURE);
- }
-
- if (!strstr(glXQueryExtensionsString(dpy,DefaultScreen(dpy)), "pbuffer")) {
- fprintf(stderr,
- "backingstore: Pbuffer extension not available. Abort\n");
- exit(EXIT_FAILURE);
- }
-
- if (!strstr(glXQueryExtensionsString(dpy,DefaultScreen(dpy)), "fbconfig")) {
- fprintf(stderr,
- "backingstore: FBconfig extension not available. Abort\n");
- exit(EXIT_FAILURE);
- }
-
- if (!strstr(glXQueryExtensionsString(dpy,DefaultScreen(dpy)), "make_current_read")) {
- fprintf(stderr,
- "backingstore: make_current_read extension not available. Abort\n");
- exit(EXIT_FAILURE);
- }
-
- /* In the window context:
-
- 1. Set the appropriate orthographic projection for easy specification
- of the raster position.
- 2. Turn off dithering so images will not be dithered twice.
- 3. Set the read buffer to GL_FRONT.
- 4. Set the draw buffer to GL_FRONT.
-
- */
-
- glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
- glDisable(GL_DITHER);
- glReadBuffer(GL_FRONT);
- glDrawBuffer(GL_FRONT);
-
- /* Set up the pbuffer */
-
- /* get the available frame buffer configurations */
-
- configs = glXChooseFBConfigSGIX(dpy,
- DefaultScreen(dpy),
- pbuffer_fb_attributes,
- &list_length);
- if (configs == NULL) {
- fprintf(stderr,
- "backingstore: There are no suitable frame buffer configurations. Abort.\n");
- exit(EXIT_FAILURE);
- }
-
- /* Now that we have a list of configs that meet minimum requirements,
- select one that matches the color depth of the window's visual.
- We check the red size only.
- */
-
- (void) glXGetConfig(dpy,
- vi,
- GLX_RED_SIZE,
- &visual_red_size);
-
- for ( i = 0 ; i < list_length; i++) {
- (void) glXGetFBConfigAttribSGIX(dpy,
- configs[i],
- GLX_RED_SIZE,
- &FBconfig_red_size);
-
- if (FBconfig_red_size == visual_red_size) {
- break;
- }
-
- }
- if (i < list_length) {
- pbuffer_cfg = configs[i];
- XFree(configs);
- }
- else {
- fprintf(stderr,
- "backingstore: could not find a FBconfig that matches the window visual. Abort.\n");
- exit(EXIT_FAILURE);
- }
-
- /* create the pbuffer */
- pbuffer = glXCreateGLXPbufferSGIX(dpy,
- pbuffer_cfg,
- width,
- height,
- pbuffer_attributes);
-
- if (pbuffer == None) {
- fprintf(stderr, "backingstore: couldn't create pbuffer. Abort.\n");
- exit(EXIT_FAILURE);
- }
-
- cx = glXCreateContextWithConfigSGIX(dpy,
- pbuffer_cfg,
- GLX_RGBA_TYPE_SGIX,
- NULL,
- GL_TRUE);
-
- if (cx == NULL) {
- fprintf(stderr,
- "backingstore: could not create an OpenGL context for the pbuffer\n");
- exit(EXIT_FAILURE);
- }
-
- /* In the pbuffer context: */
-
- status = glXMakeCurrent (dpy, pbuffer, cx);
-
- /* initialize graphics */
-
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluPerspective(90.0, 1.0, 0.5, 5.0);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- glTranslatef(0.0, 0.0, -1.5);
- glClearColor(0.0, 0.0, 0.0, 0.0);
-
- glEnable(GL_DEPTH_TEST);
- glHint(GL_LINE_SMOOTH_HINT, GL_FASTEST);
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
- /* Enable polygon offset by default */
-
- glPolygonOffsetEXT(1.0, 0.0);
- glEnable(GL_POLYGON_OFFSET_EXT);
-
- /* read arguments */
- if (argc > 1)
- dimension = atoi(argv[1]);
- printf("dimension = %d\n", dimension);
-
- /* loop drawing the cube */
-
- process_input(dpy, win);
- }
- static void flush()
- {
- glFlush();
- glXMakeCurrentReadSGI(dpy,
- win,
- pbuffer,
- win_cx);
-
- glRasterPos2i(-1, -1);
-
- glCopyPixels(0,
- 0,
- width,
- height,
- GL_COLOR);
-
- glXMakeCurrent(dpy, pbuffer, cx);
- }
- static void draw_scene(int mx, int my)
- {
- int x, y, z, i;
-
- glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
-
- glPushMatrix();
-
- /* track the mouse */
- glRotatef(0.5 * mx, 0.0, 1.0, 0.0);
- glRotatef(0.5 * my, 0.0, 0.0, 1.0);
- glTranslatef(-0.5,-0.5,-0.5);
- glScalef(1.0/dimension,1.0/dimension,1.0/dimension);
-
- /* draw the lines as hidden polygons */
- 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++)
- drawhidden(quads[i]);
- flush();
- glPopMatrix();
- }
- }
- }
-
- glPopMatrix();
- flush();
- }
-
- static void fill(Quad quad)
- {
- /* fill the polygon */
- glBegin(GL_QUADS);
- glVertex3fv(quad[0]);
- glVertex3fv(quad[1]);
- glVertex3fv(quad[2]);
- glVertex3fv(quad[3]);
- glEnd();
- }
-
- static void outline(Quad quad)
- {
- /* outline the polygon */
- glBegin(GL_LINE_LOOP);
- glVertex3fv(quad[0]);
- glVertex3fv(quad[1]);
- glVertex3fv(quad[2]);
- glVertex3fv(quad[3]);
- glEnd();
- }
-
- static void drawhidden(Quad quad)
- {
- static GLfloat black[4] = { 0.0, 0.0, 0.0, 1.0 };
- static GLfloat white[4] = { 1.0, 1.0, 1.0, 1.0 };
-
- if (delay)
- sginap(1);
- glColor4fv(white);
- outline(quad);
-
- if (hidden) {
- glColor4fv(black);
- fill(quad);
- }
- }
-
- static void process_input(Display *dpy, Window win)
- {
- XEvent event;
- int mx = 0, my = 0;
- GLboolean update;
- static int first_time = True;
-
- while (1) {
- char buf[31];
- KeySym keysym;
-
- update = False;
-
- XNextEvent(dpy, &event);
- switch(event.type) {
-
- case Expose:
- if (first_time) {
- update = True;
- first_time = False;
- }
- else {
- flush();
- }
- break;
-
- case ConfigureNotify:
- if (event.xconfigure.width == width &&
- event.xconfigure.height == height) break;
- glViewport(0, 0, event.xconfigure.width, event.xconfigure.height);
- update = True;
- break;
-
- case KeyPress:
- (void) XLookupString(&event.xkey, buf, sizeof(buf), &keysym, NULL);
- switch (keysym) {
- case XK_h:
- hidden = !hidden;
- update = GL_TRUE;
- break;
- case XK_d:
- delay = !delay;
- break;
- case XK_Escape:
- exit(EXIT_SUCCESS);
- default:
- break;
- }
- break;
-
- case ButtonRelease:
- mx = event.xbutton.x;
- my = event.xbutton.y;
- update = True;
- break;
-
- case MotionNotify:
- /* Grab all pending motion events! */
- while (XPending(dpy)) {
- XEvent peek;
- XPeekEvent(dpy, &peek);
- if (peek.type == MotionNotify &&
- peek.xany.window == event.xany.window)
- XNextEvent(dpy, &event);
- else
- break;
- }
- mx = event.xbutton.x;
- my = event.xbutton.y;
-
- update = True;
- break;
-
- default:
- break;
- }
-
- if (update) {
- draw_scene(mx, my);
- }
- }
- }
-