v18i070: A ray-tracing package, Part01/03

Rich Salz rsalz at uunet.uu.net
Tue Mar 28 04:08:41 AEST 1989


Submitted-by: Mark VandeWettering <markv at drizzle.cs.uoregon.edu>
Posting-number: Volume 18, Issue 70
Archive-name: mtvraytrace/part01

This represents the second formal release of the MTV Raytracer.  It was
written to help me understand how raytracing works, to generate cute
images, and generally because I like to program.  Feel free to use it for
any purpose, I am releasing it into the public domain.

The input format to this ray tracer is called "NFF" or Neutral File
Format, which was invented by Eric Haines' for his Standard Procedural
Database.  The SPD was designed to allow programmers to test their
raytracers on databases of varying sizes.  While not the end-all to object
file formats, it has served me well.  If you wish to change the input file
to something else, you probably only need to change the parser in
"parse.y", not any of the other code.

#! /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 archive 1 (of 3)."
# Contents:  ALGORITHMS COPYING GETOPT INSTALL Makefile README
#   antialiasing.c balls.nff bound.c config.h data.c defs.h error.c
#   extern.h getopt.c main.c nff.y pic.c pic.h pqueue.c ray.1 sphere.c
#   tokens.l trace.c vector.c
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'ALGORITHMS' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'ALGORITHMS'\"
else
echo shar: Extracting \"'ALGORITHMS'\" \(1642 characters\)
sed "s/^X//" >'ALGORITHMS' <<'END_OF_FILE'
X
X
XThis should be more complete, but I really just wanted to point people at 
Xthe papers that I used in creating this raytracer.  Much thanks to all the
Xexcellent researchers and their papers, as well as the personal communications
Xthat I have had.
X
XRay/Object Intersections:
X
XThe sphere code is almost identical to the code given in Heckbert's EXCELLENT
Xarticle "Writing a Ray Tracer" in the Siggraph Course Notes.  Paul Heckbert 
Xis to be commended on his excellent article.  The general structure of my 
Xraytracer is closely modelled after his.
X
XPolygon intersections are modelled after the method described by Eric Haines 
Xin his excellent paper, "Essential Algorithms for Ray Tracing", also in 
Xthe Siggraph course notes.  Between these two papers, much of the drudgery of 
Xdeveloping intersection code is removed.
X
XThe code for cone/cylinder intersections is fairly crude, but essentially my
Xown derivation.  
X
XRay/Bounding Volume Intersections:
X
XRather than use octrees, I decided to use Kay/Kajiya bounding volumes, 
Xas described in their 86 Siggraph paper, "Ray Tracing Complex Scenes".  Their
Xmethod has proven to be fast and simple to implement.   The bounding volumes
Xfor the cones and cylinders could be improved to provide a "tighter" bounding 
Xvolume.
X
XI "discovered" simultaneously with Eric Haines through our conversations that
Xwe could cheapen the cost of certain rays by establishing a max cutoff for 
Xdistance during the Intersect() routine.  
X
XThe shadow caching optimization was introduced to me through conversations
Xwith Eric Haines, although probably not original, and was quite simple to 
Ximplement in my raytracer.
END_OF_FILE
if test 1642 -ne `wc -c <'ALGORITHMS'`; then
    echo shar: \"'ALGORITHMS'\" unpacked with wrong size!
fi
# end of 'ALGORITHMS'
fi
if test -f 'COPYING' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'COPYING'\"
else
echo shar: Extracting \"'COPYING'\" \(574 characters\)
sed "s/^X//" >'COPYING' <<'END_OF_FILE'
X#
X# MTV's RayTracer
X#
X# markv at cs.uoregon.edu
X
XThis program is public domain.  Feel free to modify it, hack it, use 
Xit inside other programs, and even sell it.  I wrote it to better 
Xunderstand raytracing and hope that it helps others understand the 
Xraytracing process as well.
X
XShould you significantly extend my program, through bug fixes or additional
Xfeatures, send the changes back to me for inclusion in later versions
Xof the program.  I will try to make the latest version of my program 
Xavailable via anonymous ftp from drizzle.cs.uoregon.edu.
X
XMark VandeWettering
END_OF_FILE
if test 574 -ne `wc -c <'COPYING'`; then
    echo shar: \"'COPYING'\" unpacked with wrong size!
