home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- /*
- * zrgbmenu.c:
- *
- * OpenGL-Xlib doublebuffered-RGB, depth-buffering, pop-up menu examp
- *
- * zrgbmenu is the openGL "after" version of the IrisGL
- * "before" program, ~4Dgifts/examples/grafix/zrgbmenu.c
- *
- * It further implements--either manually via LEFTMOUSE, or in an
- * "automatic" (i.e. animation) mode format--movement of the polygons
- * via compound rotations to allow for continuous screen-oriented
- * rotations (see orient(), spin(), and drawScene() below). Horizontal
- * mouse movement rotates the polygons about the y-axis where right is
- * positive and left is negative. Vertical mouse movement rotates the
- * polygons about the x-axis where down is positive and up is negative.
- *
- * ratman - 1989
- * 1994, ported to OpenGL
- */
- #include <GL/glx.h>
- #include <GL/glu.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <X11/Xlib.h>
- #include <X11/Xutil.h>
- #include <X11/keysym.h>
-
- #include "pup.h"
-
- #define TRUE 1
- #define FALSE 0
-
- /* Modes the program can be in */
- #define NOTHING 0
- #define ORIENT 1
- #define SPIN 2
-
- /* Values returned from popup menu */
- #define MANUAL 1
- #define AUTOMATIC 2
- #define EXIT 3
-
-
- Display *dpy; /* The X server connection */
- Atom del_atom; /* WM_DELETE_WINDOW atom */
- Window glwin; /* handle to the GL window */
- XEvent event;
-
- /* function declarations */
-
- static void openwindow(char *);
- static void resize_buffer(void);
- static void clean_exit(void);
- void initGL(void);
- void orient(void);
- void update_scene(void);
- void spin(void);
- void drawScene(void);
- void drawPolys(void);
-
- static float objmat[16] = {
- 1.0, 0.0, 0.0, 0.0,
- 0.0, 1.0, 0.0, 0.0,
- 0.0, 0.0, 1.0, 0.0,
- 0.0, 0.0, 0.0, 1.0,
- };
-
- int xsize, ysize; /* current size-of-window keepers */
- long buffermode; /* flag tracks current window (single or double) */
- int xpos, ypos, oxpos, oypos; /* old and new mouse position */
-
- int mode = 0;
- int menu;
- int omx, mx, omy, my; /* old and new mouse position */
- float scrnaspect; /* aspect ratio value */
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- int myExpose, myConfigure, myButtPress, myKeyPress;
- int needToDraw = 0; /* don't set this to true until
- we get our first Expose event */
- long menuval;
-
-
- myExpose = myConfigure = myButtPress = myKeyPress = FALSE;
-
- openwindow(argv[0]);
-
- initGL(); /* do GL init stuff */
-
- /*
- * The event loop.
- */
- while (1) { /* standard logic: get event(s), process event(s) */
-
-
- XEvent event;
- KeySym keysym;
- char buf[4];
-
- /* this "do while" loop does the `get events' half of the "get events,
- * process events" action of the infinite while. this is to ensure
- * the event queue is always drained before the events that have come
- * in are processed.
- */
- while (XPending(dpy)) {
-
- XNextEvent(dpy, &event);
- switch (event.type) {
-
- /* "Expose" events are sort of like "REDRAW" in gl-speak in
- * terms of when a window becomes visible, or a previously
- * invisible part becomes visible.
- */
- case Expose: /* Exposures */
- needToDraw = myExpose = TRUE;
- break;
-
- /* "ConfigNotify" events are like "REDRAW" in terms of changes
- * to a window's size or position.
- */
- case ConfigureNotify: /* Resize GL manually */
- xsize = event.xconfigure.width;
- ysize = event.xconfigure.height;
- needToDraw = myConfigure = TRUE;
- break;
-
- /* Wait for "MotionNotify" events so the queue doesn't fill up
- */
- case MotionNotify:
- myButtPress = TRUE;
- xpos = event.xmotion.x;
- ypos = event.xmotion.y;
- if (mode == ORIENT) {
- update_scene();
- needToDraw=TRUE;
- }
- mode = ORIENT;
- break;
-
- /* "ButtonPress" events hail from the ButtonPressMask feed to
- * XCreateWindow via XSetWindowAttributes' event_mask field
- */
- case ButtonPress:
- if (event.xbutton.button == Button3) { /* RIGHTMOUSE: */
- menuval = dopup(menu);
- switch(menuval) {
- case MANUAL:
- mode = NOTHING;
- break;
- case AUTOMATIC:
- mode = SPIN;
- needToDraw = TRUE;
- break;
- case EXIT:
- clean_exit();
- break;
- default:
- break;
- }
- }
-
- /* Wait for "ButtonRelease" events so the queue doesn't fill up
- * the way it wud if the user sits on ButtonPresss.
- */
- case ButtonRelease:
- if (event.xbutton.button == Button1) /* LEFTMOUSE: */
- mode = NOTHING; /* switch back to */
- break; /* "manual" mode */
-
- /* "ClientMessage" is generated if the WM itself is being
- * gunned down and sends an exit signal to any running prog.
- */
- case ClientMessage:
- if (event.xclient.data.l[0] == del_atom)
- clean_exit();
- break;
-
- /* "KeyPress" events are those that would be generated before
- * whenever queueing up any KEYBD key via qdevice.
- */
- case KeyPress:
- /* save out which unmodified key (i.e. the key was
- * not modified w/something like "Shift", "Ctrl",
- * or "Alt") got pressed for use below.
- */
- XLookupString((XKeyEvent *)&event, buf, 4, &keysym, 0);
- myKeyPress = TRUE;
- break;
-
- default:
- break;
-
- } /* end switch (event.type) */
-
-
- }
-
- /* On an "Expose" event, redraw the affected pop'd or de-iconized window
- */
- if (myExpose) {
- resize_buffer();
- myExpose = FALSE; /* reset flag--queue now empty */
- }
-
- /* On a "ConfigureNotify" event, the GL window has either been moved or
- * resized. Respond accordingly and then redraw its contents.
- */
- if (myConfigure) {
- oxpos = xpos;
- oypos = ypos;
- resize_buffer();
- myConfigure = FALSE; /* reset flag--queue now empty */
- }
-
- if (needToDraw) {
- if (mode == SPIN) {
- update_scene();
- drawScene();
- /*
- * Note: Don't reset needToDraw, so we keep on
- * spinning.
- */
- } else {
- drawScene();
- needToDraw = FALSE;
- }
- }
-
- /* On a keypress of Esc key, exit program.
- */
- if (myKeyPress) {
- if (keysym == XK_Escape)
- clean_exit();
- }
-
- if (myButtPress) {
- orient();
- drawScene();
- myButtPress = FALSE;
- /*
- mode = NOTHING;
- */
- }
- } /* end while(1) */
-
- } /* end main */
-
-
-
-
- static int attributeList[] = { GLX_RGBA,
- GLX_DOUBLEBUFFER,
- GLX_RED_SIZE, 1,
- GLX_GREEN_SIZE, 1,
- GLX_BLUE_SIZE, 1,
- GLX_DEPTH_SIZE, 1,
- None };
- static int attributeList2[] = { GLX_RGBA,
- GLX_RED_SIZE, 1,
- GLX_GREEN_SIZE, 1,
- GLX_BLUE_SIZE, 1,
- GLX_DEPTH_SIZE, 1,
- None };
-
- static Bool WaitForNotify(Display *d, XEvent *e, char *arg) {
- return (e->type == MapNotify) && (e->xmap.window == (Window)arg);
- }
-
- /* openwindow -
- * establish connection to X server, get screen info, specify the
- * attributes we want the WM to try to provide, and create the GL window
- */
- static void openwindow(char *progname) {
-
- XVisualInfo *vi;
- GLXContext cx;
- Colormap cmap;
- XSizeHints Winhints; /* used to fix window size */
- XSetWindowAttributes swa;
- int scrnnum; /* X screen number */
- int xorig, yorig; /* window (upper-left) origin */
- long scrnwidth, scrnheight;
-
-
-
-
- /* define window initial size */
- xorig = 50; yorig = 40;
- xsize = 300; ysize = 240;
-
- /* Connect to the X server and get screen info */
- if ((dpy = XOpenDisplay(NULL)) == NULL) {
- fprintf(stderr, "%s: cannot connect to X server %s\n",
- progname, XDisplayName(NULL));
- exit(1);
- }
-
- scrnnum = DefaultScreen(dpy);
- scrnwidth = DisplayWidth(dpy, scrnnum);
- scrnheight = DisplayHeight(dpy, scrnnum);
-
- /* Code to keep same aspec ratio as the screen */
- scrnaspect = ((float)scrnwidth)/((float)scrnheight);
-
- /* get an appropriate visual */
- vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeList);
- if (vi == NULL) {
- fprintf(stderr, "Unable to obtain Doublebuffered visual; ");
- fprintf(stderr, "now going for singlebuffer'd...\n");
- vi = glXChooseVisual(dpy, DefaultScreen(dpy), attributeList2);
- }
- if (vi == NULL) {
- printf("Unable to obtain Singlebuffered VISUAL(????)\n");
- exit(0);
- }
-
- /* create GLX context */
- cx = glXCreateContext(dpy, vi, None, GL_TRUE);
-
- /* create a colormap */
- cmap = XCreateColormap(dpy, RootWindow(dpy, vi->screen),
- vi->visual, AllocNone);
-
- /* create a window */
- swa.colormap = cmap;
- swa.border_pixel = 0;
- swa.event_mask = StructureNotifyMask | ButtonPressMask | ButtonReleaseMask
- | ExposureMask | Button1MotionMask | KeyPressMask;
- glwin = XCreateWindow(dpy, RootWindow(dpy, vi->screen),
- xorig, yorig, xsize, ysize,
- 0, vi->depth, InputOutput, vi->visual,
- CWBorderPixel|CWColormap|CWEventMask, &swa);
-
- XMapWindow(dpy, glwin);
- XIfEvent(dpy, &event, WaitForNotify, (char*)glwin);
-
- /* connect the context to the window */
- glXMakeCurrent(dpy, glwin, cx);
-
- if (!(glwin)) {
- fprintf(stderr,"%s: couldn't create \"parent\" X window\n",progname);
- exit(1);
- }
-
- /* define string that will show up in the window title bar (and icon) */
- XStoreName(dpy, glwin, "rgb depth/dbl -buffered pop-up menu prog");
-
-
- /* specify the values for the Window Size Hints we want to enforce: this
- * window's aspect ratio needs to stay at 1:1, constrain min and max
- * window size, and specify the initial size of the window.
- */
- Winhints.width = xsize; /* specify desired x/y size of window */
- Winhints.height = ysize;
- Winhints.min_width = xorig; /* define min and max */
- Winhints.max_width = scrnheight-1; /* width and height */
- Winhints.min_height = yorig;
- Winhints.max_height = scrnheight-1;
- Winhints.min_aspect.x = scrnwidth;/* keep aspect to a scrnX:scrnY ratio */
- Winhints.max_aspect.x = scrnwidth;
- Winhints.min_aspect.y = scrnheight;
- Winhints.max_aspect.y = scrnheight;
- Winhints.flags = USSize|PMaxSize|PMinSize|PAspect; /* set the */
- XSetNormalHints(dpy, glwin, &Winhints); /* corresponding flags */
-
- /* express interest in WM killing this app */
- if ((del_atom = XInternAtom(dpy, "WM_DELETE_WINDOW", True)) != None)
- XSetWMProtocols(dpy, glwin, &del_atom, 1);
-
- menu = defpup(dpy, scrnnum,
- "OGL RGB depth-bufr'd pup prog %t|Manual Mode|Automatic Mode|Exit");
- return ;
- }
-
-
-
- /* window has been moved or resized so update viewport & CTM stuff.
- */
- static void resize_buffer() {
- scrnaspect = xsize / (double) ysize;
- glViewport(0, 0, xsize-1, ysize-1);
- }
-
-
-
- /* clean up before exiting
- */
- static void clean_exit(void)
- {
- XCloseDisplay(dpy);
- exit(0);
- }
-
-
-
- /* setup all necessary GL initialzation parameters.
- */
- void initGL(void)
- {
- glEnable(GL_DEPTH_TEST);
- glClearColor(0.16, 0.39, 0.78, 0.0);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- glLoadIdentity();
- gluPerspective(400.0, scrnaspect, 30.0, 600.0);
- }
-
-
-
- void update_scene(void) {
-
- switch (mode) {
-
- case ORIENT:
- orient();
- break;
- case SPIN:
- spin();
- break;
- }
- }
-
-
- void orient(void)
- {
- float dx, dy;
-
- glPushMatrix();
- dx = 0.01 * (xpos-oxpos);
- dy = 0.01 * (oypos-ypos);
- glLoadIdentity();
- glRotatef(dx, 1.0, 0.0, 0.0);
- glRotatef(dy, 0.0, 1.0, 0.0);
- glMultMatrixf(objmat);
- glGetFloatv(GL_MODELVIEW_MATRIX, objmat);
-
- glPopMatrix();
- }
-
-
-
- void spin (void) {
-
- glPushMatrix();
-
- glLoadIdentity();
-
- glRotatef(2.5, 1.0, 0.0, 0.0);
- glRotatef(3.0, 0.0, 1.0, 0.0);
- glRotatef(2.0, 0.0, 0.0, 1.0);
-
- glMultMatrixf(objmat);
- glGetFloatv(GL_MODELVIEW_MATRIX, objmat);
-
- glPopMatrix();
-
- }
-
-
- void drawScene(void)
- {
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-
- glLoadIdentity();
- gluPerspective(400.0, scrnaspect, 30.0, 600.0);
- glTranslatef(0.0, 0.0, -40.0);
- glMultMatrixf(objmat);
- glRotatef(-400.0, 0.0, 1.0, 0.0); /* skews orig view to show all polys */
- drawPolys();
- glXSwapBuffers(dpy, glwin);
- }
-
-
-
- float polygon1[3][3] = { {-10.0, -10.0, 0.0,},
- { 10.0, -10.0, 0.0,},
- {-10.0, 10.0, 0.0,} };
-
- float polygon2[3][3] = { { 0.0, -10.0, -10.0,},
- { 0.0, -10.0, 10.0,},
- { 0.0, 5.0, -10.0,} };
-
- float polygon3[4][3] = { {-10.0, 6.0, 4.0,},
- {-10.0, 3.0, 4.0,},
- { 4.0, -9.0, -10.0,},
- { 4.0, -6.0, -10.0,} };
-
- void drawPolys(void) {
-
- glBegin(GL_POLYGON);
- glColor4f(0.0, 0.0, 0.0, 0.0);
- glVertex3fv(&polygon1[0][0]);
- glColor4f(0.5, 0.5, 0.5, 0.0);
- glVertex3fv(&polygon1[1][0]);
- glColor4f(1.0, 1.0, 1.0, 0.0);
- glVertex3fv(&polygon1[2][0]);
- glEnd();
-
- glBegin(GL_POLYGON);
- glColor4f(1.0, 1.0, 0.0, 0.0);
- glVertex3fv(&polygon2[0][0]);
- glColor4f(0.0, 1.0, 0.5, 0.0);
- glVertex3fv(&polygon2[1][0]);
- glColor4f(0.0, 0.0, 1.0, 0.0);
- glVertex3fv(&polygon2[2][0]);
- glEnd();
-
- glBegin(GL_POLYGON);
- glColor4f(1.0, 1.0, 0.0, 0.0);
- glVertex3fv(&polygon3[0][0]);
- glColor4f(1.0, 0.0, 1.0, 0.0);
- glVertex3fv(&polygon3[1][0]);
- glColor4f(0.0, 0.0, 1.0, 0.0);
- glVertex3fv(&polygon3[2][0]);
- glColor4f(1.0, 0.0, 1.0, 0.0);
- glVertex3fv(&polygon3[3][0]);
- glEnd();
-
- }
-