Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!gatech!hubcap!ncrcae!ncr-sd!hp-sdd!hplabs!ucbvax!ucsfcgl!pixar!ph From: ph@pixar.UUCP (Paul Heckbert) Newsgroups: comp.graphics Subject: Re: Winners of Minimal Ray Tracer Contest Message-ID: <874@pixar.UUCP> Date: Thu, 25-Jun-87 03:29:42 EDT Article-I.D.: pixar.874 Posted: Thu Jun 25 03:29:42 1987 Date-Received: Sat, 27-Jun-87 04:25:51 EDT References: <860@pixar.UUCP> Organization: Pixar -- Marin County, California Lines: 178 Summary: minimal ray tracing reaches new lows Minimal ray tracing reaches new lows! I've taken some of the tricks from Darwyn Peachey's and Joe Cychosz's minimal ray tracers (posted previously) and combined them with some of my own to create a hybrid program that's the shortest of all: 888 tokens. Recall that Joe Cychosz's winning entry had 916 tokens. To compile the enclosed "paul.c", run "cc -o paul paul.c -lm". If you're able to shorten the enclosed program further, please send me mail. When my C code compacter program "rape.c" (also posted previously) is run on paul.c, /lib/cpp paul.c | sed '/^#/d' | rape -77 > paul.rape.c we get a rectangular block of C code that fits nicely on a standard 24x80 terminal screen. See the enclosed file paul.rape.c. An even more impressive thing to do with this file is reduce it to fit on a small card. If you've got the Adobe Transcript laser printer software, run: enscript -B -fCourier5 paul.rape.c and you've got a ray-tracer-on-a-business-card! Paul Heckbert Pixar 415-499-3600 P.O. Box 13719 UUCP: {sun,ucbvax}!pixar!ph San Rafael, CA 94913 ARPA: ph%pixar.uucp@ucbvax.berkeley.edu ------------------------------ # to unpack, cut here and run the following shell archive through sh # contents: paul.c ray.h paul.rape.c # sed 's/^X//' <<'EOF14163' >paul.c X/* minimal ray tracer, hybrid version - 888 tokens X * Paul Heckbert, ucbvax!pixar!ph, 13 Jun 87 X * Using tricks from Darwyn Peachey and Joe Cychosz. X * Paul Haeberli bet this couldn't be done in less than 100 lines: nyah nyah! */ X X#define TOL 1e-7 X#define AMBIENT vec U, black, amb X#define SPHERE struct sphere {vec cen, color; double rad, kd, ks, kt, kl, ir} \ X *s, *best, sph[] Xtypedef struct {double x, y, z} vec; X#include "ray.h" Xyx; Xdouble u, b, tmin, sqrt(), tan(); X Xdouble vdot(A, B) Xvec A, B; X{ X return A.x*B.x + A.y*B.y + A.z*B.z; X} X Xvec vcomb(a, A, B) /* aA+B */ Xdouble a; Xvec A, B; X{ X B.x += a*A.x; X B.y += a*A.y; X B.z += a*A.z; X return B; X} X Xvec vunit(A) Xvec A; X{ X return vcomb(1./sqrt(vdot(A, A)), A, black); X} X Xstruct sphere *intersect(P, D) Xvec P, D; X{ X best = 0; X tmin = 1e30; X s = sph+NSPHERE; X while (s-->sph) X b = vdot(D, U = vcomb(-1., P, s->cen)), X u = b*b-vdot(U, U)+s->rad*s->rad, X u = u>0 ? sqrt(u) : 1e31, X u = b-u>TOL ? b-u : b+u, X tmin = u>=TOL && uir; X d = -vdot(D, N = vunit(vcomb(-1., P = vcomb(tmin, D, P), s->cen))); X if (d<0) X N = vcomb(-1., N, black), X eta = 1/eta, X d = -d; X l = sph+NSPHERE; X while (l-->sph) X if ((e = l->kl*vdot(N, U = vunit(vcomb(-1., P, l->cen)))) > 0 && X intersect(P, U)==l) X color = vcomb(e, l->color, color); X U = s->color; X color.x *= U.x; X color.y *= U.y; X color.z *= U.z; X e = 1-eta*eta*(1-d*d); X /* the following is non-portable: we assume right to left arg evaluation. X * (use U before call to trace, which modifies U) */ X return vcomb(s->kt, X e>0 ? trace(level, P, vcomb(eta, D, vcomb(eta*d-sqrt(e), N, black))) X : black, X vcomb(s->ks, trace(level, P, vcomb(2*d, N, D)), X vcomb(s->kd, color, vcomb(s->kl, U, black)))); X} X Xmain() X{ X printf("%d %d\n", SIZE, SIZE); X while (yxray.h X/* ray.h for test1, first test scene */ X#define DEPTH 3 /* max ray tree depth */ X#define SIZE 32 /* resolution of picture in x and y */ X#define AOV 25 /* total angle of view in degrees */ X#define NSPHERE 5 /* number of spheres */ X XAMBIENT = {.02, .02, .02}; /* ambient light color */ X X/* sphere: x y z r g b rad kd ks kt kl ir */ XSPHERE = { X 0., 6., .5, 1., 1., 1., .9, .05, .2, .85, 0., 1.7, X -1., 8., -.5, 1., .5, .2, 1., .7, .3, 0., .05, 1.2, X 1., 8., -.5, .1, .8, .8, 1., .3, .7, 0., 0., 1.2, X 3., -6., 15., 1., .8, 1., 7., 0., 0., 0., .6, 1.5, X -3., -3., 12., .8, 1., 1., 5., 0., 0., 0., .5, 1.5, X}; EOF14164 sed 's/^X//' <<'EOF14165' >paul.rape.c Xtypedef struct{double x,y,z}vec;vec U,black,amb={.02,.02,.02};struct sphere{ Xvec cen,color;double rad,kd,ks,kt,kl,ir}*s,*best,sph[]={0.,6.,.5,1.,1.,1.,.9, X.05,.2,.85,0.,1.7,-1.,8.,-.5,1.,.5,.2,1.,.7,.3,0.,.05,1.2,1.,8.,-.5,.1,.8,.8, X1.,.3,.7,0.,0.,1.2,3.,-6.,15.,1.,.8,1.,7.,0.,0.,0.,.6,1.5,-3.,-3.,12.,.8,1., X1.,5.,0.,0.,0.,.5,1.5,};yx;double u,b,tmin,sqrt(),tan();double vdot(A,B)vec A X,B;{return A.x*B.x+A.y*B.y+A.z*B.z;}vec vcomb(a,A,B)double a;vec A,B;{B.x+=a* XA.x;B.y+=a*A.y;B.z+=a*A.z;return B;}vec vunit(A)vec A;{return vcomb(1./sqrt( Xvdot(A,A)),A,black);}struct sphere*intersect(P,D)vec P,D;{best=0;tmin=1e30;s= Xsph+5;while(s-->sph)b=vdot(D,U=vcomb(-1.,P,s->cen)),u=b*b-vdot(U,U)+s->rad*s X->rad,u=u>0?sqrt(u):1e31,u=b-u>1e-7?b-u:b+u,tmin=u>=1e-7&&uir;d= -vdot(D,N=vunit(vcomb(-1.,P=vcomb(tmin,D,P),s->cen X)));if(d<0)N=vcomb(-1.,N,black),eta=1/eta,d= -d;l=sph+5;while(l-->sph)if((e=l X->kl*vdot(N,U=vunit(vcomb(-1.,P,l->cen))))>0&&intersect(P,U)==l)color=vcomb(e X,l->color,color);U=s->color;color.x*=U.x;color.y*=U.y;color.z*=U.z;e=1-eta* Xeta*(1-d*d);return vcomb(s->kt,e>0?trace(level,P,vcomb(eta,D,vcomb(eta*d-sqrt X(e),N,black))):black,vcomb(s->ks,trace(level,P,vcomb(2*d,N,D)),vcomb(s->kd, Xcolor,vcomb(s->kl,U,black))));}main(){printf("%d %d\n",32,32);while(yx<32*32) XU.x=yx%32-32/2,U.z=32/2-yx++/32,U.y=32/2/tan(25/114.5915590261),U=vcomb(255., Xtrace(3,black,vunit(U)),black),printf("%.0f %.0f %.0f\n",U);}/*pixar!ph*/ EOF14165 exit