markv@uoregon.uoregon.edu (Mark VandeWettering) (08/30/88)
If you have seen this already, sorry, our nntp mail posting was flakey, and I don't think that this made it out. Here is the first release of my totally whiz-bang ray tracer. Okay, so it isn't TOTALLY whiz bang, but it does have some nice features. It uses bounding volumes, has cones, spheres, polygons and cylinders as primtives, reads Eric Haines NFF file format images and more.... Use it, abuse it, sell it, but be sure to have fun with it. I had alot of fun hacking on it. If any of you find bugs, or better yet fix bugs and add features, send them to me, and I will try to get them worked into a future release which I hope might make it into comp.sources.unix. #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 1 (of 1)." # Contents: Makefile README balls.nff bound.c cone.c data.c defs.h # error.c extern.h intersect.c main.c nff.y pic.c pic.h poly.c # pqueue.c ray.1 screen.c shade.c sphere.c tokens.l trace.c vector.c # Wrapped by markv@sol on Mon Aug 29 13:49:23 1988 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'Makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Makefile'\" else echo shar: Extracting \"'Makefile'\" \(3430 characters\) sed "s/^X//" >'Makefile' <<'END_OF_FILE' X# X# Makefile for Mark VandeWettering's X# Raytracer # 3 X# X# Optimized, doesn't do constructive solid geometry X# but does read in Eric Haine's NFF files X# directly.... X# X XPROG=ray X#CC=cc XCC=gcc X#CFLAGS=-O -f68881 XCFLAGS=-O -fforce-mem -fforce-addr -DFAST_MATH_PRIMS -g -p XYFLAGS=-d X XCSRC=data.c main.c sphere.c vector.c shade.c trace.c intersect.c\ X screen.c pic.c poly.c bound.c error.c pqueue.c cone.c XCOBJ=data.o main.o sphere.o vector.o shade.o trace.o intersect.o\ X screen.o pic.o poly.o bound.o error.o pqueue.o cone.o XNFFFILES=balls.nff XOSRC=nff.y tokens.l XOOBJ=nff.o tokens.o XHDRS=defs.h extern.h pic.h XLIBS=-lm X X$(PROG): $(COBJ) $(OOBJ) X $(CC) $(CFLAGS) -o $(PROG) $(COBJ) $(OOBJ) $(LIBS) X Xclean: X rm -f $(COBJ) $(OOBJ) X rm -f core tags X Xdepend: X sed '/^#DONT EDIT/,$$d' Makefile > Makefile.new X echo "#DONT EDIT THIS, AUTOMATICALLY GENERATED#" >> Makefile.new X $(CC) -M $(CSRC) >> Makefile.new X mv Makefile.new Makefile X Xlint: X lint $(CSRC) X Xbackup: X -mkdir .backup X cp $(CSRC) $(OSRC) $(HDR) Makefile .backup X Xnewrevision: X ci -t/dev/null $(CSRC) $(OSRC) Makefile ray.1 README $(HDRS) X Xkit: $(CRSRC) $(OSRC) Makefile ray.1 README $(NFFFILES) $(HDRS) X rm -f Part* X makekit $(CSRC) $(OSRC) Makefile ray.1 README $(NFFFILES) $(HDRS) X X#DONT EDIT THIS, AUTOMATICALLY GENERATED# Xdata.o: data.c Xdata.o: ./defs.h Xmain.o: main.c Xmain.o: /usr/include/stdio.h Xmain.o: /usr/include/sys/types.h Xmain.o: /usr/include/sys/sysmacros.h Xmain.o: /usr/include/sys/times.h Xmain.o: ./defs.h Xmain.o: ./extern.h Xsphere.o: sphere.c Xsphere.o: /usr/include/stdio.h Xsphere.o: /usr/include/math.h Xsphere.o: /usr/include/floatingpoint.h Xsphere.o: /usr/include/sys/ieeefp.h Xsphere.o: ./defs.h Xsphere.o: ./extern.h Xvector.o: vector.c Xvector.o: /usr/include/stdio.h Xvector.o: /usr/include/math.h Xvector.o: /usr/include/floatingpoint.h Xvector.o: /usr/include/sys/ieeefp.h Xvector.o: ./defs.h Xvector.o: ./extern.h Xshade.o: shade.c Xshade.o: /usr/include/stdio.h Xshade.o: /usr/include/math.h Xshade.o: /usr/include/floatingpoint.h Xshade.o: /usr/include/sys/ieeefp.h Xshade.o: ./defs.h Xshade.o: ./extern.h Xtrace.o: trace.c Xtrace.o: /usr/include/stdio.h Xtrace.o: ./defs.h Xtrace.o: ./extern.h Xintersect.o: intersect.c Xintersect.o: /usr/include/stdio.h Xintersect.o: /usr/include/math.h Xintersect.o: /usr/include/floatingpoint.h Xintersect.o: /usr/include/sys/ieeefp.h Xintersect.o: ./defs.h Xintersect.o: ./extern.h Xscreen.o: screen.c Xscreen.o: /usr/include/stdio.h Xscreen.o: /usr/include/math.h Xscreen.o: /usr/include/floatingpoint.h Xscreen.o: /usr/include/sys/ieeefp.h Xscreen.o: ./defs.h Xscreen.o: ./pic.h Xscreen.o: ./extern.h Xpic.o: pic.c Xpic.o: /usr/include/stdio.h Xpic.o: ./pic.h Xpic.o: ./defs.h Xpic.o: ./extern.h Xpoly.o: poly.c Xpoly.o: /usr/include/stdio.h Xpoly.o: /usr/include/math.h Xpoly.o: /usr/include/floatingpoint.h Xpoly.o: /usr/include/sys/ieeefp.h Xpoly.o: ./defs.h Xpoly.o: ./extern.h Xbound.o: bound.c Xbound.o: /usr/include/stdio.h Xbound.o: /usr/include/math.h Xbound.o: /usr/include/floatingpoint.h Xbound.o: /usr/include/sys/ieeefp.h Xbound.o: ./defs.h Xbound.o: ./extern.h Xerror.o: error.c Xerror.o: /usr/include/stdio.h Xerror.o: /usr/include/math.h Xerror.o: /usr/include/floatingpoint.h Xerror.o: /usr/include/sys/ieeefp.h Xerror.o: ./defs.h Xerror.o: ./extern.h Xpqueue.o: pqueue.c Xpqueue.o: /usr/include/stdio.h Xpqueue.o: /usr/include/math.h Xpqueue.o: /usr/include/floatingpoint.h Xpqueue.o: /usr/include/sys/ieeefp.h Xpqueue.o: ./defs.h Xpqueue.o: ./extern.h END_OF_FILE if test 3430 -ne `wc -c <'Makefile'`; then echo shar: \"'Makefile'\" unpacked with wrong size! fi # end of 'Makefile' fi if test -f 'README' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'README'\" else echo shar: Extracting \"'README'\" \(2361 characters\) sed "s/^X//" >'README' <<'END_OF_FILE' X######################################################################## X RAY V.3.0 by Mark VandeWettering X######################################################################## X markv@cs.uoregon.edu X------------------------------------------------------------------------ X XThis is my first release of my raytracer. While far from perfect (or Xeven complete), it does have several nifty features: X Xo It reads Eric Haine's NFF file format for objects. Included is a small X data file for spheres resting above a polygon. Obtain his NFF package X if you want some more fun data files X Xo It supports cones, cylinders, spheres, and polygons. The illumination X model it uses is primitive, but should be easy to change. Other X primitives can be added in a simple way (look at sphere.c, cone.c, X and poly.c to see what you need to do). X Xo It uses Kajiya's bounding slabs to allow a large number of objects X to be raytraced. For instance, a scene consisting of 7281 spheres X took about 7 hours on a Sun 3/50 w/68881 at 512x512 resolution. X XCAVEATS: X XI have only run this on Suns. While it probably will work on Xothers, no guarantees... X XIt writes out a file consisting of single line with the x and y size of the Ximage, followed by groups of three bytes <red green blue>. All the picture Xoutput primitives should be isolated in pic.c, so converting it to a new Xformat shouldn't be hard. X XAs I mentioned, the lighting model isn't right. In particular, refraction Xis far to primitive, and doesn't work right for intersecting objects. X XIt doesn't anti-alias. I originally planned on adding a statistically Xoptimized antialiaser, but didn't get to it. It averages the rays at the Xcorners of each pixel to obtain the pixel value. X XUndoubtably there are bugs and portability problems. If you notice anything Xtoo wierd, report them to me. If you have a fix, send it to me, and I will Xtry to incorporate it into a future release, which might be destined for Xcomp.sources.unix. If you extend/fix various limitations in the system, be Xsure to send them to me, and I will include your name in lights alongside mine. X:-) X XCOPYING X XFeel free to copy, sell, distribute, modify and hack this program into Xlittle itty bitty bits. I wrote it for fun, and hope others have fun with it Xtoo. Write me about any extensions you implement. X XMark VandeWettering END_OF_FILE if test 2361 -ne `wc -c <'README'`; then echo shar: \"'README'\" unpacked with wrong size! fi # end of 'README' fi if test -f 'balls.nff' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'balls.nff'\" else echo shar: Extracting \"'balls.nff'\" \(563 characters\) sed "s/^X//" >'balls.nff' <<'END_OF_FILE' Xv Xfrom 2.1 1.3 1.7 Xat 0 0 0 Xup 0 0 1 Xangle 45 Xhither 1 Xresolution 100 100 Xb 0.078 .361 .753 Xl 4 3 2 Xl 1 -4 4 Xl -3 1 5 Xf 1 .75 .33 1 0 0 0 0 Xp 4 X12 12 -.5 X-12 12 -.5 X-12 -12 -.5 X12 -12 -.5 Xf 1 .9 .7 .5 .5 3 0 0 Xs 0 0 0 .5 Xs .272166 .272166 .544331 .166667 Xs .643951 .172546 1.11022e-16 .166667 Xs .172546 .643951 1.11022e-16 .166667 Xs -.371785 0.0996195 .544331 .166667 Xs -.471405 .471405 1.11022e-16 .166667 Xs -.643951 -.172546 1.11022e-16 .166667 Xs 0.0996195 -.371785 .544331 .166667 Xs -.172546 -.643951 1.11022e-16 .166667 Xs .471405 -.471405 1.11022e-16 .166667 END_OF_FILE if test 563 -ne `wc -c <'balls.nff'`; then echo shar: \"'balls.nff'\" unpacked with wrong size! fi # end of 'balls.nff' fi if test -f 'bound.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'bound.c'\" else echo shar: Extracting \"'bound.c'\" \(2298 characters\) sed "s/^X//" >'bound.c' <<'END_OF_FILE' X#include <stdio.h> X#include "math.h" X#include "defs.h" X#include "extern.h" X X/* X * This function attempts to use median cut X * to generate tighter bounding volumes than the old X * code... X */ X XBuildBoundingSlabs() X{ X int low = 0 ; X int axis = 0 ; X int high, i ; X X high = nPrims ; X while (SortAndSplit(low, high, axis) == 0) { X axis = (axis + 1) % NSLABS ; X low = high ; X high = nPrims ; X } X fprintf(stderr, "%s: after adding bounding volumes, %d prims\n", X Progname, nPrims) ; X fprintf(stderr, "%s: extent of scene\n", Progname) ; X for (i = 0 ; i < NSLABS; i++) { X fprintf(stderr, "%s: <%g -- %g>\n", X Progname, X Root -> o_dmin[i], X Root -> o_dmax[i]) ; X } X} X Xstatic int Axis ; X Xint Xcompslabs(a, b) X Object **a, **b ; X{ X Flt am, bm ; X X am = (*a) -> o_dmin[Axis] + (*a) -> o_dmax[Axis] ; X bm = (*b) -> o_dmin[Axis] + (*b) -> o_dmax[Axis] ; X X if (am < bm) X return (-1) ; X else if (am == bm) X return (0) ; X else X return (1) ; X} X XSortAndSplit(first, last, axis) X int first, last ; X int axis ; X{ X Object * cp ; X CompositeData * cd ; X int size, i, j ; X Flt dmin, dmax ; X int m ; X X Axis = axis ; X X size = last - first ; X qsort((char *) (Prims + first), size, sizeof (Object *), compslabs) ; X X if (size <= BUNCHINGFACTOR) { X /* build a box to contain them */ X X cp = (Object *) malloc (sizeof(Object)) ; X cp -> o_type = T_COMPOSITE ; X cp -> o_procs = & NullProcs ; /* die if you call any */ X cp -> o_surf = NULL ; /* no surface... */ X cd = (CompositeData *) malloc (sizeof(CompositeData)) ; X cd -> c_size = size ; X X for(i = 0 ; i < size ; i++) { X cd -> c_object[i] = Prims[first + i] ; X } X X for (i = 0 ; i < NSLABS ; i++ ) { X dmin = HUGE ; X dmax = -HUGE ; X for (j = 0 ; j < size ; j++) { X if (cd -> c_object[j] -> o_dmin[i] < dmin) X dmin = cd -> c_object[j] -> o_dmin[i] ; X if (cd -> c_object[j] -> o_dmax[i] > dmax) X dmax = cd -> c_object[j] -> o_dmax[i] ; X } X cp -> o_dmin[i] = dmin ; X cp -> o_dmax[i] = dmax ; X } X cp -> o_data = (void *) cd ; X Root = cp ; X Prims[nPrims ++] = cp ; X return (1) ; X } else { X m = (first + last) / 2 ; X SortAndSplit(first, m, (axis + 1) % NSLABS) ; X SortAndSplit(m , last, (axis + 1) % NSLABS) ; X return (0) ; X } X} X X XInitSlabs() X{ X int i ; X X for (i = 0 ; i < NSLABS ; i ++) { X VecNormalize(Slab[i]) ; X } X} END_OF_FILE if test 2298 -ne `wc -c <'bound.c'`; then echo shar: \"'bound.c'\" unpacked with wrong size! fi # end of 'bound.c' fi if test -f 'cone.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'cone.c'\" else echo shar: Extracting \"'cone.c'\" \(5709 characters\) sed "s/^X//" >'cone.c' <<'END_OF_FILE' X#include <stdio.h> X#include <math.h> X#include "defs.h" X#include "extern.h" X Xtypedef struct t_conedata { X Vec cone_base ; X Flt cone_base_radius ; X Flt cone_base_d ; X Vec cone_apex ; X Flt cone_apex_radius ; X Vec cone_u ; X Vec cone_v ; X Vec cone_w ; X Flt cone_height ; X Flt cone_slope ; X Flt cone_min_d ; X Flt cone_max_d ; X} ConeData ; X Xint ConePrint (); Xint ConeIntersect (); Xint ConeNormal (); X XObjectProcs ConeProcs = { X ConePrint, X ConeIntersect, X ConeNormal, X} ; X Xint XConePrint(obj) X Object *obj ; X{ X ConeData * cp ; X X cp = (ConeData *) obj -> o_data ; X X printf("c %g %g %g %g %g %g %g %g\n", cp -> cone_base[0], X cp -> cone_base[1], X cp -> cone_base[2], X cp -> cone_base_radius, X cp -> cone_apex[0], X cp -> cone_apex[1], X cp -> cone_apex[2], X cp -> cone_apex_radius) ; X} X XConeIntersect(obj, ray, hit) X Object * obj ; X Ray * ray ; X Isect * hit ; X{ X Ray tray ; X ConeData * cd ; X Vec V, P ; X Flt a, b, c, d, disc ; X Flt t1, t2 ; X int nroots ; X X cd = (ConeData *) (obj -> o_data) ; X X /* X * First, we get the coordinates of the ray origin in X * the objects space.... X */ X X VecSub(ray -> P, cd -> cone_base, V) ; X X tray.P[0] = VecDot(V, cd -> cone_u) ; X tray.P[1] = VecDot(V, cd -> cone_v) ; X tray.P[2] = VecDot(V, cd -> cone_w) ; X X /* X VecAdd(ray -> P, ray -> D, V) ; X VecSub(V, cd -> cone_base, V) ; X */ X X tray.D[0] = VecDot(ray -> D, cd -> cone_u) ; X tray.D[1] = VecDot(ray -> D, cd -> cone_v) ; X tray.D[2] = VecDot(ray -> D, cd -> cone_w) ; X X /* X VecSub(tray.D, tray.P, tray.D) ; X */ X X a = tray.D[0] * tray.D[0] X + tray.D[1] * tray.D[1] X - cd -> cone_slope * cd -> cone_slope * tray.D[2] * tray.D[2] ; X X b = 2.0 * (tray.P[0] * tray.D[0] + tray.P[1] * tray.D[1] - X cd -> cone_slope * cd -> cone_slope * tray.P[2] * tray.D[2] X - cd -> cone_base_radius * cd -> cone_slope * tray.D[2]) ; X X c = cd -> cone_slope * tray.P[2] + cd -> cone_base_radius ; X c = tray.P[0] * tray.P[0] + tray.P[1] * tray.P[1] - (c * c) ; X X disc = b * b - 4.0 * a * c ; X X if (disc < 0.0) X return (0) ; X X disc = (Flt) sqrt(disc) ; X t1 = (-b - disc) / (2.0 * a) ; X t2 = (-b + disc) / (2.0 * a) ; X X if (t2 < rayeps) X return (0) ; X if (t1 < rayeps) { X nroots = 1 ; X t1 = t2 ; X } else { X nroots = 2 ; X } X X /* X * ensure that the points are between the two bounding planes... X */ X X switch(nroots) { X case 1: X RayPoint(ray, t1, P) ; X d = VecDot(cd -> cone_w, P) ; X if (d >= cd -> cone_min_d && d <= cd -> cone_max_d) { X hit -> isect_t = t1 ; X hit -> isect_prim = obj ; X hit -> isect_surf = obj -> o_surf ; X hit -> isect_enter = 0 ; X return(1) ; X } else { X return(0) ; X } X break ; X case 2: X RayPoint(ray, t1, P) ; X d = VecDot(cd -> cone_w, P) ; X if (d >= cd -> cone_min_d && d <= cd -> cone_max_d) { X hit -> isect_t = t1 ; X hit -> isect_prim = obj ; X hit -> isect_surf = obj -> o_surf ; X hit -> isect_enter = 1 ; X return(1) ; X } else { X RayPoint(ray, t2, P) ; X d = VecDot(cd -> cone_w, P) ; X if (d >= cd -> cone_min_d && d <= cd -> cone_max_d) { X hit -> isect_t = t2 ; X hit -> isect_prim = obj ; X hit -> isect_surf = obj -> o_surf ; X hit -> isect_enter = 0 ; X return(1) ; X } X } X return(0) ; X } X return(0) ; X} X Xint XConeNormal(obj, hit, P, N) X Object * obj ; X Isect * hit ; X Point P, N ; X{ X Flt t ; X Vec V ; X ConeData * cd ; X X cd = (ConeData *) obj -> o_data ; X X /* X * fill in the real normal... X * Project the point onto the base plane. The normal is X * a vector from the basepoint through this point, plus the slope X * times the cone_w vector... X */ X X t = - (VecDot(P, cd -> cone_w) + cd -> cone_base_d) ; X VecAddS(t, cd -> cone_w, P, V) ; X VecSub(V, cd -> cone_base, N) ; X VecNormalize(N) ; X VecAddS(- cd -> cone_slope, cd -> cone_w, N, N) ; X VecNormalize(N) ; X} X XObject * XMakeCone(basepoint, baseradius, apexpoint, apexradius) X Vec basepoint, apexpoint ; X Flt baseradius, apexradius ; X{ X Object * obj ; X ConeData * cd ; X Flt dmin, dmax, d , ftmp; X Vec tmp ; X int i ; X X obj = (Object *) malloc (sizeof (Object)) ; X obj -> o_type = T_CONE ; X obj -> o_procs = & ConeProcs ; X obj -> o_surf = CurrentSurface ; X X cd = (ConeData *) malloc (sizeof(ConeData)) ; X X VecCopy(basepoint, cd -> cone_base) ; X VecCopy(apexpoint, cd -> cone_apex) ; X X cd -> cone_base_radius = baseradius ; X cd -> cone_apex_radius = apexradius ; X X X VecSub(apexpoint, basepoint, cd -> cone_w) ; X cd -> cone_height = VecNormalize(cd -> cone_w) ; X cd -> cone_slope = (cd -> cone_apex_radius - cd -> cone_base_radius) / X (cd -> cone_height) ; X cd -> cone_base_d = - VecDot(basepoint, cd -> cone_w) ; X X MakeVector(0.0, 0.0, 1.0, tmp) ; X X if (fabs(VecDot(tmp, cd -> cone_w) - 1.0) < rayeps) { X MakeVector(0.0, 1.0, 0.0, tmp) ; X } X X /* find two axes which are at right angles to cone_w X */ X X VecCross(cd -> cone_w, tmp, cd -> cone_u) ; X VecCross(cd -> cone_u, cd -> cone_w, cd -> cone_v) ; X X cd -> cone_min_d = VecDot(cd -> cone_w, cd -> cone_base) ; X cd -> cone_max_d = VecDot(cd -> cone_w, cd -> cone_apex) ; X X if (cd -> cone_max_d < cd -> cone_min_d) { X ftmp = cd -> cone_max_d ; X cd -> cone_max_d = cd -> cone_min_d ; X cd -> cone_min_d = ftmp ; X } X X obj -> o_data = (void *) cd ; X X for (i = 0 ; i < NSLABS ; i ++) { X dmin = HUGE ; X dmax = -HUGE ; X d = VecDot(basepoint, Slab[i]) - baseradius ; X if (d < dmin) dmin = d ; if (d > dmax) dmax = d ; X d = VecDot(basepoint, Slab[i]) + baseradius ; X if (d < dmin) dmin = d ; if (d > dmax) dmax = d ; X d = VecDot(apexpoint, Slab[i]) - apexradius ; X if (d < dmin) dmin = d ; if (d > dmax) dmax = d ; X d = VecDot(apexpoint, Slab[i]) + apexradius ; X if (d < dmin) dmin = d ; if (d > dmax) dmax = d ; X X obj -> o_dmin[i] = dmin ; X obj -> o_dmax[i] = dmax ; X } X X return(obj) ; X} END_OF_FILE if test 5709 -ne `wc -c <'cone.c'`; then echo shar: \"'cone.c'\" unpacked with wrong size! fi # end of 'cone.c' fi if test -f 'data.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'data.c'\" else echo shar: Extracting \"'data.c'\" \(699 characters\) sed "s/^X//" >'data.c' <<'END_OF_FILE' X X X#include "defs.h" X Xint yylinecount ; XViewpoint Eye ; Xint Xresolution = 512 ; Xint Yresolution = 512 ; XLight Lights[MAXLIGHTS] ; Xint nLights = 0 ; XVec BackgroundColor ; XSurface * CurrentSurface ; XObject * Prims[MAXPRIMS] ; Xint nPrims = 0 ; XFlt rayeps = 1e-6 ; Xchar * Progname ; XObject * Root ; X XFlt minweight = 0.01 ; Xint maxlevel = 5 ; Xint nRays = 0 ; Xint nShadows = 0 ; Xint nReflected = 0 ; Xint nRefracted = 0 ; Xint maxQueueSize = 0 ; Xint totalQueues = 0 ; Xint totalQueueResets = 0 ; Xint tickflag = 0 ; Xint nChecked = 0 ; Xint nEnqueued = 0 ; X XVec Slab[] = { X {1.0, 0.0, 0.0}, X {0.0, 1.0, 0.0}, X {0.0, 0.0, 1.0}, X {1.0, 1.0, 0.0}, X {1.0, 0.0, 1.0}, X {0.0, 1.0, 1.0} X} ; END_OF_FILE if test 699 -ne `wc -c <'data.c'`; then echo shar: \"'data.c'\" unpacked with wrong size! fi # end of 'data.c' fi if test -f 'defs.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'defs.h'\" else echo shar: Extracting \"'defs.h'\" \(2864 characters\) sed "s/^X//" >'defs.h' <<'END_OF_FILE' X/* X * D E F S . H X * X */ X X#define NSLABS (3) X#define BUNCHINGFACTOR (10) X#define PQSIZE (10000) X Xtypedef double Flt ; Xtypedef Flt Vec[3] ; Xtypedef Vec Point ; Xtypedef Vec Color ; Xtypedef Flt Matrix[4][4] ; X X#define MakeVector(x, y, z, v) (v)[0]=(x),(v)[1]=(y),(v)[2]=(z) X#define VecNegate(a) (a)[0]=0-(a)[0];\ X (a)[1]=0-(a)[1];\ X (a)[2]=0-(a)[2]; X#define VecDot(a,b) ((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[2]) X#define VecLen(a) (sqrt(VecDot(a,a))) X#define VecCopy(a,b) (b)[0]=(a)[0];(b)[1]=(a)[1];(b)[2]=(a)[2]; X#define VecAdd(a,b,c) (c)[0]=(a)[0]+(b)[0];\ X (c)[1]=(a)[1]+(b)[1];\ X (c)[2]=(a)[2]+(b)[2] X#define VecSub(a,b,c) (c)[0]=(a)[0]-(b)[0];\ X (c)[1]=(a)[1]-(b)[1];\ X (c)[2]=(a)[2]-(b)[2] X#define VecComb(A,a,B,b,c) (c)[0]=(A)*(a)[0]+(B)*(b)[0];\ X (c)[1]=(A)*(a)[1]+(B)*(b)[1];\ X (c)[2]=(A)*(a)[2]+(B)*(b)[2] X#define VecAddS(A,a,b,c) (c)[0]=(A)*(a)[0]+(b)[0];\ X (c)[1]=(A)*(a)[1]+(b)[1];\ X (c)[2]=(A)*(a)[2]+(b)[2] X#define VecCross(a,b,c) (c)[0]=(a)[1]*(b)[2]-(a)[2]*(b)[1];\ X (c)[1]=(a)[2]*(b)[0]-(a)[0]*(b)[2];\ X (c)[2]=(a)[0]*(b)[1]-(a)[1]*(b)[0] X Xtypedef struct Ray { X Point P ; X Point D ; X} Ray ; X X#define RayPoint(ray,t,point) VecAddS(t,(ray)->D,(ray)->P,point) X X#define max(a,b) ((a)>(b)?(a):(b)) X#define min(a,b) ((a)<(b)?(a):(b)) X X/*----------------------------------------------------------------------*/ X Xtypedef struct t_surface { X Color surf_color ; X Flt surf_kd ; X Flt surf_ks ; X Flt surf_shine ; X Flt surf_kt ; X Flt surf_ior ; X} Surface ; X Xtypedef struct t_light { X Vec light_pos ; X Flt light_brightness ; X} Light ; X Xtypedef struct t_viewpoint { X Vec view_from ; X Vec view_at ; X Vec view_up ; X Flt view_angle ; X Flt view_dist ; X} Viewpoint ; X Xtypedef struct t_object { X unsigned short o_type ; X Flt o_dmin[NSLABS] ; X Flt o_dmax[NSLABS] ; X struct t_objectprocs { X int (*print) () ; X int (*intersect) () ; X int (*normal) () ; X } * o_procs ; X struct t_surface * o_surf ; X void * o_data ; X} Object ; X Xtypedef struct t_compositedata { X unsigned short c_size ; X Object * c_object[BUNCHINGFACTOR] ; X} CompositeData ; X Xtypedef struct t_objectprocs ObjectProcs ; X Xtypedef struct t_isect { X Flt isect_t ; X int isect_enter ; X Object * isect_prim ; X Surface * isect_surf ; X} Isect ; X Xtypedef struct t_pixel { X unsigned char r, g, b, q ; X} Pixel ; X X#define XMAX (1024) X#define YMAX (1024) X X#define PI (3.14159265358979323844) X#define degtorad(x) (((Flt)(x))*PI/180.0) X X#define MAXLIGHTS (10) X#define MAXPRIMS (10000) X X#define T_COMPOSITE (0) X#define T_SPHERE (1) X#define T_POLY (2) X#define T_CONE (3) X X#ifdef __GNUC__ X#define INLINE inline X X#ifdef FAST_MATH_PRIMS X#define sqrt(x)\ X ({ double __value, __arg = (x) ;\ X asm("fsqrtx %1,%0": "=f" (__value): "f" (__arg)) ;\ X __value ;}) X X#endif /* FAST_MATH_PRIMS */ X X#else /* __GNUC__ */ X X#define INLINE /* */ X X#endif /* __GNUC__ */ END_OF_FILE if test 2864 -ne `wc -c <'defs.h'`; then echo shar: \"'defs.h'\" unpacked with wrong size! fi # end of 'defs.h' fi if test -f 'error.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'error.c'\" else echo shar: Extracting \"'error.c'\" \(573 characters\) sed "s/^X//" >'error.c' <<'END_OF_FILE' X#include <stdio.h> X#include <math.h> X#include "defs.h" X#include "extern.h" X X/* X * various routines to print error messages and die... X */ X Xint NullPrint() ; Xint NullIntersect() ; Xint NullNormal() ; X XObjectProcs NullProcs = { X NullPrint, X NullIntersect, X NullNormal X} ; X XNullPrint() X{ X fprintf(stderr, "%s: called (* print)(...), dying...\n", Progname) ; X abort() ; X} X XNullIntersect() X{ X fprintf(stderr, "%s: called (* intersect)(...), dying...\n", Progname) ; X abort() ; X} X XNullNormal() X{ X fprintf(stderr, "%s: called (* normal)(...), dying...\n", Progname) ; X abort() ; X} END_OF_FILE if test 573 -ne `wc -c <'error.c'`; then echo shar: \"'error.c'\" unpacked with wrong size! fi # end of 'error.c' fi if test -f 'extern.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'extern.h'\" else echo shar: Extracting \"'extern.h'\" \(906 characters\) sed "s/^X//" >'extern.h' <<'END_OF_FILE' X X X Xextern int yylinecount ; Xextern Viewpoint Eye ; Xextern int Xresolution ; Xextern int Yresolution ; Xextern Light Lights[] ; Xextern int nLights ; Xextern Vec BackgroundColor ; Xextern Surface * CurrentSurface ; Xextern Object * Prims[] ; Xextern int nPrims ; Xextern Flt rayeps ; Xextern char * Progname ; Xextern int maxQueueSize ; Xextern int totalQueues ; Xextern int totalQueueResets ; Xextern int tickflag ; Xextern int nChecked ; Xextern int nEnqueued ; X Xextern Flt minweight ; Xextern int maxlevel ; Xextern int nRays ; Xextern int nShadows ; Xextern int nReflected ; Xextern int nRefracted ; X Xchar * malloc() ; Xchar * calloc() ; Xchar * rindex() ; X Xextern Object * MakeCone() ; Xextern Object * MakeSphere() ; Xextern Object * MakePatch() ; Xextern Object * MakePoly() ; X Xextern Flt VecNormalize() ; Xextern Vec Slab[] ; Xextern ObjectProcs NullProcs ; Xextern Object * Root ; END_OF_FILE if test 906 -ne `wc -c <'extern.h'`; then echo shar: \"'extern.h'\" unpacked with wrong size! fi # end of 'extern.h' fi if test -f 'intersect.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'intersect.c'\" else echo shar: Extracting \"'intersect.c'\" \(2570 characters\) sed "s/^X//" >'intersect.c' <<'END_OF_FILE' X#include <stdio.h> X#include <math.h> X#include <assert.h> X#include "defs.h" X#include "extern.h" X X X/* X * intersect.c X * Much nicer now, uses the nifty priority queue search X * as suggested by Kajiya... X */ X XFlt num[NSLABS] ; XFlt den[NSLABS] ; X XINLINE XCheckAndEnqueue(obj) X register Object * obj ; X{ X int i ; X Flt tmp ; X Flt tmin, tmax ; X Flt dmin = -HUGE ; X Flt dmax = HUGE ; X X nChecked ++ ; X X for (i = 0 ; i < NSLABS ; i ++) { X X /* enters the slab here... */ X tmin = (obj -> o_dmin[i] - num[i]) * den[i] ; X /* and exits here... */ X tmax = (obj -> o_dmax[i] - num[i]) * den[i] ; X X /* but we may have to swap... */ X if (tmin > tmax) { X tmp = tmin ; tmin = tmax ; tmax = tmp ; X } X X /* if exited closer than we thought, update */ X if (tmax < dmax) X dmax = tmax ; X /* if entered farther than we thought, update */ X if (tmin > dmin) X dmin = tmin ; X X if (dmin > dmax || dmax < rayeps) X return ; X } X PriorityQueueInsert(dmin, obj) ; X nEnqueued ++ ; X} X XIntersect(ray, hit) X Ray * ray ; X Isect * hit ; X{ X Isect nhit ; X int i ; X Flt min_dist = HUGE ; X Object * cobj ; X Object * pobj = NULL ; X CompositeData * cdp ; X Flt key ; X X /* If the object is simple, then return the hit that it gives you */ X X if (Root -> o_type != T_COMPOSITE) X return (Root -> o_procs -> intersect) (Root, ray, hit) ; X X for (i = 0 ; i < NSLABS ; i ++) { X num[i] = VecDot(ray -> P, Slab[i]) ; X den[i] = 1.0 / VecDot(ray -> D, Slab[i]) ; X } X X /* start with an empty priority queue */ X PriorityQueueNull() ; X X CheckAndEnqueue(Root) ; X X for (;;) { X X if (PriorityQueueEmpty()) X break ; X X PriorityQueueDelete(&key, &cobj) ; X X if (key > min_dist) { X X /* X * we have already found a primitive X * that was closer, we need look no further... X */ X break ; X X } else if (cobj -> o_type == T_COMPOSITE) { X /* X * if it is in the queue, it got hit. X * check each of its children to see if their X * bounding volumes get hit. X * if so, then push them into the priority X * queue... X */ X X cdp = (CompositeData *) cobj -> o_data ; X X for (i = 0 ; i < cdp -> c_size ; i ++ ) { X CheckAndEnqueue(cdp -> c_object[i]) ; X } X X } else { X X /* X * we have a primitive X * intersect with the primitive, and possibly X * update the nearest hit if it is indeed closer X * than the one we currently have... X */ X X if ((cobj -> o_procs -> intersect) (cobj, ray, &nhit)) { X if (nhit.isect_t < min_dist) { X pobj = cobj ; X *hit = nhit ; X min_dist = nhit.isect_t ; X } X } X } X } X X if (pobj) X return 1 ; X else X return 0 ; X} END_OF_FILE if test 2570 -ne `wc -c <'intersect.c'`; then echo shar: \"'intersect.c'\" unpacked with wrong size! fi # end of 'intersect.c' fi if test -f 'main.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'main.c'\" else echo shar: Extracting \"'main.c'\" \(1630 characters\) sed "s/^X//" >'main.c' <<'END_OF_FILE' X#include <stdio.h> X#include <sys/types.h> X#include <sys/times.h> X#include "defs.h" X#include "extern.h" X Xmain(argc, argv) X int argc ; X char * argv[] ; X{ X extern int optind ; X extern char *optarg ; X int c ; X char * infilename = NULL ; X char * outfilename = "out.pic" ; X X if ((Progname = rindex(argv[0], '/')) == NULL) X Progname = argv[0] ; X else X Progname ++ ; X X while ((c = getopt(argc, argv, "o:i:t")) != EOF) { X switch (c) { X case 'o': X outfilename = optarg ; X break ; X case 'i': X infilename = optarg ; X break ; X case 't': X tickflag = 1 ; X break ; X case '?': X fprintf(stderr, "usage: %s [-i file] [-o file]\n", X Progname) ; X exit(-1); X } X } X ReadSceneFile(infilename) ; X InitSlabs() ; X BuildBoundingSlabs() ; X Screen(&Eye, outfilename, Xresolution, Yresolution) ; X PrintStatistics() ; X} X XPrintStatistics() X{ X struct tms buf ; X X times(&buf); X printf("time spent in user code: %-6d seconds\n", buf.tms_utime/60); X printf("time spent in system code: %-6d seconds\n", buf.tms_stime/60); X printf("number of rays cast: %-6d\n", nRays); X printf("number of shadow rays: %-6d\n", nShadows); X printf("number of reflected rays: %-6d\n", nReflected); X printf("number of refracted rays: %-6d\n", nRefracted); X X printf("number of queue inserts: %-6d\n", totalQueues) ; X printf("number of queue resets: %-6d\n", totalQueueResets) ; X printf("avg number of queues/ray: %-6g\n", (Flt) totalQueues / X (Flt) totalQueueResets) ; X printf("max queue size: %-6d\n", maxQueueSize) ; X printf("number of bound checks: %-6d\n", nChecked) ; X printf("number of bound queued: %-6d\n", nEnqueued) ; X} END_OF_FILE if test 1630 -ne `wc -c <'main.c'`; then echo shar: \"'main.c'\" unpacked with wrong size! fi # end of 'main.c' fi if test -f 'nff.y' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'nff.y'\" else echo shar: Extracting \"'nff.y'\" \(3138 characters\) sed "s/^X//" >'nff.y' <<'END_OF_FILE' X%{ X#include <stdio.h> X#include <math.h> X#include "defs.h" X#include "extern.h" X Xextern char yytext[] ; Xextern FILE * yyin ; XVec * pl, * plist ; X%} X X%token VIEWPOINT FROM AT UP ANGLE HITHER RESOLUTION LIGHT X%token BACKGROUND SURFACE CONE SPHERE POLYGON PATCH NUM X X%union { X Vec vec ; X Vec * vecl ; X double flt ; X} ; X X%type <vec> point primcolor X%type <flt> num X X%% X Xscene: X camera elementlist X { X int l ; X for (l = 0 ; l < nLights ; l++) { X Lights[l].light_brightness = sqrt((Flt) nLights) / X ((Flt)nLights) ; X } X } ; X Xelementlist: X elementlist element X | ; X Xelement: X light X | background X | surface X | cone X | sphere X | polygon X | ppatch ; X Xcamera: X VIEWPOINT /* $1 */ X FROM point /* $2-$3 */ X AT point /* $4-$5 */ X UP point /* $6-$7 */ X ANGLE num /* $8-$9 */ X HITHER num /* $10-$11 */ X RESOLUTION num num /* $12-$14 */ X { X VecCopy($3, Eye.view_from) ; X VecCopy($5, Eye.view_at) ; X VecCopy($7, Eye.view_up) ; X Eye.view_angle = degtorad($9/2.0 ) ; X Eye.view_dist = $11 ; X Xresolution = (int) $13 ; X Yresolution = (int) $14 ; X } ; X Xlight: X LIGHT point X { X VecCopy($2, Lights[nLights].light_pos) ; X X /* fill in brightness of the light, after we X * know the number of lights sources in the scene X */ X nLights ++ ; X } ; X Xbackground: X BACKGROUND primcolor X { X VecCopy($2, BackgroundColor) ; X } ; X Xsurface: X SURFACE primcolor num num num num num X { X CurrentSurface = (Surface *) malloc (sizeof(Surface)) ; X VecCopy($2, CurrentSurface -> surf_color) ; X CurrentSurface -> surf_kd = $3 ; X CurrentSurface -> surf_ks = $4 ; X CurrentSurface -> surf_shine = $5 ; X CurrentSurface -> surf_kt = $6 ; X CurrentSurface -> surf_ior = $7 ; X } ; X Xcone: X CONE point num point num X { X Prims[nPrims++] = MakeCone($2, $3, $4, $5) ; X } ; Xsphere: X SPHERE point num X { X Prims[nPrims++] = MakeSphere($2, $3) ; X } ; Xpolygon: X POLYGON num X { X plist = (Vec *) calloc((int) $2, sizeof(Vec)) ; X pl = plist ; X } X pointlist X { X Prims[nPrims++] = MakePoly((int) $2, plist) ; X } ; Xppatch: X PATCH num X { X plist = (Vec *) calloc(((int)$2) * 2 , sizeof(Vec)) ; X pl = plist ; X } X pointlist X { X#ifdef DO_PATCHES X Prims[nPrims++] = MakePatch($2, plist) ; X#endif /* DO_PATCHES */ X } ; X Xprimcolor: X num num num X { X $$[0] = $1 ; X $$[1] = $2 ; X $$[2] = $3 ; X } ; X Xpoint: X num num num X { X $$[0] = $1 ; X $$[1] = $2 ; X $$[2] = $3 ; X } ; X Xpointlist: X pointlist point X { X VecCopy($2, (*pl)) ; X pl ++ ; X } X | ; X Xnum: X NUM X { X $$ = atof(yytext) ; X } ; X X%% X Xyyerror(str) X{ X fprintf(stderr, "%s: error at line %d\n", X Progname, yylinecount) ; X exit(-1) ; X} X XReadSceneFile(str) X char *str ; X{ X if (str == NULL) X yyin = stdin ; X else { X if ((yyin = fopen(str, "r")) == NULL) { X fprintf(stderr, "%s: cannot open %s\n", Progname, X str) ; X exit(-1) ; X } X } X if (yyparse() == 1) { X fprintf(stderr, "%s: invalid input specification\n", Progname); X exit(-1) ; X } X fprintf(stderr, "%s: (%d prims, %d lights)\n", X Progname, nPrims, nLights) ; X fprintf(stderr, "%s: inputfile = \"%s\"\n", Progname, str) ; X fprintf(stderr, "%s: resolution %d %d\n", Progname, Xresolution, X Yresolution) ; X} END_OF_FILE if test 3138 -ne `wc -c <'nff.y'`; then echo shar: \"'nff.y'\" unpacked with wrong size! fi # end of 'nff.y' fi if test -f 'pic.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'pic.c'\" else echo shar: Extracting \"'pic.c'\" \(1175 characters\) sed "s/^X//" >'pic.c' <<'END_OF_FILE' X X#include <stdio.h> X#include "pic.h" X#include "defs.h" X#include "extern.h" X X/*======================================================================*/ X/* PIC.C */ X/* */ X/* Simple routines for outputting a pixel map.... */ X/* */ X/* Mark VandeWettering, markv@cs.uoregon.edu */ X/*======================================================================*/ X XPic * XPicOpen(filename,x,y) X char *filename ; X{ X Pic *tmp ; X X tmp = (Pic *) malloc(sizeof (Pic)) ; X tmp -> filename = (char *) malloc (strlen(filename)+1) ; X strcpy(tmp->filename, filename); X X if (((tmp -> filep)=fopen(filename, "w"))==NULL) { X perror( filename ); X exit( 1 ); X } X X tmp -> x = x ; tmp -> y = y ; X X fprintf(tmp -> filep, "%d %d\n", x, y); X X return(tmp); X} X XPicWriteLine(pic, buf) X Pic *pic ; X Pixel *buf ; X{ X int i ; X for (i = 0; i < pic -> x ; i ++) { X fputc(buf[i].r, pic -> filep); X fputc(buf[i].g, pic -> filep); X fputc(buf[i].b, pic -> filep); X } X} X XPicClose(pic) X Pic *pic ; X{ X fclose(pic -> filep) ; X} END_OF_FILE if test 1175 -ne `wc -c <'pic.c'`; then echo shar: \"'pic.c'\" unpacked with wrong size! fi # end of 'pic.c' fi if test -f 'pic.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'pic.h'\" else echo shar: Extracting \"'pic.h'\" \(96 characters\) sed "s/^X//" >'pic.h' <<'END_OF_FILE' X/* X * pic.h X * X */ X Xtypedef struct Pic { X char * filename ; X FILE * filep ; X int x, y ; X} Pic ; END_OF_FILE if test 96 -ne `wc -c <'pic.h'`; then echo shar: \"'pic.h'\" unpacked with wrong size! fi # end of 'pic.h' fi if test -f 'poly.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'poly.c'\" else echo shar: Extracting \"'poly.c'\" \(3855 characters\) sed "s/^X//" >'poly.c' <<'END_OF_FILE' X#include <stdio.h> X#include <math.h> X#include "defs.h" X#include "extern.h" X Xtypedef struct t_polydata { X int poly_npoints ; X Vec * poly_point ; X Vec poly_normal ; X Flt poly_d ; X Flt poly_p1, poly_p2 ; X} PolyData ; X Xint PolyPrint (); Xint PolyIntersect (); Xint PolyNormal (); X XObjectProcs PolyProcs = { X PolyPrint, X PolyIntersect, X PolyNormal, X} ; X Xint XPolyPrint(obj) X Object * obj ; X{ X int i ; X PolyData * pd ; X X pd = (PolyData *) obj -> o_data ; X printf("p %d\n", pd -> poly_npoints) ; X for (i = 0 ; i < pd -> poly_npoints ; i++) { X printf("%g %g %g\n", pd -> poly_point[i][0], X pd -> poly_point[i][1], X pd -> poly_point[i][2]) ; X } X} X XPolyIntersect(obj, ray, hit) X Object * obj ; X Ray * ray ; X Isect * hit ; X{ X Flt n,d,t,m,b ; X Point V ; X int i, j, l ; X int qi, qj ; X int ri, rj ; X int c1, c2 ; X PolyData * pd ; X X pd = (PolyData *) obj -> o_data ; X n = VecDot(ray -> P, pd -> poly_normal) + pd -> poly_d ; X d = VecDot(ray -> D, pd -> poly_normal) ; X X if ((Flt) fabs(d) < rayeps) { X return(NULL); X } X X t = - n / d ; X if (t < rayeps) X return 0 ; X X RayPoint(ray,t,V); X c1 = pd -> poly_p1 ; X c2 = pd -> poly_p2 ; X X l = 0 ; X for (i = 0 ; i < pd -> poly_npoints ; i++) { X X j = (i + 1) % pd -> poly_npoints ; X X qi = 0 ; qj = 0 ; X ri = 0 ; rj = 0 ; X X if (pd -> poly_point[i][c2] == pd -> poly_point[j][c2]) X continue ; /*ignore horizontal lines */ X X if (pd -> poly_point[i][c2] < V[c2]) X qi = 1 ; X if (pd -> poly_point[j][c2] < V[c2]) X qj = 1 ; X if (qi == qj) X continue ; X X if (pd -> poly_point[i][c1] < V[c1]) X ri = 1 ; X if (pd -> poly_point[j][c1] < V[c1]) X rj = 1 ; X X if (ri & rj) { X l++ ; X continue ; X } X X if ((ri|rj) == 0) X continue ; X X X /* X * more difficult acceptance... X */ X m = (pd -> poly_point[j][c2] - pd -> poly_point[i][c2]) / X (pd -> poly_point[j][c1] - pd -> poly_point[i][c1]) ; X X b = (pd -> poly_point[j][c2] - V[c2]) - X m * (pd -> poly_point[j][c1] - V[c1]); X X if ((-b/m) < rayeps) X l++ ; X } X X if ((l % 2) == 0) X return(0); X X hit -> isect_t = t ; X hit -> isect_surf = obj -> o_surf ; X hit -> isect_prim = obj ; X hit -> isect_enter = 0 ; X return(1); X} X XPolyNormal(obj, hit, P, N) X Object * obj ; X Isect * hit ; X Point P, N ; X{ X X PolyData * pd ; X pd = (PolyData *) obj -> o_data ; X VecCopy(pd -> poly_normal, N); X} X XObject * XMakePoly(npoints, points) X int npoints ; X Vec * points ; X{ X Object * obj ; X PolyData * pd ; X Vec P1, P2 ; X Flt d, dmax, dmin ; X int i, j ; X X obj = (Object *) malloc (sizeof(Object)) ; X obj -> o_type = T_POLY ; X obj -> o_procs = & PolyProcs ; X obj -> o_surf = CurrentSurface ; X X pd = (PolyData *) malloc (sizeof(PolyData)) ; X pd -> poly_npoints = npoints ; X pd -> poly_point = points ; X X /* X * calculate the normal by giving various cross products... X */ X X VecSub(pd -> poly_point[0], pd -> poly_point[1], P1) ; X VecSub(pd -> poly_point[2], pd -> poly_point[1], P2) ; X X VecCross(P1, P2, pd -> poly_normal) ; X VecNormalize(pd -> poly_normal) ; X X if (fabs(pd -> poly_normal[0]) > fabs(pd -> poly_normal[1]) X && fabs(pd -> poly_normal[0]) > fabs(pd -> poly_normal[2])) { X pd -> poly_p1 = 1 ; X pd -> poly_p2 = 2 ; X } else if (fabs(pd -> poly_normal[1]) > fabs(pd -> poly_normal[0]) X && fabs(pd -> poly_normal[1]) > fabs(pd -> poly_normal[2])) { X pd -> poly_p1 = 0 ; X pd -> poly_p2 = 2 ; X } else { X pd -> poly_p1 = 0 ; X pd -> poly_p2 = 1 ; X } X X pd -> poly_d = - VecDot(pd -> poly_normal, pd -> poly_point[0]) ; X X obj -> o_data = (void *) pd ; X X /* X * now, calculate the values of X * the dmin and dmax 'es for the globally defined slabs... X */ X X for (i = 0 ; i < NSLABS ; i ++) { X dmin = HUGE ; X dmax = - HUGE ; X X for (j = 0 ; j < pd -> poly_npoints ; j ++) { X d = VecDot(Slab[i], pd -> poly_point[j]) ; X if (d < dmin) dmin = d ; X if (d > dmax) dmax = d ; X } X obj -> o_dmin[i] = dmin ; X obj -> o_dmax[i] = dmax ; X } X return(obj) ; X} END_OF_FILE if test 3855 -ne `wc -c <'poly.c'`; then echo shar: \"'poly.c'\" unpacked with wrong size! fi # end of 'poly.c' fi if test -f 'pqueue.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'pqueue.c'\" else echo shar: Extracting \"'pqueue.c'\" \(1511 characters\) sed "s/^X//" >'pqueue.c' <<'END_OF_FILE' X#include <stdio.h> X#include <math.h> X#include "defs.h" X#include "extern.h" X Xtypedef struct t_qelem { X Flt q_key ; X Object * q_obj ; X} Qelem ; X Xstatic int Qsize ; Xstatic Qelem Q[PQSIZE] ; X XPriorityQueueNull() X{ X Qsize = 0 ; X totalQueueResets ++ ; X#ifdef DEBUG X printf("resetting\n") ; X#endif /* DEBUG */ X} X XPriorityQueueEmpty() X{ X return (Qsize == 0) ; X} X XPriorityQueueInsert(key, obj) X Flt key ; X Object * obj ; X{ X int i ; X Qelem tmp ; X X totalQueues ++ ; X#ifdef DEBUG X printf("inserting element, key = %g\n", key) ; X#endif X Qsize ++ ; X if (Qsize > maxQueueSize) X maxQueueSize = Qsize ; X if (Qsize >= PQSIZE) { X fprintf(stderr, "%s: exhausted priority queue space\n", X Progname) ; X exit(1) ; X } X Q[Qsize].q_key = key ; X Q[Qsize].q_obj = obj ; X X i = Qsize ; X while (i > 1 && Q[i].q_key < Q[i/2].q_key) { X tmp = Q[i] ; X Q[i] = Q[i/2] ; X Q[i/2] = tmp ; X i = i / 2 ; X } X} X XPriorityQueueDelete(key, obj) X Flt * key ; X Object ** obj ; X{ X Qelem tmp ; X int i, j ; X X if (Qsize == 0) { X fprintf(stderr, "%s: priority queue is empty\n", X Progname) ; X exit(1) ; X } X X *key = Q[1].q_key ; X *obj = Q[1].q_obj ; X X#ifdef DEBUG X printf("deleting element, key = %g\n", *key) ; X#endif X X Q[1] = Q[Qsize] ; X Qsize -- ; X X i = 1 ; X X while (2 * i <= Qsize) { X X if (2 * i == Qsize) { X j = 2 * i ; X } else if (Q[2*i].q_key < Q[2*i+1].q_key) { X j = 2 * i ; X } else { X j = 2 * i + 1 ; X } X X if (Q[i].q_key > Q[j].q_key) { X tmp = Q[i] ; X Q[i] = Q[j] ; X Q[j] = tmp ; X i = j ; X } else { X break ; X } X } X} END_OF_FILE if test 1511 -ne `wc -c <'pqueue.c'`; then echo shar: \"'pqueue.c'\" unpacked with wrong size! fi # end of 'pqueue.c' fi if test -f 'ray.1' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'ray.1'\" else echo shar: Extracting \"'ray.1'\" \(1421 characters\) sed "s/^X//" >'ray.1' <<'END_OF_FILE' X.\" Copyright 1988, Mark VandeWettering X.\" This program and documentation may be distributed freely for X.\" non-commercial use only. X.TH RAY 1 "August 17, 1987" 1 X.UC 4 X.SH NAME Xray \- a reasonbly intelligent ray tracing program X.SH SYNOPSIS X.B progname X.\" sample options... X[ X.B \-i inputfile X] [ X.B \-o outputfile X] [ X.B \-t X] X.SH DESCRIPTION XThis program is an attempt at writing a reasonably useful Xraytracer for further experimentation, and for generating some Xgenerally nifty pictures. X.PP XIt reads Eric Haine's NFF file format files as input. NFF is fairly Xstraightforward, if you desire more explanation on the format, then Xobtain his set of routines. X.PP XThe X.B \-t Xflag makes the ray tracer output a period after every scanline for those Xof you who get impatient, or who are wondering if it is still working. X.PP XUse X.B \-i file Xto specify an NFF input file to render. If no input file is specified, Xit reads from standard input. X.PP XUse X.B \-o file Xto specify an output file. If unspecified, the raytracer writes its image Xon the file "out.pic". X.SH AUTHOR XMark VandeWettering X.SH BUGS XBugs! Of course there are bugs! X.PP XI think there still might be something wrong with the reflections. In Xparticular Eric Haine's "gears" database generates some wierd colors. If Xyou can find the bug, send it too me and I will let the world know of the Xproblem. X.PP XThis manual page should be expanded... END_OF_FILE if test 1421 -ne `wc -c <'ray.1'`; then echo shar: \"'ray.1'\" unpacked with wrong size! fi # end of 'ray.1' fi if test -f 'screen.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'screen.c'\" else echo shar: Extracting \"'screen.c'\" \(2432 characters\) sed "s/^X//" >'screen.c' <<'END_OF_FILE' X#include <stdio.h> X#include <math.h> X#include "defs.h" X#include "pic.h" X#include "extern.h" X XScreen(view, picfile, xres, yres) X Viewpoint *view ; X char *picfile ; X int xres, yres ; X{ X Pixel *buf, *oldbuf, *curbuf, *tmp ; X Pic *pic, *PicOpen(); X Point viewvec, leftvec ; X int red, green, blue ; X Point dir ; X Ray ray ; X Color color; X Flt frustrumwidth ; X int x, y ; X X /* X * open the picture file... X */ X X pic = PicOpen(picfile, xres, yres) ; X X /* X * allocate enough space for an entire row of pixels... X * plus one more for the average... X */ X X oldbuf = NULL ; X curbuf = (Pixel *) malloc (xres * sizeof (Pixel)) + 1 ; X buf = (Pixel *) malloc (xres * sizeof (Pixel)) + 1 ; X X /* X * determine the viewing frustrum X */ X X VecNormalize(view -> view_up); X VecSub(view -> view_at, view-> view_from, viewvec); X VecNormalize(viewvec); X VecCross(view -> view_up, viewvec, leftvec); X VecNormalize(leftvec); X X VecCopy(view -> view_from, ray.P); X X frustrumwidth = (view -> view_dist) * ((Flt) tan(view -> view_angle)) ; X X for (y=0; y < yres + 1; y++) { X for (x = 0; x < xres + 1; x++) { X VecComb(-frustrumwidth*(2.0*(Flt)y/(Flt)(yres-1)-1.0), X view -> view_up, X frustrumwidth*(2.0*(Flt)x/(Flt)(xres-1)-1.0), X leftvec, dir); X VecAdd(dir, viewvec, ray.D); X VecNormalize(ray.D); X Trace(0, 1.0, &ray, color); X X if (color[0] > 1.0) color[0] = 1.0 ; X if (color[1] > 1.0) color[1] = 1.0 ; X if (color[2] > 1.0) color[2] = 1.0 ; X X curbuf[x].r = (unsigned char) (255.0 * color[0]) ; X curbuf[x].g = (unsigned char) (255.0 * color[1]) ; X curbuf[x].b = (unsigned char) (255.0 * color[2]) ; X } X if (oldbuf) { X /* average the pixels, and write 'em out X */ X for (x = 0 ; x < xres ; x++) { X red = ((int)curbuf[x].r + (int)curbuf[x+1].r X + (int)oldbuf[x].r+ (int)oldbuf[x+1].r) ; X green = ((int)curbuf[x].g + (int)curbuf[x+1].g X + (int)oldbuf[x].g+ (int)oldbuf[x+1].g) ; X blue = ((int)curbuf[x].b + (int)curbuf[x+1].b X + (int)oldbuf[x].b+ (int)oldbuf[x+1].b) ; X buf[x].r = (unsigned char) (red / 4) ; X buf[x].g = (unsigned char) (green / 4) ; X buf[x].b = (unsigned char) (blue / 4) ; X } X PicWriteLine(pic, buf); X tmp = oldbuf ; X oldbuf = curbuf ; X curbuf = tmp ; X } else { X oldbuf = curbuf ; X curbuf = (Pixel *) malloc (xres * sizeof (Pixel)) + 1 ; X } X X if (tickflag) X fprintf(stderr, ".") ; X } X if (tickflag) fprintf(stderr, "\n") ; X PicClose(pic); X} END_OF_FILE if test 2432 -ne `wc -c <'screen.c'`; then echo shar: \"'screen.c'\" unpacked with wrong size! fi # end of 'screen.c' fi if test -f 'shade.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'shade.c'\" else echo shar: Extracting \"'shade.c'\" \(2101 characters\) sed "s/^X//" >'shade.c' <<'END_OF_FILE' X#include <stdio.h> X#include <math.h> X#include "defs.h" X#include "extern.h" X XShade(level, weight, P, N, I, hit, col) X int level ; X Flt weight ; X Vec P, N, I ; X Isect * hit; X Color col ; X{ X Ray tray ; X Color tcol ; X Vec L, H ; X Flt t ; X Flt diff ; X Flt spec ; X Surface * surf ; X int l ; X X col[0] = col[1] = col[2] = 0.0 ; X surf = hit -> isect_prim -> o_surf ; X X for (l = 0; l < nLights; l++) { X VecSub(Lights[l].light_pos, P, L); X if (VecDot(N,L) >= 0.0) { X t = VecNormalize(L); X VecCopy(P, tray.P); X VecCopy(L, tray.D); X nShadows ++ ; X if (Shadow(&tray, t)) { X diff = VecDot(N,L) * surf -> surf_kd * X Lights[l].light_brightness ; X VecAddS(diff, surf -> surf_color, col, col) ; X /* X VecAdd(L, I, H) ; X VecNormalize(H) ; X spec = surf -> surf_ks X * pow(VecDot(H,N), surf -> surf_shine) ; X col[0] += spec ; X col[1] += spec ; X col[2] += spec ; X */ X } X } X } X X VecCopy(P, tray.P); X X if(surf -> surf_ks * weight > minweight) { X nReflected ++ ; X SpecularDirection(I, N, tray.D); X VecNormalize(tray.D); X Trace(level + 1, surf -> surf_ks * weight, &tray, tcol); X VecAddS(surf -> surf_ks, tcol, col, col); X } X X if (surf -> surf_kt * weight > minweight) { X nRefracted ++ ; X if (hit -> isect_enter) X TransmissionDirection(NULL, surf, I, N, tray.D) ; X else X TransmissionDirection(surf, NULL, I, N, tray.D) ; X Trace(level + 1, surf -> surf_kt * weight, &tray, tcol) ; X VecAddS(surf -> surf_kt, tcol, col, col) ; X } X} X Xint XShadow(ray, tmax) X Ray *ray ; X Flt tmax ; X{ X Isect hit ; X int Intersect() ; X X if (Intersect(ray, &hit) && hit.isect_t < tmax - rayeps) { X return(0); X } else { X return(1); X } X} X XSpecularDirection(I, N, R) X Vec I, N, R; X{ X VecComb(1.0/fabs(VecDot(I,N)), I, 2.0, N, R); X VecNormalize(R); X} X XTransmissionDirection(m1, m2, I, N, T) X Surface *m1, *m2; X Vec I, N, T ; X{ X Flt n1, n2, eta, c1, cs2 ; X n1 = m1 ? m1 -> surf_ior : 1.0 ; X n2 = m2 ? m2 -> surf_ior : 1.0 ; X eta = n1/n2 ; X X c1 = -VecDot(I,N); X cs2 = 1.0 - eta * eta*(1.0 - c1*c1); X if (cs2 < 0.0) X return 0; X VecComb(eta, I, eta*c1-sqrt(cs2), N, T); X return(1); X} END_OF_FILE if test 2101 -ne `wc -c <'shade.c'`; then echo shar: \"'shade.c'\" unpacked with wrong size! fi # end of 'shade.c' fi if test -f 'sphere.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'sphere.c'\" else echo shar: Extracting \"'sphere.c'\" \(2078 characters\) sed "s/^X//" >'sphere.c' <<'END_OF_FILE' X#include <stdio.h> X#include <math.h> X#include "defs.h" X#include "extern.h" X Xtypedef struct t_spheredata { X Vec sph_center ; X Flt sph_radius ; X Flt sph_radius2 ; X} SphereData ; X Xint SpherePrint (); Xint SphereIntersect (); Xint SphereNormal (); X XObjectProcs SphereProcs = { X SpherePrint, X SphereIntersect, X SphereNormal, X} ; X Xint XSpherePrint(obj) X Object *obj ; X{ X SphereData * sp ; X X sp = (SphereData *) obj -> o_data ; X X printf("s %g %g %g %g\n", sp -> sph_center[0], X sp -> sph_center[1], X sp -> sph_center[2], X sp -> sph_radius) ; X} X XSphereIntersect(obj, ray, hit) X Object * obj ; X Ray * ray ; X Isect * hit ; X{ X X Flt b, disc, t; X Point V ; X SphereData * sp ; X X sp = (SphereData *) obj -> o_data ; X X VecSub((sp->sph_center), ray -> P, V); X X b = VecDot(V, ray -> D); X X disc = b * b - VecDot(V, V) + (sp -> sph_radius2) ; X X if (disc < 0.0) X return(0); X X disc = sqrt(disc); X X t = (b - disc < rayeps) ? b + disc : b - disc ; X X if (t < rayeps) { X return(0); X } X X hit -> isect_t = t ; X hit -> isect_enter = VecDot(V, V) > sp -> sph_radius2 + rayeps ? 1 : 0 ; X hit -> isect_prim = obj ; X hit -> isect_surf = obj -> o_surf ; X return (1); X} X Xint XSphereNormal(obj, hit, P, N) X Object * obj ; X Isect * hit ; X Point P, N ; X{ X SphereData * sp ; X sp = (SphereData *) obj -> o_data ; X X VecSub(P, sp -> sph_center, N); X (void) VecNormalize(N); X} X XObject * XMakeSphere(pos, radius) X Vec pos ; X Flt radius ; X{ X Object * tmp ; X int i ; X SphereData *sp ; X X tmp = (Object *) malloc (sizeof(Object)) ; X tmp -> o_type = T_SPHERE ; X tmp -> o_procs = & SphereProcs ; X tmp -> o_surf = CurrentSurface ; X sp = (SphereData *) malloc (sizeof(SphereData)) ; X VecCopy(pos, sp -> sph_center) ; X sp -> sph_radius = radius ; X sp -> sph_radius2 = radius * radius ; X tmp -> o_data = (void *) sp ; X X /* X * figure out dmin and dmax values for X * each of the slabs... X */ X X for (i = 0 ; i < NSLABS; i ++) { X tmp -> o_dmin[i] = VecDot(sp -> sph_center, Slab[i]) X - sp -> sph_radius ; X tmp -> o_dmax[i] = VecDot(sp -> sph_center, Slab[i]) X + sp -> sph_radius ; X } X return tmp ; X} END_OF_FILE if test 2078 -ne `wc -c <'sphere.c'`; then echo shar: \"'sphere.c'\" unpacked with wrong size! fi # end of 'sphere.c' fi if test -f 'tokens.l' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tokens.l'\" else echo shar: Extracting \"'tokens.l'\" \(738 characters\) sed "s/^X//" >'tokens.l' <<'END_OF_FILE' X%{ X#include <stdio.h> X#include "defs.h" X#include "y.tab.h" X#include "extern.h" X%} X X%% X[ \t] ; X\#.*$ ; X\n yylinecount ++ ; Xv return VIEWPOINT ; Xviewpoint return VIEWPOINT ; Xfrom return FROM ; Xat return AT ; Xup return UP ; Xangle return ANGLE ; Xhither return HITHER ; Xresolution return RESOLUTION ; Xl return LIGHT ; Xlight return LIGHT ; Xb return BACKGROUND ; Xbackground return BACKGROUND ; Xf return SURFACE ; Xsurface return SURFACE ; Xc return CONE ; Xcone return CONE ; Xs return SPHERE ; Xsphere return SPHERE ; Xp return POLYGON ; Xpolygon return POLYGON ; Xpp return PATCH ; Xpatch return PATCH ; X\-?[0-9]*(\.[0-9]*(e\-?[0-9]+)?)? return NUM ; X. return yytext[0] ; X X%% X Xyywrap() X{ X return 1 ; X} END_OF_FILE if test 738 -ne `wc -c <'tokens.l'`; then echo shar: \"'tokens.l'\" unpacked with wrong size! fi # end of 'tokens.l' fi if test -f 'trace.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'trace.c'\" else echo shar: Extracting \"'trace.c'\" \(584 characters\) sed "s/^X//" >'trace.c' <<'END_OF_FILE' X X#include <stdio.h> X#include "defs.h" X#include "extern.h" X XTrace(level, weight, ray, color) X int level; X Flt weight; X Ray *ray ; X Color color ; X{ X Object *prim ; X Vec P, N ; X Isect hit ; X X if (level >= maxlevel) { X color[0] = color[1] = color[2] = 0 ; X return ; X } X X nRays ++ ; X X if (Intersect(ray, &hit)) { X prim = hit.isect_prim ; X RayPoint(ray, hit.isect_t, P); X (*prim -> o_procs -> normal) (prim, &hit, P, N); X if ((VecDot(ray->D, N)) >= 0.0) { X VecNegate(N); X } X Shade(level, weight, P, N, ray -> D, &hit, color); X } else { X VecCopy(BackgroundColor, color) ; X } X} END_OF_FILE if test 584 -ne `wc -c <'trace.c'`; then echo shar: \"'trace.c'\" unpacked with wrong size! fi # end of 'trace.c' fi if test -f 'vector.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'vector.c'\" else echo shar: Extracting \"'vector.c'\" \(211 characters\) sed "s/^X//" >'vector.c' <<'END_OF_FILE' X#include <stdio.h> X#include <math.h> X#include "defs.h" X#include "extern.h" X XFlt XVecNormalize(vec) X Vec vec ; X{ X Flt len ; X len = (Flt) VecLen(vec); X vec[0]/=len ; X vec[1]/=len ; X vec[2]/=len ; X return(len) ; X} END_OF_FILE if test 211 -ne `wc -c <'vector.c'`; then echo shar: \"'vector.c'\" unpacked with wrong size! fi # end of 'vector.c' fi echo shar: End of archive 1 \(of 1\). cp /dev/null ark1isdone MISSING="" for I in 1 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have the archive. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0
johnm@trsvax.UUCP (09/01/88)
Neat! Ok, now will somebody post Eric Haine's NFF format (and any source to deal with it)? I don't ever remember having seen it come through here at any time. Thanks, John Munsch