[comp.graphics] Ray Tracer: Part 01/01

markv@uoregon.uoregon.edu (Mark VandeWettering) (08/30/88)

If you have seen this already, sorry, our nntp mail posting was flakey,
and I don't think that this made it out.

Here is the first release of my totally whiz-bang ray tracer.  Okay, so
it isn't TOTALLY whiz bang, but it does have some nice features.  It
uses bounding volumes, has cones, spheres, polygons and cylinders as
primtives, reads Eric Haines NFF file format images and more....

Use it, abuse it, sell it, but be sure to have fun with it.  I had alot
of fun hacking on it.   If any of you find bugs, or better yet fix bugs
and add features, send them to me, and I will try to get them worked
into a future release which I hope might make it into comp.sources.unix.


#! /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 1)."
# Contents:  Makefile README balls.nff bound.c cone.c data.c defs.h
#   error.c extern.h intersect.c main.c nff.y pic.c pic.h poly.c
#   pqueue.c ray.1 screen.c shade.c sphere.c tokens.l trace.c vector.c
# Wrapped by markv@sol on Mon Aug 29 13:49:23 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(3430 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X#
X# Makefile for Mark VandeWettering's 
X# Raytracer # 3
X#
X# Optimized, doesn't do constructive solid geometry
X# but does read in Eric Haine's NFF files
X# directly....
X#
X
XPROG=ray
X#CC=cc
XCC=gcc
X#CFLAGS=-O -f68881
XCFLAGS=-O -fforce-mem -fforce-addr -DFAST_MATH_PRIMS -g -p
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
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
XNFFFILES=balls.nff
XOSRC=nff.y tokens.l
XOOBJ=nff.o tokens.o
XHDRS=defs.h extern.h pic.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
Xdepend:
X	sed '/^#DONT EDIT/,$$d' Makefile > Makefile.new
X	echo "#DONT EDIT THIS, AUTOMATICALLY GENERATED#" >> Makefile.new
X	$(CC) -M $(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 ray.1 README $(NFFFILES) $(HDRS)
X	rm -f Part*
X	makekit $(CSRC) $(OSRC) Makefile ray.1 README $(NFFFILES) $(HDRS)
X
X#DONT EDIT THIS, AUTOMATICALLY GENERATED#
Xdata.o: data.c
Xdata.o: ./defs.h
Xmain.o: main.c
Xmain.o: /usr/include/stdio.h
Xmain.o: /usr/include/sys/types.h
Xmain.o: /usr/include/sys/sysmacros.h
Xmain.o: /usr/include/sys/times.h
Xmain.o: ./defs.h
Xmain.o: ./extern.h
Xsphere.o: sphere.c
Xsphere.o: /usr/include/stdio.h
Xsphere.o: /usr/include/math.h
Xsphere.o: /usr/include/floatingpoint.h
Xsphere.o: /usr/include/sys/ieeefp.h
Xsphere.o: ./defs.h
Xsphere.o: ./extern.h
Xvector.o: vector.c
Xvector.o: /usr/include/stdio.h
Xvector.o: /usr/include/math.h
Xvector.o: /usr/include/floatingpoint.h
Xvector.o: /usr/include/sys/ieeefp.h
Xvector.o: ./defs.h
Xvector.o: ./extern.h
Xshade.o: shade.c
Xshade.o: /usr/include/stdio.h
Xshade.o: /usr/include/math.h
Xshade.o: /usr/include/floatingpoint.h
Xshade.o: /usr/include/sys/ieeefp.h
Xshade.o: ./defs.h
Xshade.o: ./extern.h
Xtrace.o: trace.c
Xtrace.o: /usr/include/stdio.h
Xtrace.o: ./defs.h
Xtrace.o: ./extern.h
Xintersect.o: intersect.c
Xintersect.o: /usr/include/stdio.h
Xintersect.o: /usr/include/math.h
Xintersect.o: /usr/include/floatingpoint.h
Xintersect.o: /usr/include/sys/ieeefp.h
Xintersect.o: ./defs.h
Xintersect.o: ./extern.h
Xscreen.o: screen.c
Xscreen.o: /usr/include/stdio.h
Xscreen.o: /usr/include/math.h
Xscreen.o: /usr/include/floatingpoint.h
Xscreen.o: /usr/include/sys/ieeefp.h
Xscreen.o: ./defs.h
Xscreen.o: ./pic.h
Xscreen.o: ./extern.h
Xpic.o: pic.c
Xpic.o: /usr/include/stdio.h
Xpic.o: ./pic.h
Xpic.o: ./defs.h
Xpic.o: ./extern.h
Xpoly.o: poly.c
Xpoly.o: /usr/include/stdio.h
Xpoly.o: /usr/include/math.h
Xpoly.o: /usr/include/floatingpoint.h
Xpoly.o: /usr/include/sys/ieeefp.h
Xpoly.o: ./defs.h
Xpoly.o: ./extern.h
Xbound.o: bound.c
Xbound.o: /usr/include/stdio.h
Xbound.o: /usr/include/math.h
Xbound.o: /usr/include/floatingpoint.h
Xbound.o: /usr/include/sys/ieeefp.h
Xbound.o: ./defs.h
Xbound.o: ./extern.h
Xerror.o: error.c
Xerror.o: /usr/include/stdio.h
Xerror.o: /usr/include/math.h
Xerror.o: /usr/include/floatingpoint.h
Xerror.o: /usr/include/sys/ieeefp.h
Xerror.o: ./defs.h
Xerror.o: ./extern.h
Xpqueue.o: pqueue.c
Xpqueue.o: /usr/include/stdio.h
Xpqueue.o: /usr/include/math.h
Xpqueue.o: /usr/include/floatingpoint.h
Xpqueue.o: /usr/include/sys/ieeefp.h
Xpqueue.o: ./defs.h
Xpqueue.o: ./extern.h
END_OF_FILE
if test 3430 -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'\" \(2361 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X########################################################################
X		   RAY V.3.0 by Mark VandeWettering
X########################################################################
X			markv@cs.uoregon.edu
X------------------------------------------------------------------------
X
XThis is my first release of my raytracer.  While far from perfect (or 
Xeven complete), it does have several nifty features:
X
Xo	It reads Eric Haine's NFF file format for objects.  Included is a small
X	data file for spheres resting above a polygon.  Obtain his NFF package
X	if you want some more fun data files
X
Xo	It supports cones, cylinders, spheres, and polygons.  The illumination 
X	model it uses is primitive, but should be easy to change.  Other
X	primitives can be added in a simple way (look at sphere.c, cone.c, 
X	and poly.c to see what you need to do).
X
Xo	It uses Kajiya's bounding slabs to allow a large number of objects
X	to be raytraced.  For instance, a scene consisting of 7281 spheres
X	took about 7 hours on a Sun 3/50 w/68881 at 512x512 resolution.
X
XCAVEATS:
X
XI have only run this on Suns.  While it probably will work on 
Xothers, no guarantees...
X
XIt writes out a file consisting of single line with the x and y size of the 
Ximage, followed by groups of three bytes <red green blue>.  All the picture
Xoutput primitives should be isolated in pic.c, so converting it to a new
Xformat shouldn't be hard.
X
XAs I mentioned, the lighting model isn't right.  In particular, refraction
Xis far to primitive, and doesn't work right for intersecting objects.
X
XIt doesn't anti-alias.  I originally planned on adding a statistically 
Xoptimized antialiaser, but didn't get to it.  It averages the rays at the
Xcorners of each pixel to obtain the pixel value.
X
XUndoubtably there are bugs and portability problems.  If you notice anything
Xtoo wierd, report them to me.  If you have a fix, send it to me, and I will 
Xtry to incorporate it into a future release, which might be destined for
Xcomp.sources.unix.  If you extend/fix various limitations in the system, be 
Xsure to send them to me, and I will include your name in lights alongside mine.
X:-)
X
XCOPYING
X
XFeel free to copy, sell, distribute, modify and hack this program into 
Xlittle itty bitty bits.  I wrote it for fun, and hope others have fun with it 
Xtoo.  Write me about any extensions you implement.
X
XMark VandeWettering
END_OF_FILE
if test 2361 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
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'\" \(563 characters\)
sed "s/^X//" >'balls.nff' <<'END_OF_FILE'
Xv
Xfrom 2.1 1.3 1.7
Xat 0 0 0
Xup 0 0 1
Xangle 45
Xhither 1
Xresolution 100 100
Xb 0.078 .361 .753
Xl 4 3 2
Xl 1 -4 4
Xl -3 1 5
Xf 1 .75 .33 1 0 0 0 0
Xp 4
X12 12 -.5
X-12 12 -.5
X-12 -12 -.5
X12 -12 -.5
Xf 1 .9 .7 .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 563 -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'\" \(2298 characters\)
sed "s/^X//" >'bound.c' <<'END_OF_FILE'
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 axis = 0 ;
X	int high, i ;
X
X	high = nPrims ;
X	while (SortAndSplit(low, high, axis) == 0) {
X		axis = (axis + 1) % NSLABS ;
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	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}
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
XSortAndSplit(first, last, axis)
X int first, last ;
X int axis ;
X{
X	Object * cp ;
X	CompositeData * cd ;
X	int size, i, j ;
X	Flt dmin, dmax ;
X	int m ;
X
X	Axis = axis ;
X
X	size = last - first ;
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		Prims[nPrims ++] = cp ;
X		return (1) ;
X	} else {
X		m = (first + last) / 2 ;
X		SortAndSplit(first, m, (axis + 1) % NSLABS) ;
X		SortAndSplit(m , last, (axis + 1) % NSLABS) ;
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 2298 -ne `wc -c <'bound.c'`; then
    echo shar: \"'bound.c'\" unpacked with wrong size!
fi
# end of 'bound.c'
fi
if test -f 'cone.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'cone.c'\"
else
echo shar: Extracting \"'cone.c'\" \(5709 characters\)
sed "s/^X//" >'cone.c' <<'END_OF_FILE'
X#include <stdio.h>
X#include <math.h>
X#include "defs.h"
X#include "extern.h"
X
Xtypedef struct t_conedata {
X	Vec 		cone_base ;
X	Flt		cone_base_radius ;
X	Flt		cone_base_d ;
X	Vec		cone_apex ;
X	Flt		cone_apex_radius ;
X	Vec		cone_u ;
X	Vec		cone_v ;
X	Vec		cone_w ;
X	Flt		cone_height ;
X	Flt		cone_slope ;
X	Flt		cone_min_d ;
X	Flt		cone_max_d ;
X} ConeData ;
X
Xint ConePrint ();
Xint ConeIntersect ();
Xint ConeNormal ();
X
XObjectProcs ConeProcs = {
X	ConePrint,
X	ConeIntersect,
X	ConeNormal,
X} ;
X
Xint 
XConePrint(obj)
X Object *obj ;
X{
X	ConeData * cp ;
X
X	cp = (ConeData *) obj -> o_data ;
X
X	printf("c %g %g %g %g %g %g %g %g\n", cp -> cone_base[0], 
X				  cp -> cone_base[1],
X				  cp -> cone_base[2],
X				  cp -> cone_base_radius,
X				  cp -> cone_apex[0],
X				  cp -> cone_apex[1],
X				  cp -> cone_apex[2],
X				  cp -> cone_apex_radius) ;
X}
X
XConeIntersect(obj, ray, hit)
X Object * obj ;
X Ray * ray ;
X Isect * hit ;
X{
X	Ray tray ;
X	ConeData * cd ;
X	Vec V, P ;
X	Flt a, b, c, d, disc ;
X	Flt t1, t2 ;
X	int nroots ;
X
X	cd = (ConeData *) (obj -> o_data) ;
X
X	/*
X	 * First, we get the coordinates of the ray origin in 
X	 * the objects space....
X	 */
X	
X	VecSub(ray -> P, cd -> cone_base, V) ;
X
X	tray.P[0] = VecDot(V, cd -> cone_u) ;
X	tray.P[1] = VecDot(V, cd -> cone_v) ;
X	tray.P[2] = VecDot(V, cd -> cone_w) ;
X
X	/*
X	VecAdd(ray -> P, ray -> D, V) ;
X	VecSub(V, cd -> cone_base, V) ;
X	*/
X
X	tray.D[0] = VecDot(ray -> D, cd -> cone_u) ;
X	tray.D[1] = VecDot(ray -> D, cd -> cone_v) ;
X	tray.D[2] = VecDot(ray -> D, cd -> cone_w) ;
X
X	/*
X	VecSub(tray.D, tray.P, tray.D) ;
X	*/
X
X	a = tray.D[0] * tray.D[0] 
X	    + tray.D[1] * tray.D[1] 
X	    - cd -> cone_slope * cd -> cone_slope * tray.D[2] * tray.D[2] ;
X
X	b = 2.0 * (tray.P[0] * tray.D[0] + tray.P[1] * tray.D[1] - 
X		cd -> cone_slope * cd -> cone_slope * tray.P[2] * tray.D[2]
X		- cd -> cone_base_radius * cd -> cone_slope * tray.D[2]) ;
X
X	c = cd -> cone_slope * tray.P[2] + cd -> cone_base_radius ;
X	c = tray.P[0] * tray.P[0] + tray.P[1] * tray.P[1] - (c * c) ;
X
X	disc = b * b - 4.0 * a * c ;
X
X	if (disc < 0.0)
X		return (0) ;
X	
X	disc = (Flt) sqrt(disc) ;
X	t1 = (-b - disc) / (2.0 * a) ;
X	t2 = (-b + disc) / (2.0 * a) ;
X
X	if (t2 < rayeps)
X		return (0) ;
X	if (t1 < rayeps) {
X		nroots = 1 ;
X		t1 = t2 ;
X	} else {
X		nroots = 2 ;
X	}
X		
X	/*
X	 * ensure that the points are between the two bounding planes...
X	 */
X	
X	switch(nroots) {
X	case 1:
X		RayPoint(ray, t1, P) ;
X		d = VecDot(cd -> cone_w, P) ;
X		if (d >= cd -> cone_min_d && d <= cd -> cone_max_d) {
X			hit -> isect_t = t1 ;	
X			hit -> isect_prim = obj ;
X			hit -> isect_surf = obj -> o_surf ;
X			hit -> isect_enter = 0 ;
X			return(1) ;
X		} else {
X			return(0) ;
X		}
X		break ;
X	case 2:
X		RayPoint(ray, t1, P) ;
X		d = VecDot(cd -> cone_w, P) ;
X		if (d >= cd -> cone_min_d && d <= cd -> cone_max_d) {
X			hit -> isect_t = t1 ;	
X			hit -> isect_prim = obj ;
X			hit -> isect_surf = obj -> o_surf ;
X			hit -> isect_enter = 1 ;
X			return(1) ;
X		} else {
X			RayPoint(ray, t2, P) ;
X			d = VecDot(cd -> cone_w, P) ;
X			if (d >= cd -> cone_min_d && d <= cd -> cone_max_d) {
X				hit -> isect_t = t2 ;	
X				hit -> isect_prim = obj ;
X				hit -> isect_surf = obj -> o_surf ;
X				hit -> isect_enter = 0 ;
X				return(1) ;
X			}
X		}
X		return(0) ;
X	}
X	return(0) ;
X}
X
Xint
XConeNormal(obj, hit, P, N)
X Object * obj ;
X Isect * hit ;
X Point P, N ;
X{
X	Flt t ;
X	Vec V ;
X	ConeData * cd ;
X
X	cd = (ConeData *) obj -> o_data ;
X
X	/*
X	 * fill in the real normal...
X	 * Project the point onto the base plane.  The normal is
X	 * a vector from the basepoint through this point, plus the slope
X	 * times the cone_w vector...
X	 */
X
X	t = - (VecDot(P, cd -> cone_w) + cd -> cone_base_d) ;
X	VecAddS(t, cd -> cone_w, P, V) ;
X	VecSub(V, cd -> cone_base, N) ;
X	VecNormalize(N) ;
X	VecAddS(- cd -> cone_slope, cd -> cone_w, N, N) ;
X	VecNormalize(N) ;
X}
X
XObject *
XMakeCone(basepoint, baseradius, apexpoint, apexradius) 
X Vec basepoint, apexpoint ;
X Flt baseradius, apexradius ;
X{
X	Object * obj ;
X	ConeData * cd ;
X	Flt dmin, dmax, d , ftmp;
X	Vec tmp ;
X	int i ;
X
X	obj = (Object *) malloc (sizeof (Object)) ;
X	obj -> o_type = T_CONE ;
X	obj -> o_procs = & ConeProcs ;
X	obj -> o_surf = CurrentSurface ;
X
X	cd = (ConeData *) malloc (sizeof(ConeData)) ;
X
X	VecCopy(basepoint, cd -> cone_base) ;
X	VecCopy(apexpoint, cd -> cone_apex) ;
X
X	cd -> cone_base_radius = baseradius ;
X	cd -> cone_apex_radius = apexradius ;
X
X
X	VecSub(apexpoint, basepoint, cd -> cone_w) ;
X	cd -> cone_height = VecNormalize(cd -> cone_w) ;
X	cd -> cone_slope =  (cd -> cone_apex_radius - cd -> cone_base_radius) /
X				(cd -> cone_height) ;
X	cd -> cone_base_d = - VecDot(basepoint, cd -> cone_w) ;
X
X	MakeVector(0.0, 0.0, 1.0, tmp) ;
X
X	if (fabs(VecDot(tmp, cd ->  cone_w) - 1.0) < rayeps) {
X		MakeVector(0.0, 1.0, 0.0, tmp) ;
X	}
X
X	/* find two axes which are at right angles to cone_w
X	 */
X
X	VecCross(cd -> cone_w, tmp, cd -> cone_u) ;
X	VecCross(cd -> cone_u, cd -> cone_w, cd -> cone_v) ;
X
X	cd -> cone_min_d = VecDot(cd -> cone_w, cd -> cone_base) ;
X	cd -> cone_max_d = VecDot(cd -> cone_w, cd -> cone_apex) ;
X
X	if (cd -> cone_max_d < cd -> cone_min_d) {
X		ftmp = cd -> cone_max_d ;
X		cd -> cone_max_d = cd -> cone_min_d ;
X		cd -> cone_min_d = ftmp ;
X	}
X
X	obj -> o_data = (void *) cd ;
X
X	for (i = 0 ; i < NSLABS ; i ++) {
X		dmin = HUGE ;
X		dmax = -HUGE ;
X		d = VecDot(basepoint, Slab[i]) - baseradius ;
X		if (d < dmin) dmin = d ; if (d > dmax) dmax = d ;
X		d = VecDot(basepoint, Slab[i]) + baseradius ;
X		if (d < dmin) dmin = d ; if (d > dmax) dmax = d ;
X		d = VecDot(apexpoint, Slab[i]) - apexradius ;
X		if (d < dmin) dmin = d ; if (d > dmax) dmax = d ;
X		d = VecDot(apexpoint, Slab[i]) + apexradius ;
X		if (d < dmin) dmin = d ; if (d > dmax) dmax = d ;
X
X		obj -> o_dmin[i] = dmin ;
X		obj -> o_dmax[i] = dmax ;
X	}
X
X	return(obj) ;
X}
END_OF_FILE
if test 5709 -ne `wc -c <'cone.c'`; then
    echo shar: \"'cone.c'\" unpacked with wrong size!
fi
# end of 'cone.c'
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'\" \(699 characters\)
sed "s/^X//" >'data.c' <<'END_OF_FILE'
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 = 5 ;
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		nChecked = 0 ;
Xint		nEnqueued = 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 699 -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'\" \(2864 characters\)
sed "s/^X//" >'defs.h' <<'END_OF_FILE'
X/*
X * D E F S . H
X *
X */
X
X#define		NSLABS		(3)
X#define		BUNCHINGFACTOR	(10)
X#define		PQSIZE		(10000)
X
Xtypedef double Flt ;
Xtypedef Flt Vec[3] ;
Xtypedef Vec Point ;
Xtypedef Vec Color ;
Xtypedef Flt Matrix[4][4] ;
X
X#define MakeVector(x, y, z, v)		(v)[0]=(x),(v)[1]=(y),(v)[2]=(z)
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
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} 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	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	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#define XMAX (1024)
X#define YMAX (1024)
X
X#define PI 		(3.14159265358979323844)
X#define degtorad(x)	(((Flt)(x))*PI/180.0)
X
X#define MAXLIGHTS	(10)
X#define MAXPRIMS	(10000)
X
X#define		T_COMPOSITE	(0)
X#define		T_SPHERE	(1)
X#define		T_POLY		(2)
X#define		T_CONE		(3)
X
X#ifdef __GNUC__
X#define INLINE	inline
X
X#ifdef FAST_MATH_PRIMS
X#define sqrt(x)\
X	({ double __value, __arg = (x) ;\
X	 asm("fsqrtx %1,%0": "=f" (__value): "f" (__arg)) ;\
X	 __value ;})
X
X#endif /* FAST_MATH_PRIMS */
X
X#else /* __GNUC__ */
X
X#define INLINE	/* */
X
X#endif /* __GNUC__ */
END_OF_FILE
if test 2864 -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'\" \(573 characters\)
sed "s/^X//" >'error.c' <<'END_OF_FILE'
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 573 -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'\" \(906 characters\)
sed "s/^X//" >'extern.h' <<'END_OF_FILE'
X
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		nChecked ;
Xextern 	int		nEnqueued ;
X
Xextern 	Flt		minweight ;
Xextern 	int		maxlevel ;
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() ;
X
Xextern 	Flt		VecNormalize() ;
Xextern	Vec		Slab[] ;
Xextern	ObjectProcs	NullProcs ;
Xextern 	Object *	Root ;
END_OF_FILE
if test 906 -ne `wc -c <'extern.h'`; then
    echo shar: \"'extern.h'\" unpacked with wrong size!
