[comp.sources.misc] v05i046: ray tracing program for 3b1

sid@chinet.UUCP (Sid Grange) (11/09/88)

Posting-number: Volume 5, Issue 46
Submitted-by: "Sid Grange" <sid@chinet.UUCP>
Archive-name: tracer

[The author claims that it should be portable to other graphical Un*x systems.
Since I don't have one handy, I've no way to test that.  ++bsa]

#! /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 shell archive."
# Contents:  Makefile README.DOC README.HAK bdata.i conv.c extern.h
#   find.c g_bal.c g_bod.c macros.h refract.c rtd.h shade.c support.c
#   tracer.c
# Wrapped by sid@chinet on Mon Feb  8 20:03:07 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f Makefile -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Makefile\"
else
echo shar: Extracting \"Makefile\" \(536 characters\)
sed "s/^X//" >Makefile <<'END_OF_Makefile'
Xtracer: tracer.o shade.o find.o support.o refract.o g_bod.o g_bal.o
X	cc tracer.o shade.o find.o support.o refract.o g_bod.o g_bal.o -lm -o tracer
Xfind.o: find.c rtd.h extern.h macros.h
X	cc -c find.c 
Xshade.o: shade.c rtd.h extern.h macros.h
X	cc -c shade.c 
Xsupport.o: support.c rtd.h extern.h
X	cc -c support.c 
Xtracer.o: tracer.c rtd.h bdata.i macros.h
X	cc -c tracer.c  
Xrefract.o: refract.c rtd.h extern.h macros.h
X	cc -c refract.c  
Xg_bod.o: g_bod.c extern.h macros.h
X	cc -c g_bod.c  
Xg_bal.o: g_bal.c extern.h rtd.h
X	cc -c g_bal.c  
END_OF_Makefile
if test 536 -ne `wc -c <Makefile`; then
    echo shar: \"Makefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f README.DOC -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"README.DOC\"
else
echo shar: Extracting \"README.DOC\" \(2252 characters\)
sed "s/^X//" >README.DOC <<'END_OF_README.DOC'
X
X
X
XTRACER(99)                  FRITZZ GRAPHICS            TRACER(99)
X
X
X
XNAME
X     tracer- run a simple ray tracing procedure
X
XSYNOPSIS
X     tracer -o [filename] -i [filename] -s <filename> -S<number>
X
XDESCRIPTION
X     Tracer is a program developed originally to study how
X     ray tracing works, and was later modified to the present state
X     to make it more compatible for animated film production.
X
X     It is capable of depicting a number of balls (up to 150)
X     and a plane that is covered with a tiling of any bitmapped picture.
X
X
XOPTIONS
X     -o Chooses the output data file. If no argument is givin, stdout
X        is used. If the option is not used the default is data.dis.
X
X     -i Chooses the input (ball) data file. If no argument is given, stdin
X        is used. If the option is not used the default is bdata.i.
X 
X     -s Chooses the file containing the tiling bitmap. It requires an
X        an argument. If the option is not used the default is pat.def.
X
X     -S Chooses contrast of the pattern. 0.0 is no contrast, 1.0 is maximum
X        contrast. 1.0 is the default. (useful for fading during animation)
X
XPROGRAM NOTES
X     This program generates a file containing a header with x and y sizes,
X     followed by the data in 8-bit greyscale, one pixel to a character, in 
X     scanlines.
X     There are two neccessary input files: ball data, and a pattern bitmap.
X     The tiling bitmap can be digitized data, it must be in the form of 
X     scan lines no longer than 512 bytes followed by newlines.
X     the ball data is of the following form:
X
X     x y z rad ior refract reflect diffuse ambient
X
X     on each line where x y & z are the coordinates of the center of 
X     the ball, rad is the radius of the ball, ior is the index of refraction
X     for translucent materials (index of refraction for glass is about 1.5)
X     the last four numbers determine how much of each atrribute is used.
X     Thus a pure silver ball would have 0.0 1.0 0.0 0.0 as the last numbers,
X     and a pure glass ball would have 1.0 0.0 0.0 0.0 .
X
X
XFILES
X     ./bdata.i	default ball data
X     ./pat.def  default floor pattern
X     ./data.dis default output file
X
XBUGS
X     As with any good software, the complexity of this program hides 
X     all bugs.
X
END_OF_README.DOC
if test 2252 -ne `wc -c <README.DOC`; then
    echo shar: \"README.DOC\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f README.HAK -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"README.HAK\"
