[comp.sources.x] v11i011: xwave, Part01/01

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.