fi
# end of 'extern.h'
fi
if test -f 'intersect.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'intersect.c'\"
else
echo shar: Extracting \"'intersect.c'\" \(2570 characters\)
sed "s/^X//" >'intersect.c' <<'END_OF_FILE'
X#include <stdio.h>
X#include <math.h>
X#include <assert.h>
X#include "defs.h"
X#include "extern.h"
X
X
X/*
X * intersect.c
X * Much nicer now, uses the nifty priority queue search
X * as suggested by Kajiya...
X */
X
XFlt		num[NSLABS] ;
XFlt		den[NSLABS] ;
X
XINLINE
XCheckAndEnqueue(obj)
X register Object * obj ;
X{
X	int i ;
X	Flt tmp ;
X	Flt tmin, tmax ;
X	Flt dmin = -HUGE ;
X	Flt dmax = HUGE ;
X
X	nChecked ++ ;
X
X	for (i = 0 ; i < NSLABS ; i ++) {
X
X		/* enters the slab here...	*/
X		tmin = (obj -> o_dmin[i] - num[i]) * den[i] ;
X		/* and exits here...		*/
X		tmax = (obj -> o_dmax[i] - num[i]) * den[i] ;
X
X		/* but we may have to swap...	*/
X		if (tmin > tmax) {
X			tmp = tmin ; tmin = tmax ; tmax = tmp ;
X		}
X
X		/* if exited closer than we thought, update 	*/
X		if (tmax < dmax)
X			dmax = tmax ;
X		/* if entered farther than we thought, update 	*/
X		if (tmin > dmin)
X			dmin = tmin ;
X
X		if (dmin > dmax || dmax < rayeps)
X			return ;
X	}
X	PriorityQueueInsert(dmin, obj) ;
X	nEnqueued ++ ;
X}
X
XIntersect(ray, hit)
X Ray * ray ;
X Isect * hit ;
X{
X	Isect		nhit ;
X	int		i ;
X	Flt		min_dist = HUGE ;
X	Object *	cobj ;
X	Object * 	pobj = NULL ;
X	CompositeData 	* cdp ;
X	Flt		key ;
X
X	/* If the object is simple, then return the hit that it gives you */
X
X	if (Root -> o_type != T_COMPOSITE)
X		return (Root -> o_procs -> intersect) (Root, ray, hit) ;
X
X	for (i = 0 ; i < NSLABS ; i ++) {
X		num[i] = VecDot(ray -> P, Slab[i]) ;
X		den[i] = 1.0 / VecDot(ray -> D, Slab[i]) ;
X	}
X
X	/* start with an empty priority queue */
X	PriorityQueueNull() ;
X
X	CheckAndEnqueue(Root) ;
X
X	for (;;) {
X
X		if (PriorityQueueEmpty())
X			break ;
X
X		PriorityQueueDelete(&key, &cobj) ;
X
X		if (key > min_dist) {
X
X			/*
X			 * we have already found a primitive
X			 * that was closer, we need look no further...
X			 */
X			 break ;
X
X		} else if (cobj -> o_type == T_COMPOSITE) {
X			/* 
X			 * if it is in the queue, it got hit.
X			 * check each of its children to see if their
X			 * bounding volumes get hit.
X			 * if so, then push them into the priority
X			 * queue...
X			 */
X			
X			cdp = (CompositeData *) cobj -> o_data ;
X
X			for (i = 0 ; i < cdp -> c_size ; i ++ ) {
X				CheckAndEnqueue(cdp -> c_object[i]) ;
X			}
X
X		} else {
X
X			/*
X			 * we have a primitive 
X			 * intersect with the primitive, and possibly
X			 * update the nearest hit if it is indeed closer
X			 * than the one we currently have...
X			 */
X			
X			if ((cobj -> o_procs -> intersect) (cobj, ray, &nhit)) {
X				if (nhit.isect_t < min_dist) {
X					pobj = cobj ;
X					*hit = nhit ;
X					min_dist = nhit.isect_t ;
X				}
X			}
X		}
X	}
X
X	if (pobj)
X		return 1 ;
X	else
X		return 0 ;
X}
END_OF_FILE
if test 2570 -ne `wc -c <'intersect.c'`; then
    echo shar: \"'intersect.c'\" unpacked with wrong size!
