paulr@umbc4.umbc.edu (Paul Riddle) (02/18/91)
Submitted-by: paulr@umbc4.umbc.edu (Paul Riddle) Posting-number: Volume 11, Issue 84 Archive-name: xwave/part01 --- Xwave plots a perspective projection of a plane grid oscillating in three-space in real time. --- This is xwave version 2.0, which contains significant enhancements by Jim McBeath (jimmc@hisoft.uucp) as well as a few things from us. The original is archived as v11i011; since version 2.0 is well over twice as large, we decided to do a complete repost rather than a patch. Please refer to the README and the man page for a list of new features, there are too many to list them all here! Enjoy, Paul Riddle (paulr@umbc3.umbc.edu) Mike Friedman (mikef@umbc3.umbc.edu) Jim McBeath (jimmc@hisoft.uucp) ----------------------------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: README xwave.1 Makefile Imakefile patchlevel.h xwave.h # force.c plot.c prop.c xwave.c # Wrapped by X@orion on Sat Feb 9 15:49:03 1991 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'README' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'README'\" else echo shar: Extracting \"'README'\" \(1938 characters\) sed "s/^X//" >'README' <<'END_OF_FILE' XXwave Version 2.0 February 4, 1991 X XXwave plots a perspective projection of a plane grid oscillating in Xthree-space in real time. You can select the size of the grid, a Xforcing function to apply (and where to apply it), and what wave propagation Xmodel to use. You can display a plot of the velocity of the points in the Xgrid as well as the position. X XThe original xwave was written by Mike Friedman (mikef@umbc3.umbc.edu) Xand Paul Riddle (paulr@umbc3.umbc.edu) and posted in January 1991. XIt was tested under Ultrix 4.0, HP-UX 7.0, and SunOS 4.0.3, and worked Xon both X11R4 and X11R3 servers. This version of xwave contains Xsignificant enhancements by Jim McBeath (jimmc@hisoft.uucp), but has Xonly been tested on a Sun4 running X11R4. X XThe program works best on a risc workstation; if you have something Xslower, try using the -rows and -cols command line options. X15 by 15 works pretty well on slower machines. X XWhile the program is running, you can use the middle mouse button to move Xthe plot around, and the left and right mouse buttons to zoom it in and Xout. There are many single-key commands you can enter, such as the 'r' Xcommand to toggle continuous run mode, and space to step through one Xgeneration. X XUsers with color displays can specify the -stereo 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 XTry the -demo switch for a quick tour (e.g. "xwave -demo 4"). X XThere are a many 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 XOriginal Authors: XMike Friedman (mikef@umbc3.umbc.edu) XPaul Riddle (paulr@umbc3.umbc.edu) X XModified by: XJim McBeath (jimmc@hisoft.uucp) END_OF_FILE if test 1938 -ne `wc -c <'README'`; then echo shar: \"'README'\" unpacked with wrong size! fi # end of 'README' 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'\" \(8683 characters\) sed "s/^X//" >'xwave.1' <<'END_OF_FILE' X.TH XWAVE 1 "4 February 1991" "X Version 11" X.SH NAME Xxwave \- A real-time perspective mesh demo for X X.SH SYNOPSIS X.B xwave X[ X.I -amp XA X] X[ X.I -bound Xbits X] X[ X.I -cols XC X] X[ X.I -dampfactor XB X] X[ X.I -demo XnameOrNum X] X[ X.I -edit X] X[ X.I -force Xfuncname X] X[ X.I -forcecol XN X] X[ X.I -forcefull X] X[ X.I -forcepoint XR C X] X[ X.I -forcerow XN X] X[ X.I -omega XM X] X[ X.I -omega2 XM X] X[ X.I -plotvel X] X[ X.I -printdemo XnameOrNum X] X[ X.I -root X] X[ X.I -rows XR X] X[ X.I -springconst XK X] X[ X.I -stereo X] X[ X.I -version X] X[ X.I -wave Xfuncname X] X X.SH DESCRIPTION X.LP XXwave plots a perspective projection of a plane grid oscillating in Xthree-space in real time. You can select the size of the grid, a Xforcing function to apply (and where to apply it), and what wave propagation Xmodel to use. You can display a plot of the velocity of the points in the Xgrid as well as the position. XDouble buffering is Xsimulated using a background pixmap. XOther options are described below in the "OPTIONS" section. X.LP XWhile the wave is being displayed, you can pan and zoom, stop and start Xupdates, and make other changes. XThis is described below in the "INTERACTIVE USE" section. X X.SH OPTIONS X.TP X.B -amp A XSelect the amplitude of the forcing function. XTypical numbers are between 20 and 100. XDefault amplitude is 100. X.TP X.B -bound bits XSelect which corners and edges of the grid are bound and which are free. XBy default, all corners and edges are bound. XIf you specify a single "0" or "1" as the argument to -bound, it applies to Xall eight corners and edges. XOtherwise, each character in the string applies to one corner or edge: if Xthat character is "0", the corresponding corner or edge is free; else it is Xbound. XThe sequence of corners and edges in the string is: lrlc, lr, lrhc, hc, Xhrhc, hr, hrlc, lc, where l is low, h is high, r is row, and c is column. XFor example, -bound "00111000" means the high column end of the grid, Xincluding those corners, are bound, and all other corners and edges are free. X.TP X.B -cols C XSpecify how many columns are in the grid. XThe minimum number of columns is 2. XLarger numbers give more detailed wave displays, Xbut take longer to compute and thus do not update as quickly. XThe default is 25. X.TP X.B -dampfactor B XSpecify the damping factor used in the "wave" propagation model. XSee the -wave switch for more details. XThe default is 0.001. X.TP X.B -demo nameOrNum XSelect a demonstration to run. XEach demo is equivalent to a specific set of switches (which you can see Xwith the -printdemo command line option). XFor a quick tour of the program, run "xwave -demo N" starting with N=0 and Xincrementing until it tells you there are no more demos. X.TP X.B -edit XAllows the user to interactively shape the wave while the program is running. XWhen the program is in edit mode, the mouse controls an X-shaped cursor that Xmoves over the surface of the grid. Position the cursor to where you want Xto modify the wave and press and hold the left mouse button. At this point, Xdragging the mouse up and down will modify the amplitude of the wave and Xdragging it left and right will control the frequency. Releasing the mouse Xbutton will allow you to modify additional points. When you are finished Xediting points, press the right mouse button to enter continuous run mode. X.TP X.B -force funcname XSpecify the name of the forcing function to use. XThis can also be changed interactively (see the INTERACTIVE USE section). X.TP X.B -forcecol C XSpecify that the selected forcing function is to be Xapplied to all grid points in the specified column. X(The multisine forcing function ignores this information.) X.TP X.B -forcefull XSpecify that forcing functions which do not cover the full cycle should Xforce a zero value during the remainder of the cycle. XBy default, the forcing function takes no action during this part of the Xcycle, but lets the point move freely. XThis affects the following forcing functions: Xdelta, pulse, onehalfsine, onehalfsinesquared. X.TP X.B -forcepoint R C XSpecify that the selected forcing function is to be Xapplied to the specified grid point. X(The multisine forcing function ignores this information.) X.TP X.B -forcerow R XSpecify that the selected forcing function is to be Xapplied to all grid points in the specified row. X(The multisine forcing function ignores this information.) X.TP X.B -omega M XSpecify a frequency multiplier for forcing functions. XA larger number makes the forcing functions cycle through their values faster. X.TP X.B -omega2 M XSpecify a secondary frequency multiplier. XThis number is used in the following forcing functions: Xpulse, onehalfsine, onehalfsinesquared. XIf "-omega2 1" is specified, each of these functions will have a duty Xcycle of 1/2; if "-omega 2" is specifed, it will be 1/4, etc. X.TP X.B -plotvel XSpecify that a plot of the velocity of each point in the grid should appear Xbelow the plot of the position of each point in the grid. XThe velocity information is updated only by the "wave" propagation function. X.TP X.B -printdemo nameOrNum XPrint the switches that comprise the specified demo, then exit. X.TP X.B -root XPlot the wave in the root window. X.TP X.B -rows R XSpecify how many rows are in the grid. XThe minimum number of rows is 2. XLarger numbers give more detailed wave displays, Xbut take longer to compute and thus do not update as quickly. XThe default is 18. X.TP X.B -springconst K XSpecify the spring constant to use in the "wave" propagation function. XSee the -wave switch for more details. XThe default is 0.01. X.TP X.B -stereo XPlot separate projections in red and blue. Make sure you have your X3-d glasses handy. You also need a color display (obviously). X.TP X.B -version XPrints the current version of xwave and exits. X.TP X.B -wave funcname XSpecify the name of the wave propagation function to use. XYou can specify none, which allows you to see the "naked" forcing function. XYou can specify relax, which gives a pleasant demo with the multisine Xforcing function (the original xwave program). XYou can specify wave, which uses a physical wave propagation model. XIn the wave model, each point has a mass of 1 and a velocity as well as a Xposition. XA simple spring model is used, F = -K*x -B*v, where K is the spring constant X(specified with -springconst) and B is the damping factor (specified with X-dampfactor). XThe distance used for x is the simple vertical distance between a point and Xits neighbors. XNote that since this is a discreet simulation, the simulation is Xhighly dispersive (low frequencies travel faster), Xso single pulses do not travel very well. XHowever, you can still see the effects of reflection against a free or Xbound end, set up nice standing waves, see how the velocity is out of Xphase with the position, etc. X X.SH "INTERACTIVE USE" X.LP XWhile xwave is running, you can change the perspective by using the mouse Xbuttons. XYou can pan the picture as it is running by holding down the middle mouse Xbutton and moving the mouse. XYou can zoom in and out by holding down the left or right mouse buttons. X(Note that these operations do not work unless xwave is running in Xcontinuous run mode.) X.LP XThere are a number of single-key keyboard commands you can enter into Xthe graphics window of xwave. XThese commands can be entered whether or not xwave is in continuous run mode. XIf the command is not understood, the bell is rung. XNote that there may be a bit of delay in processing a keyboard command when Xthe program is in continuous run mode. X.TP X.B c XClear the data and reset the forcing function time; everything starts over Xagain. X.TP X.B d XLoad the forcing function data. XThis is useful when in step mode. X.TP X.B f XSelect a different forcing function. XThe new forcing function name is printed out. X.TP X.B p XPrint out data. XPrints out all velocity and position data which is non-zero. XMainly useful in step mode for debugging. X.TP X.B q XQuit the program. X.TP X.B r XToggle run/step mode. XIn run mode, the program runs continuously and updates the screen. XThis consumes 100% of the available cpu time, and looks nice. XIn step mode, you can step through each generation by pressing the Xspace bar, and see in detail how the grid changes at each step. XBy default, the program comes up in continuous run mode. X.TP X.B t XToggle timing mode. XWhen the program is in time mode, it prints an approximation of how many Xframes per second it is displaying. This is re-calculated and printed Xevery 50 frames. X.TP X.B w XSelect a different wave propagation function. XThe new propagation function name is printed out. X.TP X.B <space> XStep (when in step mode). XCalculates and displays the grid at the next time point. X X.SH AUTHORS X.LP XPaul Riddle (paulr@umbc3.umbc.edu) X.br XMike Friedman (mikef@umbc3.umbc.edu) X.br XJim McBeath (jimmc@hisoft.uucp) X END_OF_FILE if test 8683 -ne `wc -c <'xwave.1'`; then echo shar: \"'xwave.1'\" unpacked with wrong size! fi # end of 'xwave.1' fi if test -f 'Makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Makefile'\" else echo shar: Extracting \"'Makefile'\" \(261 characters\) sed "s/^X//" >'Makefile' <<'END_OF_FILE' XCC = cc X#CFLAGS = -O XCFLAGS = -g X#LDFLAGS = -s XLDFLAGS = -g XSRCS = xwave.c force.c plot.c prop.c XOBJS = xwave.o force.o plot.o prop.o XLIBS = -lm -lX11 X Xxwave: $(OBJS) X $(CC) $(LDFLAGS) -o xwave $(OBJS) $(LIBS) X X$(OBJS): xwave.h X X.o: $*.c X $(CC) $(CFLAGS) -c $@ END_OF_FILE if test 261 -ne `wc -c <'Makefile'`; then echo shar: \"'Makefile'\" unpacked with wrong size! fi # end of 'Makefile' fi if test -f 'Imakefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Imakefile'\" else echo shar: Extracting \"'Imakefile'\" \(188 characters\) sed "s/^X//" >'Imakefile' <<'END_OF_FILE' X DEPLIBS = $(DEPXLIB) XLOCAL_LIBRARIES = $(XLIB) X SYS_LIBRARIES = -lm X SRCS = xwave.c force.c plot.c prop.c X OBJS = xwave.o force.o plot.o prop.o X XComplexProgramTarget(xwave) END_OF_FILE if test 188 -ne `wc -c <'Imakefile'`; then echo shar: \"'Imakefile'\" unpacked with wrong size! fi # end of 'Imakefile' 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'\" \(776 characters\) sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE' X#define VERSION 2 X#define PATCHLEVEL 0 X#define VDATE "Febuary 1, 1991" X X/* Version 2.0: February 1, 1991 X * Extensive mods by Jim McBeath (jimmc@hisoft.uucp): X * X * Add multiple wave propagation model capability, plus spring model. X * Add multiple forcing function capability, plus numerous simple X * forcing functions (delta, pulse, sine, etc.). X * Add lots of command line switches to specify where forcing function X * is applied, size of grid, etc. X * Add boundary conditions: allow edges and corners to be separately X * specified as bound or free. X * Lots of other little changes and code rearrangement. X * X * February 9, 1990 - Mike Friedman & Paul Riddle X * Added interactive editing and timing functions X * Improved the 3-d effect provided by the -stereo option X */ END_OF_FILE if test 776 -ne `wc -c <'patchlevel.h'`; then echo shar: \"'patchlevel.h'\" unpacked with wrong size! fi # end of 'patchlevel.h' fi if test -f 'xwave.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'xwave.h'\" else echo shar: Extracting \"'xwave.h'\" \(695 characters\) sed "s/^X//" >'xwave.h' <<'END_OF_FILE' X/* xwave.h - include file for xwave X * X */ X X/* used scaled-up fixed point numbers for more resolution */ X#define SCALE 1024 X X#define IX(r,c) ((r)*maxcols + (c)) X X/* structure used to store the data values in the grid of points */ Xtypedef struct pinfo { X int pos; /* current vertical position */ X int vel; /* current vertical velocity */ X int tx,ty; /* transformed (x,y) point for plotting */ X} Pinfo; X Xtypedef struct ftab { X char *name; /* name of the function */ X int (*func)(); /* pointer to the function */ X} Ftab; X Xextern int maxrows, maxcols; X Xextern double springconst; Xextern double dampfactor; X Xextern Pinfo *Generation[]; Xextern Pinfo *CurGen; Xextern Pinfo *NextGen; X X/* end */ X X X X X X X X END_OF_FILE if test 695 -ne `wc -c <'xwave.h'`; then echo shar: \"'xwave.h'\" unpacked with wrong size! fi # end of 'xwave.h' fi if test -f 'force.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'force.c'\" else echo shar: Extracting \"'force.c'\" \(4788 characters\) sed "s/^X//" >'force.c' <<'END_OF_FILE' X/* force.c - forcing functions for xwave X * multi-sine function by Friedman and Riddle; the rest by McBeath. X */ X X#include <stdio.h> X#include "xwave.h" X Xextern int fftime; Xextern double sinTab[]; Xextern int sinTabSize; Xextern int omega; Xextern int omega2; Xextern int forcerow, forcecol; Xextern int forceptr, forceptc; Xextern int forcefull; Xextern int *editedRowVals; Xextern int *editedColVals; Xextern int *amplitudes; Xextern int *frequencies; Xextern int didedit; Xextern int numEditedPoints; X X Xint ForceIndex; Xint (*ForceFunc)(); X Xint ampl = 100; X Xint ampl1 = 150*SCALE, ampl2 = 100*SCALE; Xint inc1 = -1, inc2 = -1; X X/* original forcing function by Friedman and Riddle */ XForceFuncMultiSine() X{ X int t; X int row,col,i; X X t = (fftime++)%sinTabSize; X/* make the assignment only if row and col are in range */ X#define CLOAD(r,c) if (r<maxrows && c<maxcols) CurGen[IX(r,c)].pos X X/* load freq. and amp. matrices */ X#define FVAL(r,c) frequencies[r*maxcols+c] X#define AVAL(r,c) amplitudes[r*maxcols+c] X X if (!didedit) { X /* Load some of the cells */ X CLOAD(1,2) = (int)(ampl1*sinTab[(30*t)%sinTabSize]); X CLOAD(2,4) = (int)(ampl2*sinTab[(25*t)%sinTabSize]); X CLOAD(1,6) = (int)(ampl1*sinTab[19*(10+t)%sinTabSize]); X CLOAD(2,8) = (int)(ampl2*sinTab[(20*t)%sinTabSize]); X CLOAD(15,8) = (int)(ampl2*sinTab[(5*t)%sinTabSize]); X CLOAD(7,10) = (int)(ampl2*sinTab[(30*t)%sinTabSize]); X CLOAD(9,14) = (int)(ampl2*sinTab[(20*t)%sinTabSize]); X CLOAD(12,16) = (int)((ampl2+50)*sinTab[(3*t)%sinTabSize]); X CLOAD(7,3) = (int)(ampl2*sinTab[(40*t)%sinTabSize]); X X /* Increment and/or decrement our amplitudes */ X if (ampl2 == 0) X inc2 = 5*SCALE; X else if (ampl2 == 350*SCALE) X inc2 = -1*SCALE; X ampl2 += inc2; X if (ampl1 == 0) X inc1 = 5*SCALE; X else if (ampl1 == 200*SCALE) X inc1 = -1*SCALE; X ampl1 += inc1; X } X else { /* wave the edited points instead of set points */ X row = editedRowVals[0]; X col = editedColVals[0]; X for (i=0;i<numEditedPoints;i++) { X row = editedRowVals[i]; X col = editedColVals[i]; X CurGen[row*maxcols+col].pos = (int)(AVAL(row,col)*SCALE* X sinTab[(FVAL(row,col)*t)%sinTabSize]); X } X } X} X XForceX(x) Xint x; X{ X int r,c; X X if (forcerow>=0) { X for (c=0; c<maxcols; c++) { X CurGen[IX(forcerow,c)].pos = x; X CurGen[IX(forcerow,c)].vel = 0; X } X } X if (forcecol>=0) { X for (r=0; r<maxrows; r++) { X CurGen[IX(r,forcecol)].pos = x; X CurGen[IX(r,forcecol)].vel = 0; X } X } X if (forceptr>=0) { X CurGen[IX(forceptr,forceptc)].pos = x; X CurGen[IX(forceptr,forceptc)].vel = 0; X } X} X XForceSine() X{ X int t; X int x; X X t = (omega*fftime++)%sinTabSize; X x = (int)(ampl*SCALE*sinTab[t]); X ForceX(x); X} X XForceDelta() X{ X int t; X int x; X X t = (omega*fftime++)%sinTabSize; X if (t==0) X x = (int)(ampl*SCALE); X else { X if (!forcefull) return; X x = 0; X } X ForceX(x); X} X XForcePulse() X{ X int t,t2; X int x; X X t = (omega*fftime++)%sinTabSize; X t2 = omega2*t; X if (t2<=sinTabSize/2) X x = ampl*SCALE; X else { X if (!forcefull) return; X x = 0; X } X ForceX(x); X} X XForceOneHalfSine() X{ X int t,t2; X int x; X int r,c; X X t = (omega*fftime++)%sinTabSize; X t2 = omega2*t; X if (t2<sinTabSize/2) X x = (int)(ampl*SCALE*sinTab[t2]); X else { X if (!forcefull) return; X x = 0; X } X ForceX(x); X} X XForceOneHalfSineSquared() X{ X int t,t2; X int x; X int r,c; X X t = (omega*fftime++)%sinTabSize; X t2 = omega2*t; X if (t2<sinTabSize/2) X x = (int)(ampl*SCALE*sinTab[t2]*sinTab[t2]); X else { X if (!forcefull) return; X x = 0; X } X ForceX(x); X} X XFtab ForceTab[] = { X { "multisine", ForceFuncMultiSine }, X { "delta", ForceDelta }, X { "pulse", ForcePulse }, X { "sine", ForceSine }, X { "onehalfsine", ForceOneHalfSine }, X { "onehalfsinesquared", ForceOneHalfSineSquared }, X}; Xint ForceTabSize = sizeof(ForceTab)/sizeof(ForceTab[0]); X XInitForceFunc() X{ X ForceIndex = 0; X ForceFunc = ForceTab[ForceIndex].func; X} X XPrintForceFuncs(fp) XFILE *fp; X{ X int i; X X fprintf(fp,"Forcing functions are:\n"); X for (i=0; i<ForceTabSize; i++) { X fprintf(fp," %s",ForceTab[i].name); X } X fprintf(fp,"\n"); X} X XSetNextForceFunc() X{ X ForceIndex++; X if (ForceIndex>=ForceTabSize) ForceIndex = 0; X ForceFunc = ForceTab[ForceIndex].func; X printf("Forcing function is set to %s\n", X ForceTab[ForceIndex].name); X} X XSetNamedForceFunc(s) Xchar *s; X{ X int i; X X for (i=0; i<ForceTabSize; i++) { X if (strcmp(ForceTab[i].name,s)==0) { X ForceIndex = i; X ForceFunc = ForceTab[ForceIndex].func; X return 1; X } X } X return 0; /* not found */ X} X X/* end */ END_OF_FILE if test 4788 -ne `wc -c <'force.c'`; then echo shar: \"'force.c'\" unpacked with wrong size! fi # end of 'force.c' fi if test -f 'plot.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'plot.c'\" else echo shar: Extracting \"'plot.c'\" \(9847 characters\) sed "s/^X//" >'plot.c' <<'END_OF_FILE' X/* plot.c - line drawing and other X functions for xwave. X * Code here mainly written by Friedman and Riddle, X * separated into functions by jimmc. Feb '91 X */ X X#include <X11/Xlib.h> X#include <X11/Xutil.h> X#include <X11/Xos.h> X#include <stdio.h> X#include "xwave.h" X X#define STARTX -50 X#define STARTY 50 X#define STARTYVOFF 200 X#define WIDTH 400 X#define HEIGHT 500 X Xextern double sqrt(); X Xextern int flagstereo; Xextern int flagroot; Xextern int flagplotvel; Xextern int flagedit; X Xextern int *editedRowVals; Xextern int *editedColVals; Xextern int *frequencies; Xextern int *amplitudes; Xextern int running; X X XDisplay *dpy; Xint screen; XWindow win; X XColormap cmap; XXColor red, blue, purple; X XGC gc,gc2; Xint scrnWidth = WIDTH, scrnHeight = HEIGHT; XPixmap buffer; X Xint FD = 25, PD = 15; Xint gap = 10; Xint px= 0, py= 0; X Xint numEditedPoints=0; X X/* This sets the window up. */ Xvoid InitWindow () 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 (flagroot) { 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 KeyPressMask); X XStoreName (dpy, win, "XWave"); X XMapWindow (dpy, win); X } X gc = XCreateGC (dpy, win, 0L, (XGCValues *) 0); X gc2= XCreateGC (dpy, win, 0L, (XGCValues *) 0); X XSetLineAttributes (dpy,gc2,20,LineSolid,CapButt,JoinMiter); X XSetForeground (dpy, gc2, WhitePixel (dpy, screen)); X X if (flagstereo) X InitColor (); X buffer = XCreatePixmap (dpy, DefaultRootWindow (dpy), scrnWidth, X scrnHeight, DefaultDepth (dpy, screen)); X} X X/* This loads the red, blue and purple colors into the color map. */ XInitColor () X{ X cmap = DefaultColormap (dpy, screen); X blue.red = 0; X blue.blue = 60000; X blue.green = 0; X X red.red = 40000; X red.blue = 0; X red.green = 0; X X purple.red = 40000; X purple.blue = 60000; X purple.green = 0; X X X if (!(XAllocColor (dpy, cmap, &red)) || X !(XAllocColor (dpy, cmap, &blue)) || X !(XAllocColor (dpy, cmap, &purple))) { X (void) fprintf (stderr, "Error: Cannot allocate colors\n"); X exit (1); X } X} X XWaitForExpose() X{ X /* X * Grab an expose event from the server, then we can get started X */ X for (;;) { X XEvent event; X XNextEvent(dpy, &event); X if (event.type == Expose) break; X } X#if 0 X XWarpPointer (dpy, None, win, 0, 0, 0, 0, scrnWidth / 2, X scrnHeight / 2); X#endif 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 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 plotLineBlue(x0,y0,z0,x1,y1,z1) \ X XSetForeground (dpy, gc, blue.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 plotLine(x0,y0,z0,x1,y1,z1) \ X if (flagstereo) { \ X plotLineRed((x0),(y0),(z0),(x1),(y1),(z1)); \ X plotLineBlue((x0),(y0),(z0),(x1),(y1),(z1)); \ X } else {\ X XSetForeground (dpy, gc, WhitePixel (dpy, screen)); \ 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 X/* Plot the current generation in our background pixmap */ XPlotCur(which) Xint which; /* 0 means plot position, 1 means plot vel */ X{ X int r, c; X struct pinfo *pi, *pir; X X /* get transformed values for all points in grid */ X if (which) { /* velocity */ X /* velocity stuff added by jimmc */ X int kscale = (int)(SCALE*sqrt(springconst)); X /* low spring constant gives smaller velocities, so X * scale up for smaller spring constansts */ X int startyv = STARTY + STARTYVOFF; X for (r = 0; r < maxrows; r++) { X for (c = 0; c < maxcols; c++) { X pi = CurGen+IX(r,c); X pi->tx = gap * c + STARTX + px; X pi->ty = pi->vel/kscale + gap * r + startyv+ py; X } X } X } else { /* position */ X for (r = 0; r < maxrows; r++) { X for (c = 0; c < maxcols; c++) { X pi = CurGen+IX(r,c); X pi->tx = gap * c + STARTX + px; X pi->ty = pi->pos/SCALE + gap * r + STARTY + py; X } X } X } X X /* now plot all the line segments */ X for (r = 0; r < maxrows - 1; r++) { X for (c = 0; c < maxcols - 1; c++) { X pi = CurGen+IX(r,c); X pir = pi+maxcols; /* access CurGen[IX(r+1,c)] */ X /* pi[1] accesses CurGen[IX(r,c+1)] */ X plotLine (pi->tx, pi->ty, r, pi[1].tx, pi[1].ty, r); X plotLine (pi->tx, pi->ty, r, pir->tx, pir->ty, r+1); X } X /* do the last column (c==maxcols-1) */ X pi = CurGen+IX(r,c); X pir = pi+maxcols; /* access CurGen[IX(r+1,c)] */ X plotLine (pi->tx, pi->ty, r, pir->tx, pir->ty, r+1); X X } X /* now do the last row (r==maxrows-1) */ X for (c = 0; c < maxcols - 1; c++) { X pi = CurGen+IX(r,c); X /* pi[1] accesses CurGen[IX(r,c+1)] */ X plotLine (pi->tx, pi->ty, r, pi[1].tx, pi[1].ty, r); X } X} X XShowData() X{ X PlotCur(0); /* plot the image of the next time point into buffer */ X if (flagplotvel) X PlotCur(1); /* plot velocity also */ X X /* display the buffer we just drew */ X XCopyArea (dpy, buffer, win, gc, 0, 0, scrnWidth, scrnHeight, 0, 0); X if (flagstereo) X XSetForeground (dpy, gc, purple.pixel); X else X XSetForeground (dpy, gc, BlackPixel (dpy, screen)); X XFillRectangle (dpy, buffer, gc, 0, 0, scrnWidth, scrnHeight); X} X XHandleResize(event) XXEvent *event; X{ 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 XSetForeground (dpy, gc, BlackPixel (dpy, screen)); X XFillRectangle (dpy, buffer, gc, 0, 0, scrnWidth, scrnHeight); X XSetForeground (dpy, gc, WhitePixel (dpy, screen)); X } X} X XDoQueryPointer(pxp,pyp) Xint *pxp, *pyp; X{ X static int lastx=0, lasty=0; X int thisx, thisy; X int dx, dy; X int kb; X Window junk_win; X int junk; X X XQueryPointer (dpy, win, &junk_win, &junk_win, &junk, &junk, X &thisx, &thisy, &kb); 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 if (kb & Button2Mask) { X dx = thisx - lastx; X dy = thisy - lasty; X px += dx; X py += dy; X } X lastx = thisx; X lasty = thisy; X} X Xvoid edit () X /* This allows the user to select the wave points and their frequencies */ X{ X int px,py,junk; X Window junkWin; X int x,ax,z,r,c,kb,i; X int xoff,yoff; X int row,col; X X xoff = scrnWidth/2 - 275; X yoff = scrnHeight/2 - 350; X xoff = 0; X yoff = 0; X X X for (;;) { X if (QLength (dpy)) X ProcessEvent(); X X XQueryPointer (dpy, win, &junkWin, &junkWin, &junk, &junk,&px, &py, &kb); X if (px<0) X px = 0; X X x = (px/10 % maxcols) * gap + STARTX + xoff; X ax = px/10 % maxcols; X z = (py/10 % (maxrows-1)) + 1; X if (z < 1) X z = 1; X X /* display the cursor */ X X plotLine (x-5,yoff+STARTY+gap*(z-1),z-1, x+5,yoff+STARTY+gap*(z+1),z+1); X plotLine (x-5,yoff+STARTY+gap*(z+1),z+1, x+5,yoff+STARTY+gap*(z-1),z-1); X plotLine (x-6,yoff+STARTY+gap*(z-1),z-1, x+4,yoff+STARTY+gap*(z+1),z+1); X plotLine (x-6,yoff+STARTY+gap*(z+1),z+1, x+4,yoff+STARTY+gap*(z-1),z-1); X X X if (kb & Button3Mask) { /* right button starts the waving */ X flagedit = !flagedit; X return; X } X X if (kb & Button1Mask) { /* left button held down to change amp. & freq. */ X while (1) { X X if (QLength (dpy)) X ProcessEvent(); X X for (i=0;i<numEditedPoints;i++) { X row = editedRowVals[i]; X col = editedColVals[i]; X CurGen[row*maxcols+col].pos = amplitudes[row*maxcols+col]; X } X X XQueryPointer (dpy,win,&junkWin,&junkWin, &junk, &junk,&px, &py, &kb); X XDrawLine (dpy,buffer,gc2,0,scrnHeight-25,px,scrnHeight-25); X X frequencies[z*maxcols+ax] = (int)((float)px / (float)scrnWidth * 32); X X if (frequencies[z*maxcols+ax] < 0) X frequencies[z*maxcols+ax] = 0; X printf ("frequency=%d \r",frequencies[z*maxcols+ax]); X fflush(stdout); X X if (!(kb & Button1Mask)) { /* release button to move edit cursor */ X numEditedPoints++; X break; X } X CurGen[z*maxcols+ax].pos = (py - scrnHeight/2)*SCALE; X amplitudes[z*maxcols+ax] = py - scrnHeight/2; X editedRowVals[numEditedPoints] = z; X editedColVals[numEditedPoints] = ax; X X Step(); X X ShowData(); X X } X X } X Step(); X X ShowData(); X X } X} X X/* end */ X END_OF_FILE if test 9847 -ne `wc -c <'plot.c'`; then echo shar: \"'plot.c'\" unpacked with wrong size! fi # end of 'plot.c' fi if test -f 'prop.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'prop.c'\" else echo shar: Extracting \"'prop.c'\" \(8429 characters\) sed "s/^X//" >'prop.c' <<'END_OF_FILE' X/* Wave propagation X * relax prop func by Friedman and Riddle; X * the rest by jimmc, Feb '91. X */ X X#include <stdio.h> X#include "xwave.h" X Xint bound[8] = { 1, 1, 1, 1, 1, 1, 1, 1 }; X#define boundlrlc bound[0] X#define boundlr bound[1] X#define boundlrhc bound[2] X#define boundhc bound[3] X#define boundhrhc bound[4] X#define boundhr bound[5] X#define boundhrlc bound[6] X#define boundlc bound[7] X Xint WaveIndex; Xint (*WaveFunc)(); X XCalcBoundedNext() X{ X int r, c; X X if (boundlr) { X r = 0; X for (c=1; c<maxcols-1; c++) X NextGen[IX(r,c)].pos = CurGen[IX(r,c)].pos; X } X if (boundhr) { X r = maxrows-1; X for (c=1; c<maxcols-1; c++) X NextGen[IX(r,c)].pos = CurGen[IX(r,c)].pos; X } X if (boundlc) { X c = 0; X for (r=1; r<maxrows-1; r++) X NextGen[IX(r,c)].pos = CurGen[IX(r,c)].pos; X } X if (boundhc) { X c = maxcols - 1; X for (r=1; r<maxrows-1; r++) X NextGen[IX(r,c)].pos = CurGen[IX(r,c)].pos; X } X if (boundlrlc) X NextGen[IX(0,0)].pos = CurGen[IX(0,0)].pos; X if (boundlrhc) X NextGen[IX(0,maxcols-1)].pos = CurGen[IX(0,maxcols-1)].pos; X if (boundhrlc) X NextGen[IX(maxrows-1,0)].pos = CurGen[IX(maxrows-1,0)].pos; X if (boundhrhc) X NextGen[IX(maxrows-1,maxcols-1)].pos = X CurGen[IX(maxrows-1,maxcols-1)].pos; X} X X/* The trivial case - next generation is exactly like this one (useful for X * examing the forcing function without having any propagation effects get X * in the way) X */ XCalcNone() X{ X int r, c; X X for (r = 0; r < maxrows; r++) X for (c = 0; c < maxcols; c++) X NextGen[IX(r,c)].pos = CurGen[IX(r,c)].pos; X} X X/* original propagation model written by Friedman and Riddle. X * A relaxation model; no velocity component, so no wave propagation; X * next generation position of each point is independent of current position. X */ XCalcRelax() X{ X int r, c; X X for (r = 1; r < maxrows - 1; r++) X for (c = 1; c < maxcols - 1; c++) X NextGen[IX(r,c)].pos = (int) (0.25 * X ( CurGen[IX(r - 1,c)].pos X + CurGen[IX(r,c - 1)].pos X + CurGen[IX(r,c + 1)].pos X + CurGen[IX(r + 1,c)].pos)); X X /* boundary stuff added by jimmc */ X if (!boundlr) { X r = 0; X for (c=1; c<maxcols-1; c++) { X NextGen[IX(r,c)].pos = (int) ( X ( CurGen[IX(r,c - 1)].pos X + CurGen[IX(r,c + 1)].pos X + CurGen[IX(r + 1,c)].pos) / 3.0 ); X } X } X if (!boundhr) { X r = maxrows-1; X for (c=1; c<maxcols-1; c++) { X NextGen[IX(r,c)].pos = (int) ( X ( CurGen[IX(r,c - 1)].pos X + CurGen[IX(r,c + 1)].pos X + CurGen[IX(r - 1,c)].pos) / 3.0 ); X } X } X if (!boundlc) { X c = 0; X for (r=1; r<maxrows-1; r++) { X NextGen[IX(r,c)].pos = (int) ( X ( CurGen[IX(r - 1,c)].pos X + CurGen[IX(r,c + 1)].pos X + CurGen[IX(r + 1,c)].pos) / 3.0 ); X } X } X if (!boundhc) { X c = maxcols - 1; X for (r=1; r<maxrows-1; r++) { X NextGen[IX(r,c)].pos = (int) ( X ( CurGen[IX(r - 1,c)].pos X + CurGen[IX(r,c - 1)].pos X + CurGen[IX(r + 1,c)].pos) / 3.0 ); X } X } X if (!boundlrlc) X NextGen[IX(0,0)].pos = (int) ( X ( CurGen[IX(1,0)].pos X + CurGen[IX(0,1)].pos) / 2.0 ); X if (!boundlrhc) X NextGen[IX(0,maxcols-1)].pos = (int) ( X ( CurGen[IX(1,maxcols-2)].pos X + CurGen[IX(0,maxcols-1)].pos) / 2.0 ); X if (!boundhrlc) X NextGen[IX(maxrows-1,0)].pos = (int) ( X ( CurGen[IX(maxrows-2,0)].pos X + CurGen[IX(maxrows-1,1)].pos) / 2.0 ); X if (!boundhrhc) X NextGen[IX(maxrows-1,maxcols-1)].pos = (int) ( X ( CurGen[IX(maxrows-2,maxcols-1)].pos X + CurGen[IX(maxrows-1,maxcols-2)].pos) / 2.0 ); X CalcBoundedNext(); X} X X/* wave propagation using simple damped spring model. X * Spring model is f = - k*x - b*v where k is spring constant, b is damping X * factor. X * x is sum of offsets from four neighbors (to which other end of springs X * are attached). X */ XCalcWave() X{ X int r, c; X int f; X X for (r = 1; r < maxrows - 1; r++) { X for (c = 1; c < maxcols - 1; c++) { X f = (int) (springconst * ( X CurGen[IX(r-1,c)].pos + CurGen[IX(r,c-1)].pos + X CurGen[IX(r,c+1)].pos + CurGen[IX(r+1,c)].pos - X 4*CurGen[IX(r,c)].pos) - X dampfactor*CurGen[IX(r,c)].vel); X /* a=f/m; assume m=1, so a=f */ X NextGen[IX(r,c)].vel = CurGen[IX(r,c)].vel + f; X NextGen[IX(r,c)].pos = CurGen[IX(r,c)].pos + X NextGen[IX(r,c)].vel; X } X } X if (!boundlr) { X r = 0; X for (c=1; c<maxcols-1; c++) { X f = (int) (springconst * ( X CurGen[IX(r,c-1)].pos + X CurGen[IX(r,c+1)].pos + CurGen[IX(r+1,c)].pos - X 3*CurGen[IX(r,c)].pos) - X dampfactor*CurGen[IX(r,c)].vel); X /* a=f/m; assume m=1, so a=f */ X NextGen[IX(r,c)].vel = CurGen[IX(r,c)].vel + f; X NextGen[IX(r,c)].pos = CurGen[IX(r,c)].pos + X NextGen[IX(r,c)].vel; X } X } X if (!boundhr) { X r = maxrows-1; X for (c=1; c<maxcols-1; c++) { X f = (int) (springconst * ( X CurGen[IX(r,c-1)].pos + X CurGen[IX(r,c+1)].pos + CurGen[IX(r-1,c)].pos - X 3*CurGen[IX(r,c)].pos) - X dampfactor*CurGen[IX(r,c)].vel); X /* a=f/m; assume m=1, so a=f */ X NextGen[IX(r,c)].vel = CurGen[IX(r,c)].vel + f; X NextGen[IX(r,c)].pos = CurGen[IX(r,c)].pos + X NextGen[IX(r,c)].vel; X } X } X if (!boundlc) { X c = 0; X for (r=1; r<maxrows-1; r++) { X f = (int) (springconst * ( X CurGen[IX(r+1,c)].pos + X CurGen[IX(r,c+1)].pos + CurGen[IX(r-1,c)].pos - X 3*CurGen[IX(r,c)].pos) - X dampfactor*CurGen[IX(r,c)].vel); X /* a=f/m; assume m=1, so a=f */ X NextGen[IX(r,c)].vel = CurGen[IX(r,c)].vel + f; X NextGen[IX(r,c)].pos = CurGen[IX(r,c)].pos + X NextGen[IX(r,c)].vel; X } X } X if (!boundhc) { X c = maxcols - 1; X for (r=1; r<maxrows-1; r++) { X f = (int) (springconst * ( X CurGen[IX(r+1,c)].pos + X CurGen[IX(r,c-1)].pos + CurGen[IX(r-1,c)].pos - X 3*CurGen[IX(r,c)].pos) - X dampfactor*CurGen[IX(r,c)].vel); X /* a=f/m; assume m=1, so a=f */ X NextGen[IX(r,c)].vel = CurGen[IX(r,c)].vel + f; X NextGen[IX(r,c)].pos = CurGen[IX(r,c)].pos + X NextGen[IX(r,c)].vel; X } X } X if (!boundlrlc) { X r = 0; c = 0; X f = (int) (springconst * ( X CurGen[IX(r,c+1)].pos + CurGen[IX(r+1,c)].pos - X 2*CurGen[IX(r,c)].pos) - X dampfactor*CurGen[IX(r,c)].vel); X /* a=f/m; assume m=1, so a=f */ X NextGen[IX(r,c)].vel = CurGen[IX(r,c)].vel + f; X NextGen[IX(r,c)].pos = CurGen[IX(r,c)].pos + X NextGen[IX(r,c)].vel; X } X if (!boundlrhc) { X r = 0; c = maxcols-1; X f = (int) (springconst * ( X CurGen[IX(r,c-1)].pos + CurGen[IX(r+1,c)].pos - X 2*CurGen[IX(r,c)].pos) - X dampfactor*CurGen[IX(r,c)].vel); X /* a=f/m; assume m=1, so a=f */ X NextGen[IX(r,c)].vel = CurGen[IX(r,c)].vel + f; X NextGen[IX(r,c)].pos = CurGen[IX(r,c)].pos + X NextGen[IX(r,c)].vel; X } X if (!boundhrlc) { X r = maxrows-1; c = 0; X f = (int) (springconst * ( X CurGen[IX(r,c+1)].pos + CurGen[IX(r-1,c)].pos - X 2*CurGen[IX(r,c)].pos) - X dampfactor*CurGen[IX(r,c)].vel); X /* a=f/m; assume m=1, so a=f */ X NextGen[IX(r,c)].vel = CurGen[IX(r,c)].vel + f; X NextGen[IX(r,c)].pos = CurGen[IX(r,c)].pos + X NextGen[IX(r,c)].vel; X } X if (!boundhrhc) { X r = maxrows-1; c = maxcols-1; X f = (int) (springconst * ( X CurGen[IX(r,c-1)].pos + CurGen[IX(r-1,c)].pos - X 2*CurGen[IX(r,c)].pos) - X dampfactor*CurGen[IX(r,c)].vel); X /* a=f/m; assume m=1, so a=f */ X NextGen[IX(r,c)].vel = CurGen[IX(r,c)].vel + f; X NextGen[IX(r,c)].pos = CurGen[IX(r,c)].pos + X NextGen[IX(r,c)].vel; X } X CalcBoundedNext(); X} X XFtab WaveTab[] = { X { "relax", CalcRelax }, X { "wave", CalcWave }, X { "none", CalcNone }, X}; Xint WaveTabSize = sizeof(WaveTab)/sizeof(WaveTab[0]); X XInitWaveFunc() X{ X WaveIndex = 0; X WaveFunc = WaveTab[WaveIndex].func; X} X XPrintWaveFuncs(fp) XFILE *fp; X{ X int i; X X fprintf(fp,"Wave propagation functions are:\n"); X for (i=0; i<WaveTabSize; i++) { X fprintf(fp," %s",WaveTab[i].name); X } X fprintf(fp,"\n"); X} X XSetNextWaveFunc() X{ X WaveIndex++; X if (WaveIndex>=WaveTabSize) WaveIndex = 0; X WaveFunc = WaveTab[WaveIndex].func; X printf("Wave propagation function is set to %s\n", X WaveTab[WaveIndex].name); X} X XSetNamedWaveFunc(s) Xchar *s; X{ X int i; X X for (i=0; i<WaveTabSize; i++) { X if (strcmp(WaveTab[i].name,s)==0) { X WaveIndex = i; X WaveFunc = WaveTab[WaveIndex].func; X return 1; X } X } X return 0; /* not found */ X} X XSetBound(s) Xchar *s; X{ X int i; X int t; X X if (!s) return; X if (strcmp(s,"0")==0) s="00000000"; X if (strcmp(s,"1")==0) s="11111111"; X for (i=0; *s && i<8; i++) { X bound[i] = (*s++!='0'); X } X} X X/* end */ END_OF_FILE if test 8429 -ne `wc -c <'prop.c'`; then echo shar: \"'prop.c'\" unpacked with wrong size! fi # end of 'prop.c' 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'\" \(11740 characters\) sed "s/^X//" >'xwave.c' <<'END_OF_FILE' X/****************************************************************************** X** xwave - A 3-d perspective mesh for X X** X** Original Authors: (Jan 1991) X** Mike Friedman (mikef@umbc3.umbc.edu) X** Paul Riddle (paulr@umbc3.umbc.edu) X** X** Additional Help: X** Joe Poole (joe@umbc3.umbc.edu) X** X** University of Maryland, Baltimore County X* X* Enhanced by Jim McBeath (jimmc@hisoft.uucp) Feb 1991 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#include "xwave.h" X#include "patchlevel.h" X#include <sys/types.h> X#include <sys/time.h> X X X#define DFLTMAXROWS 18 X#define DFLTMAXCOLS 25 X#define GENS 2 X#define SINTABSIZE 400 X#define TWOPI 6.283 X X#define NFRAMES 50 X X#define ROOT 0x1 X X#define SPRINGCONST 0.01 X#define DAMPFACTOR 0.001 X Xextern double atof(); X Xextern int (*ForceFunc)(); Xextern int (*WaveFunc)(); X Xextern Display *dpy; Xextern int ampl; X Xextern int numEditedPoints; X Xint maxrows = DFLTMAXROWS; Xint maxcols = DFLTMAXCOLS; Xint CurIndex = 0; Xint NextIndex = 1; Xstruct pinfo *Generation[GENS]; Xstruct pinfo NullPinfo = {0}; Xstruct pinfo *CurGen; Xstruct pinfo *NextGen; X Xint *amplitudes; Xint *frequencies; Xint *editedRowVals; Xint *editedColVals; X Xdouble sinTab[SINTABSIZE]; Xint sinTabSize = SINTABSIZE; X Xint running = 1; Xint fftime; Xint omega=5; Xint omega2=10; Xint forcerow = -1; Xint forcecol = -1; Xint forceptr = -1; Xint forceptc = -1; Xint forcefull = 0; X Xdouble springconst = SPRINGCONST; Xdouble dampfactor = DAMPFACTOR; X Xint flagtime=0; Xint flagstereo=0; Xint flagroot=0; Xint flagplotvel=0; Xint flagedit=0; Xint didedit=0; X Xint nf; Xint start; X X Xchar * Xsmalloc(s) Xint s; X{ X extern char *malloc(); X char *p; X X p = malloc(s); X if (p) return p; X fprintf(stderr,"No more memory\n"); X exit(2); X} X Xchar * Xscalloc(n,s) Xint n,s; X{ X extern char *calloc(); X char *p; X X p = calloc(n,s); X if (p) return p; X fprintf(stderr,"No more memory\n"); X exit(2); X} X Xchar *demoorig[] = { "original" }; /* the original - no args */ Xchar *demodeltapoint[] = { "deltapoint", "-force", "delta", "-wave", "wave", X "-omega", "2" }; Xchar *demodeltarow[] = { "deltarow", "-force", "delta", "-wave", "wave", X "-forcerow", "8", "-amp", "30", "-omega", "2", "-bound", "0" }; Xchar *demosineh[] = { "sineh", "-force", "onehalfsinesquared", "-wave", "wave", X "-rows", "2", "-cols", "50", "-forcecol", "0", "-bound", "00111000", X "-omega", "1", "-omega2", "4" }; Xchar *demosine[] = { "sine", "-force", "sine", "-wave", "wave", X "-rows", "2", "-cols", "48", "-forcecol", "0", "-bound", "00111000", X "-omega", "5", "-plotvel", "-springconst", "0.05" }; Xchar *demopulse[] = { "pulse", "-force", "pulse", "-forcefull", "-wave", "wave", X "-omega", "1", "-omega2", "4", "-rows", "2", "-cols", "46", X "-forcecol", "0", "-bound", "00111000", "-springconst", "0.05", X "-plotvel" }; Xchar *demopulse2[] = { "pulse", "-force", "pulse", "-wave", "wave", X "-omega", "2", "-omega2", "4" }; X/* remember to add new demo to demoinfo table below */ X Xstruct { X char **p; X int n; X} demoinfo [] = { X { demoorig, sizeof(demoorig)/sizeof(demoorig[0]) }, X { demodeltapoint, sizeof(demodeltapoint)/sizeof(demodeltapoint[0]) }, X { demodeltarow, sizeof(demodeltarow)/sizeof(demodeltarow[0]) }, X { demosineh, sizeof(demosineh)/sizeof(demosineh[0]) }, X { demosine, sizeof(demosine)/sizeof(demosine[0]) }, X { demopulse, sizeof(demopulse)/sizeof(demopulse[0]) }, X { demopulse2, sizeof(demopulse2)/sizeof(demopulse2[0]) }, X}; Xint demoinfocount = sizeof(demoinfo)/sizeof(demoinfo[0]); X Xint XfindDemo(s) Xchar *s; X{ X int i; X X i = atoi(s); X if (i>0 || strcmp(s,"0")==0) { X if (i>=demoinfocount) { X (void)fprintf(stderr,"Max demo number is %d\n", X demoinfocount-1); X exit(1); X } X return i; /* he specified a number (index) */ X } X for (i=0; i<demoinfocount; i++) { X if (strcmp(demoinfo[i].p[0],s)==0) X return i; X } X (void)fprintf(stderr,"No such demo switch %s\n",s); X exit(1); X} X XDemoSwitch(s) Xchar *s; X{ X int n; X X n = findDemo(s); X ProcessArgs(demoinfo[n].n,demoinfo[n].p); X} X XPrintDemoSwitch(s) Xchar *s; X{ X int i,n; X X n = findDemo(s); X for (i=0; i<demoinfo[n].n; i++) { X printf("%s ",demoinfo[n].p[i]); X } X printf("\n"); X exit(0); X} X XListDemoSwitches(fp) XFILE *fp; X{ X int i; X X fprintf(fp,"Demo switches are:\n"); X for (i=0; i<demoinfocount; i++) { X fprintf(fp," %s", demoinfo[i].p[0]); X } X fprintf(fp,"\n"); X} X XProcessArgs(argc,argv) Xint argc; Xchar *argv[]; X{ X int i; X X for (i=1; i<argc; i++) { X if (strcmp (argv[i], "-edit")==0) { X flagedit = 1; X didedit = 1; X } X else if (strcmp (argv[i], "-root")==0) X flagroot = 1; X else if (strcmp (argv[i], "-stereo")==0) X flagstereo = 1; X else if (strcmp(argv[i],"-springconst")==0) { X springconst = atof(argv[++i]); X } X else if (strcmp(argv[i],"-dampfactor")==0) { X dampfactor = atof(argv[++i]); X } X else if (strcmp(argv[i],"-rows")==0) { X maxrows = atoi(argv[++i]); X if (maxrows<2) maxrows = 2; X else if (maxrows>25) maxrows = 25; X } X else if (strcmp(argv[i],"-cols")==0) { X maxcols = atoi(argv[++i]); X if (maxcols<2) maxcols = 2; X } X else if (strcmp(argv[i],"-omega")==0) { X omega = atoi(argv[++i]); X if (omega<=0) omega=1; /* can't divide by 0 */ X } X else if (strcmp(argv[i],"-omega2")==0) { X omega2 = atoi(argv[++i]); X if (omega2<=0) omega2=1; /* can't divide by 0 */ X } X else if (strcmp(argv[i],"-amp")==0) { /* forcing amplitude */ X ampl = atoi(argv[++i]); X if (ampl<=0) ampl = 100; X } X else if (strcmp(argv[i],"-force")==0) { X if (!SetNamedForceFunc(argv[++i])) { X usage(); X exit(1); X } X } X else if (strcmp(argv[i],"-forcerow")==0) { X forcerow = atoi(argv[++i]); X } X else if (strcmp(argv[i],"-forcecol")==0) { X forcecol = atoi(argv[++i]); X } X else if (strcmp(argv[i],"-forcepoint")==0) { X forceptr = atoi(argv[++i]); X forceptc = atoi(argv[++i]); X } X else if (strcmp(argv[i],"-forcefull")==0) { X forcefull = 1; X } X else if (strcmp(argv[i],"-bound")==0) { X SetBound(argv[++i]); X } X else if (strcmp(argv[i],"-wave")==0) { X if (!SetNamedWaveFunc(argv[++i])) { X usage(); X exit(1); X } X } X else if (strcmp(argv[i],"-demo")==0) { X DemoSwitch(argv[++i]); X } X else if (strcmp(argv[i],"-printdemo")==0) { X PrintDemoSwitch(argv[++i]); X } X else if (strcmp(argv[i],"-plotvel")==0) { X flagplotvel = 1; X } X else if (strcmp(argv[i],"-version")==0) { X (void)printf("xwave version %d.%d, %s\n", X VERSION, PATCHLEVEL, VDATE); X exit(0); X } X else { X usage(); X exit (1); X } X } X} X XCheckArgs() X{ X if (forcerow >= maxrows) X forcerow = maxrows/2; X if (forcecol >= maxcols) X forcecol = maxcols/2; X if (forceptr >= maxrows) X forceptr = maxrows/2; X if (forceptc >= maxcols) X forceptc = maxcols/2; X if (forcerow<0 && forcecol<0) { X if (forceptr<0) X forceptr = maxrows/2; X if (forceptc<0) X forceptc = maxcols/2; X } else { X forceptr = forceptc = -1; X } X} X Xusage() X{ X (void)fprintf(stderr, "Usage: xwave [-edit] [-root] [-stereo] [-springconst K]\n"); X (void)fprintf(stderr, " [-dampfactor B] [-rows r] [-cols c]\n"); X (void)fprintf(stderr, " [-force func] [-wave func] [-bound bits]\n"); X (void)fprintf(stderr, " [-omega n] [-omega2 n] [-amp n]\n"); X (void)fprintf(stderr, " [-forcerow r] [-forcecol c] [-forcepoint r c]\n"); X (void)fprintf(stderr, " [-forcefull]\n"); X (void)fprintf(stderr, " [-demo D] [-printdemo D] [-plotvel] [-version]\n"); X PrintForceFuncs(stderr); X PrintWaveFuncs(stderr); X ListDemoSwitches(stderr); X} X XAllocData() X{ X Generation[0] = (struct pinfo *)smalloc(sizeof(struct pinfo)* X maxrows*maxcols); X Generation[1] = (struct pinfo *)smalloc(sizeof(struct pinfo)* X maxrows*maxcols); X amplitudes = (int *)scalloc(maxrows*maxcols,sizeof(int)); X frequencies = (int *)scalloc(maxrows*maxcols,sizeof(int)); X editedRowVals = (int *)scalloc(maxrows,sizeof(int)); X editedColVals = (int *)scalloc(maxcols,sizeof(int)); X} X XClearData() X{ X int r, c, g; X X /* clear the forcing function timer */ X fftime = 0; X X /* Zero out the generation matrix */ X for (r = 0; r < maxrows; r++) X for (c = 0; c < maxcols; c++) X for (g = 0; g<GENS; g++) X Generation[g][IX(r,c)] = NullPinfo; X X CurIndex = 0; X NextIndex = 1; X CurGen = Generation[CurIndex]; X NextGen = Generation[NextIndex]; X} X X/* This routine initializes the sine table. The table is accessed during X * computation to speed things up somewhat. */ Xvoid setupSinTable (sinTab) Xdouble *sinTab; X{ X int i; X double t = 0.0; X X for (i = 0; i < SINTABSIZE; i++, t += TWOPI / SINTABSIZE) X sinTab[i] = sin (t); X} X XDumpCur() X{ X int r,c; X int v,p; X X for (r = 0; r < maxrows; r++) { X for (c = 0; c < maxcols; c++) { X v = CurGen[IX(r,c)].vel; X p = CurGen[IX(r,c)].pos; X if (v!=0 || p!=0) X printf("[%d,%d]=(%d,%d)\n",r,c,v,p); X } X } X} X XProcessKey(s) Xchar *s; X{ X if (strcmp(s,"t")==0) { /* time # frames */ X nf=0; X flagtime=!flagtime; X } X else if (strcmp(s,"c")==0) { /* clear */ X ClearData(); X ShowData(); X } X else if (strcmp(s,"d")==0) { /* (load) data */ X (*ForceFunc)(); X ShowData(); X } X else if (strcmp(s,"f")==0) { /* forcing function */ X SetNextForceFunc(); X } X else if (strcmp(s,"p")==0) { /* print data */ X DumpCur(); X } X else if (strcmp(s," ")==0) { /* step */ X Step(); X ShowData(); X } X else if (strcmp(s,"r")==0) /* run mode */ X running = !running; X else if (strcmp(s,"q")==0) /* q to exit */ X exit(0); X else if (strcmp(s,"w")==0) { /* wave propagation function */ X SetNextWaveFunc(); X } X else XBell(dpy,25); /* unknown */ X} X XProcessEvent() 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 XEvent event; X int t; X char cbuf[20]; X X XNextEvent (dpy, &event); X switch (event.type) { X case ConfigureNotify: X HandleResize(&event); X break; X case KeyPress: X if (!flagedit) { X t = XLookupString(&event,cbuf,sizeof(cbuf), X (KeySym *)NULL, (XComposeStatus *)NULL); X if (t<=0) break; X flagedit = 0; X cbuf[t] = '\0'; X ProcessKey(cbuf); X break; X } X default: X break; X } X} X XStep() X{ X (*WaveFunc)(); /* calculate values at the next time point */ X CurIndex ^= 1; /* swap next and current buffers */ X NextIndex ^= 1; X CurGen = Generation[CurIndex]; X NextGen = Generation[NextIndex]; X X (*ForceFunc)(); /* apply forcing function */ X X} X Xmain (argc, argv) Xint argc; Xchar *argv[]; X{ X int t; X X InitWaveFunc(); X InitForceFunc(); X X ProcessArgs(argc,argv); X CheckArgs(); /* check for consistency etc. */ X AllocData(); X ClearData(); X InitWindow (); X setupSinTable (sinTab); X if (flagroot) X WaitForExpose(); X while (1) { X if (running) { X if (flagtime) { X if (nf==0) X start = time((time_t)0); X if (nf==NFRAMES) { X printf("#frames/sec.~%f\n", X (float)nf/((time((time_t)0)-start))); X nf = 0; X } X else X nf++; X } X if (QLength (dpy)) { X ProcessEvent(); X } X DoQueryPointer(); X if (flagedit) X edit(); X Step(); X ShowData(); X } X else { X ProcessEvent(); X if (flagedit) X edit(); X } X } X /* NOTREACHED */ X} X X/* end */ X X X X X X X END_OF_FILE if test 11740 -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 Heller ------------------------------------------------ O'Reilly && Associates Zyrcom Inc Senior Writer President argv@ora.com argv@zipcode.com