fi
# end of 'COPYING'
fi
if test -f 'GETOPT' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'GETOPT'\"
else
echo shar: Extracting \"'GETOPT'\" \(3178 characters\)
sed "s/^X//" >'GETOPT' <<'END_OF_FILE'
XDate: Tue, 25 Dec 84 19:20:50 EST
XFrom: Keith Bostic <harvard!seismo!keith>
XTo: genrad!sources
XSubject: public domain getopt(3)
X
XThere have recently been several requests for a public
Xdomain version of getopt(3), recently.  Thought this
Xmight be worth reposting.
X
X		Keith Bostic
X			ARPA: keith at seismo 
X			UUCP: seismo!keith
X
X======================================================================
XIn April of this year, Henry Spencer (utzoo!henry) released a public
Xdomain version of getopt (USG, getopt(3)).  Well, I've been trying to
Xport some USG dependent software and it didn't seem to work.  The problem
Xended up being that the USG version of getopt has some external variables
Xthat aren't mentioned in the documentation.  Anyway, to fix these problems,
XI rewrote the public version of getopt.  It has the following advantages:
X
X	-- it includes those "unknown" variables
X	-- it's smaller/faster 'cause it doesn't use the formatted
X		output conversion routines in section 3 of the UNIX manual.
X	-- the error messages are the same as S5's.
X	-- it has the same side-effects that S5's has.
X	-- the posted bug on how the error messages are flushed has been
X		implemented.  (posting by Tony Hansen; pegasus!hansen)
X
XI won't post the man pages since Henry already did; a special note,
Xit's not documented in the S5 manual that the options ':' and '?' are
Xillegal.  It should be obvious, but I thought I'd mention it...
XThis software was derived from binaries of S5 and the S5 man page, and is
X(I think?) totally (I'm pretty sure?) compatible with S5 and backward
Xcompatible to Henry's version.
X
X		Keith Bostic
X			ARPA: keith at seismo 
X			UUCP: seismo!keith
X
X*UNIX is a trademark of Bell Laboratories
X
X.. cut along the dotted line .........................................
X
X#include <stdio.h>
X
X/*
X * get option letter from argument vector
X */
Xint	opterr = 1,		/* useless, never set or used */
X	optind = 1,		/* index into parent argv vector */
X	optopt;			/* character checked for validity */
Xchar	*optarg;		/* argument associated with option */
X
X#define BADCH	(int)'?'
X#define EMSG	""
X#define tell(s)	fputs(*nargv,stderr);fputs(s,stderr); \
X		fputc(optopt,stderr);fputc('\n',stderr);return(BADCH);
X
Xgetopt(nargc,nargv,ostr)
Xint	nargc;
Xchar	**nargv,
X	*ostr;
X{
X	static char	*place = EMSG;	/* option letter processing */
X	register char	*oli;		/* option letter list index */
X	char	*index();
X
X	if(!*place) {			/* update scanning pointer */
X		if(optind >= nargc || *(place = nargv[optind]) != '-' || !*++place) return(EOF);
X		if (*place == '-') {	/* found "--" */
X			++optind;
X			return(EOF);
X		}
X	}				/* option letter okay? */
X	if ((optopt = (int)*place++) == (int)':' || !(oli = index(ostr,optopt))) {
X		if(!*place) ++optind;
X		tell(": illegal option -- ");
X	}
X	if (*++oli != ':') {		/* don't need argument */
X		optarg = NULL;
X		if (!*place) ++optind;
X	}
X	else {				/* need an argument */
X		if (*place) optarg = place;	/* no white space */
X		else if (nargc <= ++optind) {	/* no arg */
X			place = EMSG;
X			tell(": option requires an argument -- ");
X		}
X	 	else optarg = nargv[optind];	/* white space */
X		place = EMSG;
X		++optind;
X	}
X	return(optopt);			/* dump back option letter */
X}
X
X
X
END_OF_FILE
if test 3178 -ne `wc -c <'GETOPT'`; then
    echo shar: \"'GETOPT'\" unpacked with wrong size!
fi
# end of 'GETOPT'
fi
if test -f 'INSTALL' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'INSTALL'\"
else
echo shar: Extracting \"'INSTALL'\" \(1170 characters\)
sed "s/^X//" >'INSTALL' <<'END_OF_FILE'
X
XTo install the MTV raytracer is quite simple:
X
X1.	Edit config.h to indicate whether your computer understands void
X	or not.  You might also have to define SYSV if you are running on 
X	a SYSV system.
X
X2.	Check the Makefile.  The way it is currently distributed it is
X	set up to run on suns with the 68881 processor, using the sun C 
X	compiler.  If you have the gnu C compiler, uncomment the other
X	set of CFLAGS and the definition of gcc as the C compiler.
X
X	You can expect much faster run times using gcc.  I have hacked in
X	some assembler macros so it uses the 68881 for square roots inline,
X	rather than calling the library function.  If you don't have gcc
X	and are running on a sun, I urge you to get it.
X
X3.	Type make.  It should compile.
X
X4.	To test, try running it on the "balls.nff" file. 
X
X		balls -i balls.nff -o balls.pic -r 100 -t
X	
X5.	To display the image, you need to hack a filter to change it into
X	a format your display device can understand.  The format is simple
X	and described in the README.  Alternatively, you could ftp an 
X	appropriate filter from drizzle.cs.uoregon.edu, where I try to keep
X	an archive of filters that people have sent to me.   
END_OF_FILE
if test 1170 -ne `wc -c <'INSTALL'`; then
    echo shar: \"'INSTALL'\" unpacked with wrong size!
fi
# end of 'INSTALL'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(2230 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X#
X# Makefile for Mark VandeWettering's 
X# MTV RAYTRACER
X#
X
XPROG=ray
XCC=cc
X#CC=gcc
XCFLAGS=-f68881 -O
X#CFLAGS=-DFAST_MATH_PRIMS -finline-functions -g -O
X#CFLAGS=-m68000 -O -msoft-float
XYFLAGS=-d
X
XCSRC=data.c main.c sphere.c vector.c shade.c trace.c intersect.c\
X	screen.c pic.c poly.c bound.c error.c pqueue.c cone.c\
X	color.c antialiasing.c tri.c getopt.c
X
XCOBJ=data.o main.o sphere.o vector.o shade.o trace.o intersect.o\
X	screen.o pic.o poly.o bound.o error.o pqueue.o cone.o\
X	color.o antialiasing.o tri.o getopt.o
X
XNFFFILES=balls.nff
XDOCFILES=README ray.1 COPYING BIBLIO ALGORITHMS NFF GETOPT INSTALL
XOSRC=nff.y tokens.l
XOOBJ=nff.o tokens.o
XHDRS=defs.h extern.h pic.h config.h
XLIBS=-lm
X
X$(PROG):	$(COBJ) $(OOBJ)
X	$(CC) $(CFLAGS) -o $(PROG) $(COBJ) $(OOBJ) $(LIBS)
X
Xclean:
X	rm -f $(COBJ) $(OOBJ)
X	rm -f core tags
X
X# This rule isn't guaranteed to work, it relies on gcc...
X# to change in the final distributed version...
X
Xdepend: 	$(CSRC) $(OSRC) $(HDR)
X	sed '/^#DONT EDIT/,$$d' Makefile > Makefile.new
X	echo "#DONT EDIT THIS, AUTOMATICALLY GENERATED#" >> Makefile.new
X	$(CC) -MM $(CSRC) >> Makefile.new
X	mv Makefile.new Makefile
X
Xlint:
X	lint $(CSRC)
X
Xbackup:
X	-mkdir .backup
X	cp $(CSRC) $(OSRC) $(HDR) Makefile .backup
X
Xnewrevision:
X	ci -t/dev/null $(CSRC) $(OSRC) Makefile ray.1 README $(HDRS)
X
Xkit:	$(CRSRC) $(OSRC) Makefile $(DOCFILES) $(NFFFILES) $(HDRS)
X	rm -f Part*
X	makekit $(CSRC) $(OSRC) Makefile $(DOCFILES) $(NFFFILES) $(HDRS)
X
X#DONT EDIT THIS, AUTOMATICALLY GENERATED#
Xdata.o : data.c defs.h config.h 
Xmain.o : main.c defs.h config.h extern.h 
Xsphere.o : sphere.c defs.h config.h extern.h 
Xvector.o : vector.c defs.h config.h extern.h 
Xshade.o : shade.c defs.h config.h extern.h 
Xtrace.o : trace.c defs.h config.h extern.h 
Xintersect.o : intersect.c defs.h config.h extern.h 
Xscreen.o : screen.c defs.h config.h pic.h extern.h 
Xpic.o : pic.c pic.h defs.h config.h extern.h 
Xpoly.o : poly.c defs.h config.h extern.h 
Xbound.o : bound.c defs.h config.h extern.h 
Xerror.o : error.c defs.h config.h extern.h 
Xpqueue.o : pqueue.c defs.h config.h extern.h 
Xcone.o : cone.c defs.h config.h extern.h 
Xcolor.o : color.c defs.h config.h 
Xantialiasing.o : antialiasing.c defs.h config.h 
Xtri.o : tri.c defs.h config.h extern.h 
END_OF_FILE
if test 2230 -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'\" \(3205 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X########################################################################
X			  MTV RAYTRACER*
X	     written by Mark Terrence VandeWettering
X		      markv at cs.uoregon.edu
X########################################################################
X* Well, I have had the initials since 1964, Music Television can't say
X  that :-)
X
XThis represents the second formal release of the MTV Raytracer.
XIt was written to help me understand how raytracing works, to
Xgenerate cute images, and generally because I like to program. 
XFeel free to use it for any purpose, I am releasing it into the 
Xpublic domain.
X
XThe input format to this ray tracer is called "NFF" or Neutral File
XFormat, which was invented by Eric Haines' for his Standard Procedural
XDatabase.  The SPD was designed to allow programmers to test their
Xraytracers on databases of varying sizes.  While not the end-all to
Xobject file formats, it has served me well.  If you wish to change the
Xinput file to something else, you probably only need to change the
Xparser in "parse.y", not any of the other code.
X
XNFF supports the following primitives:
X	spheres
X	cylinders
X	cones
X	polygons
X	polygonal patches (normals are interpolated from corner points)
X
XThe MTV raytracer supports all of these primitives, with the minor
Xlimitation that polygonal patches must be triangles (have only three
Xvertices).  I am sure some clever person can convert patches with more
Xsides to triangles, I haven't found the need yet.
X
XThe output from the raytracer is very simple, and not directly tied to
Xany specific device.   It consists of a single line, with format in 
XC scanf style of "%d %d\n", which gives the resolution of the image.
XIt is then followed by x*y sets of (red green blue) bytes.  We have 
Xpretty unstandard hardware here,  (I convert these to Utah Raster
XToolkit form and then filter that to display on a Tek4115) but I do 
Xmaintain an archive of source which has been sent to me for this
Xpurpose.  More below--
X
XBy the time you read this, this raytracer should be available via
Xanonymous ftp from drizzle.cs.uoregon.edu.  I will try to archive
Xsource code for displaying the ".pic" files, as well as interesting
Xobjects that I run accross.  Filters already exist to display images on
Xsuns, to convert to PostScript and Impress, as well as X bitmaps Also
Xavailable is Eric Haines' SPD source code, so you can generate your own
Xfractal spheres, mountains, gears etc.
X
XBy placing this in the comp.sources.unix, I hope to get this to more of
Xthe people who have requested it.  I will entertain e-mail with
Xquestions, and even requests for the source code, but remember that I am
Xa grad student only, and have limited time.  If it takes me a long time
Xto reply, send mail to me again.
X
XThanks must go to Eric Haines especially, whose e-mail conversations
Xhave been interesting and fruitful.  Also thanks to the numerous
Xauthors whose research into raytracing has seen implementation in this
Xraytracer, and have provided a host of ideas about image synthesis.
XAlso thanks to Jeff Eaton and David Koblas, whose criticism and sense of
Xcompetition drove this poor hacker to write a better program than he
Xcould have without them.
X
XTa Ta For Now...
XMark VandeWettering
END_OF_FILE
if test 3205 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'antialiasing.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'antialiasing.c'\"
else
echo shar: Extracting \"'antialiasing.c'\" \(809 characters\)
sed "s/^X//" >'antialiasing.c' <<'END_OF_FILE'
X/***********************************************************************
X * $Author: markv $
X * $Revision: 1.1 $
X * $Date: 88/09/17 01:10:52 $
X * $Log:	antialiasing.c,v $
X * Revision 1.1  88/09/17  01:10:52  markv
X * Initial revision
X * 
X ***********************************************************************/
X
X#include <stdio.h>
X#include <math.h>
X#include "defs.h"
X
X/***********************************************************************
X *
X * Flt rnd() ;
X *
X * returns a (psuedo-)random number in the range 0-1.  This may
X * not be portable, for now it assumes that random() returns an
X * int in the range 0-(2^31-1).  Caveat Emptor!
X ***********************************************************************/
X
X#define MAXRAND		(2147483647.0)
X
XFlt
Xrnd ()
X{
X	return (((Flt) random ()) / ((Flt) MAXRAND));
X}
END_OF_FILE
if test 809 -ne `wc -c <'antialiasing.c'`; then
    echo shar: \"'antialiasing.c'\" unpacked with wrong size!
fi
# end of 'antialiasing.c'
fi
if test -f 'balls.nff' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'balls.nff'\"
else
echo shar: Extracting \"'balls.nff'\" \(558 characters\)
sed "s/^X//" >'balls.nff' <<'END_OF_FILE'
Xv
Xfrom 2.1 1.3 0.0
Xat 0 0 0
Xup 0 1 1
Xangle 45
Xhither 1
Xresolution 50 50
Xb SkyBlue
Xl 4 3 2
Xl 1 -4 4
Xl -3 1 5
Xf yellow_green 1 0 0 0 0
Xp 4
X12 12 -.5
X-12 12 -.5
X-12 -12 -.5
X12 -12 -.5
Xf SteelBlue .5 .5 3 0 0
Xs 0 0 0 .5
Xs .272166 .272166 .544331 .166667
Xs .643951 .172546 1.11022e-16 .166667
Xs .172546 .643951 1.11022e-16 .166667
Xs -.371785 0.0996195 .544331 .166667
Xs -.471405 .471405 1.11022e-16 .166667
Xs -.643951 -.172546 1.11022e-16 .166667
Xs 0.0996195 -.371785 .544331 .166667
Xs -.172546 -.643951 1.11022e-16 .166667
Xs .471405 -.471405 1.11022e-16 .166667
END_OF_FILE
if test 558 -ne `wc -c <'balls.nff'`; then
    echo shar: \"'balls.nff'\" unpacked with wrong size!