fi
# end of 'intersect.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'\" \(1630 characters\)
sed "s/^X//" >'main.c' <<'END_OF_FILE'
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
X	if ((Progname = rindex(argv[0], '/')) == NULL) 
X		Progname = argv[0] ;
X	else 
X		Progname ++ ;
X
X	while ((c = getopt(argc, argv, "o:i:t")) != EOF) {
X		switch (c) {
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]\n",
X				Progname) ;
X			exit(-1);
X		}
X	}
X	ReadSceneFile(infilename) ;
X	InitSlabs() ;
X	BuildBoundingSlabs() ;
X	Screen(&Eye, outfilename, Xresolution, Yresolution) ;
X	PrintStatistics() ;
X}
X
XPrintStatistics()
X{
X	struct tms buf ;
X
X	times(&buf);
X	printf("time spent in user code:   %-6d seconds\n", buf.tms_utime/60);
X	printf("time spent in system code: %-6d seconds\n", buf.tms_stime/60);
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}
END_OF_FILE
if test 1630 -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'\" \(3138 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 
X
X%union {
X	Vec	vec ;
X	Vec *	vecl ;
X	double	flt ;
X} ;
X
X%type <vec>	point primcolor 
X%type <flt>	num 
X
X%%
X
Xscene:
X	camera elementlist 
X	{
X		int l ;
X		for (l = 0 ; l < nLights ; l++) {
X			Lights[l].light_brightness =  sqrt((Flt) nLights) / 
X							((Flt)nLights) ;
X		}
X	} ;
X
Xelementlist:
X	elementlist element
X	|  ;
X
Xelement:
X	light
X	| background
X	| surface
X	| 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		Xresolution = (int) $13 ;
X		Yresolution = (int) $14 ;
X	} ;
X
Xlight:
X	LIGHT point 
X	{
X		VecCopy($2, Lights[nLights].light_pos) ;
X
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		Prims[nPrims++] = MakeCone($2, $3, $4, $5) ;
X	} ;
Xsphere:
X	SPHERE point num 
X	{
X		Prims[nPrims++] = MakeSphere($2, $3) ;
X	} ;
Xpolygon:
X	POLYGON num 
X	{
X		plist = (Vec *) calloc((int) $2, sizeof(Vec)) ;
X		pl = plist ;
X	} 
X	pointlist 
X	{
X		Prims[nPrims++] = MakePoly((int) $2, plist) ;
X	} ;
Xppatch:
X	PATCH num
X	{
X		plist = (Vec *) calloc(((int)$2) * 2 , sizeof(Vec)) ;
X		pl = plist ;
X	} 
X	pointlist
X	{
X#ifdef DO_PATCHES
X		Prims[nPrims++] = MakePatch($2, plist) ;
X#endif /* DO_PATCHES */
X	} ;
X
Xprimcolor:
X	num num num 
X	{
X		$$[0] = $1 ;
X		$$[1] = $2 ;
X		$$[2] = $3 ;
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{
X	fprintf(stderr, "%s: error at line %d\n", 
X		Progname, yylinecount) ;
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 %d %d\n", Progname, Xresolution,
X		Yresolution) ;
X}
END_OF_FILE
if test 3138 -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'\" \(1175 characters\)
sed "s/^X//" >'pic.c' <<'END_OF_FILE'
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@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
XPicWriteLine(pic, buf)
X Pic *pic ;
X Pixel *buf ;
X{
X	int i ;
X	for (i = 0; i < pic -> x ; i ++) {
X		fputc(buf[i].r, pic -> filep);
X		fputc(buf[i].g, pic -> filep);
X		fputc(buf[i].b, pic -> filep);
X	}
X}
X
XPicClose(pic)
X Pic *pic ;
X{
X	fclose(pic -> filep) ;
X}
END_OF_FILE
if test 1175 -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'\" \(96 characters\)
sed "s/^X//" >'pic.h' <<'END_OF_FILE'
X/*
X * pic.h
X *
X */
X
Xtypedef struct Pic {
X	char	* filename ;
X	FILE	* filep ;
X	int	x, y ;
X} Pic ;
END_OF_FILE
if test 96 -ne `wc -c <'pic.h'`; then
    echo shar: \"'pic.h'\" unpacked with wrong size!
