home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Source Code 1994 March
/
Source_Code_CD-ROM_Walnut_Creek_March_1994.iso
/
netsrcs
/
raytrace
< prev
next >
Wrap
Internet Message Format
|
1986-08-28
|
17KB
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