else
echo shar: Extracting \"README.HAK\" \(1259 characters\)
sed "s/^X//" >README.HAK <<'END_OF_README.HAK'
X***** A Hackers Guide to Tracer *****
Xtracer consists of a bunch of files containing a program that does 
Xray tracing (No shit sherlock).
XThes files are as follows:
Xtracer.c:	main() sets up the initial rays and stores values
X		in a file. booboo prints an error message and quits.
Xshade.c:	shade() calculates the intensity returned by a ray. It is
X	 	recursive, and also makes a call to refract().
Xrefract.c:	The most difficult part of the program. This file contains
X		refract(), inside(), refk() and getcapt().
X		and these do all the refraction calculations.
Xfind.c:		contains find(),findo() (for when a ray is inside a ball)
X		and shadow() and finds() for shadows.
Xsupport.c:	supportive subroutines. right now only contains mt_vec
X		as all the others were either discarded or converted to 
X		macros.
Xg_bal.c		g_bal() gets the ball data and points bl[] at them.
Xg_bod.c		g_bod() loads the floor pattern into suzie.
X
Xmacros.h	contains all the macro definitions. Definitely to be looked at.
Xrtd.h		header file containing all the structure definitions.
Xextern.h	keeps track of all global variables used through the program.
X
Xbdata.i		sample ball data file.
X
Xpat.def \
Xcheck.pat\
Xsusie.pat >-    sample pattern files. (susie is not for the purient).
Xship.pat /
X
END_OF_README.HAK
if test 1259 -ne `wc -c <README.HAK`; then
    echo shar: \"README.HAK\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f bdata.i -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"bdata.i\"
else
echo shar: Extracting \"bdata.i\" \(213 characters\)
sed "s/^X//" >bdata.i <<'END_OF_bdata.i'
X
X-30.0 10.0 400.0 50.0 0.0 0.0 0.0 0.9 0.1
X210.0 175.0 400.0 50.0 0.0 0.0 0.3 0.6 0.1
X40.0 110.0 450.0 50.0 0.0 0.0 0.6 0.3 0.1
X140.0 65.0 450.0 50.0 0.0 0.0 0.9 0.0 0.1
X
X220.0 70.0 100.0 60.0 1.4 0.9 0.0 0.0 0.1
END_OF_bdata.i
if test 213 -ne `wc -c <bdata.i`; then
    echo shar: \"bdata.i\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f conv.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"conv.c\"
else
echo shar: Extracting \"conv.c\" \(824 characters\)
sed "s/^X//" >conv.c <<'END_OF_conv.c'
X#include <stdio.h>
X#include <tam.h>
X#include <fcntl.h>
X  
Xextern errno;
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X
X{
X  char *malloc();
X  char *cd,*d;
X  short *bm,*c;
X  int fd, cont;
X register int a,b;
X
X	cont = 60; 
X/*	if((argc == 2) && (atoi(argv[1]) >1) && (atoi(argv[1]) <100))
X		cont = atoi(argv[1]);*/
X 
X    if ((fd=open(argv[1],O_RDONLY|O_NDELAY))==0) {
X      fprintf("couldn't open %s for read\n", argv[1]);
X      exit(-1);
X    }
X    if(lseek(fd,8,0)<0)
X      exit(-1);
X    cd=malloc(134400);
X    if(read(fd,cd,134400)!=134400)
X      exit(-1);
X    bm=malloc(14974);
X    c=bm+7487;
X    for(a=287;a>=0;a--) {
X      d=a*420+cd;
X      for(b=415;b>=0;b--) {
X        if(!(b&15))
X          c-=1;
X        *c=(*c<<1)|(*(d+b)>60);
X      }
X    }
X    cd=bm;
X    a = 0;
X    while(a++ != 14974)
X	    fprintf(stdout, "%c", *cd++);
X}
END_OF_conv.c
if test 824 -ne `wc -c <conv.c`; then
    echo shar: \"conv.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f extern.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"extern.h\"