fi
# end of 'pic.h'
fi
if test -f 'poly.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'poly.c'\"
else
echo shar: Extracting \"'poly.c'\" \(3855 characters\)
sed "s/^X//" >'poly.c' <<'END_OF_FILE'
X#include <stdio.h>
X#include <math.h>
X#include "defs.h"
X#include "extern.h"
X
Xtypedef struct t_polydata {
X	int 	poly_npoints ;
X	Vec	* poly_point ;
X	Vec	poly_normal ;
X	Flt 	poly_d ;
X	Flt	poly_p1, poly_p2 ;
X} PolyData ;
X
Xint PolyPrint ();
Xint PolyIntersect ();
Xint PolyNormal ();
X
XObjectProcs PolyProcs = {
X	PolyPrint,
X	PolyIntersect,
X	PolyNormal,
X} ;
X
Xint 
XPolyPrint(obj)
X Object * obj ;
X{
X	int i ;
X	PolyData * pd ;
X
X	pd = (PolyData *) obj -> o_data ;
X	printf("p %d\n", pd -> poly_npoints) ;
X	for (i = 0 ; i < pd -> poly_npoints ; i++) {
X		printf("%g %g %g\n", pd -> poly_point[i][0],
X					pd -> poly_point[i][1],
X					pd -> poly_point[i][2]) ;
X	}
X}
X
XPolyIntersect(obj, ray, hit)
X Object * obj ;
X Ray * ray ;
X Isect * hit ;
X{
X	Flt n,d,t,m,b ;
X	Point V ;
X	int i, j, l ;
X	int qi, qj ;
X	int ri, rj ;
X	int c1, c2 ;
X	PolyData * pd ;
X
X	pd = (PolyData *) obj -> o_data ;
X	n = VecDot(ray -> P, pd -> poly_normal) + pd -> poly_d ;
X	d = VecDot(ray -> D, pd -> poly_normal) ;
X
X	if ((Flt) fabs(d) < rayeps) {
X		return(NULL);
X	}
X
X	t = - n / d ;
X	if (t < rayeps)
X		return 0 ;
X
X	RayPoint(ray,t,V);
X	c1 = pd -> poly_p1 ;
X	c2 = pd -> poly_p2 ;
X
X	l = 0 ;
X	for (i = 0 ; i < pd -> poly_npoints ; i++) {
X
X		j = (i + 1) % pd -> poly_npoints ;
X
X		qi = 0 ; qj = 0 ;
X		ri = 0 ; rj = 0 ;
X
X		if (pd -> poly_point[i][c2] == pd -> poly_point[j][c2])
X			continue ;		/*ignore horizontal lines */
X
X		if (pd -> poly_point[i][c2] < V[c2])
X			qi = 1 ;
X		if (pd -> poly_point[j][c2] < V[c2])
X			qj = 1 ;
X		if (qi == qj)
X			continue ;
X
X		if (pd -> poly_point[i][c1] < V[c1])
X			ri = 1 ;
X		if (pd -> poly_point[j][c1] < V[c1])
X			rj = 1 ;
X
X		if (ri & rj) {
X			l++ ;
X			continue ;
X		}
X
X		if ((ri|rj) == 0)
X			continue ;
X
X
X		/* 
X		 * more difficult acceptance...
X		 */
X		m = (pd -> poly_point[j][c2] - pd -> poly_point[i][c2]) /
X			(pd -> poly_point[j][c1] - pd -> poly_point[i][c1]) ;
X		
X		b = (pd -> poly_point[j][c2] - V[c2]) - 
X			m * (pd -> poly_point[j][c1] - V[c1]);
X
X		if ((-b/m) < rayeps)
X			l++ ;
X	}
X
X	if ((l % 2) == 0)
X		return(0);
X	
X	hit -> isect_t = t ;
X	hit -> isect_surf = obj -> o_surf ;
X	hit -> isect_prim = obj ;
X	hit -> isect_enter = 0 ;
X	return(1);
X}
X
XPolyNormal(obj, hit, P, N)
X Object * obj ;
X Isect * hit ;
X Point P, N ;
X{
X
X	PolyData * pd ;
X	pd = (PolyData *) obj -> o_data ;
X	VecCopy(pd -> poly_normal, N);
X}
X
XObject *
XMakePoly(npoints, points)
X int npoints ;
X Vec * points ;
X{
X	Object * obj ;
X	PolyData * pd ;
X	Vec P1, P2 ;
X	Flt d, dmax, dmin ;
X	int i, j ;
X
X	obj = (Object *) malloc (sizeof(Object)) ;
X	obj -> o_type = T_POLY ;
X	obj -> o_procs = & PolyProcs ;
X	obj -> o_surf = CurrentSurface ;
X
X	pd = (PolyData *) malloc (sizeof(PolyData)) ;
X	pd -> poly_npoints = npoints ;
X	pd -> poly_point = points ;
X
X	/*
X	 * calculate the normal by giving various cross products...
X	 */
X	
X	VecSub(pd -> poly_point[0], pd -> poly_point[1], P1) ;
X	VecSub(pd -> poly_point[2], pd -> poly_point[1], P2) ;
X
X	VecCross(P1, P2, pd -> poly_normal) ;
X	VecNormalize(pd -> poly_normal) ;
X
X	if (fabs(pd -> poly_normal[0]) > fabs(pd -> poly_normal[1])
X		&& fabs(pd -> poly_normal[0]) > fabs(pd -> poly_normal[2])) {
X		pd -> poly_p1 = 1 ;
X		pd -> poly_p2 = 2 ;
X	} else if (fabs(pd -> poly_normal[1]) > fabs(pd -> poly_normal[0]) 
X		&& fabs(pd -> poly_normal[1]) > fabs(pd -> poly_normal[2])) {
X		pd -> poly_p1 = 0 ;
X		pd -> poly_p2 = 2 ;
X	} else {
X		pd -> poly_p1 = 0 ;
X		pd -> poly_p2 = 1 ;
X	}
X
X	pd -> poly_d = - VecDot(pd -> poly_normal, pd -> poly_point[0]) ;
X
X	obj -> o_data = (void *) pd ;
X
X	/*
X	 * now, calculate the values of 
X	 * the dmin and dmax 'es for the globally defined slabs...
X	 */
X	
X	for (i = 0 ; i < NSLABS ; i ++) {
X		dmin = HUGE ;
X		dmax = - HUGE ;
X
X		for (j = 0 ; j < pd -> poly_npoints ; j ++) {
X			d = VecDot(Slab[i], pd -> poly_point[j]) ;
X			if (d < dmin) dmin = d ;
X			if (d > dmax) dmax = d ;
X		}
X		obj -> o_dmin[i] = dmin ;
X		obj -> o_dmax[i] = dmax ;
X	}
X	return(obj) ;
X}
END_OF_FILE
if test 3855 -ne `wc -c <'poly.c'`; then
    echo shar: \"'poly.c'\" unpacked with wrong size!
