[comp.sources.atari.st] v01i079: raymovi2 -- Raytrace movie generator part02/02

koreth@ssyx.ucsc.edu.ucsc.edu (Steven Grimm) (12/20/88)

Submitted-by: aking@bbn.com (Allen King)
Posting-number: Volume 1, Issue 79
Archive-name: raymovi2/part02

#!/bin/sh
# this is part 2 of a multipart archive
# do not concatenate these parts, unpack them in order with /bin/sh
# file RAYMOVI.DOK continued
#
CurArch=2
if test ! -r s2_seq_.tmp
then echo "Please unpack part 1 first!"
     exit 1; fi
( read Scheck
  if test "$Scheck" != $CurArch
  then echo "Please unpack part $Scheck next!"
       exit 1;
  else exit 0; fi
) < s2_seq_.tmp || exit 1
sed 's/^X//' << 'SHAR_EOF' >> RAYMOVI.DOK
XThus following the completion of every frame, RAYMOVI saves the current 
Xconfiguration on the disk so that if the computation of the next frame 
Xis interupted, it may be restarted.  The checkpointing information
Xis written in a file named CHECKPT, in configuration file format. Starting
XRAYMOVI with CHECKPT will continue an interupted computation, redoing
Xonly any work which was in progress on the interupted frame.
X
X
X
X			CONFIGURATION FILE FORMAT
X
X
X   The following section discusses the format of the configuration files,
Xwhich specify initial ball positions, velocities and optical properties, 
Xas well as lighting and viewing perspectives, picture resolution, and gravity.
XThe configuration file name to be used is specified initially with a dialog. 
XThe file is then read line at a time. The character in column 1 specifies the 
Xmeaning of the rest of each line. Lines may be up to 200 characters long. Lines 
Xbeginning with whitespace are comments. The following other formats are 
Xsupported:
X
X
X
X     - - - 'p' Format: - - -
X
Xspecifies the physical size and velocity of a ball. There are 7 properties 
Xrequired for each ball, and they all must be specified on one line in the 
Xfollowing order: 
X
X (1) x coordinate of center		(2) x velocity
X (3) y coordinate			(4) y velocity   
X (5) z coordinate			(6) z velocity
X (7) radius
X
XSome Notes:
X A) In the coordinate system used, Y is upward, X is to the right, and Z 
X    is depth (increasing Z moves farthur away).
X B) Balls will bounce off the floor (the plane Y == 0) and an invisible 
X    viewing port (the plane Z==0). Be sure to start them so that the whole
X    extent of the ball is above the floor and farther away than the
X    invisible viewing port.
X C) If balls start out overlapping, they will stick together.
X    This turned out to be a serendipitous bug in the bounce algorithm,
X    and produces the string of pearls from which PEARLS gets its name.
X D) The current version is compiled for up to 15 balls maximum.
X
X   The first p-format statement in the file defines the "first" ball RAYMOVI 
Xknows about, the second the second and so on. Here are 6 balls which
Xform an interesting scene:
X
X   x     vx      y     vy    z      vz   radius
X  (1)    (2)	(3)    (4)   (5)    (6)  (7)	  (see (1)-(7) above)
Xp 195.0,-20,	130.0, 0,    250.0, 10,  30.0 	these are the 4 linked balls:
Xp 150.0, -5, 	100.0, 20,   250.0, 10,  30.0 		"
Xp 105.0,  5,	 70.0, 20,   250.0,-20,  30.0 		"
Xp  60.0, 20,	 40.0,  0,   250.0,-20,  30.0 		"
Xp   0.0,-10,	300.0, 20,   600.0,  0, 300.0	this is the big ball
Xp 200.0,  2,	 50.0,  5,    60.0, 30,  50.0	a medium size (lone) ball
X
X
X
X
X     - - - 'o' Format: - - - 
X
Xspecifies the optical properties of a ball. The following 8 properties 
Xmust be put on one line, and in order:
X
X (1) index of refraction
X
X (2) amount of refraction (transparent)
X (3) amount of reflection (mirror)
X (4) amount of diffuse light (omnidirectional)
X (5) amount of ambient light (from light source)
X
X (6) surface color redness
X (7) surface color greenness
X (8) surface color blueness
X
X
XSome notes are in order to make realistic objects:
X A) All parameters should be positive or zero.
X B) Items (2) through (5) should sum to less than 1.0
X C) Surface colors (6) through (8) modulate the effect the diffuse and ambient
X    reflective properties defined by (4) and (5). None should be greater than 
X    1.0.
X C) Due to the size of the ST's color palette, surface color items (6) 
X    through (8) are constrained to be patterns corresponding to one of the 
X    following three colors:
X
X		white:		(6) == (7) == (8) == 1.0
X		red:		(6) == (7) == 1.0, (8) == 0.0
X		blue:		(6) == 0.0, (7) == (8) == 1.0
X
X
X   The i'th 'o' Format line refers to the same ball as the i'th 'p' Format line.
XHere are the optical properties for the scene:
X
X  (1)  (2)  (3)  (4)  (5)    (6) (7) (8)
Xo 0.0, 0.0, 0.3, 0.6, 0.1,   1.0,0.0,0.0   diffuse red, somewhat reflective
Xo 0.0, 0.0, 0.6, 0.3, 0.1,   1.0,1.0,1.0   reflective, somewhat white
Xo 0.0, 0.0, 0.9, 0.0, 0.1,   1.0,1.0,1.0   reflective, some ambient
Xo 0.0, 0.0, 0.0, 0.8, 0.2,   1.0,0.0,0.0   diffuse red, some ambient
Xo 0.0, 0.0, 0.7, 0.1, 0.2,   1.0,1.0,1.0   reflective and ambient (the big one)
Xo 1.6, 0.8, 0.0, 0.0, 0.2,   1.0,1.0,1.0   refractive
X
X
X
X
X     - - - 'v' Format: - - -
X
Xspecifies the viewpoint of the display. x, y, and z values are required.
X
Xv 215.0, 	100.0,       -550.0
X  |		|	     z coordinate of viewpoint
X  |		y coordinate of viewpoint
X  x coordinate of viewpoint
X
XAll rays start at the viewpoint and pass through a rectangle in the Z=0
Xplane. The rectangle is sized according to the size of the screen -- namely
Xon a 320x200 low resolution screen, it is defined by 0.0 < X < 320.0 and
X0.0 < Y < 200.0. (Actually, borders eat a few pixels on all sides.)
X
X
X     - - - 'l' Format: - - -
X
X   specifies the location of the lightsource, and its diameter. Like before
Xits x, y, and z coordinates, now followed by the diameter of the light.
X
Xl 150.0, 	950.0,          0.0, 		100.0
X
X
X     - - - 'r' Format: - - -
X
Xspecifies the resolution of the picture to be produced, in Rays projected
Xthrough each Pixel, followed by the color schema index, a number from 1 
Xthrough 3.
X
Xr .20, 3
X
X   The inputted value of Rays Per Pixel will be rounded up to the next 
Xgreater power of 4.0. Thus in the line above, the .20 will be rounded up 
Xto (4.0)**(-1) = .25.
X
X   The time to compute images varies linearly with the resolution (Rays Per
XPixel) chosen. The constant of proportionality varies greatly depending on 
Xthe complication of the scene, but for the 6-ball scene here on a 520ST:
X
X	  .0625 rays per pixel	  4 min
X	  .25 rays per pixel	 15 min
X	 1.0 rays per pixel	  1 hr
X	 4.0 rays per pixel       4 hrs
X	16.0 rays per pixel	 16 hrs
X
XI tend to use .25 rays per pixel to experiment with positions and velocities,
Xsince one can generate a couple dozen frames overnight. Once the positions
Xlook good, a few nights of 4.0 rays per pixel produces good looking images.
XI can tell the difference between 16.0 and 4.0 rays per pixel (sort of) but
Xit is hardly worth the time it takes. 0.625 is skimping, but its quick.
X
X
X   The color index specifies how the 16 colors of the low resolution monitor
Xare divided amongst hues and saturation. Three values are accepted currently:
X
X	1:	white			16 saturations
X	2:	white, red		8 saturations each
X	3:	white, red, blue	6 saturations each
X
XAlthough the ray tracing algorithm computes arbitrary red/green/blue hues,
Xthe palate limitations of the ST prohibit their display.
X
X
X
X
X     - - - 'g' Format: - - -
X
Xspecifies the strength of gravity, the mutual attraction between balls,
Xand if balls bounce (in order). The following is realistic:
X
Xg 32.0, 0.3, 1
X
X(Note: if balls do not bounce, they may occupy the same space. In that case
Xthe current the ray tracing algorithm does not properly render refractive 
Xobjects.)
X
X     - - - 'f' Format: - - -
X
Xspecifies the first 5 characters of the filename to be used to save 
Xcompleted pictures. (The rest of the name is the frame sequence number,
Xand the suffix .PI1)  Also specified are the starting and ending frame
Xnumbers to be computed (positive integers less than 999).
X
Xf pearl, 1, 20
X
Xgenerates 20 frames on the disk, labeled PEARLL001.PI1 through PEARL020.PI1.
XAt 32K per frame, that will just about fill a double sided drive.
X
X
X
X			--------------
X
X   Thats it for now. Tell me of you ventures, send me interesting 
Xconfigurations you find, and enjoy!
X
X
X
X		Allen King	aking  bfly-vax.bbn.com  ucbvax
X		30 Gibson St	1-617-449-3359 evenings	
X		Needham Ma.	
X		02192
SHAR_EOF
chmod 0600 RAYMOVI.DOK || echo "restore of RAYMOVI.DOK fails"
sed 's/^X//' << 'SHAR_EOF' > RAYMOVI.LNK &&
X\include\gemstart.o main.o wndows.o movie.o file.o shade.o find.o support.o
X\include\aesbind \include\vdibind \include\gemlib \include\osbind.o 
X\include\libf
SHAR_EOF
chmod 0600 RAYMOVI.LNK || echo "restore of RAYMOVI.LNK fails"
sed 's/^X//' << 'SHAR_EOF' > README &&
X			RAYMOVI.PRG
X
X   RAYMOVI.PRG renders 3-dimensional scenes in a world of reflective and 
Xrefractive spheres, using ray tracing techniques. Animated sequences of 
Xframes can be generated, showing reflective balls linked and bouncing in 
Xa gravitational field. They resemble a string of bouncing pearls.
X
X   RAYMOVI.PRG runs only on a color ST in low resolution. 1 Meg is required 
Xto generate images with resolutions greater than one ray per pixel or for 
Xreplay of movies from RAM. Operation with only 512K is possible, but will 
Xproduce slightly aliased pictures (one ray per pixel) which can only be 
Xdisplayed statically, slowly from floppy, or from hard disk (if you have 
Xa disk blaster program).
X
X	    --------------------------------------------------
X
X   The files in RAYMOV2S.ARC, the source arc, are:
X
XC Sources:  	BLASTRAM.C, MAIN.C, WNDOWS.C, FILE.C, MOVIE.C, SHADE.C, 
X		FIND.C, SUPPORT.C
XInclude files:	RTD.H, STYLE.H, COLORS.H, EXTERN.H
XPgm Generation: MAKEFILE, BLASTRAM.LNK, RAYMOVI.LNK
XRAYMOVI.DOK	documentation
XPEARLS		the numeric description of an interesting scene
X
X   RAYMOVI was last compiled with ALCYON. The MAKEFILE and *.LNK are 
X(therefore) pretty crufty. Use them accordingly.
X
X   RAYMOVI requires an 8K stack. Modify your copy of gemstart.s (or
Xwhatever defines your stack size) appropriately.
X
X
X	Allen King	aking  pebbles.bbn.com  ucbvax
X	30 Gibson St	1-617-449-3359 evenings	
X	Needham Ma.	
X	02192
X
X
X
SHAR_EOF
chmod 0600 README || echo "restore of README fails"
sed 's/^X//' << 'SHAR_EOF' > RTD.H &&
X#define NCOLORS 3
X#define HUGE 1e15
X#define EPSILON 1e-3
X
Xstruct vector
X    {
X    double x;
X    double y;
X    double z;
X    double l;
X    double xzl;
X    } ;
X
Xstruct ray
X    {
X    struct vector org;
X    struct vector dir;
X    } ;
X
Xstruct sphere
X    {
X    struct vector cent;
X    double rad;
X    } ;
X
Xstruct ball
X    {
X    struct sphere s;
X    double ior;
X    double rfr;
X    double rfl;
X    double dif;
X    double amb;
X    double red;
X    double green;
X    double blue;
X    struct vector v;
X    };
X
Xstruct mat
X    {
X    struct vector x;  	/* first !row! */
X    struct vector y;  	/*second !row! */
X    struct vector z;	 /* third !row! */
X    };
X
SHAR_EOF
chmod 0600 RTD.H || echo "restore of RTD.H fails"
sed 's/^X//' << 'SHAR_EOF' > SHADE.C &&
X/*
XFrom harvard!husc6!caip!nike!ucbcad!ucbvax!sdcsvax!net1!fritzz 25 Jul 86 21:35:59 GMT
XArticle 2915 of net.sources:
XRelay-Version: version B 2.10.2 9/18/84; site bbnccv.UUCP
XPath: bbnccv!harvard!husc6!caip!nike!ucbcad!ucbvax!sdcsvax!net1!fritzz
X>From: fritzz@net1.UCSD.EDU (Friedrich Knauss)
XNewsgroups: net.sources
XSubject: basic ray tracing: part 1 (tracer.c)
XMessage-ID: <190@net1.UCSD.EDU>
XDate: 25 Jul 86 21:35:59 GMT
XDate-Received: 27 Jul 86 01:07:29 GMT
XReply-To: fritzz@net1.UUCP (Friedrich Knauss)
XOrganization: University of California, San Diego
X*/
X/*
X * this subroutine does all the gritty work- it calculates 
X * what shade each pixel should be. I like recursion.
X */
X
X#include <math.h>
X#include "rtd.h"
X#include "extern.h"
X#define time(x) 0
X
X/* LEVEL defines number of levels of recursion */
X#define LEVEL 5
Xint debug;
X#define dprintf if (debug) printf
X
Xshade (r, red, green, blue)
Xstruct ray *r;
Xdouble *red, *green, *blue;
X{   int     i, c,
X            refract ();
X    struct ray  refr;
X    double  rd, gn, blu, tmp;
X    double  lght_red, lght_green, lght_blue,
X            x, y, z,
X            l, k,
X            dot (), find (), findo ();
X    struct vector   new, norm;
X    struct mat  trans;
X    struct sphere   ss;
X
X    if (++level <= LEVEL)
X    {	c = -1;
X	l = HUGE;
X
X	dprintf("LEVEL %d: ", level);
X        /* get vector length and xz component for mt() */
X	vecl (&r->dir);
X	vexzl (&r->dir);
X
X        /* make a transform matrix that rotates something in space so
X            that the ray will be aligned with the x axis */
X
X	mt (&r->dir, &trans);
X
X        /* for starters we find out whether we hit anything. */
X
X	for (i = 0; i < nob; i++)
X	{   ss.rad = bl[i].s.rad;
X	    sv (&ss.cent, &bl[i].s.cent, &r->org);
X	    if ((k = find (&trans, &ss)) > 0.0 && k < l)
X	    {	c = i;
X		l = k;
X	    }
X	}
X	if (c >= 0.0) 		/* WE HIT SOMETHING */
X	{   x = l * trans.x.x;
X	    y = l * trans.x.y;
X	    z = l * trans.x.z;
X	    mv (x, y, z, &new);
X
X	    /* move the new orgin of the ray to the intersection */
X
X	    av (&refr.org, &new, &r->org);
X	    av (&r->org, &new, &r->org);
X	    mv (r->dir.x, r->dir.y, r->dir.z, &refr.dir);
X
X	    /* get a normal vector for the intersection point */
X
X	    sv (&norm, &r->org, &bl[c].s.cent);
X	    vecl (&norm); 
X
X	    /* ambient lighting */
X
X	    tmp = 255.0 * bl[c].amb;
X	    lght_red = tmp * bl[c].red;
X	    lght_green = tmp * bl[c].green;
X	    lght_blue = tmp * bl[c].blue;
X	    dprintf(" ball[%d]", c);
X	    dprintf(", ambient=%d,%d,%d\n",
X		(int)lght_red, (int)lght_green, (int)lght_blue);
X
X	    /* shaded lighting (diffuse). subroutine shadow is in find.c */
X
X	    if (bl[c].dif != 0.0)
X	    {	sv (&new, &ls.cent, &r->org);
X		vecl (&new); 
X		if ((k = dot (&new, &norm)) > 0.0)
X		{   shadow (&r->org, &rd, &gn, &blu);
X		    dprintf("diffuse = %d, %d, %d\n",(int)rd,(int)gn,(int)blu);
X		    tmp = bl[c].dif * k / (new.l * norm.l);
X		    lght_red   += tmp * rd * bl[c].red;
X		    lght_green += tmp * rd * bl[c].green;
X		    lght_blue  += tmp * rd * bl[c].blue;
X	    }   }
X
X	    /*reflection... easy */
X
X	    if (bl[c].rfl != 0.0)
X	    {	vecl (&norm); 
X	  	/* make the normal unit length */
X		scamult ((1.0 / norm.l), &norm);
X		/* get the length of the ray's component in the normal direction */
X 		x = 2.0 * dot (&norm, &r->dir);
X		scamult (x, &norm);
X		/* subtract double the normal component- !reflection! */
X		sv (&r->dir, &r->dir, &norm);
X		shade (r, &rd, &gn, &blu);
X		dprintf("reflection = %d, %d, %d, tmp=%d\n", 
X			(int)rd, (int)gn, (int)blu, (int)tmp);
X		tmp = bl[c].rfl;
X		lght_red   += tmp * rd;
X		lght_green += tmp * gn;
X		lght_blue  += tmp * blu;
X	    }
X
X	    /* refraction. this is ugly, which is why I choose to deal with
X		   it in it's own subroutine which comes after this one */
X
X	    if (bl[c].rfr != 0.0)
X	    {	dprintf(" refraction\n");
X	    	refract (&refr, &bl[c], &rd, &gn, &blu);
X		tmp = bl[c].rfr;
X		dprintf("refraction = %d, %d, %d\n",(int)rd,(int)gn,(int)blu);
X		lght_red   += tmp * rd;
X		lght_green += tmp * gn;
X		lght_blue  += tmp * blu;
X	}   }
X	else 			/* hit no objects... */
X	{   if ((r->dir.y) < 0.0) /* crosses floor */
X	    {	z = -(r->org.y) / (r->dir.y);
X		(r->org.x) += z * (r->dir.x);
X		(r->org.z) += z * (r->dir.z);
X		(r->org.y) = 0.0;
X		dprintf("floor (%d, %d): ", (int)r->org.x, (int)r->org.z);
X		if (  ((int) ((r->org.x) / 9.0) % 8 == 0) 
X		   || ((int) ((r->org.z) / 9.0) % 8 == 0))
X		{   lght_red = lght_green = lght_blue = 0.0;
X		    dprintf("black. 0,0,0\n"); 
X		}		/* this is for texture, grid on the ground */
X		else 		/* get shading for the squares... */
X		{   sv (&new, &ls.cent, &r->org);
X		    vecl (&new); 
X		    shadow (&r->org, &rd, &gn, &blu);
X		    tmp = 0.6 * new.y / new.l;
X		    lght_blue   = tmp * blu + 100.0;	 /* tile pattern: */
X		    if ((int)r->org.x/72 & (int)r->org.z/72 & 0x15)
X		    {	lght_red = lght_green = 0.0;		/* blue */
X		        dprintf("blue. %d, %d, %d\n", 
X				(int)lght_red, (int)lght_green, (int)lght_blue);
X		    }
X		    else
X		    {	lght_red   = tmp * rd + 100.0;		/* white */
X			lght_green = tmp * gn + 100.0;
X			dprintf("white. %d,%d,%d\n", 
X			    (int)lght_red, (int)lght_green, (int)lght_blue);
X	    }	}   }
X	    else	/* didn't hit ground... sky */
X	    {	lght_red = lght_green = lght_blue = 0.0;
X		dprintf("sky. %d,%d,%d\n", 
X			(int)lght_red, (int)lght_green, (int)lght_blue);
X	    }
X	    dprintf("lght_= %d,%d,%d\n", 
X		(int)lght_red, (int)lght_green, (int)lght_blue);
X    }	}   
X    /* to many levels return 0 cause it shouldn't matter */
X    else
X    {	lght_red = lght_green = lght_blue = 0.0;
X	dprintf(">5 levels. 0, 0, 0\n");
X    }
X    level--;
X
X    if (lght_red < 0.0) 	lght_red = 0.0;
X    if (lght_red > 255.0)	lght_red = 255.0;
X
X    if (lght_green < 0.0) 	lght_green = 0.0;
X    if (lght_green > 255.0)	lght_green = 255.0;
X
X    if (lght_blue < 0.0) 	lght_blue = 0.0;
X    if (lght_blue > 255.0)	lght_blue = 255.0;
X
X    *red = lght_red;
X    *green = lght_green;
X    *blue = lght_blue;
X
X    dprintf("returned: %d, %d, %d\n", (int)*red, (int)*green, (int)*blue);
X}
X
Xint     refract (r, bll, red, green, blue)
Xstruct ray *r;
Xstruct ball *bll;
Xdouble *red, *green, *blue;
X{
X    struct vector   new, norm;
X    struct mat  trans;
X    double  l,
X            refk ();
X    struct sphere   ss;
X
X    sv (&norm, &r->org, &bll->s.cent);
X    vecl (&norm);
X    vecl (&r->dir);
X
X    /* get the addition factor for the normal */
X
X    scamult (refk (&norm, &r->dir, bll->ior), &norm);
X    av (&r->dir, &r->dir, &norm);
X
X    /* find the point where the ray leaves the sphere. just like shade. */
X
X    vexzl (&r->dir);
X    vecl (&r->dir);
X    mt (&r->dir, &trans);
X    ss.rad = bll->s.rad;
X    sv (&ss.cent, &bll->s.cent, &r->org);
X    l = findo (&trans, &ss);
X    mv (l * trans.x.x, l * trans.x.y, l * trans.x.z, &new);
X    av (&r->org, &r->org, &new);
X
X    /* redirect the ray and continue tracing */
X
X    sv (&norm, &r->org, &bll->s.cent);
X    vecl (&norm);
X    vecl (&r->dir);
X    scamult (refk (&norm, &r->dir, 1.0 / bll->ior), &norm);
X    av (&r->dir, &r->dir, &norm);
X
X    shade (r, red, green, blue);
X}
X
X
Xdouble  refk (nrm, in, ior)
Xstruct vector  *nrm, *in;
Xdouble  ior;
X{   double  dt, ln, li, ret;
X
X    dt = dot (nrm, in);
X    ln = nrm->x * nrm->x + nrm->y * nrm->y + nrm->z * nrm->z;
X    li = in->x * in->x + in->y * in->y + in->z * in->z;
X    ret = dt * dt - ln * li * (1 - ior);
X    if (ret < 0.0)
X	ret = 0.0;
X    if (dt < 0)
X	ret = (-dt - sqrt (ret)) / ln;
X    else
X	ret = (-dt + sqrt (ret)) / ln;
X    return (ret);
X}
X
Xprintv(s, v)
Xchar *s;
Xstruct vector *v;
X{	printf("%s.x = %f, .y = %f, .z = %f\n", s, v->x, v->y, v->z);
X}
SHAR_EOF
chmod 0600 SHADE.C || echo "restore of SHADE.C fails"
sed 's/^X//' << 'SHAR_EOF' > STYLE.H &&
X/* cosmetic C definitions */
X
X#define EQ ==                   
X#define IS ==
X#define NEQ !=
X#define ISNT !=
X#define AND &&
X#define OR ||
X#define NOT !
X#define NULL 0
X#define TRUE 1
X#define FALSE 0
X#define TRUE_STRING(i) (i IS TRUE ? "TRUE" : "FALSE")
X
X#define u unsigned
X
Xtypedef char boolean;
Xtypedef char *string;
X
X#define plural(i)       ( ((i) EQ 1) ? "":"s")
X
SHAR_EOF
chmod 0600 STYLE.H || echo "restore of STYLE.H fails"
sed 's/^X//' << 'SHAR_EOF' > SUPPORT.C &&
X/*
X *   supportive subroutines...
X */
X#include <math.h>
X#include <stdio.h>
X#undef min
X#include "rtd.h"
X#include "extern.h"
X#define time(x) 0
X
X/* returns dot product of two vectors */
X
Xdouble  dot (v1, v2)
X    struct vector  *v1,
X                   *v2;
X{
X    double  r;
X    r = v1->x * v2->x + v1->y * v2->y + v1->z * v2->z;
X    return (r);
X}
X
X
X/* multiplies a vector by a scalar */
X
Xscamult (scal, vect)
X    double  scal;
X    struct vector  *vect;
X{
X    vect->x *= scal;
X    vect->y *= scal;
X    vect->z *= scal;
X    vect->l *= scal;
X    vect->xzl *= scal; 
X}
X
X
X/* loads a vector with given x,y,z values */
X
Xmv (x, y, z, _vp) 
X    double  x,
X            y,
X            z;
X    struct vector  *_vp;
X{
X    _vp->x = x;
X    _vp->y = y;
X    _vp->z = z;
X}
X
X
X/* vector subtraction: v1 = v2 - v3 */
X
Xsv (v1, v2, v3) 
X    struct vector  *v1,
X                   *v2,
X                   *v3;
X{
X    v1->x = v2->x - v3->x;
X    v1->y = v2->y - v3->y;
X    v1->z = v2->z - v3->z;
X}
X
X
X
X/* vector addition: v1 = v2 + v3 */
X
Xav (v1, v2, v3) 
X    struct vector  *v1,
X                   *v2,
X                   *v3;
X{
X    v1->x = v2->x + v3->x;
X    v1->y = v2->y + v3->y;
X    v1->z = v2->z + v3->z;
X}
X
X
X/*  loads a transform matrix so that when vec is multiplied by it,
X    the result is (1,0,0). it does so with out deforming space */
X
Xmt (vec, trans) 
X    struct vector  *vec;
X    struct mat *trans;
X{
X    vecl (vec);
X    vexzl (vec);
X
X    if (vec->xzl == 0.0) {
X	trans->x.x = 0.0;
X	trans->x.y = 1.0;
X	trans->x.z = 0.0;
X	trans->y.x = -1.0;
X	trans->y.y = 0.0;
X	trans->y.z = 0.0;
X	trans->z.x = 0.0;
X	trans->z.y = 0.0;
X	trans->z.z = 1.0;
X    }
X    else {
X	trans->x.x = (vec->x) / (vec->l);
X	trans->x.y = (vec->y) / (vec->l);
X	trans->x.z = (vec->z) / (vec->l);
X	trans->y.x = -(vec->x) * (vec->y) / ((vec->l) * (vec->xzl));
X	trans->y.y = (vec->xzl) / (vec->l);
X	trans->y.z = -(vec->z) * (vec->y) / ((vec->l) * (vec->xzl));
X	trans->z.x = -(vec->z) / (vec->xzl);
X	trans->z.y = 0;
X	trans->z.z = (vec->x) / (vec->xzl);
X    }
X}
X
X/* multiply vector by matrix: vc1 = m*vc2 */
X
Xmt_vec (vc1, m, vc2)
X    struct vector  *vc1,
X                   *vc2;
X    struct mat *m;
X{
X    double  x,
X            y,
X            z;
X
X    x = dot (&(m->x), vc2);
X    y = dot (&(m->y), vc2);
X    z = dot (&(m->z), vc2);
X    mv (x, y, z, vc1);
X}
X
X
X
X/* will update a file containing information on 
Xhow we are coming along... useful for long runs*/
X
Xupdate (x, xmin, xmax)
X    float   x,
X            xmin,
X            xmax;
X{
X    FILE * fff;
X    static int  t;
X    static double   size,
X                    xm;
X    int     tt,
X            ttt,
X            hr,
X            min,
X            sec;
X
X
X    fprintf (stderr, "%d\n", (int) x);
X    return;
X
X
X    if (x == xmin) {
X/*	  fff = fopen ("time.update", "w"); */
X	fff = stderr;
X	fprintf (fff, "starting...\n");
X/*	  fclose (fff); */
X	t = time (0);
X	xm = xmin;
X	size = (xmax - xmin);
X    }
X    else {
X	x -= xm;
X	tt = time (0) - t;
X	ttt = (double) tt * size / x;
X	tt = (double) tt * (size - x) / x;
X	hr = tt / 3600;
X	min = (tt % 3600) / 60;
X	sec = tt % 60;
X/*	  fff = fopen ("time.update", "w"); */
X	fff = stderr;
X	fprintf (fff, "%5.1f%% done.\n", 100.0 * x / size);
X	fprintf (fff, "%d:%2d:%2d left.\n", hr, min, sec);
X	hr = ttt / 3600;
X	min = (ttt % 3600) / 60;
X	sec = ttt % 60;
X	fprintf (fff, "%d:%2d:%2d  total estimate.\n", hr, min, sec);
X/*	  fclose (fff); */
X    }
X}
X
X
X/* loads a vectors length... saves time to do this only when needed */
X
Xvecl (v)
X    struct vector *v;
X{
X    v->l = sqrt ((v->x) * (v->x) + (v->y) * (v->y) + (v->z) * (v->z));
X}
X
X
X/* loads a vectors xz component. needed for mt */
X
Xvexzl (v)
X    struct vector *v;
X{
X    v->xzl = sqrt ((v->x) * (v->x) + (v->z) * (v->z));
X}
X
X
SHAR_EOF
chmod 0600 SUPPORT.C || echo "restore of SUPPORT.C fails"
sed 's/^X//' << 'SHAR_EOF' > WNDOWS.C &&
X/* wndows.c
X *   manage the interface to GEM windows
X
XEntry Points:
X	w_open(type,name)			***
X	w_close()
X        w_lClut(new, old)
X
XOutward Calls:
X	wOnewSize()
X
X */
X
X#include <obdefs.h>
X#include <define.h>
X#include <gemdefs.h>
X#include <vdibind.h>
X#include <osbind.h>
X
X#define MIN_WIDTH  (2*gl_wbox)
X#define MIN_HEIGHT (3*gl_hbox)
Xint gl_hchar, gl_wchar, gl_wbox, gl_hbox;	/* system sizes */
X
Xint	ps_handle;	/* physical screen (workstation) handle */
Xint	vs_handle;	/* virtual screen (workstation) handle */
Xint	wi_handle;	/* window handle */
X
Xint	xdesk,ydesk,hdesk,wdesk;	/* size of whole desktop */
Xint	xwork,ywork,hwork,wwork;	/* size of current working window */
Xint	xold,yold,hold,wold;		/* size of screen before FULL cmd */
X
Xint	contrl[12], intin[128], ptsin[128], intout[128];
Xint	ptsout[128];	/* storage for gem bindings */
X
Xchar *p_menu;
Xint WiKind;
X
Xw_open(kind, name, menue_id)
Xint kind;		/* properties of window (e.g. MOVER|CLOSER|...) */
Xchar *name;
Xint menue_id;		/* open menue? */
X{	char n2[30];
X	appl_init();
X	open_vwork();
X 	open_window(kind, name);
X	WiKind = kind;
X	sprintf(n2, "%s.rsc", name);
X	open_rsc(n2, menue_id);
X	graf_mouse(ARROW,0x0L);
X	return (wi_handle);
X}
X
Xw_close()
X{	if (p_menu)
X		menu_bar(p_menu, FALSE);
X	wind_close(wi_handle);
X	graf_shrinkbox(xwork+wwork/2,ywork+hwork/2,gl_wbox,gl_hbox,xwork,ywork,wwork,hwork);
X	wind_delete(wi_handle);
X	v_clsvwk(vs_handle);
X	appl_exit();
X}
X
Xint work_in[11];	/* Input to GSX parameter array */
Xint work_out[57];	/* Output from GSX parameter array */
X
Xopen_vwork()
X{	int i;
X
X	ps_handle=graf_handle(&gl_wchar,&gl_hchar,&gl_wbox,&gl_hbox);
X	for(i=0;i<10;work_in[i++]=1);
X	work_in[10]=2;
X	vs_handle=ps_handle;
X	v_opnvwk(work_in,&vs_handle,work_out);
X	if (vs_handle == 0)
X		panic("v_opnvwk couldn't open window",0L,0L);
X}
X
Xopen_window(kind, name)
Xint kind;
Xchar *name;
X{	wind_get(0/*whole screen*/,WF_WORKXYWH, &xdesk, &ydesk, &wdesk, &hdesk);
X	wi_handle=wind_create(kind,xdesk,ydesk,wdesk,hdesk);
X
X	wind_set(wi_handle, WF_NAME,name, 0,0);
X	graf_growbox(xdesk+wdesk/2,ydesk+hdesk/2,gl_wbox,gl_hbox,xdesk,ydesk,wdesk,hdesk);
X	wind_open(wi_handle,xdesk,ydesk,wdesk,hdesk);
X	wind_get(wi_handle,WF_WORKXYWH,&xwork,&ywork,&wwork,&hwork);
X	wwork--;	/* ywork--;/**/ hwork--;
X	set_clip(xwork, ywork, wwork, hwork);
X	wOnewSize(xwork, ywork, wwork, hwork);
X	if (wdesk>500 && 2 != form_alert(1,"[3][16 Colors Required.|\
XSet Preferences to Low|Resolution and Restart.][okay|ignore warning]")) 
X		exit();/**/
X}
X
Xopen_rsc(myname, menue)
Xchar *myname;
Xint menue;
X{	if (menue)
X	{	if (rsrc_load(myname)==0) panic("File %s missing!",myname,0L);
X		if (rsrc_gaddr(R_TREE, menue, &p_menu)==0)
X			panic ("AES/rsrc_gaddr() error",0L,0L);
X		if (menu_bar(p_menu, TRUE)==0) panic ("AES/menu_bar() error",0L,0L);
X}	}
X
Xtypedef int CLUT[16][3];
XCLUT (*clut_current);
X
Xw_lClut(new, old)
XCLUT new, old;
X{	int i;
X	clut_current = new;
X	for (i=0; i<16; i++)
X	{	if (old)
X			vq_color(vs_handle, i, 0, old[i]);
X		if (new)
X			vs_color(vs_handle, i, new[i]);
X}	}
X
Xdi_header(dx, str)
Xint dx;
Xchar *str;
X{	set_clip(xdesk, ydesk, wdesk, hdesk);
X/*	v_gtext(vs_handle, ((dx>0)? Wx0: Wx1) +dx, Wy0-3, str);/**/
X	v_gtext(vs_handle, xdesk + (dx<0)*wdesk + dx, ydesk-3, str);
X	set_clip(xwork, ywork, wwork, hwork);
X}
X
Xdi_bg(dx, clr)
Xint dx, clr;
X{	int pxy[4];
X	set_clip(xdesk, ydesk, wdesk, hdesk);
X	vsf_color(wi_handle, clr);
X	pxy[0] = xdesk+dx;	pxy[2] = pxy[0] + 8;
X	pxy[1] = ydesk-10/*3*/;	pxy[3] = pxy[1] + 18;
X	v_bar(wi_handle, pxy);
X	set_clip(xwork, ywork, wwork, hwork);
X}
Xset_clip(x,y,w,h)
Xint x,y,w,h;
X{	int clip[4];
X
X	clip[0]=x;	/* set vdi's clip rectangle */
X	clip[1]=y;
X	clip[2]=x+w;
X	clip[3]=y+h;
X	vs_clip(wi_handle,1,clip);
X}
SHAR_EOF
chmod 0600 WNDOWS.C || echo "restore of WNDOWS.C fails"
rm -f s2_seq_.tmp
echo "You have unpacked the last part"
exit 0