else
echo shar: Extracting \"extern.h\" \(130 characters\)
sed "s/^X//" >extern.h <<'END_OF_extern.h'
Xextern double suzie[300][300],sam;
Xextern struct ball *bl[];
Xextern struct sphere ls;
Xextern int level,nob;
Xextern int xsue,ysue;
END_OF_extern.h
if test 130 -ne `wc -c <extern.h`; then
    echo shar: \"extern.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f find.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"find.c\"
else
echo shar: Extracting \"find.c\" \(1942 characters\)
sed "s/^X//" >find.c <<'END_OF_find.c'
X#include <math.h>
X#include "rtd.h"
X#include "extern.h"
X#include "macros.h"
X
X
Xdouble  findo (m, s) /* finds where a ray inside the ball exits. */
Xstruct mat *m;
Xstruct sphere  *s;
X{
X/* foops id the rotated position vector. */
X    struct vector   foops;
X    double  t;
X    MTV (foops, (*m), s -> cent);
X/* see if it hits the ball (it better)*/
X    t = s -> rad * s -> rad - foops.y * foops.y - foops.z * foops.z;
X    if (t > 0)
X	t = foops.x + sqrt (t);
X    else
X	t = 0;
X/* return how far along the ray you were when you hit */
X    return (t);
X}
X
Xdouble  find (m, s)/* finds whether a ray hits a ball*/
Xstruct mat *m;
Xstruct sphere  *s;
X{
X    struct vector   foops;
X    double  t;
X    MTV (foops, (*m), s -> cent);
X    t = s -> rad * s -> rad - foops.y * foops.y - foops.z * foops.z;
X    if (t > 0)
X	t = foops.x - sqrt (t);
X    else
X	t = 0;
X    return (t);
X}
X
Xdouble  finds (m, s)/* finds if a ball is between a point and a 
X			lightsource. Returns how obscuring the ball is */
Xstruct mat *m;
Xstruct sphere  *s;
X{
X    struct vector   foops;
X    double  t;
X    MTV (foops, (*m), s -> cent);
X    t = s -> rad - sqrt (foops.y * foops.y + foops.z * foops.z);
X    if (t > 0)
X	t = t / foops.x;
X    else
X	t = 0;
X    return (t);
X}
X
X
X
X
Xdouble  shadow (p)/* finds if a point is in a shadow, or if it is on edge */
Xstruct vector  *p;
X{
X    struct mat  trans;
X    struct sphere   ss;
X    struct vector   d;
X    int     c,
X            i;
X    double  l,
X            k,
X            x,
X            y,
X            z,
X            finds ();
X    l = 0.0;
X    c = -1;
X    SV (d, ls.cent, (*p));
X    d.l = LEN (d);
X    d.xzl = XZL (d);
X    mt (&(d), &trans);
X
X    for (i = 0; i < nob; i++) {
X	ss.rad = bl[i] -> s.rad;
X	SV (ss.cent, bl[i] -> s.cent, (*p));
X	if ((k = finds (&trans, &ss)) > l) {
X	    c = i;
X	    l = k;
X	}
X    }
X    if (c == -1)
X	k = 200.0;
X    else {
X	k = 1.0 - l / ((ls.rad) / (d.l));
X	if (k < 0.0)
X	    k = 0.0;
X	k *= 200.0;
X    }
X    return (k);
X}
END_OF_find.c
if test 1942 -ne `wc -c <find.c`; then
    echo shar: \"find.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f g_bal.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"g_bal.c\"
