home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume5
/
tracer
/
shade.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-02-03
|
3KB
|
134 lines
/*
* 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);
}