fi
# end of 'balls.nff'
fi
if test -f 'bound.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'bound.c'\"
else
echo shar: Extracting \"'bound.c'\" \(3724 characters\)
sed "s/^X//" >'bound.c' <<'END_OF_FILE'
X/***********************************************************************
X * $Author: markv $
X * $Revision: 1.3 $
X * $Date: 88/10/31 14:47:22 $
X * $Log:	bound.c,v $
X * Revision 1.3  88/10/31  14:47:22  markv
X * Removed the noisy printout which gave the bounds of the scene...
X * 
X * Revision 1.2  88/09/14  13:54:46  markv
X * Check for overflow of array Prims[].  Should fix problems
X * with rendering the gears at size factor 4.
X * 
X * Revision 1.1  88/09/11  11:00:36  markv
X * Initial revision
X * 
X ***********************************************************************/
X#include <stdio.h>
X#include <math.h>
X#include "defs.h"
X#include "extern.h"
X
X/*
X * This function attempts to use median cut
X * to generate tighter bounding volumes than the old
X * code...
X */
X
XBuildBoundingSlabs()
X{
X	int low = 0 ;
X	int high, i ;
X
X	high = nPrims ;
X	while (SortAndSplit(low, high) == 0) {
X		low = high ;
X		high = nPrims ;
X	}
X	fprintf(stderr, "%s: after adding bounding volumes, %d prims\n",
X		Progname, nPrims) ;
X	fprintf(stderr, "%s: extent of scene\n", Progname) ;
X#ifdef NOISY
X	for (i = 0 ; i < NSLABS; i++) {
X		fprintf(stderr, "%s: <%g -- %g>\n",
X				Progname,
X				Root -> o_dmin[i],
X				Root -> o_dmax[i]) ;
X	}
X#endif /* NOISY */
X}
X
Xstatic int Axis ;
X
Xint 
Xcompslabs(a, b)
X Object **a, **b ;
X{
X	Flt am, bm ;
X
X	am = (*a) -> o_dmin[Axis] + (*a) -> o_dmax[Axis] ;
X	bm = (*b) -> o_dmin[Axis] + (*b) -> o_dmax[Axis] ;
X
X	if (am < bm)
X		return (-1) ;
X	else if (am == bm)
X		return (0) ;
X	else
X		return (1) ;
X}
X
Xint
XFindAxis(first, last)
X int first, last ;
X{
X	Flt	mins[NSLABS] ;
X	Flt	maxs[NSLABS] ;
X	int	i, j , which ;
X	Flt 	d = -HUGE, e ;
X	for (i = 0 ; i < NSLABS ; i++) {
X		mins[i] = HUGE ;
X		maxs[i] = -HUGE ;
X	}
X
X	for (i = first ; i < last ; i++) {
X		for (j = 0 ; j < NSLABS ; j++) {
X			if (Prims[i] -> o_dmin[j] < mins[j])
X				mins[j] = Prims[i] -> o_dmin [j] ;
X			if (Prims[i] -> o_dmin[j] > maxs[j])
X				maxs[j] = Prims[i] -> o_dmax [j] ;
X		}
X	}
X
X	for (i = 0 ; i < NSLABS ; i++) {
X		e = maxs[i] - mins[i] ;
X		if (e > d) {
X			d = e ;
X			which = i ;
X		}
X	}
X	return(which) ;
X}
X
XSortAndSplit(first, last)
X int first, last ;
X{
X	Object * cp ;
X	CompositeData * cd ;
X	int size, i, j ;
X	Flt dmin, dmax ;
X	int m ;
X
X	Axis = FindAxis(first, last) ;
X
X	size = last - first ;
X
X	/*
X	 * actually, we could do this faster in several ways.
X	 * we could use a logn algorithm to find the median
X	 * along the given axis, and then a linear algorithm to 
X	 * partition along the axis. Oh well...
X	 */
X
X	qsort((char *) (Prims + first), size, sizeof (Object *), compslabs) ;
X
X	if (size <= BUNCHINGFACTOR) {
X		/* build a box to contain them */
X
X		cp = (Object *) malloc (sizeof(Object)) ;
X		cp -> o_type = T_COMPOSITE ;
X		cp -> o_procs = & NullProcs ; 	/* die if you call any 	*/
X		cp -> o_surf = NULL ;		/* no surface...	*/
X		cd = (CompositeData *) malloc (sizeof(CompositeData)) ;
X		cd -> c_size = size ;
X
X		for(i = 0 ; i < size ; i++) {
X			cd -> c_object[i] = Prims[first + i] ;
X		}
X
X		for (i = 0 ; i < NSLABS ; i++ ) {
X			dmin = HUGE ;
X			dmax = -HUGE ;
X			for (j = 0 ; j < size ; j++) {
X				if (cd -> c_object[j] -> o_dmin[i] < dmin)
X					dmin = cd -> c_object[j] -> o_dmin[i] ;
X				if (cd -> c_object[j] -> o_dmax[i] > dmax)
X					dmax = cd -> c_object[j] -> o_dmax[i] ;
X			}
X			cp -> o_dmin[i] = dmin ;
X			cp -> o_dmax[i] = dmax ;
X		}
X		cp -> o_data = (void *) cd ;
X		Root = cp ;
X		if (nPrims < MAXPRIMS) {
X			Prims[nPrims ++] = cp ;
X			return (1) ;
X		} else {
X			fprintf(stderr, "too many primitives, max is %d\n",
X				MAXPRIMS) ;
X				exit(0);
X		}
X	} else {
X		m = (first + last) / 2 ;
X		SortAndSplit(first, m) ;
X		SortAndSplit(m , last) ;
X		return (0) ;
X	}
X}
X	
X
XInitSlabs()
X{
X	int i ;
X
X	for (i = 0 ; i < NSLABS ; i ++) {
X		VecNormalize(Slab[i]) ;
X	}
X}
END_OF_FILE
if test 3724 -ne `wc -c <'bound.c'`; then
    echo shar: \"'bound.c'\" unpacked with wrong size!
fi
# end of 'bound.c'
fi
if test -f 'config.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'config.h'\"
else
echo shar: Extracting \"'config.h'\" \(1292 characters\)
sed "s/^X//" >'config.h' <<'END_OF_FILE'
X/***********************************************************************
X * $Log:	config.h,v $
X * Revision 1.2  88/09/12  13:02:06  markv
X * Changed BUNCHINGFACTOR to something larger.
X * Added defines for compilers which don't support void.
X * Added a conditional define for SHADOW_CACHING
X * 
X * Revision 1.1  88/09/11  11:00:48  markv
X * Initial revision
X * 
X ***********************************************************************/
X
X#ifdef SYS_V
X#define index 	strchr
X#define rindex 	strrchr
X#endif /* SYS_V */
X
X#define		NSLABS		(3)
X#define		BUNCHINGFACTOR	(4)
X#define		PQSIZE		(100)
X
X#define		XMAX		(1024)
X#define		YMAX		(1024)
X#define		MAXLIGHTS	(10)
X#define		MAXPRIMS	(40000)
X#define		MAXLEVEL 	(5)
X
X/***********************************************************************
X * If your compiler doesn't grok the void type, then define NO_VOID
X * here...
X ***********************************************************************/
X
X/* #define NO_VOID */
X#ifdef		NO_VOID
X#define		void		char
X#endif 		/* NO_VOID */
X
X/***********************************************************************
X * Shadow caching is an interesting optimization.  I'd leave it in, 
X * I think it can really only help.
X ***********************************************************************/
X
X#define SHADOW_CACHING
END_OF_FILE
if test 1292 -ne `wc -c <'config.h'`; then
    echo shar: \"'config.h'\" unpacked with wrong size!
fi
# end of 'config.h'
fi
if test -f 'data.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'data.c'\"
else
echo shar: Extracting \"'data.c'\" \(1389 characters\)
sed "s/^X//" >'data.c' <<'END_OF_FILE'
X/***********************************************************************
X * $Author: markv $
X * $Revision: 1.3 $
X * $Date: 88/09/17 01:23:10 $
X * $Log:	data.c,v $
X * Revision 1.3  88/09/17  01:23:10  markv
X * Added definitions for antialias related variables
X * 
X * Revision 1.2  88/09/12  12:52:03  markv
X * Added counter for shadow cache hits.  Made the max level of 
X * recursion equal to the define MAXLEVEL in defs.h
X * 
X * Revision 1.1  88/09/11  11:02:13  markv
X * Initial revision
X * 
X ***********************************************************************/
X#include "defs.h"
X
Xint 		yylinecount ;
XViewpoint 	Eye ;
Xint 		Xresolution = 512 ;
Xint 		Yresolution = 512 ;
XLight		Lights[MAXLIGHTS] ;
Xint		nLights = 0 ;
XVec		BackgroundColor ;
XSurface		* CurrentSurface ;
XObject		* Prims[MAXPRIMS] ;
Xint		nPrims = 0 ;
XFlt		rayeps = 1e-6 ;
Xchar *		Progname ;
XObject		* Root ;
X
XFlt		minweight = 0.01 ;
Xint		maxlevel = MAXLEVEL ;
Xint		nRays = 0 ;
Xint		nShadows = 0 ;
Xint		nReflected = 0 ;
Xint		nRefracted = 0 ;
Xint		maxQueueSize = 0 ;
Xint		totalQueues = 0 ;
Xint		totalQueueResets = 0 ;
Xint		tickflag = 0 ;
Xint		filtflag = 0 ;
Xint		jitterflag = 0 ;
Xint		resolutionflag = 0 ;
Xint		maxsamples = 0 ;
Xint		nChecked = 0 ;
Xint		nEnqueued = 0 ;
Xint		nShadowCacheHits = 0 ;
X
XVec	Slab[] = {
X	{1.0, 0.0, 0.0},
X	{0.0, 1.0, 0.0},
X	{0.0, 0.0, 1.0},
X	{1.0, 1.0, 0.0},
X	{1.0, 0.0, 1.0},
X	{0.0, 1.0, 1.0}
X} ;
END_OF_FILE
if test 1389 -ne `wc -c <'data.c'`; then
    echo shar: \"'data.c'\" unpacked with wrong size!