else
echo shar: Extracting \"g_bal.c\" \(652 characters\)
sed "s/^X//" >g_bal.c <<'END_OF_g_bal.c'
X#include <stdio.h>
X#include "rtd.h"
X#include "extern.h"
Xg_bal (df)
XFILE * df;
X{
X    int     i;
X    double  x,
X            y,
X            z,
X            r,
X            ior,
X            rfr,
X            rfl,
X            dif,
X            amb;
X    for (i = 0;
X	    fscanf (df, "%F %F %F %F %F %F %F %F %F",
X		&x, &y, &z, &r, &ior, &rfr, &rfl, &dif, &amb) != EOF;
X	    i++) {
X	bl[i] = (struct ball   *) malloc (sizeof (struct ball));
X	bl[i] -> s.cent.x = x;
X	bl[i] -> s.cent.y = y;
X	bl[i] -> s.cent.z = z;
X	bl[i] -> s.rad = r;
X	bl[i] -> ior = ior;
X	bl[i] -> rfr = rfr;
X	bl[i] -> rfl = rfl;
X	bl[i] -> dif = dif;
X	bl[i] -> amb = amb;
X    }
X    return (i);
X}
X
END_OF_g_bal.c
if test 652 -ne `wc -c <g_bal.c`; then
    echo shar: \"g_bal.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f g_bod.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"g_bod.c\"
else
echo shar: Extracting \"g_bod.c\" \(595 characters\)
sed "s/^X//" >g_bod.c <<'END_OF_g_bod.c'
X#include <stdio.h>
X#include <math.h>
X#include "extern.h"
X#include "macros.h"
X
X
Xg_bod (f)
XFILE * f;
X{
X    int     k,
X            x;
X    double  big = 0.0,
X            little = HUGE;
X    char    buf[512];
X
X
X    for (ysue = 0;; ysue++) {
X	if (fgets (buf, 512, f) == NULL)
X	    break;
X	xsue = strlen (buf) - 1;
X	for (x = 0; x < xsue; x++) {
X	    k = buf[x];
X	    suzie[x][ysue] = (double) k;
X	    if (big < k)
X		big = k;
X	    if (little > k)
X		little = k;
X	}
X    }
X    big = big - little;
X    for (k = 0; k < ysue; k++)
X	for (x = 0; x < xsue; x++)
X	    suzie[x][k] = (suzie[x][k] - little) / big;
X}
END_OF_g_bod.c
if test 595 -ne `wc -c <g_bod.c`; then
    echo shar: \"g_bod.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f macros.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"macros.h\"
else
echo shar: Extracting \"macros.h\" \(1116 characters\)
sed "s/^X//" >macros.h <<'END_OF_macros.h'
X/* some of the most important stuff in the program */
X#define DOT(v1,v2) (v1.x*v2.x+v1.y*v2.y+v1.z*v2.z)
X/* returns dot product of two vectors */
X#define LN2(v)	   (DOT(v,v))
X/* returns the square of the length of a vector */
X#define LEN(v)	   sqrt(LN2(v))
X/* guess */
X#define XZL(v)	   sqrt(v.x*v.x+v.z*v.z)
X/* returns the component in the xz plane of a vector */
X#define SCMLT(sc,vct) vct.x*= sc;vct.y*= sc;vct.z*= sc;vct.l*= sc;
X/* multiplies a vetor by a scalar */
X#define MV(a,b,c,v)   v.x= a;v.y= b;v.z= c;
X/* makes a vector. wouldn't need this with c++ */
X#define SV(t,u,v)  t.x=u.x-v.x;t.y=u.y-v.y;t.z=u.z-v.z;
X/*subtract vector t=u-v */
X#define AV(t,u,v)  t.x=u.x+v.x;t.y=u.y+v.y;t.z=u.z+v.z;
X/* add vector t=u+v */
X#define MTV(v1,m,v2) MV(DOT(m.x,v2),DOT(m.y,v2),DOT(m.z,v2),v1)
X/* multiply transpose matrix by vector. v1=m*v2 */
X
X#define LEVEL 5/* levels of recursion */
X#define RLEV  3/*don't want as many inside the ball, takes forever as it is*/
X
X#define XMIN 10.0
X#define XMAX 220.0
X#define YMIN 10.0
X#define YMAX 170.0
X/* window size,  virtual units */
X#define SCALE  2.0
X/* maginification factor */
END_OF_macros.h
if test 1116 -ne `wc -c <macros.h`; then
    echo shar: \"macros.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f refract.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"refract.c\"
