Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Path: utzoo!mnetor!uunet!seismo!husc6!think!ames!ucbcad!ucbvax!ucsfcgl!pixar!ph
From: ph@pixar.UUCP (Paul Heckbert)
Newsgroups: comp.graphics
Subject: ray tracer source
Message-ID: <917@pixar.UUCP>
Date: Sat, 11-Jul-87 20:17:51 EDT
Article-I.D.: pixar.917
Posted: Sat Jul 11 20:17:51 1987
Date-Received: Mon, 13-Jul-87 00:39:20 EDT
Organization: Pixar -- Marin County, California
Lines: 1710
Keywords: ray tracing
The following is C source to a ray tracer written by Masataka Ohta of Japan
which he mailed me in connection with my minimal ray tracer contest.
It was too good (and hence too long) to be a contender in that contest, but
he asked me to post it to the net.
Masataka also wrote the ray tracer used in SEIBU/SEDIC's "Mandala" and
"Maitreya" animations, which were shown at SIGGRAPH a few years back.
Paul Heckbert
ps: I made minor enhancements to his code to set resolution at run-time.
==========================================
# to unpack, cut here and run the following shell archive through sh
# contents: README Makefile ray.h alloc.c bg.c dindex.c initdir.c
# input.c intersect.c main.c scan.c shade.c shape.c trace.c test.v
# random.c
#
sed 's/^X//' <<'EOF26628' >README
XThis is a public domain ray tracing program with the following features:
X * shadows
X * specular reflection
X * transparency with refraction
X * antialiasing
X * high speed
X
XIt computes ray-object intersections very fast by exploiting ray coherence.
XFor many scenes, the program can compute ray-object intersections
Xin constant time, regardless of the number of objects.
X
XThe technique is described in the paper "Ray Coherence Theorem
Xand Constant Time Ray Tracing Algorithm",
X"Computer Graphics 1987, Proceedings of CG International '87"
XSpringer-Verlag, pp. 303-314.
X
XAny suggestions or beautiful pictures generated
Xusing this program are welcome.
X
X Masataka Ohta
X
X Computer Center, Tokyo Institute of Technology,
X 2-12-1, O-okayama, Meguro-ku, Tokyo 152, JAPAN
X
X mohta%titcce.cc.titech.junet@relay.cs.net
X
X==========================================================
X
XTo test the program:
X
X "make test.pic" will produce a beautiful(?) image of nine spheres.
X
X "make test1000.pic" will produce an image of 1,000 spheres.
X
X
XUsage: ray [options]
X
XOptions:
X
X -a:
X do anti-aliasing
X
X -r res
X set resolution to res (default 128)
X
X -t:
X output timing information
X
X -s:
X use classical slow algorithm
X
X -o:
X disable object ordering optimization
X
X -d:
X debug
X
X -b:
X no shading
X
X
XFile format:
X
X scene file: (an ascii file, see test.v or "make test1000.v" for example)
X f
X l
X
X
X l
X
X
X .
X .
X .
X o
X
X
X .
X .
X .
X
X .
X .
X .
X o
X
X .
X .
X .
X e
X
X picture file: (a binary file, make test.pic for an example)
X
X
X
X pixel array has the form:
X struct {unsigned char r, g, b;} array[yres][xres];
X screen space y=0 is at the top
X
XCurrently supported light source types: (should be programmable)
X
X point light source with constant intensity of (1,1,1)
X regardless to the distance to the light source
X
XCurrently supported shapes: (may be changed by modifying shape.c)
X
X number: 0
X shape: sphere
X number of parameters: 4
X first parameter: x coordinate value of the center
X second parameter: y coordinate value of the center
X third parameter: z coordinate value of the center
X forth parameter: radius
X
XCurrently supported shades: (may be changed by modifying shade.c)
X
X number: 0
X shade: lambert with shadows
X number of parameters: 6
X first to third parameters: RGB value of ambient
X 4th to 6th parameters: RGB value of diffuse
X
X number: 1
X shade: phong type specular with shadows
X number of parameters: 10
X first to third parameters: RGB value of ambient
X 4th to 6th parameters: RGB value of diffuse
X 7th to 9th parameters: RGB value of specular
X 10th parameter: specular width factor
X
X number: 2
X shade: mirror (i.e. reflective ) with phong
X type specular with shadows
X number of parameters: 13
X first to third parameters: RGB value of ambient
X 4th to 6th parameters: RGB value of diffuse
X 7th to 9th parameters: RGB value of specular
X 10th parameter: specular width factor
X 11th to 13th parameters: RGB ratio of reflection
X
X number: 3
X shade: glass (i.e. reflective and refractive)
X with phong type specular with shadows
X number of parameters: 17
X first to third parameters: RGB value of ambient
X 4th to 6th parameters: RGB value of diffuse
X 7th to 9th parameters: RGB value of specular
X 10th parameter: specular width factor
X 11th to 13th parameters: RGB ratio of reflection
X 14th to 16th parameters: RGB ratio of refraction
X 17th parameter: refractive index
X
XViewing parameters:
X
X eye: fixed at (0,0,0)
X eye direction: fixed to (0,0,1)
X field of view: variable from 0 to 180 degree (with 'f' option)
X
XResolution:
X
X set with 'r' option, defaults to 128
X picture is always square
X
XLimitations:
X
X coordinate transformation should be supported
X
X light source type should be programmable
X
X more complex shapes should be supported
X
X more sophisticated syntax should be used (eg. comments, symbolic names)
X
X dynamic loading of light source, shape and shade functions
X should be possible
EOF26628
sed 's/^X//' <<'EOF26629' >Makefile
XSRC=alloc.c bg.c dindex.c initdir.c input.c intersect.c main.c\
X scan.c shade.c shape.c trace.c
X
XOBJ=alloc.o bg.o dindex.o initdir.o input.o intersect.o main.o\
X scan.o shade.o shape.o trace.o
X
XHDR=ray.h
X
XCFLAGS=-O
X
Xray: $(OBJ)
X cc $(CFLAGS) $(OBJ) -o ray -lm
X
Xray.lint: $(HDR) $(SRC)
X lint -b $(SRC) -lm >ray.lint
X
X$(OBJ): ray.h
X
Xprint:
X print Makefile $(HDR) $(SRC)
X
Xray.shar: README Makefile $(HDR) $(SRC) test.v random.c
X shar README Makefile $(HDR) $(SRC) test.v random.c >ray.shar
X
Xclean:
X rm -f $(OBJ) ray random test.pic test1000.v test1000.pic lint
X
Xrandom: random.c
X cc -O random.c -o random -lm
X
Xtest.pic: ray
X ray test.v test.pic
X
Xtest1000.v: random
X echo f 90 >test1000.v
X echo l 1 1 -3 >>test1000.v
X echo l -4 0 -1 >>test1000.v
X random 1000 0.07 >>test1000.v
X echo e >>test1000.v
X
Xtest1000.pic: ray test1000.v
X ray test1000.v test1000.pic
EOF26629
sed 's/^X//' <<'EOF26630' >ray.h
X#define MAXOBJECTS 1010
X#define MAXLEVEL 4
X
X#define MINT 1e-6
X
Xstruct point {double x,y,z;};
X
Xstruct vector {double x,y,z;};
X
Xstruct circle {
X struct vector o;
X double c,s;
X};
X
Xstruct ray {
X int obj; /* origin index */
X struct point a; /* origin coordinate */
X struct vector l; /* direction */
X};
X
Xstruct color {double r,g,b};
X
Xstruct intersect {
X int obj;
X double t;
X struct vector n;
X} intersect();
X
Xstruct object {
X int flags;
X struct point center;
X double radius;
X struct intersect (*shape)();
X double *spparams;
X struct color (*shade)();
X double *sdparams;
X}
X objects[MAXOBJECTS];
X
X#define EYE 1 /* object is eye */
X#define LIGHT 2 /* object is light source */
X#define REFLECT 4 /* object is reflective */
X#define REFRACT 8 /* object is refractive */
X#define RAYORIGIN (EYE|LIGHT|REFLECT|REFRACT)
X#define SELF 16 /* rays from an object may */
X /* intersect the object again */
X
Xint res;
Xint maxobj,lights;
X
Xstruct objlist2 {
X int obj;
X struct objlist *next;
X};
X
Xstruct objlist {
X int obj;
X struct objlist *next;
X float t;
X}
X ***candidates;
X
Xstruct dirlist {
X int dir;
X struct dirlist *next;
X};
X
Xstruct vector nilvect,normalize(),reflect(),refract();
Xstruct color trace(),bgcolor();
X
Xint fflag,dflag,aflag,tflag,sflag,oflag;
X
Xint alsize;
X
X/* This should be modified to be word alignment of alloc macro
X * 0x1 for 2 byte alignment
X * 0x3 for 4 byte alignment
X */
X#define ALMASK 0x1
X
Xchar *myalloc(),*freep,*endp;
Xchar *malloc();
X
X#define alloc(type) ((alsize=(sizeof(type)+ALMASK)&~ALMASK),\
X (type *) (endp>freep+alsize\
X ?(freep+=alsize)-alsize\
X :myalloc(alsize)))
X
X#define nalloc(type,n) ((alsize=(sizeof(type)*(n)+ALMASK)&~ALMASK),\
X (type *) (endp>freep+alsize\
X ?(freep+=alsize)-alsize\
X :myalloc(alsize)))
X
Xint raycount,shadowcount;
X
Xint NRECTS,DIRECTIONS;
X
Xstruct shapetab {
X void (*shapeinitfunc)();
X struct intersect (*shapefunc)();
X int nparams;
X}
X *shapetab;
X
Xint nshapetab;
X
Xstruct shadetab {
X void (*shadeinitfunc)();
X struct color (*shadefunc)();
X int nparams;
X}
X *shadetab;
X
Xint nshadetab;
X
Xdouble fovf;
EOF26630
sed 's/^X//' <<'EOF26631' >alloc.c
X#include "ray.h"
X
Xchar *freep=(char *)0,*endp=(char *)0,*malloc();
X
X#define ALLOCUNIT 16384
X
Xchar *myalloc(s)
Xint s;
X{int size;
Xchar *a;
X if(s>ALLOCUNIT)
X size=s;
X else
X size=ALLOCUNIT;
X a=malloc((unsigned)size);
X if(a==0)
X { perror("malloc");
X exit(1);
X }
X freep=a+s;
X endp=a+size;
X return a;
X}
EOF26631
sed 's/^X//' <<'EOF26632' >bg.c
X#include "ray.h"
X
X/*ARGSUSED*/
Xstruct color bgcolor(r)
Xstruct ray r;
X{struct color c;
X if(r.l.y>0)
X c.r=c.g=c.b=0.2;
X else
X c.r=c.g=c.b=0.2-0.8*r.l.y;
X return c;
X}
EOF26632
sed 's/^X//' <<'EOF26633' >dindex.c
X#include "ray.h"
X
Xdindex(v)
Xstruct vector v;
X{double x,y,z,ax,ay,az;
X x=v.x;
X y=v.y;
X z=v.z;
X ax=(x>0)?x:-x;
X ay=(y>0)?y:-y;
X az=(z>0)?z:-z;
X if(ax>=ay&&ax>=az)
X if(x>0)
X return index2(y,z,ax);
X else
X return index2(y,z,ax)+(NRECTS*NRECTS);
X else if(ay>=ax&&ay>=az)
X if(y>0)
X return index2(z,x,ay)+(2*NRECTS*NRECTS);
X else
X return index2(z,x,ay)+(3*NRECTS*NRECTS);
X else
X if(z>0)
X return index2(x,y,az)+(4*NRECTS*NRECTS);
X else
X return index2(x,y,az)+(5*NRECTS*NRECTS);
X}
X
Xindex2(x,y,r)
Xdouble r,x,y;
X{register int m,n;
X m=(r+x)/(r*2)*NRECTS;
X if(m==NRECTS)
X m=NRECTS-1;
X n=(r+y)/(r*2)*NRECTS;
X if(n==NRECTS)
X n=NRECTS-1;
X return n*NRECTS+m;
X}
EOF26633
sed 's/^X//' <<'EOF26634' >initdir.c
X#include
X#include
X
X#include "ray.h"
X
Xstruct circle *dvl;
X
Xstruct dirlist **neighbor;
X
Xint *markdir;
X
Xinitdir()
X{register int o0,o1,d;
Xregister double l;
Xstruct point c0,c1;
Xregister double r0,r1;
Xstruct circle cir;
Xregister struct objlist *ol;
Xint origins;
X origins=0;
X for(o0=0;o0100)
X { if(origins)
X NRECTS=100/sqrt((double)origins);
X else
X NRECTS=100;
X }
X if(NRECTS<4)
X NRECTS=4;
X DIRECTIONS=6*NRECTS*NRECTS;
X dvl=nalloc(struct circle,DIRECTIONS);
X neighbor=nalloc(struct dirlist *,DIRECTIONS);
X markdir=nalloc(int,DIRECTIONS);
X candidates=nalloc(struct objlist **,maxobj);
X for(o0=0;o0=l)
X { for(d=0;dobj=o1;
X ol->next=candidates[o0][d];
X if(oflag)
X ol->t=0;
X candidates[o0][d]=ol;
X }
X }
X else
X { cir.s=(r0+r1)/l;
X cir.c=sqrt(1-cir.s*cir.s);
X d=dindex(cir.o);
X if(oflag)
X ttraverse(d,&cir,o1,
X candidates[o0],l-r0-r1);
X else
X traverse(d,&cir,o1,candidates[o0]);
X tclear(d);
X }
X }
X if(oflag)
X for(d=0;dnext)
X c++;
X fprintf(stderr,"Image complexity %g\n",((double)c)/DIRECTIONS);
X for(o0=1;o0next)
X c++;
X fprintf(stderr,"Shadow complexity for light %d %g\n",
X o0,((double)c)/DIRECTIONS);
X }
X }
X}
X
Xtraverse(d,cir,o,ol)
Xregister int d;
Xregister struct circle *cir;
Xregister int o;
Xregister struct objlist **ol;
X{register struct dirlist *dl;
Xregister struct objlist *ol2;
X markdir[d]=1;
X if(!overlap(&dvl[d],cir))
X return;
X ol2=(struct objlist *)alloc(struct objlist2);
X ol2->obj=o;
X ol2->next=ol[d];
X ol[d]=ol2;
X for(dl=neighbor[d];dl;dl=dl->next)
X if(!markdir[dl->dir])
X traverse(dl->dir,cir,o,ol);
X}
X
Xttraverse(d,cir,o,ol,t)
Xregister int d;
Xregister struct circle *cir;
Xregister int o;
Xregister struct objlist **ol;
Xregister double t;
X{register struct dirlist *dl;
Xregister struct objlist *ol2;
X markdir[d]=1;
X if(!overlap(&dvl[d],cir))
X return;
X ol2=alloc(struct objlist);
X ol2->obj=o;
X ol2->next=ol[d];
X ol2->t=t;
X ol[d]=ol2;
X for(dl=neighbor[d];dl;dl=dl->next)
X if(!markdir[dl->dir])
X ttraverse(dl->dir,cir,o,ol,t);
X}
X
Xtclear(d)
Xregister int d;
X{register struct dirlist *dl;
X markdir[d]=0;
X for(dl=neighbor[d];dl;dl=dl->next)
X if(markdir[dl->dir])
X tclear(dl->dir);
X}
X
Xoverlap(cir0,cir1)
Xregister struct circle *cir0,*cir1;
X{ return
X cir0->o.x*cir1->o.x+cir0->o.y*cir1->o.y+cir0->o.z*cir1->o.z
X >
X cir0->c*cir1->c-cir0->s*cir1->s;
X}
X
Xstruct circle initdvl2(x,y,z,dx0,dy0,dz0,dx1,dy1,dz1)
Xdouble x,y,z,dx0,dy0,dz0,dx1,dy1,dz1;
X{int i;
Xdouble l,c,minc;
Xstruct vector v[4];
Xstruct circle cir;
X for(i=0;i<4;i++)
X { v[i].x=x;
X v[i].y=y;
X v[i].z=z;
X }
X v[1].x+=dx0;
X v[1].y+=dy0;
X v[1].z+=dz0;
X v[2].x+=dx0+dx1;
X v[2].y+=dy0+dy1;
X v[2].z+=dz0+dz1;
X v[3].x+=dx1;
X v[3].y+=dy1;
X v[3].z+=dz1;
X cir.o.x=cir.o.y=cir.o.z=0;
X for(i=0;i<4;i++)
X { cir.o.x+=v[i].x/4;
X cir.o.y+=v[i].y/4;
X cir.o.z+=v[i].z/4;
X l=1/sqrt(v[i].x*v[i].x+v[i].y*v[i].y+v[i].z*v[i].z);
X v[i].x*=l;
X v[i].y*=l;
X v[i].z*=l;
X }
X l=1/sqrt(cir.o.x*cir.o.x+cir.o.y*cir.o.y+cir.o.z*cir.o.z);
X cir.o.x*=l;
X cir.o.y*=l;
X cir.o.z*=l;
X minc=1;
X for(i=0;i<4;i++)
X { c=cir.o.x*v[i].x+cir.o.y*v[i].y+cir.o.z*v[i].z;
X if(cdir=m;
X dl2->next=dl;
X return dl2;
X}
X
Xinitneighbor()
X{int i;
Xdouble d;
X for(i=0;iz==0)
X { printf("\tz=0\n");
X return;
X }
X printf("\t%g %g\n",v->x/v->z,v->y/v->z);
X}
Xsortlist(ol)
Xregister struct objlist *ol;
X{register struct objlist *ol2,*ol3;
Xdouble t;
Xint obj;
X if(!ol)
X return;
X for(;ol->next;ol=ol->next)
X { ol3=ol;
X for(ol2=ol->next;ol2;ol2=ol2->next)
X if(ol2->tt)
X ol3=ol2;
X if(ol!=ol3)
X { t=ol->t;
X ol->t=ol3->t;
X ol3->t=t;
X obj=ol->obj;
X ol->obj=ol3->obj;
X ol3->obj=obj;
X }
X }
X}
EOF26634
sed 's/^X//' <<'EOF26635' >input.c
X#include
X#include
X
X#include "ray.h"
X
Xinput(s)
Xchar *s;
X{struct object *o;
XFILE *f;
Xint i,sp,sd;
Xchar c;
Xdouble fov;
X if((f=fopen(s,"r"))==0)
X { perror(s);
X exit(1);
X }
X o=objects;
X if(fscanf(f," f %lf ",&fov)!=1||fov<=0||fov>=180)
X { fprintf(stderr,"field of view format error\n");
X exit(1);
X }
X fovf=tan(fov*3.14159/360)/sqrt(2.0);
X o->flags=EYE;
X o->center.x=o->center.y=o->center.z=0;
X o->radius=0;
X o++;
X lights=0;
X while(fscanf(f," l %lf %lf %lf ",&o->center.x,&o->center.y,
X &o->center.z)==3)
X { o->flags=LIGHT;
X o->radius=0;
X o++;
X lights++;
X }
X maxobj=lights+1;
X while(fscanf(f," o %d %d ",&sp,&sd)==2)
X { if(maxobj==MAXOBJECTS)
X { fprintf("too much objects\n");
X exit(1);
X }
X if(sp<0||sp>=nshapetab)
X { fprintf(stderr,"shape number range error\n");
X exit(1);
X }
X if(sd<0||sd>=nshadetab)
X { fprintf(stderr,"shade number range error\n");
X exit(1);
X }
X o= &objects[maxobj];
X o->flags=0;
X
X o->shape=shapetab[sp].shapefunc;
X o->spparams=nalloc(double,shapetab[sp].nparams);
X for(i=0;ispparams[i])!=1)
X { fprintf(stderr,"shape parameter error\n");
X exit(1);
X }
X }
X (*shapetab[sp].shapeinitfunc)(o);
X
X o->shade=shadetab[sd].shadefunc;
X o->sdparams=nalloc(double,shadetab[sd].nparams);
X for(i=0;isdparams[i])!=1)
X { fprintf(stderr,"shade parameter error\n");
X exit(1);
X }
X }
X (*shadetab[sd].shadeinitfunc)(o);
X
X maxobj++;
X }
X if(fscanf(f," %c",&c)!=1||c!='e')
X { fprintf(stderr,"end command not found\n");
X exit(1);
X }
X (void) fclose(f);
X}
EOF26635
sed 's/^X//' <<'EOF26636' >intersect.c
X#include "ray.h"
X
Xstruct intersect intersect(r)
Xstruct ray r;
X{struct intersect i,imin;
Xregister struct objlist *ol;
Xregister int o;
X imin.obj=0;
X if(fflag)
X { if(objects[r.obj].flags&SELF)
X { i=(*objects[r.obj].shape)(r,r.obj);
X if(i.obj)
X imin=i;
X }
X for(ol=candidates[r.obj][dindex(r.l)];ol;ol=ol->next)
X { if(oflag&&imin.obj&&imin.tt)
X break;
X i=(*objects[ol->obj].shape)(r,ol->obj);
X if(i.obj&&(!imin.obj||i.tmain.c
X#include
X#include
X#include
X
X#include "ray.h"
X
Xmain(ac,av)
Xint ac;
Xchar **av;
X{int g;
Xstruct rusage ru;
Xstruct timeval tu,tu2;
X raycount=0;
X shadowcount=0;
X fflag=1;
X dflag=0;
X aflag=0;
X tflag=0;
X sflag=1;
X oflag=1;
X while(av[1]&&*av[1]=='-')
X { switch(av[1][1])
X {case 's': /* classical slow algorithm */
X fflag=0;
X break;
X case 'd': /* debug flag */
X dflag=1;
X break;
X case 'a': /* do anti-aliasing */
X aflag=1;
X break;
X case 't': /* produce timing information */
X tflag=1;
X break;
X case 'b': /* no shading */
X sflag=0;
X break;
X case 'o': /* don't order candidates */
X oflag=0;
X break;
X case 'r': /* set image resolution */
X res = atoi(av[2]);
X ac--;
X av++;
X break;
X default:
X usage();
X }
X ac--;
X av++;
X }
X if(ac!=3)
X usage();
X initshape();
X initshade();
X input(av[1]);
X if(fflag)
X { (void) getrusage(0,&ru);
X tu=ru.ru_utime;
X initdir();
X if(tflag)
X fprintf(stderr,"Directions=%d Objects=%d\n",
X DIRECTIONS,maxobj);
X (void) getrusage(0,&ru);
X tu2=ru.ru_utime;
X if(tflag)
X { fprintf(stderr,"Initializeation time ");
X printtime(tu,tu2);
X }
X }
X else
X { if(tflag)
X fprintf(stderr,"Objects=%d\n",maxobj);
X }
X if((g=creat(av[2],0666))<0)
X { perror(av[2]);
X exit(3);
X }
X (void) getrusage(0,&ru);
X tu=ru.ru_utime;
X if(aflag)
X ascan(g);
X else
X scan(g);
X (void) getrusage(0,&ru);
X tu2=ru.ru_utime;
X if(tflag)
X { fprintf(stderr," Computation time ");
X printtime(tu,tu2);
X fprintf(stderr,"\n%d rays traced",raycount);
X fprintf(stderr," %d shadows tested\n",shadowcount);
X }
X (void) close(g);
X exit(0);
X}
X
Xusage()
X{ fprintf(stderr,
X "Usage: ray [-sdatbo] [-r res] scenefile picfile\n");
X exit(1);
X}
X
Xprinttime(t0,t1)
Xstruct timeval t0,t1;
X{int sec,usec;
X usec=t1.tv_usec-t0.tv_usec;
X sec=t1.tv_sec-t0.tv_sec;
X if(usec<0)
X { usec+=1000000;
X sec--;
X }
X fprintf(stderr,"%4d.%03d",sec,usec/1000);
X}
EOF26637
sed 's/^X//' <<'EOF26638' >scan.c
X#include
X#include
X
X#include "ray.h"
X
Xint res = 128, xres, yres;
X#define MAXRES 2048
X
Xtypedef struct {int xres, yres;} pichead;
Xtypedef unsigned char icolor[3];
X
Xchar aaflag[5][4*MAXRES+1];
Xicolor aabuf[5][4*MAXRES+1];
X
Xpixel(ic,x,y)
Xicolor ic;
Xregister double x,y;
X{register double t;
Xstruct ray r;
Xstruct color c;
Xregister double m;
X x*=fovf;
X y*=fovf;
X r.obj=0;
X r.a.x=r.a.y=r.a.z=0;
X t=1/sqrt(x*x+y*y+1);
X r.l.x=x*t;
X r.l.y=y*t;
X r.l.z=t;
X c=trace(0,r);
X m=c.r;
X if(m1.0)
X { c.r/=m;
X c.g/=m;
X c.b/=m;
X }
X ic[0]=c.r*255;
X ic[1]=c.g*255;
X ic[2]=c.b*255;
X}
X
Xaapixel2(ic,i,j)
Xicolor ic;
Xregister int i,j;
X{register double x,y;
X x=((double)(j-2*xres))/(2*xres);
X y=((double)(2*yres-i))/(2*yres);
X pixel(ic,x,y);
X}
X
Xaapixel(ic,i,j,ai,s)
Xicolor ic;
Xregister int i,j,ai,s;
X{register int k;
Xicolor c,c00,c01,c10,c11;
X if(!aaflag[ai][j])
X { aapixel2(aabuf[ai][j],i,j);
X aaflag[ai][j]=1;
X }
X if(!aaflag[ai+s][j])
X { aapixel2(aabuf[ai+s][j],i+s,j);
X aaflag[ai+s][j]=1;
X }
X if(!aaflag[ai][j+s])
X { aapixel2(aabuf[ai][j+s],i,j+s);
X aaflag[ai][j+s]=1;
X }
X if(!aaflag[ai+s][j+s])
X { aapixel2(aabuf[ai+s][j+s],i+s,j+s);
X aaflag[ai+s][j+s]=1;
X }
X for(k=0;k<3;k++)
X { c00[k]=aabuf[ai][j][k];
X c10[k]=aabuf[ai+s][j][k];
X c01[k]=aabuf[ai][j+s][k];
X c11[k]=aabuf[ai+s][j+s][k];
X }
X c[0]=(c00[0]+c01[0]+c10[0]+c11[0])/4;
X c[1]=(c00[1]+c01[1]+c10[1]+c11[1])/4;
X c[2]=(c00[2]+c01[2]+c10[2]+c11[2])/4;
X if(s==1||nearc(c,c00)&&nearc(c,c01)&&nearc(c,c10)&&nearc(c,c11))
X { ic[0]=c[0];
X ic[1]=c[1];
X ic[2]=c[2];
X return;
X }
X s/=2;
X aapixel(c00,i,j,ai,s);
X aapixel(c01,i+s,j,ai+s,s);
X aapixel(c10,i,j+s,ai,s);
X aapixel(c11,i+s,j+s,ai+s,s);
X ic[0]=(c00[0]+c01[0]+c10[0]+c11[0])/4;
X ic[1]=(c00[1]+c01[1]+c10[1]+c11[1])/4;
X ic[2]=(c00[2]+c01[2]+c10[2]+c11[2])/4;
X}
X
Xscan(f)
Xregister int f;
X{register int i,j;
Xregister double x,y;
Xicolor buf[MAXRES];
X scaninit(f);
X for(i=0;iMAXRES)
X { fprintf(stderr, "res=%d too large, must be less than %d\n",
X res, MAXRES);
X exit(1);
X }
X head.xres = xres = res;
X head.yres = yres = res;
X (void) write(f,(char *)&head,sizeof head);
X}
X
Xnearc(c0,c1)
Xicolor c0,c1;
X{register int d;
X d=abs(c0[0]-c1[0])+abs(c0[1]-c1[1])+abs(c0[2]-c1[2]);
X return d<15;
X}
EOF26638
sed 's/^X//' <<'EOF26639' >shade.c
X#include
X
X#include "ray.h"
X
Xvoid initdiffuse(),initspecular(),initmirror(),initglass();
Xstruct color diffuse(),specular(),mirror(),glass();
X
Xdouble phong();
X
Xinitshade()
X{ nshadetab=4;
X shadetab=nalloc(struct shadetab,nshadetab);
X shadetab[0].shadeinitfunc=initdiffuse;
X shadetab[0].shadefunc=diffuse;
X shadetab[0].nparams=6;
X shadetab[1].shadeinitfunc=initspecular;
X shadetab[1].shadefunc=specular;
X shadetab[1].nparams=10;
X shadetab[2].shadeinitfunc=initmirror;
X shadetab[2].shadefunc=mirror;
X shadetab[2].nparams=13;
X shadetab[3].shadeinitfunc=initglass;
X shadetab[3].shadefunc=glass;
X shadetab[3].nparams=17;
X}
X
Xshadow(o,r)
Xint o;
Xstruct ray r;
X{struct intersect i;
X shadowcount++;
X i=intersect(r);
X return i.obj!=o;
X}
X
Xdouble phong(n,e,li,g)
Xstruct vector n,e,li;
Xdouble g;
X{struct vector h;
Xdouble l,c,t;
X h.x=e.x+li.x;
X h.y=e.y+li.y;
X h.z=e.z+li.z;
X l= -(h.x*n.x+h.y*n.y+h.z*n.z);
X if(l<0)
X return 0.0;
X c=l*l/(h.x*h.x+h.y*h.y+h.z*h.z);
X t=(1-c)/c;
X if(t>10*g)
X return 0;
X return exp(-t/g);
X}
X
Xstruct vector nilvect={0.0,0.0,0.0};
X
Xstruct vector reflect(n,u)
Xstruct vector n,u;
X{struct vector v;
Xdouble p;
X p=2*(n.x*u.x+n.y*u.y+n.z*u.z);
X v.x=u.x-p*n.x;
X v.y=u.y-p*n.y;
X v.z=u.z-p*n.z;
X return v;
X}
X
Xstruct vector refract(n,u,ni)
Xstruct vector n,u;
Xdouble ni;
X{struct vector v;
Xdouble p,t;
X p=n.x*u.x+n.y*u.y+n.z*u.z;
X if(p<0)
X { t=1-(1-p*p)/(ni*ni);
X if(t<=0)
X return nilvect;
X t= -p/ni-sqrt(t);
X }
X else
X { ni=1/ni;
X t=1-(1-p*p)/(ni*ni);
X if(t<=0)
X return nilvect;
X t= -p/ni+sqrt(t);
X }
X v.x=u.x/ni+t*n.x;
X v.y=u.y/ni+t*n.y;
X v.z=u.z/ni+t*n.z;
X return v;
X}
X
Xvoid initdiffuse(o)
Xstruct object *o;
X{
X#ifdef lint
X o=o;
X#endif
X}
X
Xvoid initspecular(o)
Xstruct object *o;
X{
X#ifdef lint
X o=o;
X#endif
X}
X
Xvoid initmirror(o)
Xstruct object *o;
X{ o->flags|=REFLECT;
X}
X
Xvoid initglass(o)
Xstruct object *o;
X{ o->flags|=REFLECT|REFRACT|SELF;
X}
X
Xstruct color diffuse(n,r,i)
Xint n;
Xstruct ray r;
Xstruct intersect i;
X{int j;
Xstruct color c;
Xdouble l,vx,vy,vz;
Xstruct ray r2;
Xdouble *sdparams;
X#ifdef lint
X n=n;
X#endif
X sdparams=objects[i.obj].sdparams;
X c.r=sdparams[0];
X c.g=sdparams[1];
X c.b=sdparams[2];
X for(j=1;j0&&!shadow(i.obj,r2))
X { c.r+=l*sdparams[3];
X c.g+=l*sdparams[4];
X c.b+=l*sdparams[5];
X }
X }
X return c;
X}
X
Xstruct color specular(n,r,i)
Xint n;
Xstruct ray r;
Xstruct intersect i;
X{int j;
Xstruct color c;
Xdouble l,x,y,z,sp;
Xstruct ray r2;
Xstruct vector e,li;
Xdouble *sdparams;
X#ifdef lint
X n=n;
X#endif
X sdparams=objects[i.obj].sdparams;
X c.r=sdparams[0];
X c.g=sdparams[1];
X c.b=sdparams[2];
X x=r.a.x+i.t*r.l.x;
X y=r.a.y+i.t*r.l.y;
X z=r.a.z+i.t*r.l.z;
X e.x=x-objects[0].center.x;
X e.y=y-objects[0].center.y;
X e.z=z-objects[0].center.z;
X l=1/sqrt(e.x*e.x+e.y*e.y+e.z*e.z);
X e.x*=l;
X e.y*=l;
X e.z*=l;
X for(j=1;j0&&!shadow(i.obj,r2))
X { c.r+=l*sdparams[3];
X c.g+=l*sdparams[4];
X c.b+=l*sdparams[5];
X sp=phong(i.n,e,li,sdparams[9]);
X c.r+=sp*sdparams[6];
X c.g+=sp*sdparams[7];
X c.b+=sp*sdparams[8];
X }
X }
X return c;
X}
X
Xstruct color mirror(n,r,i)
Xint n;
Xstruct ray r;
Xstruct intersect i;
X{int j;
Xstruct color c,rc;
Xdouble l,x,y,z,sp;
Xstruct ray r2;
Xstruct vector e,li;
Xdouble *sdparams;
X sdparams=objects[i.obj].sdparams;
X c.r=sdparams[0];
X c.g=sdparams[1];
X c.b=sdparams[2];
X x=r.a.x+i.t*r.l.x;
X y=r.a.y+i.t*r.l.y;
X z=r.a.z+i.t*r.l.z;
X e.x=x-objects[0].center.x;
X e.y=y-objects[0].center.y;
X e.z=z-objects[0].center.z;
X l=1/sqrt(e.x*e.x+e.y*e.y+e.z*e.z);
X e.x*=l;
X e.y*=l;
X e.z*=l;
X for(j=1;j0&&!shadow(i.obj,r2))
X { c.r+=l*sdparams[3];
X c.g+=l*sdparams[4];
X c.b+=l*sdparams[5];
X sp=phong(i.n,e,li,sdparams[9]);
X c.r+=sp*sdparams[6];
X c.g+=sp*sdparams[7];
X c.b+=sp*sdparams[8];
X }
X }
X r2.obj=i.obj;
X r2.a.x=x;
X r2.a.y=y;
X r2.a.z=z;
X r2.l=reflect(i.n,r.l);
X rc=trace(n+1,r2);
X c.r+=rc.r*sdparams[10];
X c.g+=rc.g*sdparams[11];
X c.b+=rc.b*sdparams[12];
X return c;
X}
X
Xstruct color glass(n,r,i)
Xint n;
Xstruct ray r;
Xstruct intersect i;
X{int j;
Xstruct color c,rc;
Xdouble l,x,y,z,sp;
Xstruct ray r2;
Xstruct vector e,li;
Xdouble *sdparams;
X sdparams=objects[i.obj].sdparams;
X c.r=sdparams[0];
X c.g=sdparams[1];
X c.b=sdparams[2];
X x=r.a.x+i.t*r.l.x;
X y=r.a.y+i.t*r.l.y;
X z=r.a.z+i.t*r.l.z;
X e.x=x-objects[0].center.x;
X e.y=y-objects[0].center.y;
X e.z=z-objects[0].center.z;
X l=1/sqrt(e.x*e.x+e.y*e.y+e.z*e.z);
X e.x*=l;
X e.y*=l;
X e.z*=l;
X for(j=1;j0&&!shadow(i.obj,r2))
X { c.r+=l*sdparams[3];
X c.g+=l*sdparams[4];
X c.b+=l*sdparams[5];
X sp=phong(i.n,e,li,sdparams[9]);
X c.r+=sp*sdparams[6];
X c.g+=sp*sdparams[7];
X c.b+=sp*sdparams[8];
X }
X }
X r2.obj=i.obj;
X r2.a.x=x;
X r2.a.y=y;
X r2.a.z=z;
X r2.l=reflect(i.n,r.l);
X rc=trace(n+1,r2);
X c.r+=rc.r*sdparams[10];
X c.g+=rc.g*sdparams[11];
X c.b+=rc.b*sdparams[12];
X r2.l=refract(i.n,r.l,sdparams[16]);
X if(r2.l.x==0&&r2.l.y==0&&r2.l.z==0)
X return c;
X rc=trace(n+1,r2);
X c.r+=rc.r*sdparams[13];
X c.g+=rc.g*sdparams[14];
X c.b+=rc.b*sdparams[15];
X return c;
X}
EOF26639
sed 's/^X//' <<'EOF26640' >shape.c
X#include
X
X#include "ray.h"
X
Xvoid initsphere();
Xstruct intersect sphere();
X
Xinitshape()
X{ nshapetab=1;
X shapetab=nalloc(struct shapetab,nshapetab);
X shapetab[0].shapeinitfunc=initsphere;
X shapetab[0].shapefunc=sphere;
X shapetab[0].nparams=4;
X}
X
Xvoid initsphere(o)
Xstruct object *o;
X{ o->center.x=o->spparams[0];
X o->center.y=o->spparams[1];
X o->center.z=o->spparams[2];
X o->radius=o->spparams[3];
X}
X
Xstruct intersect sphere(r,obj)
Xstruct ray r;
Xregister int obj;
X{struct vector v,n;
Xregister double *p,b,c,d,t,t0,t1;
Xstruct intersect i;
X i.obj=0;
X p=objects[obj].spparams;
X v.x=r.a.x-p[0];
X v.y=r.a.y-p[1];
X v.z=r.a.z-p[2];
X b=r.l.x*v.x+r.l.y*v.y+r.l.z*v.z;
X c=v.x*v.x+v.y*v.y+v.z*v.z-p[3]*p[3];
X d=b*b-c;
X if(d<0)
X return i;
X d=sqrt(d);
X if(b>=0)
X { t0= -b-d;
X t1=c/(-b-d);
X }
X else
X { t0=c/(-b+d);
X t1= -b+d;
X }
X if(t0>MINT)
X t=t0;
X else if(t1>MINT)
X t=t1;
X else
X return i;
X i.obj=obj;
X i.t=t;
X n.x=r.a.x+r.l.x*t-p[0];
X n.y=r.a.y+r.l.y*t-p[1];
X n.z=r.a.z+r.l.z*t-p[2];
X t=sqrt(n.x*n.x+n.y*n.y+n.z*n.z);
X i.n.x=n.x/t;
X i.n.y=n.y/t;
X i.n.z=n.z/t;
X return i;
X}
EOF26640
sed 's/^X//' <<'EOF26641' >trace.c
X#include "ray.h"
X
Xstruct color black={0,0,0},white={1.0,1.0,1.0};
X
Xstruct color trace(n,r)
Xregister int n;
Xstruct ray r;
X{struct intersect i;
X if(n>=MAXLEVEL)
X return bgcolor(r);
X raycount++;
X i=intersect(r);
X if(i.obj>0)
X { if(sflag)
X return (*objects[i.obj].shade)(n,r,i);
X else
X return white;
X }
X else
X { if(sflag)
X return bgcolor(r);
X else
X return black;
X }
X}
EOF26641
sed 's/^X//' <<'EOF26642' >test.v
Xf 109.5
Xl 10 10 -5
Xl -20 0 -5
Xo 0 1
X -5 -5 10 3
X 0.2 0 0 0.2 0 0 0.6 0.0 0.0 0.01
Xo 0 1
X -3 5 10 2
X 0 0.2 0 0 0.2 0 0.0 0.6 0.0 0.01
Xo 0 1
X 6 -2 10 2
X 0 0 0.2 0 0 0.2 0.0 0.0 0.6 0.01
Xo 0 1
X 0 -4 20 7
X 0.2 0.2 0 0.2 0.2 0 0.6 0.6 0.6 0.01
Xo 0 2
X 5 5 15 5
X 0 0 0 0 0 0 0.9 0.9 0.9 0.01 0.9 0.9 0.9
Xo 0 3
X -1 1 7 3
X 0 0 0 0 0 0 0.2 0.2 0.2 0.01 0.1 0.1 0.1
X 0.9 0.9 0.9 1.2
Xe
EOF26642
sed 's/^X//' <<'EOF26643' >random.c
X#include
X#include
X
Xdouble rnd()
X{ return (random()&0xffff)/65536.0;
X}
X
Xmain(ac,av)
Xint ac;
Xchar **av;
X{int i,j,n;
Xdouble x,y,z,r,cr,d,l;
X if(ac!=3&&ac!=4)
X { fprintf(stderr,"Usage: %s number radious [seed]\n",
X av[0]);
X exit(1);
X }
X n=atoi(av[1]);
X r=atof(av[2]);
X if(ac==4)
X srandom(atoi(av[3]));
X if(n<0||r<=0)
X { fprintf(stderr,"Usage: %s number radious [seed]\n",
X av[0]);
X exit(1);
X }
X for(i=0;i