fi
# end of 'data.c'
fi
if test -f 'defs.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'defs.h'\"
else
echo shar: Extracting \"'defs.h'\" \(4057 characters\)
sed "s/^X//" >'defs.h' <<'END_OF_FILE'
X/***********************************************************************
X * $Log:	defs.h,v $
X * Revision 1.4  88/10/06  12:54:57  markv
X * I forgot (of course) that gcc runs on non-sun machines.  I have
X * defined the FASTPRIMS so that if you are running a sun, you get them
X * otherwise, you don't.
X * 
X * Revision 1.3  88/10/04  14:34:49  markv
X * Added changes to allow for optimized CSG (courtesy of Glassner and
X * Bronsvoort.
X * 
X * Revision 1.2  88/09/12  13:03:28  markv
X * Added space in the Light structure for caching shadow objects.
X * 
X * Revision 1.1  88/09/11  11:00:49  markv
X * Initial revision
X * 
X * Revision 1.1  88/09/09  11:59:55  markv
X * Initial revision
X * 
X ***********************************************************************/
X
X#include "config.h"
X
Xtypedef double Flt ;
Xtypedef Flt Vec[3] ;
Xtypedef Vec Point ;
Xtypedef Vec Color ;
X
X/*----------------------------------------------------------------------*/
X
X#ifndef DUMB_CPP 
X
X#define MakeVector(x, y, z, v)		(v)[0]=(x),(v)[1]=(y),(v)[2]=(z)
X#define VecScale(S,a)	(a)[0] *= S ; (a)[1] *= S ; (a)[2] *= S
X#define VecNegate(a)	(a)[0]=0-(a)[0];\
X			(a)[1]=0-(a)[1];\
X			(a)[2]=0-(a)[2];
X#define VecDot(a,b)	((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[2])
X#define VecLen(a)	(sqrt(VecDot(a,a)))
X#define VecCopy(a,b)	 (b)[0]=(a)[0];(b)[1]=(a)[1];(b)[2]=(a)[2];
X#define VecAdd(a,b,c)	 (c)[0]=(a)[0]+(b)[0];\
X			 (c)[1]=(a)[1]+(b)[1];\
X			 (c)[2]=(a)[2]+(b)[2]
X#define VecSub(a,b,c)	 (c)[0]=(a)[0]-(b)[0];\
X			 (c)[1]=(a)[1]-(b)[1];\
X			 (c)[2]=(a)[2]-(b)[2]
X#define VecComb(A,a,B,b,c)	(c)[0]=(A)*(a)[0]+(B)*(b)[0];\
X				(c)[1]=(A)*(a)[1]+(B)*(b)[1];\
X			 	(c)[2]=(A)*(a)[2]+(B)*(b)[2]
X#define VecAddS(A,a,b,c)	 (c)[0]=(A)*(a)[0]+(b)[0];\
X				 (c)[1]=(A)*(a)[1]+(b)[1];\
X				 (c)[2]=(A)*(a)[2]+(b)[2]
X#define VecCross(a,b,c)	 (c)[0]=(a)[1]*(b)[2]-(a)[2]*(b)[1];\
X			 (c)[1]=(a)[2]*(b)[0]-(a)[0]*(b)[2];\
X			 (c)[2]=(a)[0]*(b)[1]-(a)[1]*(b)[0]
X#define VecPrint(msg,v)		printf("%s %g %g %g\n", msg,\
X					(v)[0],(v)[1],(v)[2])
X#define VecZero(v)	(v)[0]=0.0;(v)[1]=0.0;v[2]=0.0
X
X#endif /* not DUMB_CPP */
X
X/*----------------------------------------------------------------------*/
X
Xtypedef struct Ray {
X	Point P ;
X	Point D ;
X} Ray ;
X
X#define RayPoint(ray,t,point)	VecAddS(t,(ray)->D,(ray)->P,point)
X
X#define max(a,b) 	((a)>(b)?(a):(b))
X#define min(a,b) 	((a)<(b)?(a):(b))
X
X/*----------------------------------------------------------------------*/
X
Xtypedef struct t_surface {
X	Color	surf_color ;
X	Flt	surf_kd ;
X	Flt	surf_ks ;
X	Flt	surf_shine ;
X	Flt 	surf_kt ;
X	Flt	surf_ior ;
X} Surface ;
X
Xtypedef struct t_light {
X	Vec	light_pos ;
X	Flt	light_brightness ;
X	struct t_object * light_obj_cache[MAXLEVEL] ;
X} Light ;
X
Xtypedef struct t_viewpoint {
X	Vec	view_from ;
X	Vec	view_at ;
X	Vec	view_up ;
X	Flt	view_angle ;
X	Flt	view_dist ;
X} Viewpoint ;
X
Xtypedef struct t_object {
X	unsigned short 	o_type ;
X	Flt	o_dmin[NSLABS] ;
X	Flt	o_dmax[NSLABS] ;
X	struct t_objectprocs {
X		int 	(*print) () ;
X		int 	(*intersect) () ;
X		int 	(*normal) () ;
X	} * o_procs ;
X	struct t_surface 	* o_surf ;
X	struct t_object		* o_parent ;
X	unsigned short		* o_inside ;
X	void	* o_data ;
X} Object ;
X
Xtypedef struct t_compositedata {
X	unsigned short 	c_size ;
X	Object *	c_object[BUNCHINGFACTOR] ;
X} CompositeData ;
X
Xtypedef struct t_objectprocs ObjectProcs ;
X
Xtypedef struct t_isect {
X	Flt 		isect_t ;
X	int 		isect_enter ;
X	Vec		isect_normal ;
X	Object 		* isect_prim ;
X	Surface 	* isect_surf ;
X} Isect ;
X
Xtypedef struct t_pixel {
X	unsigned char r, g, b, q ;
X} Pixel ;
X
X#ifndef PI
X#define PI 		(3.14159265358979323844)
X#endif /* PI */
X
X#define degtorad(x)	(((Flt)(x))*PI/180.0)
X
X#define		T_COMPOSITE	(0)
X#define		T_SPHERE	(1)
X#define		T_POLY		(2)
X#define		T_CONE		(3)
X#define		T_CONE		(3)
X#define		T_TRI		(4)
X
X#ifdef __GNUC__
X#define INLINE	inline
X
X#if defined(FAST_MATH_PRIMS) && defined(sun)
X#define sqrt(x)\
X	({ double __value, __arg = (x) ;\
X	 asm("fsqrtx %1,%0": "=f" (__value): "f" (__arg)) ;\
X	 __value ;})
X#endif /* FAST_MATH_PRIMS */
X
X#else /* __GNUC__ */
X
X#define INLINE	/* inline not supported  */
X
X#endif /* __GNUC__ */
END_OF_FILE
if test 4057 -ne `wc -c <'defs.h'`; then
    echo shar: \"'defs.h'\" unpacked with wrong size!
fi
# end of 'defs.h'
fi
if test -f 'error.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'error.c'\"
else
echo shar: Extracting \"'error.c'\" \(878 characters\)
sed "s/^X//" >'error.c' <<'END_OF_FILE'
X/***********************************************************************
X * $Author: markv $
X * $Revision: 1.1 $
X * $Date: 88/09/11 11:00:39 $
X * $Log:	error.c,v $
X * Revision 1.1  88/09/11  11:00:39  markv
X * Initial revision
X * 
X ***********************************************************************/
X#include <stdio.h>
X#include <math.h>
X#include "defs.h"
X#include "extern.h"
X
X/*
X * various routines to print error messages and die...
X */
X
Xint NullPrint() ;
Xint NullIntersect() ;
Xint NullNormal() ;
X
XObjectProcs NullProcs = {
X	NullPrint,
X	NullIntersect,
X	NullNormal
X} ;
X
XNullPrint()
X{
X	fprintf(stderr, "%s: called (* print)(...), dying...\n", Progname) ;
X	abort() ;
X}
X
XNullIntersect()
X{
X	fprintf(stderr, "%s: called (* intersect)(...), dying...\n", Progname) ;
X	abort() ;
X}
X
XNullNormal()
X{
X	fprintf(stderr, "%s: called (* normal)(...), dying...\n", Progname) ;
X	abort() ;
X}
END_OF_FILE
if test 878 -ne `wc -c <'error.c'`; then
    echo shar: \"'error.c'\" unpacked with wrong size!