else
echo shar: Extracting \"refract.c\" \(2965 characters\)
sed "s/^X//" >refract.c <<'END_OF_refract.c'
X#include <math.h>
X#include "rtd.h"
X#include "macros.h"
X#include "extern.h"
X
Xint	rlev;
Xint     refract (r, bll)
Xstruct ray *r;
Xstruct ball *bll;
X{
X    struct vector   new,
X                    norm;
X    struct mat  trans;
X    struct ray  ir;
X    double  l,
X            refk (), getcapt (), capt, inside ();
X    double  stupid;
X    struct sphere   ss;
X
X    SV (norm, r -> org, bll -> s.cent);
X    norm.l = bll-> s.rad;
X
X    capt = getcapt (&norm, &(r -> dir), bll -> ior);
X
X
X/* get the addition factor for the normal for refraction*/
X    stupid = refk (&(norm), &(r -> dir), bll -> ior);
X    SCMLT (stupid, norm);
X
X    AV (ir.dir, r -> dir, norm);
X    MV (r -> org.x, r -> org.y, r -> org.z, ir.org);
X
X/* now get it for reflection */
X    SV (norm, r -> org, bll -> s.cent);
X    norm.l = bll -> s.rad;
X    SCMLT (1.0 / norm.l, norm);
X    stupid = 2.0 * DOT (norm, r -> dir);
X    SCMLT (stupid, norm);
X    SV (r -> dir, r -> dir, norm);
X
X    return ((int) ((1.0 - capt) * (double) shade (r) + ((capt) * inside (&ir, bll))));
X}
X
Xdouble  inside (r, bll)
Xstruct ray *r;
Xstruct ball *bll;
X{
X    struct vector   new,
X                    norm;
X    struct mat  trans;
X    struct ray  er;
X    double  findo (), lght, l, refk (), getcapt (), capt;
X    double  stupid;
X    struct sphere   ss;
X
X
X    if (++rlev < RLEV) {
X	r -> dir.l = LEN (r -> dir);
X	r -> dir.xzl = XZL (r -> dir);
X	mt (&(r -> dir), &trans);
X	ss.rad = bll -> s.rad;
X	SV (ss.cent, bll -> s.cent, r -> org);
X
X	l = findo (&trans, &ss);
X	MV (l * trans.x.x, l * trans.x.y, l * trans.x.z, new);
X	AV (er.org, r -> org, new);
X	AV (r -> org, r -> org, new);
X	SV (norm, er.org, bll -> s.cent);
X
X	norm.l = bll -> s.rad;
X	capt = getcapt (&norm, &(r -> dir), 1.0 / bll -> ior);
X
X	stupid = refk (&norm, &(r -> dir), 1.0 / bll -> ior);
X	SCMLT (stupid, norm);
X	AV (er.dir, norm, r -> dir);
X
X	SCMLT (1.0 / norm.l, norm);
X	stupid = 2.0 * DOT (norm, r -> dir);
X	SCMLT (stupid, norm);
X	SV (r -> dir, r -> dir, norm);
X	lght = (1.0 - capt) * inside (r, bll) + (capt * (double) shade (&er));
X    }
X    else
X	lght = 0.0;
X    rlev--;
X     if (lght<0.0) lght=0.0;
X     if (lght>255.0) lght=255.0;
X    return (lght);
X}
X
X
X
Xdouble  refk (nrm, in, ior)
Xstruct vector  *nrm,
X               *in;
Xdouble  ior;
X{
X    double  dt,
X            ln,
X            li,
X            ret;
X
X    ior = ior * ior;
X    dt = DOT ((*nrm), (*in));
X    ln = LN2 ((*nrm));
X    li = LN2 ((*in));
X    if (dt < 0)
X	ret = (-dt - sqrt (dt * dt - ln * li * (1 - ior))) / ln;
X    else
X	ret = (-dt + sqrt (dt * dt - ln * li * (1 - ior))) / ln;
X    return (ret);
X}
X
Xdouble  getcapt (nrm, dr, ior)
Xstruct vector  *nrm,
X               *dr;
Xdouble  ior;
X{
X    double  dt,
X            cs1,
X            cs2,
X            p,
X            s;
X    dt = DOT ((*nrm), (*dr));
X    dt = dt * dt / LN2 ((*nrm)) / LN2 ((*dr));
X    cs1 = sqrt (dt);
X    cs2 = sqrt (1.0 - (1.0 - dt) / ior);
X    p = cs1 / (cs1 + ior * cs2);
X    s = cs1 / (ior * cs1 + cs2);
X    return (2.0 * (p * p + s * s));
X}
END_OF_refract.c
if test 2965 -ne `wc -c <refract.c`; then
    echo shar: \"refract.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f rtd.h -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"rtd.h\"
