rsalz@uunet.uu.net (Rich Salz) (03/28/89)
Submitted-by: Mark VandeWettering <markv@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@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@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@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@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@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@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@uunet.uu.net.