fi
# end of 'error.c'
fi
if test -f 'extern.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'extern.h'\"
else
echo shar: Extracting \"'extern.h'\" \(1787 characters\)
sed "s/^X//" >'extern.h' <<'END_OF_FILE'
X/***********************************************************************
X * $Log:	extern.h,v $
X * Revision 1.3  88/09/17  01:22:05  markv
X * Added definitions for new antialiasing variables, plus
X * function definitions for functions which return the chi-squared
X * values.
X * 
X * Revision 1.2  88/09/12  13:11:13  markv
X * Added extern definition for nShadowCacheHits
X * 
X * Revision 1.1  88/09/11  11:00:49  markv
X * Initial revision
X * 
X ***********************************************************************/
Xextern  int 		yylinecount ;
Xextern	Viewpoint 	Eye ;
Xextern	int 		Xresolution ;
Xextern	int 		Yresolution ;
Xextern	Light		Lights[] ;
Xextern	int		nLights ;
Xextern	Vec		BackgroundColor ;
Xextern	Surface		* CurrentSurface ;
Xextern	Object		* Prims[] ;
Xextern	int		nPrims ;
Xextern 	Flt		rayeps ;
Xextern	char *		Progname ;
Xextern 	int		maxQueueSize ;
Xextern 	int		totalQueues ;
Xextern	int		totalQueueResets ;
Xextern 	int		tickflag ;
Xextern 	int		filtflag ;
Xextern 	int		jitterflag ;
Xextern 	int		resolutionflag ;
Xextern  int		nChecked ;
Xextern 	int		nEnqueued ;
Xextern  int		nShadowCacheHits ;
X
Xextern 	Flt		minweight ;
Xextern 	int		maxlevel ;
Xextern	int		maxsamples ;
Xextern	Flt		variance ;
Xextern  Flt		maxerror ;
Xextern 	int		nRays ;
Xextern	int		nShadows ;
Xextern	int		nReflected ;
Xextern 	int		nRefracted ;
X
Xchar *		malloc() ;
Xchar *		calloc() ;
Xchar *		rindex() ;
X
Xextern	Object *	MakeCone() ;
Xextern	Object *	MakeSphere() ;
Xextern	Object *	MakePatch() ;
Xextern	Object *	MakePoly() ;
Xextern	Object * 	MakeTri() ;
X
Xextern 	Flt		VecNormalize() ;
Xextern 	Flt		rnd() ;
Xextern	Flt		critchisq() ;
Xextern	Flt		pochisq() ;
Xextern	Vec		Slab[] ;
Xextern	ObjectProcs	NullProcs ;
Xextern 	Object *	Root ;
X
X#ifdef DUMB_CPP
X
Xextern Flt	VecDot() ;
Xextern Flt 	VecLen() ;
X
X#endif /* DUMB_CPP */
END_OF_FILE
if test 1787 -ne `wc -c <'extern.h'`; then
    echo shar: \"'extern.h'\" unpacked with wrong size!
fi
# end of 'extern.h'
fi
if test -f 'getopt.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'getopt.c'\"
else
echo shar: Extracting \"'getopt.c'\" \(1407 characters\)
sed "s/^X//" >'getopt.c' <<'END_OF_FILE'
X
X#include <stdio.h>
X
X/*
X * get option letter from argument vector
X */
Xint	opterr = 1,		/* useless, never set or used */
X	optind = 1,		/* index into parent argv vector */
X	optopt;			/* character checked for validity */
Xchar	*optarg;		/* argument associated with option */
X
X#define BADCH	(int)'?'
X#define EMSG	""
X#define tell(s)	fputs(*nargv,stderr);fputs(s,stderr); \
X		fputc(optopt,stderr);fputc('\n',stderr);return(BADCH);
X
Xgetopt(nargc,nargv,ostr)
Xint	nargc;
Xchar	**nargv,
X	*ostr;
X{
X	static char	*place = EMSG;	/* option letter processing */
X	register char	*oli;		/* option letter list index */
X	char	*index();
X
X	if(!*place) {			/* update scanning pointer */
X		if(optind >= nargc || *(place = nargv[optind]) != '-' || !*++place) return(EOF);
X		if (*place == '-') {	/* found "--" */
X			++optind;
X			return(EOF);
X		}
X	}				/* option letter okay? */
X	if ((optopt = (int)*place++) == (int)':' || !(oli = index(ostr,optopt))) {
X		if(!*place) ++optind;
X		tell(": illegal option -- ");
X	}
X	if (*++oli != ':') {		/* don't need argument */
X		optarg = NULL;
X		if (!*place) ++optind;
X	}
X	else {				/* need an argument */
X		if (*place) optarg = place;	/* no white space */
X		else if (nargc <= ++optind) {	/* no arg */
X			place = EMSG;
X			tell(": option requires an argument -- ");
X		}
X	 	else optarg = nargv[optind];	/* white space */
X		place = EMSG;
X		++optind;
X	}
X	return(optopt);			/* dump back option letter */
X}
END_OF_FILE
if test 1407 -ne `wc -c <'getopt.c'`; then
    echo shar: \"'getopt.c'\" unpacked with wrong size!
fi
# end of 'getopt.c'
fi
if test -f 'main.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'main.c'\"
else
echo shar: Extracting \"'main.c'\" \(3268 characters\)
sed "s/^X//" >'main.c' <<'END_OF_FILE'
X/***********************************************************************
X * $Author: markv $
X * $Revision: 1.6 $
X * $Date: 88/10/31 14:33:44 $
X * $Log:	main.c,v $
X * Revision 1.6  88/10/31  14:33:44  markv
X * Removed non-functioning antialiasing...
X * 
X * Revision 1.5  88/10/04  14:29:16  markv
X * Added flags having to do with antialiasing, both statistically
X * optimized and jittered.
X * 
X * Revision 1.4  88/09/13  16:08:21  markv
X * Moved InitSlabs, must occur before ReadSceneFile
X * 
X * Revision 1.3  88/09/13  16:05:44  markv
X * Usage message now prints -t flag as well.
X * 
X * Revision 1.2  88/09/12  12:53:11  markv
X * Added printout of new statistic on shadow cache hits.
X * 
X * Revision 1.1  88/09/11  11:02:23  markv
X * Initial revision
X * 
X ***********************************************************************/
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/times.h>
X#include "defs.h"
X#include "extern.h"
X
Xmain(argc, argv)
X int argc ;
X char * argv[] ;
X{
X	extern int optind ;
X	extern char *optarg ;
X	int c ;
X	char * infilename = NULL ;
X	char * outfilename = "out.pic" ;
X	struct tms pbuf, tbuf ;
X
X	if ((Progname = rindex(argv[0], '/')) == NULL) 
X		Progname = argv[0] ;
X	else 
X		Progname ++ ;
X
X	while ((c = getopt(argc, argv, "r:a:o:i:tfj:")) != EOF) {
X		switch (c) {
X		case 'r':
X			resolutionflag = atoi(optarg) ;
X			break ;
X		case 'f':
X			filtflag = 1 ;
X			break ;
X		case 'j':
X			jitterflag = 1 ;
X			maxsamples = atoi(optarg) ;
X			if (maxsamples <= 0) {
X				fprintf(stderr, "%s: samples must be > 0\n",
X					Progname) ;
X				exit(1) ;
X			}
X			break ;
X		case 'o':
X			outfilename = optarg ;
X			break ;
X		case 'i':
X			infilename = optarg ;
X			break ;
X		case 't':
X			tickflag = 1 ;
X			break ;
X		case '?':
X			fprintf(stderr, "usage: %s [-i file] [-o file] [-t]\n",
X				Progname) ;
X			exit(-1);
X		}
X	}
X
X	InitSlabs() ;			/* Normalizes slab normals...	*/
X	ReadSceneFile(infilename) ;
X	if (resolutionflag > 0) {
X		Xresolution = Yresolution = resolutionflag ;
X	}
X	BuildBoundingSlabs() ;
X	times(&pbuf) ;
X	Screen(&Eye, outfilename, Xresolution, Yresolution) ;
X	times(&tbuf) ;
X	tbuf.tms_utime -= pbuf.tms_utime ;
X	tbuf.tms_stime -= pbuf.tms_stime ;
X	PrintStatistics(&pbuf, &tbuf) ;
X}
X
XPrintStatistics(pbuf, tbuf)
X struct tms *pbuf, *tbuf ;
X{
X
X	printf("preprocess time (user code)	%-6d seconds\n",
X			pbuf -> tms_utime / 60) ;
X	printf("preprocess time (system code)	%-6d seconds\n",
X			pbuf -> tms_stime / 60) ;
X	printf("tracing time (user code)	%-6d seconds\n",
X			tbuf -> tms_utime / 60 ) ;
X	printf("tracing time (system code)	%-6d seconds\n",
X			tbuf -> tms_stime / 60 ) ;
X
X	printf("number of rays cast:	   %-6d\n", nRays);
X	printf("number of shadow rays:	   %-6d\n", nShadows);
X	printf("number of reflected rays:  %-6d\n", nReflected);
X	printf("number of refracted rays:  %-6d\n", nRefracted);
X
X	printf("number of queue inserts:   %-6d\n", totalQueues) ;
X	printf("number of queue resets:    %-6d\n", totalQueueResets) ;
X	printf("avg number of queues/ray:  %-6g\n", (Flt) totalQueues /
X						(Flt) totalQueueResets) ;
X	printf("max queue size:		   %-6d\n", maxQueueSize) ;
X	printf("number of bound checks:	   %-6d\n", nChecked) ;
X	printf("number of bound queued:	   %-6d\n", nEnqueued) ;
X	printf("number of shadow hits:	   %-6d\n", nShadowCacheHits) ;
X}
END_OF_FILE
if test 3268 -ne `wc -c <'main.c'`; then
    echo shar: \"'main.c'\" unpacked with wrong size!