else
echo shar: Extracting \"rtd.h\" \(434 characters\)
sed "s/^X//" >rtd.h <<'END_OF_rtd.h'
Xstruct color {
Xint r;int g;int b;};
X
Xstruct vector {
Xdouble x;
Xdouble y;
Xdouble z;
Xdouble l;
Xdouble xzl;} ;
X
Xstruct ray {
Xstruct vector org;
Xstruct vector dir;} ;
X
Xstruct sphere {
Xstruct vector cent;
Xdouble rad;} ;
X
Xstruct ball {
Xstruct sphere s;
Xdouble ior;
Xdouble rfr;
Xdouble rfl;
Xdouble dif;
Xdouble amb;
X};
X
Xstruct mat {
Xstruct vector x;  /* first !row! */
Xstruct vector y;  /*second !row! */
Xstruct vector z;}; /* third !row! */
X
END_OF_rtd.h
if test 434 -ne `wc -c <rtd.h`; then
    echo shar: \"rtd.h\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f shade.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"shade.c\"
else
echo shar: Extracting \"shade.c\" \(3454 characters\)
sed "s/^X//" >shade.c <<'END_OF_shade.c'
X/*
X * this subroutine does all the gritty work- it calculates 
X * what shade each pixel should be. I like recursion.
X */
X#include <math.h>
X#include "rtd.h"
X#include "macros.h"
X#include "extern.h"
X
Xint     shade (r)
Xstruct ray *r;
X{
X    int     i,
X            c,
X            refract ();
X    struct ray  refr;
X    double  lght,
X            x,
X            y,
X            z,
X            l,
X            k,
X            dot (), find (), shadow ();
X    int     sx,
X            sy;
X    double  stupid;
X    struct vector   new,
X                    norm;
X    struct mat  trans;
X    struct sphere   ss;
X    if (++level <= LEVEL) {
X	c = -1;
X	l = HUGE;
X/* get vector length and xz component for mt() */
X	r -> dir.l = LEN (r -> dir);
X	r -> dir.xzl = XZL (r -> dir);
X/* make a transform matrix that rotates something in space so
X   that the ray will be aligned with the x axis */
X	mt (&(r -> dir), &trans);
X
X/* for starters we find out whether we hit anything. */
X	for (i = 0; i < nob; i++) {
X	    ss.rad = bl[i] -> s.rad;
X	    SV (ss.cent, bl[i] -> s.cent, r -> org);
X	    if ((k = find (&trans, &ss)) > 0.0 && k < l) {
X		c = i;
X		l = k;
X	    }
X	}
X	if (c >= 0 && (l * trans.x.y + r -> org.y) > 0.0) {
X				/* WE HIT SOMETHING */
X	    MV (l * trans.x.x, l * trans.x.y, l * trans.x.z, new);
X	    new.l=l;
X/* move the new orgin of the ray to the intersection */
X	    AV (refr.org, new, r -> org);
X	    AV (r -> org, new, r -> org);
X	    MV (r -> dir.x, r -> dir.y, r -> dir.z, refr.dir);
X/* get a normal vector for the intersection point */
X	    SV (norm, r -> org, bl[c] -> s.cent);
X	    norm.l=bl[c] ->s.rad;
X
X/* ambient lighting */
X	    lght = 200.0 * bl[c] -> amb;
X
X/* shaded lighting (diffuse). subroutine shadow is in find.c */
X	    if (bl[c] -> dif != 0.0) {
X		SV (new, ls.cent, r -> org);
X		new.l = LEN(new);
X		if ((k = DOT (new, norm)) > 0.0)
X		    lght += bl[c] -> dif * shadow (&(r -> org)) * k / (new.l) / (norm.l);
X	    }
X
X/*reflection... easy */
X	    if (bl[c] -> rfl != 0.0) {
X/* make the normal unit length */
X		SCMLT ((1.0 / norm.l), norm);
X/* get the length of the ray's component in the normal direction */
X		stupid = 2.0 * DOT (norm, r -> dir);
X		SCMLT (stupid, norm);
X/* subtract double the normal component- !reflection! */
X		SV (r -> dir, r -> dir, norm);
X		lght += bl[c] -> rfl * (double) shade (r);
X	    }
X
X/* refraction. this is ugly, which is why I choose to deal with
X   it in it's own subroutine which comes after this one */
X	    if (bl[c] -> rfr != 0.0) {
X		lght += bl[c] -> rfr * (double) refract (&refr, bl[c]);
X	    }
X
X
X
X	}
X	else {			/* hit no objects... */
X	    if ((r -> dir.y) < 0.0) {/* crosses floor */
X		z = -(r -> org.y) / (r -> dir.y);
X		(r -> org.x) += z * (r -> dir.x);
X		(r -> org.z) += z * (r -> dir.z);
X		(r -> org.y) = 0.0;
X
X		SV (new, ls.cent, r -> org);
X		new.l = LEN(new);
X		sx = (int) (r -> org.x / 1.5) % xsue;
X		if (sx < 0)
X		    sx += xsue;
X		sy = -(int) (r -> org.z / 1.5) % ysue;
X		if (sy < 0)
X		    sy += ysue;
X		lght = (sam * suzie[sx][sy] + 1.0 - sam) * (0.8 *
X			shadow (&(r -> org)) * (new.y) / (new.l) + 40.0);
X
X
X	    }
X	    else {		/* check to see if it hit lightsource */
X		SV (ss.cent, ls.cent, r -> org);
X		ss.rad = ls.rad;
X		if (find (&trans, &(ss.cent)) > 0.0)
X		    lght = 255;
X		else
X		    lght = 0;
X	    }
X	}
X    }
X/* to many levels return 0 cause it shouldn't matter */
X    else
X	lght = 0;
X    level--;
X    if (lght < 0.0)
X	lght = 0.0;
X    if (lght > 255.0)
X	lght = 255.0;
X    return ((int) lght);
X}
END_OF_shade.c
if test 3454 -ne `wc -c <shade.c`; then
    echo shar: \"shade.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f support.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"support.c\"