fi
# end of 'poly.c'
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'\" \(1511 characters\)
sed "s/^X//" >'pqueue.c' <<'END_OF_FILE'
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 1511 -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'\" \(1421 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.\" non-commercial use only.  
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.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.
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.SH AUTHOR
XMark VandeWettering
X.SH BUGS
XBugs!  Of course there are bugs!
X.PP
XI think there still might be something wrong with the reflections.  In 
Xparticular Eric Haine's "gears" database generates some wierd colors.  If 
Xyou can find the bug, send it too me and I will let the world know of the
Xproblem.
X.PP
XThis manual page should be expanded...
END_OF_FILE
if test 1421 -ne `wc -c <'ray.1'`; then
    echo shar: \"'ray.1'\" unpacked with wrong size!
fi
# end of 'ray.1'
fi
if test -f 'screen.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'screen.c'\"
else
echo shar: Extracting \"'screen.c'\" \(2432 characters\)
sed "s/^X//" >'screen.c' <<'END_OF_FILE'
X#include <stdio.h>
X#include <math.h>
X#include "defs.h"
X#include "pic.h"
X#include "extern.h"
X
XScreen(view, picfile, xres, yres)
X Viewpoint *view ;
X char *picfile ;
X int xres, yres ;
X{
X	Pixel 	*buf, *oldbuf, *curbuf, *tmp ;
X	Pic  	*pic, *PicOpen();
X	Point 	viewvec, leftvec ;
X	int red, green, blue ;
X	Point	dir ;
X	Ray 	ray ;
X	Color	color;
X	Flt	frustrumwidth ;
X	int 	x, y ;
X
X	/*
X	 * open the picture file...
X	 */
X
X	pic = PicOpen(picfile, xres, yres) ;
X
X	/*
X	 * allocate enough space for an entire row of pixels...
X	 * plus one more for the average...
X	 */
X
X	oldbuf = NULL ;
X	curbuf = (Pixel *) malloc (xres * sizeof (Pixel)) + 1 ;
X	buf = (Pixel *) malloc (xres * sizeof (Pixel)) + 1 ;
X
X	/*
X	 * determine the viewing frustrum
X	 */
X
X	VecNormalize(view -> view_up);
X	VecSub(view -> view_at, view-> view_from, viewvec);
X	VecNormalize(viewvec);
X	VecCross(view -> view_up, viewvec, leftvec);
X	VecNormalize(leftvec);
X
X	VecCopy(view -> view_from, ray.P);
X
X	frustrumwidth = (view -> view_dist) * ((Flt) tan(view -> view_angle)) ;
X
X	for (y=0; y < yres + 1; y++) {
X		for (x = 0; x < xres + 1; x++) {
X			VecComb(-frustrumwidth*(2.0*(Flt)y/(Flt)(yres-1)-1.0),
X				view -> view_up,
X				frustrumwidth*(2.0*(Flt)x/(Flt)(xres-1)-1.0),
X				leftvec, dir);
X			VecAdd(dir, viewvec, ray.D);
X			VecNormalize(ray.D);
X			Trace(0, 1.0, &ray, color);
X
X			if (color[0] > 1.0) color[0] = 1.0 ;
X			if (color[1] > 1.0) color[1] = 1.0 ;
X			if (color[2] > 1.0) color[2] = 1.0 ;
X
X			curbuf[x].r = (unsigned char) (255.0 * color[0]) ;
X			curbuf[x].g = (unsigned char) (255.0 * color[1]) ;
X			curbuf[x].b = (unsigned char) (255.0 * color[2]) ;
X		}
X		if (oldbuf) {
X			/* average the pixels, and write 'em out
X			 */
X			for (x = 0 ; x < xres ; x++) {
X				red = ((int)curbuf[x].r + (int)curbuf[x+1].r
X				     + (int)oldbuf[x].r+ (int)oldbuf[x+1].r) ;
X				green = ((int)curbuf[x].g + (int)curbuf[x+1].g
X				     + (int)oldbuf[x].g+ (int)oldbuf[x+1].g) ;
X				blue = ((int)curbuf[x].b + (int)curbuf[x+1].b
X				     + (int)oldbuf[x].b+ (int)oldbuf[x+1].b) ;
X				buf[x].r = (unsigned char) (red / 4) ;
X				buf[x].g = (unsigned char) (green / 4) ;
X				buf[x].b = (unsigned char) (blue / 4) ;
X			}
X			PicWriteLine(pic, buf);
X			tmp = oldbuf ;
X			oldbuf = curbuf ;
X			curbuf = tmp ;
X		} else {
X			oldbuf = curbuf ;
X			curbuf = (Pixel *) malloc (xres * sizeof (Pixel)) + 1 ;
X		}
X
X		if (tickflag)
X			fprintf(stderr, ".") ;
X	}
X	if (tickflag) fprintf(stderr, "\n") ;
X	PicClose(pic);
X}
END_OF_FILE
if test 2432 -ne `wc -c <'screen.c'`; then
    echo shar: \"'screen.c'\" unpacked with wrong size!
