home *** CD-ROM | disk | FTP | other *** search
- From fritzz@net1.UCSD.EDU (john) Wed Aug 27 16:21:25 1986
- Path: beno!seismo!columbia!caip!clyde!cbatt!cbosgd!ucbvax!sdcsvax!net1!fritzz
- From: fritzz@net1.UCSD.EDU (john)
- Newsgroups: net.sources
- Subject: one more time... ray tracing
- Message-ID: <247@net1.UCSD.EDU>
- Date: 27 Aug 86 20:21:25 GMT
- Reply-To: fritzz@net1.UUCP (john)
- Organization: abercrombie bmf graphics
- Lines: 725
-
-
- well, it seems that between a few typo's in my old source, news
- truncating the articles, and our news acting strange, it is belatedly
- time for son of son of tracer. I keep on promising that I won't post
- these anymore, but demand stays demanding, so here it is:
- tracer 2.1
- it is in three shars, with this the first one holding all code and
- header files, and the other two holding support documents and data files
- including the much demanded susie (you guys are all sick, it's only
- black and white =)
- so, without further ado:
- ----------------------------------------------
-
-
- # This is a shell archive. Remove anything before this line,
- # then unpack it by saving it in a file and typing "sh file".
- #
- # Wrapped by wizard!fritzz on Wed Aug 27 13:03:37 PDT 1986
- # Contents: find.c g_bal.c g_bod.c refract.c shade.c support.c tracer.c
- # extern.h macros.h rtd.h
-
- echo x - find.c
- sed 's/^@//' > "find.c" <<'@//E*O*F find.c//'
- #include <math.h>
- #include "rtd.h"
- #include "extern.h"
- #include "macros.h"
-
-
- double findo (m, s) /* finds where a ray inside the ball exits. */
- struct mat *m;
- struct sphere *s;
- {
- /* foops id the rotated position vector. */
- struct vector foops;
- double t;
- MTV (foops, (*m), s -> cent);
- /* see if it hits the ball (it better)*/
- t = s -> rad * s -> rad - foops.y * foops.y - foops.z * foops.z;
- if (t > 0)
- t = foops.x + sqrt (t);
- else
- t = 0;
- /* return how far along the ray you were when you hit */
- return (t);
- }
-
- double find (m, s)/* finds whether a ray hits a ball*/
- struct mat *m;
- struct sphere *s;
- {
- struct vector foops;
- double t;
- MTV (foops, (*m), s -> cent);
- t = s -> rad * s -> rad - foops.y * foops.y - foops.z * foops.z;
- if (t > 0)
- t = foops.x - sqrt (t);
- else
- t = 0;
- return (t);
- }
-
- double finds (m, s)/* finds if a ball is between a point and a
- lightsource. Returns how obscuring the ball is */
- struct mat *m;
- struct sphere *s;
- {
- struct vector foops;
- double t;
- MTV (foops, (*m), s -> cent);
- t = s -> rad - sqrt (foops.y * foops.y + foops.z * foops.z);
- if (t > 0)
- t = t / foops.x;
- else
- t = 0;
- return (t);
- }
-
-
-
-
- double shadow (p)/* finds if a point is in a shadow, or if it is on edge */
- struct vector *p;
- {
- struct mat trans;
- struct sphere ss;
- struct vector d;
- int c,
- i;
- double l,
- k,
- x,
- y,
- z,
- finds ();
- l = 0.0;
- c = -1;
- SV (d, ls.cent, (*p));
- d.l = LEN (d);
- d.xzl = XZL (d);
- mt (&(d), &trans);
-
- for (i = 0; i < nob; i++) {
- ss.rad = bl[i] -> s.rad;
- SV (ss.cent, bl[i] -> s.cent, (*p));
- if ((k = finds (&trans, &ss)) > l) {
- c = i;
- l = k;
- }
- }
- if (c == -1)
- k = 200.0;
- else {
- k = 1.0 - l / ((ls.rad) / (d.l));
- if (k < 0.0)
- k = 0.0;
- k *= 200.0;
- }
- return (k);
- }
- @//E*O*F find.c//
- chmod u=rw,g=r,o=r find.c
-
- echo x - g_bal.c
- sed 's/^@//' > "g_bal.c" <<'@//E*O*F g_bal.c//'
- #include <stdio.h>
- #include "rtd.h"
- #include "extern.h"
- g_bal (df)
- FILE * df;
- {
- int i;
- double x,
- y,
- z,
- r,
- ior,
- rfr,
- rfl,
- dif,
- amb;
- for (i = 0;
- fscanf (df, "%F %F %F %F %F %F %F %F %F",
- &x, &y, &z, &r, &ior, &rfr, &rfl, &dif, &amb) != EOF;
- i++) {
- bl[i] = (struct ball *) malloc (sizeof (struct ball));
- bl[i] -> s.cent.x = x;
- bl[i] -> s.cent.y = y;
- bl[i] -> s.cent.z = z;
- bl[i] -> s.rad = r;
- bl[i] -> ior = ior;
- bl[i] -> rfr = rfr;
- bl[i] -> rfl = rfl;
- bl[i] -> dif = dif;
- bl[i] -> amb = amb;
- }
- return (i);
- }
-
- @//E*O*F g_bal.c//
- chmod u=rw,g=r,o=r g_bal.c
-
- echo x - g_bod.c
- sed 's/^@//' > "g_bod.c" <<'@//E*O*F g_bod.c//'
- #include <stdio.h>
- #include <math.h>
- #include "extern.h"
- #include "macros.h"
-
-
- g_bod (f)
- FILE * f;
- {
- int k,
- x;
- double big = 0.0,
- little = HUGE;
- char buf[512];
-
-
- for (ysue = 0;; ysue++) {
- if (fgets (buf, 512, f) == NULL)
- break;
- xsue = strlen (buf) - 1;
- for (x = 0; x < xsue; x++) {
- k = buf[x];
- suzie[x][ysue] = (double) k;
- if (big < k)
- big = k;
- if (little > k)
- little = k;
- }
- }
- big = big - little;
- for (k = 0; k < ysue; k++)
- for (x = 0; x < xsue; x++)
- suzie[x][k] = (suzie[x][k] - little) / big;
- }
- @//E*O*F g_bod.c//
- chmod u=rw,g=r,o=r g_bod.c
-
- echo x - refract.c
- sed 's/^@//' > "refract.c" <<'@//E*O*F refract.c//'
- #include <math.h>
- #include "rtd.h"
- #include "macros.h"
- #include "extern.h"
-
- int rlev;
- int refract (r, bll)
- struct ray *r;
- struct ball *bll;
- {
- struct vector new,
- norm;
- struct mat trans;
- struct ray ir;
- double l,
- refk (), getcapt (), capt, inside ();
- double stupid;
- struct sphere ss;
-
- SV (norm, r -> org, bll -> s.cent);
- norm.l = bll-> s.rad;
-
- capt = getcapt (&norm, &(r -> dir), bll -> ior);
-
-
- /* get the addition factor for the normal for refraction*/
- stupid = refk (&(norm), &(r -> dir), bll -> ior);
- SCMLT (stupid, norm);
-
- AV (ir.dir, r -> dir, norm);
- MV (r -> org.x, r -> org.y, r -> org.z, ir.org);
-
- /* now get it for reflection */
- SV (norm, r -> org, bll -> s.cent);
- norm.l = bll -> s.rad;
- SCMLT (1.0 / norm.l, norm);
- stupid = 2.0 * DOT (norm, r -> dir);
- SCMLT (stupid, norm);
- SV (r -> dir, r -> dir, norm);
-
- return ((int) ((1.0 - capt) * (double) shade (r) + ((capt) * inside (&ir, bll))));
- }
-
- double inside (r, bll)
- struct ray *r;
- struct ball *bll;
- {
- struct vector new,
- norm;
- struct mat trans;
- struct ray er;
- double findo (), lght, l, refk (), getcapt (), capt;
- double stupid;
- struct sphere ss;
-
-
- if (++rlev < RLEV) {
- r -> dir.l = LEN (r -> dir);
- r -> dir.xzl = XZL (r -> dir);
- mt (&(r -> dir), &trans);
- ss.rad = bll -> s.rad;
- SV (ss.cent, bll -> s.cent, r -> org);
-
- l = findo (&trans, &ss);
- MV (l * trans.x.x, l * trans.x.y, l * trans.x.z, new);
- AV (er.org, r -> org, new);
- AV (r -> org, r -> org, new);
- SV (norm, er.org, bll -> s.cent);
-
- norm.l = bll -> s.rad;
- capt = getcapt (&norm, &(r -> dir), 1.0 / bll -> ior);
-
- stupid = refk (&norm, &(r -> dir), 1.0 / bll -> ior);
- SCMLT (stupid, norm);
- AV (er.dir, norm, r -> dir);
-
- SCMLT (1.0 / norm.l, norm);
- stupid = 2.0 * DOT (norm, r -> dir);
- SCMLT (stupid, norm);
- SV (r -> dir, r -> dir, norm);
- lght = (1.0 - capt) * inside (r, bll) + (capt * (double) shade (&er));
- }
- else
- lght = 0.0;
- rlev--;
- if (lght<0.0) lght=0.0;
- if (lght>255.0) lght=255.0;
- return (lght);
- }
-
-
-
- double refk (nrm, in, ior)
- struct vector *nrm,
- *in;
- double ior;
- {
- double dt,
- ln,
- li,
- ret;
-
- ior = ior * ior;
- dt = DOT ((*nrm), (*in));
- ln = LN2 ((*nrm));
- li = LN2 ((*in));
- if (dt < 0)
- ret = (-dt - sqrt (dt * dt - ln * li * (1 - ior))) / ln;
- else
- ret = (-dt + sqrt (dt * dt - ln * li * (1 - ior))) / ln;
- return (ret);
- }
-
- double getcapt (nrm, dr, ior)
- struct vector *nrm,
- *dr;
- double ior;
- {
- double dt,
- cs1,
- cs2,
- p,
- s;
- dt = DOT ((*nrm), (*dr));
- dt = dt * dt / LN2 ((*nrm)) / LN2 ((*dr));
- cs1 = sqrt (dt);
- cs2 = sqrt (1.0 - (1.0 - dt) / ior);
- p = cs1 / (cs1 + ior * cs2);
- s = cs1 / (ior * cs1 + cs2);
- return (2.0 * (p * p + s * s));
- }
- @//E*O*F refract.c//
- chmod u=rw,g=r,o=r refract.c
-
- echo x - shade.c
- sed 's/^@//' > "shade.c" <<'@//E*O*F shade.c//'
- /*
- * this subroutine does all the gritty work- it calculates
- * what shade each pixel should be. I like recursion.
- */
- #include <math.h>
- #include "rtd.h"
- #include "macros.h"
- #include "extern.h"
-
- int shade (r)
- struct ray *r;
- {
- int i,
- c,
- refract ();
- struct ray refr;
- double lght,
- x,
- y,
- z,
- l,
- k,
- dot (), find (), shadow ();
- int sx,
- sy;
- double stupid;
- struct vector new,
- norm;
- struct mat trans;
- struct sphere ss;
- if (++level <= LEVEL) {
- c = -1;
- l = HUGE;
- /* get vector length and xz component for mt() */
- r -> dir.l = LEN (r -> dir);
- r -> dir.xzl = XZL (r -> dir);
- /* make a transform matrix that rotates something in space so
- that the ray will be aligned with the x axis */
- mt (&(r -> dir), &trans);
-
- /* for starters we find out whether we hit anything. */
- for (i = 0; i < nob; i++) {
- ss.rad = bl[i] -> s.rad;
- SV (ss.cent, bl[i] -> s.cent, r -> org);
- if ((k = find (&trans, &ss)) > 0.0 && k < l) {
- c = i;
- l = k;
- }
- }
- if (c >= 0 && (l * trans.x.y + r -> org.y) > 0.0) {
- /* WE HIT SOMETHING */
- MV (l * trans.x.x, l * trans.x.y, l * trans.x.z, new);
- new.l=l;
- /* move the new orgin of the ray to the intersection */
- AV (refr.org, new, r -> org);
- AV (r -> org, new, r -> org);
- MV (r -> dir.x, r -> dir.y, r -> dir.z, refr.dir);
- /* get a normal vector for the intersection point */
- SV (norm, r -> org, bl[c] -> s.cent);
- norm.l=bl[c] ->s.rad;
-
- /* ambient lighting */
- lght = 200.0 * bl[c] -> amb;
-
- /* shaded lighting (diffuse). subroutine shadow is in find.c */
- if (bl[c] -> dif != 0.0) {
- SV (new, ls.cent, r -> org);
- new.l = LEN(new);
- if ((k = DOT (new, norm)) > 0.0)
- lght += bl[c] -> dif * shadow (&(r -> org)) * k / (new.l) / (norm.l);
- }
-
- /*reflection... easy */
- if (bl[c] -> rfl != 0.0) {
- /* make the normal unit length */
- SCMLT ((1.0 / norm.l), norm);
- /* get the length of the ray's component in the normal direction */
- stupid = 2.0 * DOT (norm, r -> dir);
- SCMLT (stupid, norm);
- /* subtract double the normal component- !reflection! */
- SV (r -> dir, r -> dir, norm);
- lght += bl[c] -> rfl * (double) shade (r);
- }
-
- /* refraction. this is ugly, which is why I choose to deal with
- it in it's own subroutine which comes after this one */
- if (bl[c] -> rfr != 0.0) {
- lght += bl[c] -> rfr * (double) refract (&refr, bl[c]);
- }
-
-
-
- }
- else { /* hit no objects... */
- if ((r -> dir.y) < 0.0) {/* crosses floor */
- z = -(r -> org.y) / (r -> dir.y);
- (r -> org.x) += z * (r -> dir.x);
- (r -> org.z) += z * (r -> dir.z);
- (r -> org.y) = 0.0;
-
- SV (new, ls.cent, r -> org);
- new.l = LEN(new);
- sx = (int) (r -> org.x / 1.5) % xsue;
- if (sx < 0)
- sx += xsue;
- sy = -(int) (r -> org.z / 1.5) % ysue;
- if (sy < 0)
- sy += ysue;
- lght = (sam * suzie[sx][sy] + 1.0 - sam) * (0.8 *
- shadow (&(r -> org)) * (new.y) / (new.l) + 40.0);
-
-
- }
- else { /* check to see if it hit lightsource */
- SV (ss.cent, ls.cent, r -> org);
- ss.rad = ls.rad;
- if (find (&trans, &(ss.cent)) > 0.0)
- lght = 255;
- else
- lght = 0;
- }
- }
- }
- /* to many levels return 0 cause it shouldn't matter */
- else
- lght = 0;
- level--;
- if (lght < 0.0)
- lght = 0.0;
- if (lght > 255.0)
- lght = 255.0;
- return ((int) lght);
- }
- @//E*O*F shade.c//
- chmod u=rw,g=r,o=r shade.c
-
- echo x - support.c
- sed 's/^@//' > "support.c" <<'@//E*O*F support.c//'
- /*
- * supportive subroutines...
- */
-
- #include <math.h>
- #include <stdio.h>
- #include "rtd.h"
- #include "extern.h"
-
-
- mt (vec, trans)
- struct vector *vec;
- struct mat *trans;
- {
- if (vec -> xzl == 0.0) {
- trans -> x.x = 0.0;
- trans -> x.y = 1.0;
- trans -> x.z = 0.0;
- trans -> y.x = -1.0;
- trans -> y.y = 0.0;
- trans -> y.z = 0.0;
- trans -> z.x = 0.0;
- trans -> z.y = 0.0;
- trans -> z.z = 1.0;
- }
- else {
- trans -> x.x = (vec -> x) / (vec -> l);
- trans -> x.y = (vec -> y) / (vec -> l);
- trans -> x.z = (vec -> z) / (vec -> l);
- trans -> y.x = -(vec -> x) * (vec -> y) / ((vec -> l) * (vec -> xzl));
- trans -> y.y = (vec -> xzl) / (vec -> l);
- trans -> y.z = -(vec -> z) * (vec -> y) / ((vec -> l) * (vec -> xzl));
- trans -> z.x = -(vec -> z) / (vec -> xzl);
- trans -> z.y = 0;
- trans -> z.z = (vec -> x) / (vec -> xzl);
- }
- }
- @//E*O*F support.c//
- chmod u=rw,g=r,o=r support.c
-
- echo x - tracer.c
- sed 's/^@//' > "tracer.c" <<'@//E*O*F tracer.c//'
-
-
- /* tracer version 2.1 */
- #include <stdio.h>
- #include <math.h>
- #include "rtd.h"
- #include "macros.h"
-
-
- FILE * fp;
- double suzie[300][300],
- sam = 1.0;
- int xsue,
- ysue;
- struct ball *bl[150];
- int level,
- nob;
- struct sphere ls;
-
- main (argc, argv)
- int argc;
- char **argv;
- {
- FILE * df, *texfile;
- static double xco,
- yco;
- struct ray rr;
- struct vector vp;
- double x,
- y,
- z;
- int i,
- in = 0,
- out = 0,
- tex = 0;
- int c;
-
- /* command interp */
-
- for (i = 1; i < argc; i++) {
- if (argv[i][0] != '-')
- booboo ("Options strt with a '-' bozo");
- c = argv[i][1];
-
- switch (c) {
- case ('i'):
- if (in)
- booboo ("Sorry, but you may only have one input file");
- in = 1;
- if ((i + 1) >= argc || argv[i + 1][0] == '-')/* no arg */
- df = stdin;
- else
- if ((df = fopen (argv[++i], "r")) == NULL)
- booboo ("input file not found");
- break;
- case ('o'):
- if (out)
- booboo ("Sorry, but you may have only one output file");
- out = 1;
- if ((i + 1) >= argc || argv[i + 1][0] == '-')/* no arg */
- fp = stdout;
- else
- fp = fopen (argv[++i], "w");
- break;
- case ('s'):
- if (tex)
- booboo ("Sorry, but you may have only one image file");
- if ((i + 1) >= argc || argv[i + 1][0] == '-')/* no arg */
- booboo ("-s requires an argument");
- tex = 1;
- if ((texfile = fopen (argv[++i], "r")) == NULL)
- booboo ("image file not found");
- break;
- booboo ("this line shouldn't do anything");
- case ('S'):
- if (argv[i][2] < '0' || argv[i][2] > '9'){
- printf("%c\n",argv[i][2]);
- booboo ("-S needs a numerical argument");}
- sam = atof (&(argv[i][2]));
- break;
- default:
- booboo ("Unrecognized option. Better try again");
- }
- }
-
-
- if (!in)
- if ((df = fopen ("bdata.i", "r")) == NULL)
- booboo ("bdata.i not found");
- if (!out)
- fp = fopen ("data.dis", "w");
- if (!tex)
- if ((texfile = fopen ("pat.def", "r")) == NULL)
- booboo ("pat.def not found");
-
-
-
- nob = g_bal (df);
- g_bod (texfile);
-
-
-
- MV (95.0, 140.0, -200.0, vp);
- MV (0.0, 900.0, 0.0, ls.cent);
- ls.rad = 40;
- fprintf (fp, "%d %d\n", (int) ((XMAX - XMIN) * SCALE +0.9999999), (int) ((YMAX - YMIN) * SCALE +0.9999999));
-
- for (yco = YMAX * SCALE; yco > YMIN * SCALE; yco--)
- for (xco = XMIN * SCALE; xco < XMAX * SCALE; xco++) {
- MV (xco / SCALE, yco / SCALE, 0.0, rr.org);
- SV (rr.dir, rr.org, vp);
- fprintf (fp, "%c", shade (&rr));
- }
- }
-
- booboo (str)
- char *str; {
- printf ("%s\n", str);
- exit (-1);
- }
- @//E*O*F tracer.c//
- chmod u=rw,g=r,o=r tracer.c
-
- echo x - extern.h
- sed 's/^@//' > "extern.h" <<'@//E*O*F extern.h//'
- extern double suzie[300][300],sam;
- extern struct ball *bl[];
- extern struct sphere ls;
- extern int level,nob;
- extern int xsue,ysue;
- @//E*O*F extern.h//
- chmod u=rw,g=r,o=r extern.h
-
- echo x - macros.h
- sed 's/^@//' > "macros.h" <<'@//E*O*F macros.h//'
- /* some of the most important stuff in the program */
- #define DOT(v1,v2) (v1.x*v2.x+v1.y*v2.y+v1.z*v2.z)
- /* returns dot product of two vectors */
- #define LN2(v) (DOT(v,v))
- /* returns the square of the length of a vector */
- #define LEN(v) sqrt(LN2(v))
- /* guess */
- #define XZL(v) sqrt(v.x*v.x+v.z*v.z)
- /* returns the component in the xz plane of a vector */
- #define SCMLT(sc,vct) vct.x*= sc;vct.y*= sc;vct.z*= sc;vct.l*= sc;
- /* multiplies a vetor by a scalar */
- #define MV(a,b,c,v) v.x= a;v.y= b;v.z= c;
- /* makes a vector. wouldn't need this with c++ */
- #define SV(t,u,v) t.x=u.x-v.x;t.y=u.y-v.y;t.z=u.z-v.z;
- /*subtract vector t=u-v */
- #define AV(t,u,v) t.x=u.x+v.x;t.y=u.y+v.y;t.z=u.z+v.z;
- /* add vector t=u+v */
- #define MTV(v1,m,v2) MV(DOT(m.x,v2),DOT(m.y,v2),DOT(m.z,v2),v1)
- /* multiply transpose matrix by vector. v1=m*v2 */
-
- #define LEVEL 5/* levels of recursion */
- #define RLEV 3/*don't want as many inside the ball, takes forever as it is*/
-
- #define XMIN 10.0
- #define XMAX 220.0
- #define YMIN 10.0
- #define YMAX 170.0
- /* window size, virtual units */
- #define SCALE 2.0
- /* maginification factor */
- @//E*O*F macros.h//
- chmod u=rw,g=r,o=r macros.h
-
- echo x - rtd.h
- sed 's/^@//' > "rtd.h" <<'@//E*O*F rtd.h//'
- struct color {
- int r;int g;int b;};
-
- struct vector {
- double x;
- double y;
- double z;
- double l;
- double xzl;} ;
-
- struct ray {
- struct vector org;
- struct vector dir;} ;
-
- struct sphere {
- struct vector cent;
- double rad;} ;
-
- struct ball {
- struct sphere s;
- double ior;
- double rfr;
- double rfl;
- double dif;
- double amb;
- };
-
- struct mat {
- struct vector x; /* first !row! */
- struct vector y; /*second !row! */
- struct vector z;}; /* third !row! */
-
- @//E*O*F rtd.h//
- chmod u=rw,g=r,o=r rtd.h
-
- exit 0
-
-
-