else
echo shar: Extracting \"support.c\" \(834 characters\)
sed "s/^X//" >support.c <<'END_OF_support.c'
X/*
X *    supportive subroutines...
X */
X
X#include <math.h>
X#include <stdio.h>
X#include "rtd.h"
X#include "extern.h"
X
X
Xmt (vec, trans)
Xstruct vector  *vec;
Xstruct mat *trans;
X{
X    if (vec -> xzl == 0.0) {
X	trans -> x.x = 0.0;
X	trans -> x.y = 1.0;
X	trans -> x.z = 0.0;
X	trans -> y.x = -1.0;
X	trans -> y.y = 0.0;
X	trans -> y.z = 0.0;
X	trans -> z.x = 0.0;
X	trans -> z.y = 0.0;
X	trans -> z.z = 1.0;
X    }
X    else {
X	trans -> x.x = (vec -> x) / (vec -> l);
X	trans -> x.y = (vec -> y) / (vec -> l);
X	trans -> x.z = (vec -> z) / (vec -> l);
X	trans -> y.x = -(vec -> x) * (vec -> y) / ((vec -> l) * (vec -> xzl));
X	trans -> y.y = (vec -> xzl) / (vec -> l);
X	trans -> y.z = -(vec -> z) * (vec -> y) / ((vec -> l) * (vec -> xzl));
X	trans -> z.x = -(vec -> z) / (vec -> xzl);
X	trans -> z.y = 0;
X	trans -> z.z = (vec -> x) / (vec -> xzl);
X    }
X}
END_OF_support.c
if test 834 -ne `wc -c <support.c`; then
    echo shar: \"support.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f tracer.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"tracer.c\"
