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