fi
# end of 'screen.c'
fi
if test -f 'shade.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'shade.c'\"
else
echo shar: Extracting \"'shade.c'\" \(2101 characters\)
sed "s/^X//" >'shade.c' <<'END_OF_FILE'
X#include <stdio.h>
X#include <math.h>
X#include "defs.h"
X#include "extern.h"
X
XShade(level, weight, P, N, I, hit, col) 
X int level ;
X Flt weight ;
X Vec P, N, I ;
X Isect * hit;
X Color col ;
X{
X	Ray 	tray ;
X	Color 	tcol ;
X	Vec 	L, H ;
X	Flt 	t ;
X	Flt	diff ;
X	Flt 	spec ;
X	Surface	* surf ;
X	int l ;
X
X	col[0] = col[1] = col[2] = 0.0 ;
X	surf = hit -> isect_prim -> o_surf ;
X
X	for (l = 0; l < nLights; l++) {
X		VecSub(Lights[l].light_pos, P, L);
X		if (VecDot(N,L) >= 0.0) {
X			t = VecNormalize(L);
X			VecCopy(P, tray.P);
X			VecCopy(L, tray.D);
X			nShadows ++ ;
X			if (Shadow(&tray, t)) {
X				diff = VecDot(N,L) * surf -> surf_kd *
X					Lights[l].light_brightness ;
X				VecAddS(diff, surf -> surf_color, col, col) ;
X				/*
X				VecAdd(L, I, H) ;
X				VecNormalize(H) ;
X				spec = surf -> surf_ks 
X					* pow(VecDot(H,N), surf -> surf_shine) ;
X				col[0] += spec ;
X				col[1] += spec ;
X				col[2] += spec ;
X				*/
X			}
X		}
X	}
X
X	VecCopy(P, tray.P);
X
X	if(surf -> surf_ks * weight > minweight) {
X		nReflected ++ ;
X		SpecularDirection(I, N, tray.D);
X		VecNormalize(tray.D);
X		Trace(level + 1, surf -> surf_ks * weight, &tray, tcol);
X		VecAddS(surf -> surf_ks, tcol, col, col);
X	}
X
X	if (surf -> surf_kt * weight > minweight) { 
X		nRefracted ++ ;
X		if (hit -> isect_enter) 
X			TransmissionDirection(NULL, surf, I, N, tray.D) ;
X		else	
X			TransmissionDirection(surf, NULL, I, N, tray.D) ;
X		Trace(level + 1, surf -> surf_kt * weight, &tray, tcol) ;
X		VecAddS(surf -> surf_kt, tcol, col, col) ;
X	}
X}
X
Xint
XShadow(ray, tmax)
X Ray *ray ;
X Flt tmax ;
X{
X	Isect hit ;
X	int Intersect() ;
X
X	if (Intersect(ray, &hit) && hit.isect_t < tmax - rayeps) {
X		return(0);
X	} else {
X		return(1);
X	}
X}
X
XSpecularDirection(I, N, R)
X Vec I, N, R;
X{
X	VecComb(1.0/fabs(VecDot(I,N)), I, 2.0, N, R);
X	VecNormalize(R);
X}
X
XTransmissionDirection(m1, m2, I, N, T)
X Surface *m1, *m2;
X Vec I, N, T ;
X{
X	Flt n1, n2, eta, c1, cs2 ;
X	n1 = m1 ? m1 -> surf_ior : 1.0 ;
X	n2 = m2 ? m2 -> surf_ior : 1.0 ;
X	eta = n1/n2 ;
X
X	c1 = -VecDot(I,N);
X	cs2 = 1.0 - eta * eta*(1.0 - c1*c1);
X	if (cs2 < 0.0)
X		return 0;
X	VecComb(eta, I, eta*c1-sqrt(cs2), N, T);
X	return(1);
X}
END_OF_FILE
if test 2101 -ne `wc -c <'shade.c'`; then
    echo shar: \"'shade.c'\" unpacked with wrong size!
fi
# end of 'shade.c'
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'\" \(2078 characters\)
sed "s/^X//" >'sphere.c' <<'END_OF_FILE'
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 2078 -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'\" \(738 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.			return yytext[0] ;
X
X%%
X
Xyywrap()
X{
X	return 1 ;
X}
END_OF_FILE
if test 738 -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'\" \(584 characters\)
sed "s/^X//" >'trace.c' <<'END_OF_FILE'
X
X#include <stdio.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 ;
X		return ;
X	}
X		
X	nRays ++ ;
X
X	if (Intersect(ray, &hit)) {
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 584 -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'\" \(211 characters\)
sed "s/^X//" >'vector.c' <<'END_OF_FILE'
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}
END_OF_FILE
if test 211 -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 1\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have the archive.
    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

johnm@trsvax.UUCP (09/01/88)

Neat!

Ok, now will somebody post Eric Haine's NFF format (and any source to deal
with it)?  I don't ever remember having seen it come through here at any time.

Thanks,
John Munsch