else
echo shar: Extracting \"tracer.c\" \(2624 characters\)
sed "s/^X//" >tracer.c <<'END_OF_tracer.c'
X
X
X/* tracer version 2.1 */
X#include <stdio.h>
X#include <math.h>
X#include "rtd.h"
X#include "macros.h"
X
X
XFILE * fp;
Xdouble  suzie[300][300],
X        sam = 1.0;
Xint     xsue,
X        ysue;
Xstruct ball *bl[150];
Xint     level,
X        nob;
Xstruct sphere   ls;
X
Xmain (argc, argv)
Xint     argc;
Xchar  **argv;
X{
X    FILE * df, *texfile;
X    static double   xco,
X                    yco;
X    struct ray  rr;
X    struct vector   vp;
X    double  x,
X            y,
X            z;
X    int     i,
X            in = 0,
X            out = 0,
X            tex = 0;
X    int     c;
X
X/* command interp */
X
X    for (i = 1; i < argc; i++) {
X	if (argv[i][0] != '-')
X	    booboo ("Options strt with a '-' bozo");
X	c = argv[i][1];
X
X	switch (c) {
X	    case ('i'): 
X		if (in)
X		    booboo ("Sorry, but you may only have one input file");
X		in = 1;
X		if ((i + 1) >= argc || argv[i + 1][0] == '-')/* no arg */
X		    df = stdin;
X		else
X		    if ((df = fopen (argv[++i], "r")) == NULL)
X			booboo ("input file not found");
X		break;
X	    case ('o'): 
X		if (out)
X		    booboo ("Sorry, but you may have only one output file");
X		out = 1;
X		if ((i + 1) >= argc || argv[i + 1][0] == '-')/* no arg */
X		    fp = stdout;
X		else
X		    fp = fopen (argv[++i], "w");
X		break;
X	    case ('s'): 
X		if (tex)
X		    booboo ("Sorry, but you may have only one image file");
X		if ((i + 1) >= argc || argv[i + 1][0] == '-')/* no arg */
X		    booboo ("-s requires an argument");
X		tex = 1;
X		if ((texfile = fopen (argv[++i], "r")) == NULL)
X		    booboo ("image file not found");
X		break;
X		booboo ("this line shouldn't do anything");
X	    case ('S'): 
X		if (argv[i][2] < '0' || argv[i][2] > '9'){
Xprintf("%c\n",argv[i][2]);
X		    booboo ("-S needs a numerical argument");}
X		sam = atof (&(argv[i][2]));
X		break;
X	    default: 
X		booboo ("Unrecognized option. Better try again");
X	}
X    }
X
X
X    if (!in)
X	if ((df = fopen ("bdata.i", "r")) == NULL)
X	    booboo ("bdata.i not found");
X    if (!out)
X	fp = fopen ("data.dis", "w");
X    if (!tex)
X	if ((texfile = fopen ("pat.def", "r")) == NULL)
X	    booboo ("pat.def not found");
X
X
X
X    nob = g_bal (df);
X    g_bod (texfile);
X
X
X
X    MV (95.0, 140.0, -200.0, vp);
X    MV (0.0, 900.0, 0.0, ls.cent);
X    ls.rad = 40;
X    fprintf (fp, "%d %d\n", (int) ((XMAX - XMIN) * SCALE +0.9999999), (int) ((YMAX - YMIN) * SCALE +0.9999999));
X
X    for (yco = YMAX * SCALE; yco > YMIN * SCALE; yco--)
X	for (xco = XMIN * SCALE; xco < XMAX * SCALE; xco++) {
X	    MV (xco / SCALE, yco / SCALE, 0.0, rr.org);
X	    SV (rr.dir, rr.org, vp);
X	    fprintf (fp, "%c", shade (&rr));
X	}
X}
X
Xbooboo (str)
Xchar   *str; {
X    printf ("%s\n", str);
X    exit (-1);
X}
END_OF_tracer.c
if test 2624 -ne `wc -c <tracer.c`; then
    echo shar: \"tracer.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of shell archive.
exit 0