paulr@umbc5.umbc.edu (Paul Riddle) (01/30/91)
Submitted-by: paulr@umbc5.umbc.edu (Paul Riddle) Posting-number: Volume 11, Issue 11 Archive-name: xwave/part01 This is a short demo program that plots a perspective projection of a 3-d mesh and waves it around in real time. We thought it might make an interesting submission, so we decided to clean it up a little bit and send it to you (now that the semester's over, we have time to do things like that :-) Anyhow, enjoy... Paul Riddle (paulr@umbc3.umbc.edu) Mike Friedman (mikef@umbc3.umbc.edu) -------------------cut-------------------------------------- #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of shell archive." # Contents: Imakefile Makefile README patchlevel.h xwave.1 xwave.c # Wrapped by paulr@elnath on Wed Jan 2 15:31:48 1991 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'Imakefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Imakefile'\" else echo shar: Extracting \"'Imakefile'\" \(105 characters\) sed "s/^X//" >'Imakefile' <<'END_OF_FILE' X DEPLIBS = $(DEPXLIB) XLOCAL_LIBRARIES = $(XLIB) X SYS_LIBRARIES = -lm X XSimpleProgramTarget(xwave) END_OF_FILE if test 105 -ne `wc -c <'Imakefile'`; then echo shar: \"'Imakefile'\" unpacked with wrong size! fi # end of 'Imakefile' fi if test -f 'Makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Makefile'\" else echo shar: Extracting \"'Makefile'\" \(172 characters\) sed "s/^X//" >'Makefile' <<'END_OF_FILE' XCC = cc XCFLAGS = -O XLDFLAGS = -s XSRCS = xwave.c XOBJS = xwave.o XLIBS = -lm -lX11 X Xxwave: $(OBJS) X $(CC) $(LDFLAGS) -o xwave $(OBJS) $(LIBS) X X.o: $*.c X $(CC) $(CFLAGS) -c $@ END_OF_FILE if test 172 -ne `wc -c <'Makefile'`; then echo shar: \"'Makefile'\" unpacked with wrong size! fi # end of 'Makefile' fi if test -f 'README' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'README'\" else echo shar: Extracting \"'README'\" \(1152 characters\) sed "s/^X//" >'README' <<'END_OF_FILE' Xxwave is a simple demo program that plots a perspective projection Xof a 3-d mesh surface and then "waves" it in real time. We have Xtested it under Ultrix 4.0, HP-UX 7.0, and SunOS 4.0.3. It works Xon both X11R4 and X11R3 servers. X XThe program works best on a risc workstation; if you have something Xslower, try making the MAXROWS and MAXCOLS constants smaller numbers. X15 by 15 works pretty well on slower machines. X XWhile the program is running, you can use the mouse to move the Xplot around, and the left and right mouse buttons to zoom it in and Xout. X XUsers with color displays can specify the -3d option. Be sure to Xhave your 3-d glasses ready (if you don't have any, you can make Xthem out of red and blue cellophane :-). The effect is pretty Xinteresting. X XThere are a few more options; these are all described in the man Xpage. Inquiries, bug reports, etc. should be directed to Xpaulr@umbc3.umbc.edu. X XXwave may be freely copied and redistributed in any form, providing Xthe authors' names stay with the source code. Let us know if you Xlike it, improve it, etc. X XAuthors: XMike Friedman (mikef@umbc3.umbc.edu) XPaul Riddle (paulr@umbc3.umbc.edu) END_OF_FILE if test 1152 -ne `wc -c <'README'`; then echo shar: \"'README'\" unpacked with wrong size! fi # end of 'README' fi if test -f 'patchlevel.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'patchlevel.h'\" else echo shar: Extracting \"'patchlevel.h'\" \(21 characters\) sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE' X#define PATCHLEVEL 1 END_OF_FILE if test 21 -ne `wc -c <'patchlevel.h'`; then echo shar: \"'patchlevel.h'\" unpacked with wrong size! fi # end of 'patchlevel.h' fi if test -f 'xwave.1' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xwave.1'\" else echo shar: Extracting \"'xwave.1'\" \(721 characters\) sed "s/^X//" >'xwave.1' <<'END_OF_FILE' X.TH xwave 1 X.SH Name Xxwave \- A real-time perspective mesh demo for X X.SH Syntax X.B xwave X[ X.I -root X] X[ X.I -3d X] X.SH Description Xxwave plots a perspective projection of a 3-d mesh and waves it. XAll calculations are done in real time. Double buffering is Xsimulated using a background pixmap. X XWhile the wave is being displayed, you can move it around using Xthe mouse, and zoom it in and out using the left and right mouse Xbuttons. X.SH Options X.IP \-root XPlot the wave in the root window. X.IP \-3d XPlot separate projections in red and blue. Make sure you have your X3-d glasses handy. You also need a color display (obviously). X.SH Authors XPaul Riddle (paulr@umbc3.umbc.edu) X.br XMike Friedman (mikef@umbc3.umbc.edu) X END_OF_FILE if test 721 -ne `wc -c <'xwave.1'`; then echo shar: \"'xwave.1'\" unpacked with wrong size! fi # end of 'xwave.1' fi if test -f 'xwave.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xwave.c'\" else echo shar: Extracting \"'xwave.c'\" \(9527 characters\) sed "s/^X//" >'xwave.c' <<'END_OF_FILE' X/****************************************************************************** X** xwave - A 3-d perspective mesh for X X** X** Authors: X** Mike Friedman (mikef@umbc3.umbc.edu) X** Paul Riddle (paulr@umbc3.umbc.edu) X** X** University of Maryland, Baltimore County X******************************************************************************/ X X#include <X11/Xlib.h> X#include <X11/Xutil.h> X#include <X11/Xos.h> X#include <stdio.h> X#include <math.h> X X#include "patchlevel.h" X X#define STARTX 20 X#define STARTY 50 X#define MAXROWS 18 X#define MAXCOLS 25 X#define GENS 2 X#define TWOPI10 400 /* 62*5 */ X#define TWOPI 6.283 X#define WIDTH 400 X#define HEIGHT 500 X X#define ROOT 0x1 X#define THREED 0x2 X Xint FD = 25, PD = 15; X XColormap cmap; XXColor red, blue; X XGC gc; XWindow win; XDisplay *dpy; Xint screen, scrnWidth = WIDTH, scrnHeight = HEIGHT; XPixmap buffer; X Xunsigned short flags = 0; X X/****************************************************************************** X** module: initColor X** X** This loads the red and blue colors into the color map. X******************************************************************************/ X Xvoid initColor () X{ X cmap = DefaultColormap (dpy, screen); X red.red = 40000; X red.blue = 0; X red.green = 0; X blue.red = 0; X blue.blue = 60000; X blue.green = 0; X X if (!(XAllocColor (dpy, cmap, &red)) || X !(XAllocColor (dpy, cmap, &blue))) { X (void) fprintf (stderr, "Error: Cannot allocate colors\n"); X exit (1); X } X} X X/****************************************************************************** X** module: initialize X** X** This sets the window up. X******************************************************************************/ X Xvoid initialize () X{ X if (!(dpy = XOpenDisplay (""))) { X (void) fprintf (stderr, "Error: Can't open display\n"); X exit (1); X } X screen = DefaultScreen (dpy); X if (flags & ROOT) { X win = DefaultRootWindow (dpy); X scrnWidth = DisplayWidth (dpy, screen); X scrnHeight = DisplayHeight (dpy, screen); X } X else { X win = XCreateSimpleWindow (dpy, DefaultRootWindow (dpy), X 0, 0, scrnWidth, scrnHeight, 1, X WhitePixel (dpy, screen), X BlackPixel (dpy, screen)); X XSelectInput (dpy, win, ExposureMask | StructureNotifyMask); X XStoreName (dpy, win, "XWave"); X XMapWindow (dpy, win); X } X gc = XCreateGC (dpy, win, 0L, (XGCValues *) 0); X if (flags & THREED) X initColor (); X buffer = XCreatePixmap (dpy, DefaultRootWindow (dpy), scrnWidth, X scrnHeight, DefaultDepth (dpy, screen)); X} X X/****************************************************************************** X** module: setupSinTable X** X** This routine initializes the sine table. The table is accessed during X** computation to speed things up somewhat. X******************************************************************************/ X Xvoid setupSinTable (sinTab) X double *sinTab; X{ X int i; X double t = 0.0; X X for (i = 0; i < TWOPI10; i++, t += TWOPI / TWOPI10) X sinTab[i] = sin (t); X} X X/* X * Perspective projections of points in 3-space to screen coordinates. X * These are implemented as macros to avoid function call overhead without X * (well, almost without..) sacrificing readability of the code. X */ X X#define xrpers(x,y,z) ((int) (PD - FD * (PD - (x)) / (FD - (z)) + 100)) X#define yrpers(x,y,z) ((int) (FD * (y) / (FD - (z)) + 150)) X#define xlpers(x,y,z) ((int) (-PD - FD * (-PD - (x)) / (FD - (z)) + 100)) X#define ylpers(x,y,z) ((int) (FD * (y) / (FD - (z)) + 150)) X X/* X * Line plotting routines. Again, these are all macros. X */ X X#define plotLineRed(x0,y0,z0,x1,y1,z1) \ X XSetForeground (dpy, gc, red.pixel); \ X XDrawLine (dpy, buffer, gc, \ X xlpers ((float) (x0), (float) (y0), (float) (z0)), \ X ylpers ((float) (x0), (float) (y0), (float) (z0)), \ X xlpers ((float) (x1), (float) (y1), (float) (z1)), \ X ylpers ((float) (x1), (float) (y1), (float) (z1))) X X#define plotLineBlue(x0,y0,z0,x1,y1,z1) \ X XSetForeground (dpy, gc, blue.pixel); \ X XDrawLine (dpy, buffer, gc, \ X xrpers ((float) (x0), (float) (y0), (float) (z0)), \ X yrpers ((float) (x0), (float) (y0), (float) (z0)), \ X xrpers ((float) (x1), (float) (y1), (float) (z1)), \ X yrpers ((float) (x1), (float) (y1), (float) (z1))) X X#define plotLine(x0,y0,z0,x1,y1,z1) \ X if (flags & THREED) { \ X plotLineRed((x0),(y0),(z0),(x1),(y1),(z1)); \ X plotLineBlue((x0),(y0),(z0),(x1),(y1),(z1)); \ X } else \ X XDrawLine (dpy, buffer, gc, \ X xlpers ((float) (x0), (float) (y0), (float) (z0)), \ X ylpers ((float) (x0), (float) (y0), (float) (z0)), \ X xlpers ((float) (x1), (float) (y1), (float) (z1)), \ X ylpers ((float) (x1), (float) (y1), (float) (z1))) X Xmain (argc, argv) X int argc; X char *argv[]; X{ X double sinTab[TWOPI10]; X register int t, gap = 10; X int r, c, px, py, junk, kb; X int amplitude1 = 150, amplitude2 = 100, cur = 0, next = 1, inc1 = -1, X inc2 = -1; X int Generation[MAXROWS][MAXCOLS][GENS]; X Window junk_win; X X /* X * Check args and set appropriate program flags X */ X while (++argv, --argc) { X if (!strcmp (*argv, "-root")) X flags |= ROOT; X else if (!strcmp (*argv, "-3d")) X flags |= THREED; X else { X (void) fprintf (stderr, "Usage: xwave [-root] [-3d]\n"); X exit (1); X } X } X X /* X * Zero out the generation matrix X */ X for (r = 0; r < MAXROWS; r++) X for (c = 0; c < MAXCOLS; c++) X Generation[r][c][0] = Generation[r][c][1] = 0; X X /* X * Set up the window and the sine table X */ X initialize (); X setupSinTable (sinTab); X X /* X * Grab an expose event from the server, then we can get started X */ X if (!(flags & ROOT)) { X for (;;) { X XEvent event; X XNextEvent(dpy, &event); X if (event.type == Expose) break; X } X XWarpPointer (dpy, None, win, 0, 0, 0, 0, scrnWidth / 2, X scrnHeight / 2); X } X X /* X * Finally, go into an infinite loop of computing and plotting generations X */ X for (;;) X for (t = 0;t < TWOPI10; t++) { X X /* X * Handle resizes. When a resize happens, we need to re-allocate X * the background pixmap. Note that the bigger the window, the X * larger the area that needs to get copied, and therefore the X * slower the program gets. X */ X if (QLength (dpy)) { X XEvent event; X XNextEvent (dpy, &event); X switch (event.type) { X case ConfigureNotify: X if (event.xconfigure.width != scrnWidth || X event.xconfigure.height != scrnHeight) { X XFreePixmap (dpy, buffer); X scrnWidth = event.xconfigure.width; X scrnHeight = event.xconfigure.height; X buffer = XCreatePixmap (dpy, DefaultRootWindow (dpy), X scrnWidth, scrnHeight, X DefaultDepth (dpy, screen)); X } X default: X break; X } X } X XQueryPointer (dpy, win, &junk_win, &junk_win, &junk, &junk, X &px, &py, &kb); X px -= 275; X py -= 350; X X /* X * Give the user something to do :-) X */ X if ((kb & Button1Mask) && gap > 10) gap--; X if ((kb & Button3Mask) && gap < 50) gap++; X X /* X * Load some of the cells X */ X Generation[1][2][cur]=(int)(amplitude1*sinTab[(30*t)%TWOPI10]); X Generation[2][4][cur]=(int)(amplitude2*sinTab[(25*t)%TWOPI10]); X Generation[1][6][cur]=(int)(amplitude1*sinTab[19*(10+t)%TWOPI10]); X Generation[2][8][cur]=(int)(amplitude2*sinTab[(20*t)%TWOPI10]); X Generation[15][8][cur]=(int)(amplitude2*sinTab[(5*t)%TWOPI10]); X Generation[7][10][cur]=(int)(amplitude2*sinTab[(30*t)%TWOPI10]); X Generation[9][14][cur]=(int)(amplitude2*sinTab[(20*t)%TWOPI10]); X Generation[12][16][cur]=(int)((amplitude2+50)*sinTab[(3*t)%TWOPI10]); X Generation[7][3][cur]=(int)(amplitude2*sinTab[(40*t)%TWOPI10]); X X /* X * Increment and/or decrement our amplitudes X */ X if (amplitude2 == 0) X inc2 = 5; X else if (amplitude2 == 350) X inc2 = -1; X amplitude2 += inc2; X if (amplitude1 == 0) X inc1 = 5; X else if (amplitude1 == 200) X inc1 = -1; X amplitude1 += inc1; X X /* X * Interpolate the values of all the other cells in the matrix X */ X for (r = 1; r < MAXROWS - 1; r++) X for (c = 1; c < MAXCOLS - 1; c++) X Generation[r][c][next] = X (int) (0.25 * (Generation[r - 1][c][cur] X + Generation[r][c - 1][cur] X + Generation[r][c + 1][cur] X + Generation[r + 1][c][cur])); X X /* X * Plot the new generation in our background pixmap X */ X for (r = 1; r < MAXROWS - 1; r++) { X for (c = 0; c < MAXCOLS - 1; c++) { X int xCoord, yCoord; X xCoord = gap * c + STARTX; X yCoord = Generation[r][c][next] + gap * r + STARTY; X X plotLine (xCoord + px, yCoord + py, r, X gap * (c + 1) + STARTX + px, X Generation[r][c + 1][next] + X gap * r + STARTY + py, r); X plotLine (xCoord + px, yCoord + py, r, xCoord + px, X Generation[r + 1][c][next] + X gap * (r + 1) + STARTY + py, r + 1); X } X } X cur ^= 1; X next ^= 1; X X /* X * Swap the background buffer and the window so the new generation X * shows up on the window. X */ X XCopyArea (dpy, buffer, win, gc, 0, 0, scrnWidth, scrnHeight, 0, 0); X XSetForeground (dpy, gc, BlackPixel (dpy, screen)); X XFillRectangle (dpy, buffer, gc, 0, 0, scrnWidth, scrnHeight); X XSetForeground (dpy, gc, WhitePixel (dpy, screen)); X } X} END_OF_FILE if test 9527 -ne `wc -c <'xwave.c'`; then echo shar: \"'xwave.c'\" unpacked with wrong size! fi # end of 'xwave.c' fi echo shar: End of shell archive. exit 0 -- dan ---------------------------------------------------- O'Reilly && Associates argv@sun.com / argv@ora.com Opinions expressed reflect those of the author only.