fi
# end of 'main.c'
fi
if test -f 'nff.y' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'nff.y'\"
else
echo shar: Extracting \"'nff.y'\" \(3873 characters\)
sed "s/^X//" >'nff.y' <<'END_OF_FILE'
X%{
X#include <stdio.h>
X#include <math.h>
X#include "defs.h"
X#include "extern.h"
X
Xextern char yytext[] ;
Xextern FILE * yyin ;
XVec * pl, * plist ;
X%}
X
X%token VIEWPOINT FROM AT UP ANGLE HITHER RESOLUTION LIGHT
X%token BACKGROUND SURFACE CONE SPHERE POLYGON PATCH NUM TOKEN
X
X%union {
X	Vec	vec ;
X	Vec *	vecl ;
X	double	flt ;
X	Object * obj ;
X} ;
X
X%type <vec>	point primcolor TOKEN
X%type <obj>	cone sphere polygon ppatch
X%type <flt>	num 
X
X%%
X
Xscene:
X	camera elementlist 
X	{
X		int i, l ;
X		for (l = 0 ; l < nLights ; l++) {
X			Lights[l].light_brightness =  sqrt((Flt) nLights) / 
X							((Flt)nLights) ;
X			for (i = 0 ; i < MAXLEVEL ; i++) {
X				Lights[l].light_obj_cache[i] = NULL ;
X			}
X		}
X	} ;
X
Xelementlist:
X	elementlist element
X	|  ;
X
Xelement:
X	light
X	| background
X	| surface
X	| object 
X	{
X		char buf[80] ;
X		if (nPrims >= MAXPRIMS) {
X			sprintf(buf, "max objects = %d", MAXPRIMS) ;
X			yyerror(buf) ;
X		}
X	}	;
X
Xobject:	  cone
X	| sphere
X	| polygon
X	| ppatch ;
X
Xcamera:
X	VIEWPOINT			/* $1      */
X	FROM point			/* $2-$3   */
X	AT point			/* $4-$5   */
X	UP point			/* $6-$7   */
X	ANGLE num 			/* $8-$9   */
X	HITHER num			/* $10-$11 */
X	RESOLUTION num num		/* $12-$14 */
X	{
X		VecCopy($3, Eye.view_from) ;
X		VecCopy($5, Eye.view_at) ;
X		VecCopy($7, Eye.view_up) ;
X		Eye.view_angle = degtorad($9/2.0 ) ;
X		Eye.view_dist = $11 ;
X		if (resolutionflag > 0) {
X			/* ignore the specified resolution... */
X			Xresolution = Yresolution = resolutionflag ;
X		} else {
X			Xresolution = (int) $13 ;
X			Yresolution = (int) $14 ;
X		}
X	} ;
X
Xlight:
X	LIGHT point 
X	{
X		VecCopy($2, Lights[nLights].light_pos) ;
X		/* fill in brightness of the light, after we 
X		 * know the number of lights sources in the scene
X		 */
X		nLights ++ ;
X	} ;
X
Xbackground:
X	BACKGROUND primcolor
X	{
X		VecCopy($2, BackgroundColor) ;
X	} ;
X
Xsurface:
X	SURFACE primcolor num num num num num 
X	{
X		CurrentSurface = (Surface *) malloc (sizeof(Surface)) ;
X		VecCopy($2, CurrentSurface -> surf_color) ;
X		CurrentSurface -> surf_kd = $3 ;
X		CurrentSurface -> surf_ks = $4 ;
X		CurrentSurface -> surf_shine = $5 ;
X		CurrentSurface -> surf_kt = $6 ;
X		CurrentSurface -> surf_ior = $7 ;
X	} ;
X
Xcone:
X	CONE point num point num 
X	{
X		$$ = MakeCone($2, $3, $4, $5) ;
X		Prims[nPrims++] = $$ ;
X
X	} ;
Xsphere:
X	SPHERE point num 
X	{
X		$$ = MakeSphere($2, $3) ;
X		Prims[nPrims++] = $$ ;
X	} ;
X
Xpolygon:
X	POLYGON num 
X	{
X		plist = (Vec *) calloc((int) $2, sizeof(Vec)) ;
X		pl = plist ;
X	} 
X	pointlist 
X	{
X		$$ = MakePoly((int) $2, plist) ;
X		Prims[nPrims++] = $$ ;
X	} ;
Xppatch:
X	PATCH num
X        {
X		if ((int) $2 != 3)
X			fprintf(stderr, "patches must have 3 vertices...\n") ;
X		plist = (Vec *) calloc(2 * (int) $2, sizeof(Vec)) ;
X		pl = plist ;
X	}
X	pointlist
X	{
X		$$ = MakeTri(plist) ;
X		Prims[nPrims++] = $$ ;
X	} ;
X
Xprimcolor:
X	num num num 
X	{
X		$$[0] = $1 ;
X		$$[1] = $2 ;
X		$$[2] = $3 ;
X	}  
X	| TOKEN
X	{
X		char buf[80] ;
X
X		if (LookupColorByName(yytext, $$) == 0) {
X			sprintf(buf, "cannot find color \"%s\"\n",
X				yytext) ;
X			yyerror(buf) ;
X		}
X	} ;
X
Xpoint:
X	num num num
X	{
X		$$[0] = $1 ;
X		$$[1] = $2 ;
X		$$[2] = $3 ;
X	} ;
X
Xpointlist:
X	pointlist point
X	{
X		VecCopy($2, (*pl)) ;
X		pl ++ ;
X	} 
X	| ;
X
Xnum:
X	NUM
X		{
X			$$ = atof(yytext) ;
X		} ;
X
X%%
X
Xyyerror(str)
X char * str ;
X{
X	fprintf(stderr, "%s: error at line %d\n", 
X		Progname, yylinecount) ;
X	fprintf(stderr, "%s: %s\n", Progname, str) ;
X	exit(-1) ;
X}
X
XReadSceneFile(str)
X char *str ;
X{
X	if (str == NULL) 
X		yyin = stdin ;
X	else {
X		if ((yyin = fopen(str, "r")) == NULL) {
X			fprintf(stderr, "%s: cannot open %s\n", Progname,
X						str) ;
X			exit(-1) ;
X		}
X	}
X	if (yyparse() == 1) {
X		fprintf(stderr, "%s: invalid input specification\n", Progname);
X		exit(-1) ;
X	}
X	fprintf(stderr, "%s: %d prims, %d lights\n", 
X			Progname, nPrims, nLights) ;
X	fprintf(stderr, "%s: inputfile = \"%s\"\n", Progname, str) ;
X	fprintf(stderr, "%s: resolution %dx%d\n", Progname, Xresolution,
X		Yresolution) ;
X}
END_OF_FILE
if test 3873 -ne `wc -c <'nff.y'`; then
    echo shar: \"'nff.y'\" unpacked with wrong size!
fi
# end of 'nff.y'
fi
if test -f 'pic.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'pic.c'\"
else
echo shar: Extracting \"'pic.c'\" \(1689 characters\)
sed "s/^X//" >'pic.c' <<'END_OF_FILE'
X/***********************************************************************
X * $Author: markv $
X * $Revision: 1.2 $
X * $Date: 88/10/04 14:30:44 $
X * $Log:	pic.c,v $
X * Revision 1.2  88/10/04  14:30:44  markv
X * Changed pixel writing primitives to write individual pixels rather
X * than scanlines.  Simplifies certain loops inside Screen.
X * 
X * Revision 1.1  88/09/11  11:00:41  markv
X * Initial revision
X * 
X ***********************************************************************/
X
X#include <stdio.h>
X#include "pic.h"
X#include "defs.h"
X#include "extern.h"
X
X/*======================================================================*/
X/* PIC.C								*/
X/*                                                                      */
X/* Simple routines for outputting a pixel map....                       */
X/*                                                                      */
X/* Mark VandeWettering, markv at cs.uoregon.edu                            */
X/*======================================================================*/
X
XPic *
XPicOpen(filename,x,y)
X char *filename ;
X{
X	Pic	*tmp ;
X
X	tmp = (Pic *) malloc(sizeof (Pic)) ;
X	tmp -> filename = (char *) malloc (strlen(filename)+1) ;
X	strcpy(tmp->filename, filename);
X
X	if (((tmp -> filep)=fopen(filename, "w"))==NULL) {
X		perror( filename );
X		exit( 1 );
X	}
X
X	tmp -> x = x ; tmp -> y = y ;
X
X	fprintf(tmp -> filep, "%d %d\n", x, y);
X
X	return(tmp);
X}
X
XPicWritePixel(pic, color)
X Pic *pic ;
X Color color ;
X{
X	fputc((unsigned char) (255.0 * color[0]), pic -> filep) ;
X	fputc((unsigned char) (255.0 * color[1]), pic -> filep) ;
X	fputc((unsigned char) (255.0 * color[2]), pic -> filep) ;
X}
X
XPicClose(pic)
X Pic *pic ;
X{
X	fclose(pic -> filep) ;
X}
END_OF_FILE
if test 1689 -ne `wc -c <'pic.c'`; then
    echo shar: \"'pic.c'\" unpacked with wrong size!
fi
# end of 'pic.c'
fi
if test -f 'pic.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'pic.h'\"
else
echo shar: Extracting \"'pic.h'\" \(376 characters\)
sed "s/^X//" >'pic.h' <<'END_OF_FILE'
X/***********************************************************************
X * $Log:	pic.h,v $
X * Revision 1.1  88/09/11  11:00:50  markv
X * Initial revision
X * 
X * Revision 1.1  88/09/09  11:59:56  markv
X * Initial revision
X * 
X ***********************************************************************/
Xtypedef struct Pic {
X	char	* filename ;
X	FILE	* filep ;
X	int	x, y ;
X} Pic ;
END_OF_FILE
if test 376 -ne `wc -c <'pic.h'`; then
    echo shar: \"'pic.h'\" unpacked with wrong size!
fi
# end of 'pic.h'
fi
if test -f 'pqueue.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'pqueue.c'\"
else
echo shar: Extracting \"'pqueue.c'\" \(1818 characters\)
sed "s/^X//" >'pqueue.c' <<'END_OF_FILE'
X/***********************************************************************
X * $Author: markv $
X * $Revision: 1.1 $
X * $Date: 88/09/11 11:00:42 $
X * $Log:	pqueue.c,v $
X * Revision 1.1  88/09/11  11:00:42  markv
X * Initial revision
X * 
X ***********************************************************************/
X
X#include <stdio.h>
X#include <math.h>
X#include "defs.h"
X#include "extern.h"
X
Xtypedef struct t_qelem {
X	Flt	q_key ;
X	Object	* q_obj ;
X} Qelem ;
X
Xstatic int 	Qsize ;
Xstatic Qelem	Q[PQSIZE] ;
X
XPriorityQueueNull()
X{
X	Qsize = 0 ;
X	totalQueueResets ++ ;
X#ifdef DEBUG	
X	printf("resetting\n") ;
X#endif /* DEBUG */
X}
X
XPriorityQueueEmpty()
X{
X	return (Qsize == 0) ;
X}
X
XPriorityQueueInsert(key, obj)
X Flt key ;
X Object * obj ;
X{
X	int i ; 
X	Qelem tmp ;
X
X	totalQueues ++ ;
X#ifdef DEBUG
X	printf("inserting element, key = %g\n", key) ;
X#endif
X 	Qsize ++ ;
X	if (Qsize > maxQueueSize)
X		maxQueueSize = Qsize ;
X	if (Qsize >= PQSIZE) {
X		fprintf(stderr, "%s: exhausted priority queue space\n", 
X			Progname) ;
X		exit(1) ;
X	}
X	Q[Qsize].q_key = key ;
X	Q[Qsize].q_obj = obj ;
X
X	i = Qsize ;
X	while (i > 1 && Q[i].q_key < Q[i/2].q_key) {
X		tmp = Q[i] ;
X		Q[i] = Q[i/2] ;
X		Q[i/2] = tmp ;
X		i = i / 2 ;
X	}
X}
X
XPriorityQueueDelete(key, obj)
X Flt * key ;
X Object ** obj ;
X{
X	Qelem tmp ;
X	int i, j ;
X
X	if (Qsize == 0) {
X		fprintf(stderr, "%s: priority queue is empty\n",
X			Progname) ;
X		exit(1) ;
X	}
X
X	*key = Q[1].q_key ;
X	*obj = Q[1].q_obj ;
X
X#ifdef DEBUG
X	printf("deleting element, key = %g\n", *key) ;
X#endif
X
X	Q[1] = Q[Qsize] ;
X	Qsize -- ;
X
X	i = 1 ;
X
X	while (2 * i <= Qsize) {
X
X		if (2 * i == Qsize) {
X			j = 2 * i ;
X		} else if (Q[2*i].q_key < Q[2*i+1].q_key) {
X			j = 2 * i ;
X		} else {
X			j = 2 * i + 1 ;
X		}
X
X		if (Q[i].q_key > Q[j].q_key) {
X			tmp = Q[i] ;
X			Q[i] = Q[j] ;
X			Q[j] = tmp ;
X			i = j ;
X		} else {
X			break ;
X		}
X	}
X}
END_OF_FILE
if test 1818 -ne `wc -c <'pqueue.c'`; then
    echo shar: \"'pqueue.c'\" unpacked with wrong size!
fi
# end of 'pqueue.c'
fi
if test -f 'ray.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'ray.1'\"
else
echo shar: Extracting \"'ray.1'\" \(2127 characters\)
sed "s/^X//" >'ray.1' <<'END_OF_FILE'
X.\" Copyright 1988, Mark VandeWettering
X.\" This program and documentation may be distributed freely for
X.\" any use whatsoever...
X.TH RAY 1 "August 17, 1987" 1
X.UC 4 
X.SH NAME
Xray \- a reasonbly intelligent ray tracing program
X.SH SYNOPSIS
X.B progname
X.\" sample options...
X[
X.B \-i inputfile
X] [
X.B \-o outputfile
X] [
X.B \-t 
X] [
X.B \-j # of samples
X] [
X.B \-f
X] [
X.B \-r resolution
X]
X.SH DESCRIPTION
XThis program is an attempt at writing a reasonably useful
Xraytracer for further experimentation, and for generating some
Xgenerally nifty pictures.  
X.PP
XIt reads Eric Haine's NFF file format files as input.  NFF is fairly
Xstraightforward, if you desire more explanation on the format, then 
Xobtain his set of routines.  They are available for download via anonymous
Xftp from drizzle.cs.uoregon.edu (128.223.4.1) in the pub subdirectory.
X.PP
XThe
X.B \-t
Xflag makes the ray tracer output a period after every scanline for those
Xof you who get impatient, or who are wondering if it is still working.
X.PP
XUse
X.B \-i file
Xto specify an NFF input file to render.  If no input file is specified, 
Xit reads from standard input.
X.PP
XUse
X.B \-o file
Xto specify an output file.  If unspecified, the raytracer writes its image
Xon the file "out.pic".
X.PP
XNormally the raytracer performs no antialiasing.  Images tend to look choppy.
XA cheap but imperfect solution is to specify the
X.B \-f 
Xflag, which tells the raytracer to make the pixel value the average of the 
Xfour pixels.  A more expensive but nicer way to antialias is to use the 
X.B \-j #samples
Xflag.  This uses jittered sampling to determine the value of a pixel, with 
Xa constant number of samples per pixel.  A pretty good value for the number
Xof samples is sixteen, but the image will take sixteen times as long to render.
X.PP
XThe 
X.B \-r 
Xflag allows you to override the resolution which is specified
Xfrom within the NFF file.   It is often useful when you don't
Xwant to edit the NFF file to get a more or less detailed image
Xthan you specified in the file.
X
X.SH AUTHOR
XMark VandeWettering
X.SH BUGS
XBugs!  Of course there are bugs!  Report them to markv at cs.uoregon.edu....
END_OF_FILE
if test 2127 -ne `wc -c <'ray.1'`; then
    echo shar: \"'ray.1'\" unpacked with wrong size!
fi
# end of 'ray.1'
fi
if test -f 'sphere.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'sphere.c'\"
else
echo shar: Extracting \"'sphere.c'\" \(2385 characters\)
sed "s/^X//" >'sphere.c' <<'END_OF_FILE'
X/***********************************************************************
X * $Author: markv $
X * $Revision: 1.1 $
X * $Date: 88/09/11 11:00:44 $
X * $Log:	sphere.c,v $
X * Revision 1.1  88/09/11  11:00:44  markv
X * Initial revision
X * 
X ***********************************************************************/
X
X#include <stdio.h>
X#include <math.h>
X#include "defs.h"
X#include "extern.h"
X
Xtypedef struct t_spheredata {
X	Vec 		sph_center ;
X	Flt 		sph_radius ;
X	Flt 		sph_radius2 ;
X} SphereData ;
X
Xint SpherePrint ();
Xint SphereIntersect ();
Xint SphereNormal ();
X
XObjectProcs SphereProcs = {
X	SpherePrint,
X	SphereIntersect,
X	SphereNormal,
X} ;
X
Xint 
XSpherePrint(obj)
X Object *obj ;
X{
X	SphereData * sp ;
X
X	sp = (SphereData *) obj -> o_data ;
X
X	printf("s %g %g %g %g\n", sp -> sph_center[0], 
X				   sp -> sph_center[1],
X				   sp -> sph_center[2],
X				   sp -> sph_radius) ;
X}
X
XSphereIntersect(obj, ray, hit)
X Object * obj ;
X Ray * ray ;
X Isect * hit ;
X{
X
X	Flt b, disc, t;
X	Point V ;
X	SphereData * sp ;
X
X	sp = (SphereData *) obj -> o_data ;
X
X	VecSub((sp->sph_center), ray -> P, V);
X
X	b = VecDot(V, ray -> D);
X
X	disc = b * b - VecDot(V, V) + (sp -> sph_radius2) ;
X
X	if (disc < 0.0)
X		return(0);
X
X	disc = sqrt(disc);
X
X	t = (b - disc < rayeps) ? b + disc : b - disc ;
X
X	if (t < rayeps) {
X		return(0);
X	}
X
X	hit -> isect_t = t ;
X	hit -> isect_enter = VecDot(V, V) > sp -> sph_radius2 + rayeps ? 1 : 0 ;
X	hit -> isect_prim = obj ;
X	hit -> isect_surf = obj -> o_surf ;
X	return (1);
X}
X
Xint
XSphereNormal(obj, hit, P, N)
X Object * obj ;
X Isect * hit ;
X Point P, N ;
X{
X	SphereData * sp ;
X	sp = (SphereData *) obj -> o_data ;
X
X	VecSub(P, sp -> sph_center, N);
X	(void) VecNormalize(N);
X}
X
XObject *
XMakeSphere(pos, radius)
X Vec pos ;
X Flt radius ;
X{
X	Object * tmp ;
X	int i ;
X	SphereData *sp ;
X
X	tmp = (Object *) malloc (sizeof(Object)) ;
X	tmp -> o_type = T_SPHERE ;
X	tmp -> o_procs = & SphereProcs ;
X	tmp -> o_surf = CurrentSurface ;
X	sp = (SphereData *) malloc (sizeof(SphereData)) ;
X	VecCopy(pos, sp -> sph_center) ;
X	sp -> sph_radius = radius ;
X	sp -> sph_radius2 = radius * radius ;
X	tmp -> o_data = (void *) sp ;
X
X	/*
X	 * figure out dmin and dmax values for 
X	 * each of the slabs...
X	 */
X	
X	for (i = 0 ; i < NSLABS; i ++) {
X		tmp -> o_dmin[i] = VecDot(sp -> sph_center, Slab[i]) 
X			- sp -> sph_radius ;
X		tmp -> o_dmax[i] = VecDot(sp -> sph_center, Slab[i]) 
X			+ sp -> sph_radius ;
X	}
X	return tmp ;
X}
END_OF_FILE
if test 2385 -ne `wc -c <'sphere.c'`; then
    echo shar: \"'sphere.c'\" unpacked with wrong size!
fi
# end of 'sphere.c'
fi
if test -f 'tokens.l' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tokens.l'\"
else
echo shar: Extracting \"'tokens.l'\" \(768 characters\)
sed "s/^X//" >'tokens.l' <<'END_OF_FILE'
X%{
X#include <stdio.h>
X#include "defs.h"
X#include "y.tab.h"
X#include "extern.h"
X%}
X
X%%
X[ \t]			;
X\#.*$			;
X\n			yylinecount ++ ;
Xv			return VIEWPOINT ;
Xviewpoint		return VIEWPOINT ;
Xfrom			return FROM ;
Xat			return AT ;
Xup			return UP ;
Xangle			return ANGLE ;
Xhither			return HITHER ;
Xresolution		return RESOLUTION ;
Xl			return LIGHT ;
Xlight			return LIGHT ;
Xb			return BACKGROUND ;
Xbackground		return BACKGROUND ;
Xf			return SURFACE ;
Xsurface			return SURFACE ;
Xc			return CONE ;
Xcone			return CONE ;
Xs			return SPHERE ;
Xsphere			return SPHERE ;
Xp			return POLYGON ;
Xpolygon			return POLYGON ;
Xpp			return PATCH ;
Xpatch			return PATCH ;
X\-?[0-9]*(\.[0-9]*(e\-?[0-9]+)?)? 	return NUM ;
X[A-Za-z0-9_]+		return TOKEN ;
X.			return yytext[0] ;
X
X%%
X
Xyywrap()
X{
X	return 1 ;
X}
END_OF_FILE
if test 768 -ne `wc -c <'tokens.l'`; then
    echo shar: \"'tokens.l'\" unpacked with wrong size!
fi
# end of 'tokens.l'
fi
if test -f 'trace.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'trace.c'\"
else
echo shar: Extracting \"'trace.c'\" \(1031 characters\)
sed "s/^X//" >'trace.c' <<'END_OF_FILE'
X/***********************************************************************
X * $Author: markv $
X * $Revision: 1.2 $
X * $Date: 88/09/12 13:01:15 $
X * $Log:	trace.c,v $
X * Revision 1.2  88/09/12  13:01:15  markv
X * Fixed Trace to call Intersect with the max dist argument of HUGE.
X * 
X * Revision 1.1  88/09/11  11:00:45  markv
X * Initial revision
X * 
X ***********************************************************************/
X
X#include <stdio.h>
X#include <math.h>
X#include "defs.h"
X#include "extern.h"
X
XTrace(level, weight, ray, color) 
X int level;
X Flt weight;
X Ray *ray ;
X Color color ;
X{
X	Object *prim ;
X	Vec P, N ;
X	Isect hit ;
X
X	if (level >= maxlevel) {
X		color[0] = color[1] = color[2] = 0.0 ;
X		return ;
X	}
X		
X	nRays ++ ;
X
X	if (Intersect(ray, &hit, HUGE)) {
X		prim = hit.isect_prim ;
X		RayPoint(ray, hit.isect_t, P);
X		(*prim -> o_procs -> normal) (prim, &hit, P, N);
X		if ((VecDot(ray->D, N)) >= 0.0) {
X			VecNegate(N);
X		}
X		Shade(level, weight, P, N, ray -> D, &hit, color);
X	} else {
X		VecCopy(BackgroundColor, color) ;
X	}
X}
END_OF_FILE
if test 1031 -ne `wc -c <'trace.c'`; then
    echo shar: \"'trace.c'\" unpacked with wrong size!
fi
# end of 'trace.c'
fi
if test -f 'vector.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'vector.c'\"
else
echo shar: Extracting \"'vector.c'\" \(1707 characters\)
sed "s/^X//" >'vector.c' <<'END_OF_FILE'
X/***********************************************************************
X * $Author: markv $
X * $Revision: 1.1 $
X * $Date: 88/09/11 11:00:46 $
X * $Log:	vector.c,v $
X * Revision 1.1  88/09/11  11:00:46  markv
X * Initial revision
X * 
X ***********************************************************************/
X#include <stdio.h>
X#include <math.h>
X#include "defs.h"
X#include "extern.h"
X
XFlt 
XVecNormalize(vec)
X Vec vec ;
X{
X	Flt len ;
X	len = (Flt) VecLen(vec);
X	vec[0]/=len ;
X	vec[1]/=len ;
X	vec[2]/=len ;
X	return(len) ;
X}
X
X#ifdef DUMB_CPP
X/*
X * Some machines can't handle all the vector operations, so if we define
X * DUMB_CPP, we replace them with equivalent function calls...
X */
X
XMakeVector(x, y, z, v)
X Flt x, y, z ;
X Vec v ;
X{
X	v[0] = x ; v[1] = y ; v[2] = z ;
X}
X
XVecNegate(v)
X Vec v ;
X{
X	v[0] = -v[0] ;
X	v[1] = -v[1] ;
X	v[2] = -v[2] ;
X}
X
XFlt 
XVecDot(a, b)
X Vec a, b ;
X{
X	return a[0] * b[0] + a[1] * b[1] + a[2] * b[2] ;
X}
X
XFlt
XVecLen(a)
X Vec a;
X{
X	return sqrt(VecDot(a, a)) ;
X}
X
XVecCopy(a, b) 
X Vec a, b ;
X{
X	b[0] = a[0] ;
X	b[1] = a[1] ;
X	b[2] = a[2] ;
X}
X
XVecAdd(a, b, c)
X Vec a, b, c ;
X{
X	c[0] = a[0] + b[0] ;
X	c[1] = a[1] + b[1] ;
X	c[2] = a[2] + b[2] ;
X}
X
XVecSub(a, b, c)
X Vec a, b, c ;
X{
X	c[0] = a[0] - b[0] ;
X	c[1] = a[1] - b[1] ;
X	c[2] = a[2] - b[2] ;
X}
X
XVecComb(A, a, B, b, c)
X Flt A, B ;
X Vec a, b, c ;
X{
X	c[0] = A * a[0] + B * b[0] ;	
X	c[1] = A * a[1] + B * b[1] ;	
X	c[2] = A * a[2] + B * b[2] ;	
X}
X
XVecAddS(A, a, b, c)
X Flt A ;
X Vec a, b, c ;
X{
X	c[0] = A * a[0] + b[0] ;	
X	c[1] = A * a[1] + b[1] ;	
X	c[2] = A * a[2] + b[2] ;	
X}
X
XVecCross(a, b, c)
X Vec a, b, c ;
X{
X	c[0] = a[1] * b[2] - a[2] * b[1] ;
X	c[1] = a[2] * b[0] - a[0] * b[2] ;
X	c[2] = a[0] * b[1] - a[1] * b[0] ;
X}
X
X#endif /* DUMB_CPP */
END_OF_FILE
if test 1707 -ne `wc -c <'vector.c'`; then
    echo shar: \"'vector.c'\" unpacked with wrong size!
fi
# end of 'vector.c'
fi
echo shar: End of archive 1 \(of 3\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 2 3 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 3 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0

-- 
Please send comp.sources.unix-related mail to rsalz at uunet.uu.net.



More information about the Comp.sources.unix mailing list