home *** CD-ROM | disk | FTP | other *** search
- /*
- * this subroutine does all the gritty work- it calculates
- * what shade each pixel should be. I like recursion.
- */
- #include <math.h>
- #include <stdio.h>
- #include "MyMath.h"
- #include "rtd.h"
- #include "macros.h"
- #include "extern.h"
-
- extern FFP big,
- little;
-
- int shade (r)
- struct ray *r;
- {
- int i,
- c,
- refract ();
-
- struct ray refr;
-
- FFP lght,
- z,
- l,
- k,
- sanity,
- find (), shadow ();
-
- int sx,
- sy;
-
- FFP stupid;
-
- struct vector new,
- norm;
-
- struct mat trans;
-
- struct sphere ss;
-
- if (++level <= LEVEL) {
- c = -1;
- l = ieee_to_ffp(1.0e37);
-
- /* 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);
- k = find (&trans, &ss);
- /*
- if( SPTst( k ) > 0 )
- printf("k = %f\n", ffp_to_ieee(k) );
- */
- if (
- ( SPTst( k ) > 0 ) /* k>0.0 */
- &&
- ( SPCmp(l, k) > 0 ) /* k<l */
- ) {
- c = i;
- l = k;
- }
- }
-
- if (
- c >= 0 &&
- SPTst( SPAdd( SPMul(l, trans.x.y), r->org.y)) > 0
- ) {
- /* WE HIT SOMETHING */
- /*
- printf("HIT: ball # %d, l = %f\n",
- c, ffp_to_ieee(l) );
- */
- MV (SPMul(l, trans.x.x),SPMul(l, trans.x.y),SPMul(l, trans.x.z),new );
-
- /*
- 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 = LEN (norm);
-
- /* ambient lighting */
- lght = SPMul( SPFlt(200), bl[c] -> amb);
-
- /*
- shaded lighting (diffuse).
- subroutine shadow is in find.c
- */
- if ( SPTst( bl[c] -> dif) ) {
- SV (new, ls.cent, r -> org);
- new.l = LEN (new);
-
- if( SPTst( (k=DOT(new, norm)) ) > 0)
- lght = SPAdd(
- SPDiv(
- (norm.l),
- SPDiv(
- (new.l),
- SPMul(
- SPMul(
- bl[c]->dif,
- shadow( &(r -> org) )
- ),
- k
- )
- )
- ),
- lght
- );
-
- /*
- lght += bl[c]->dif *
- shadow( &(r -> org) ) *
- k / (new.l) / (norm.l);
- */
- }
-
- /*reflection... easy */
- if ( SPTst(bl[c] -> rfl) ) {
- /* make the normal unit length */
- norm.l = LEN (norm);
- SCMLT ( SPDiv(norm.l, SPFlt(1) ), norm);
-
- /*
- get the length of the ray's
- component in the normal direction
- */
- stupid = SPMul(
- SPFlt(2),
- DOT (norm, r -> dir)
- );
- SCMLT (stupid, norm);
-
- /*
- subtract double the normal
- component-!reflection!
- */
- SV (r -> dir, r -> dir, norm);
- lght = SPAdd(
- lght,
- SPMul(
- bl[c] -> rfl,
- SPFlt( shade (r) )
- )
- );
- /*
- lght += bl[c] -> rfl * (double) shade (r);
- */
- }
-
- /*
- refraction. this is ugly as sin,
- which is why I choose to deal with
- it in it's own subroutine, which is
- in it's own file now.
- */
- if ( SPTst(bl[c] -> rfr) ) {
- lght = SPAdd(
- lght,
- SPMul(
- bl[c] -> rfr,
- SPFlt( refract (&refr, bl[c] ) )
- )
- );
- /*
- lght += bl[c] -> rfr *
- (double) refract (&refr, bl[c]);
- */
- }
-
- } else {
- /* hit no objects... */
- if (SPTst(r -> dir.y) < 0) {
- /* crosses floor */
- z = SPDiv(
- (r -> dir.y),
- SPNeg(r -> org.y)
- );
-
- (r -> org.x) = SPAdd(
- (r -> org.x),
- SPMul(
- z,
- (r -> dir.x)
- )
- );
-
- (r -> org.z) = SPAdd(
- (r -> org.z),
- SPMul(
- z,
- (r -> dir.z)
- )
- );
- /*
- z = -(r -> org.y) / (r -> dir.y);
- (r -> org.x) += z * (r -> dir.x);
- (r -> org.z) += z * (r -> dir.z);
- */
-
- (r -> org.y) = SPFlt(0);
-
- /*
- find out the mod of the value to
- see where it hits susie. (ouch)
- mess here if you only want the
- pattern once.
- */
- SV (new, ls.cent, r -> org);
- new.l = LEN (new);
-
- sx = SPFix(
- SPDiv(
- ieee_to_ffp(1.5),
- r -> org.x
- )
- ) % xsue;
-
- if (sx < 0)
- sx += xsue;
-
- sy = -SPFix(
- SPDiv(
- ieee_to_ffp(1.5),
- r -> org.z
- )
- ) % ysue;
-
- /*
- 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);
- */
-
- sanity = SPMul(
- sam,
- SPAdd(
- SPSub(
- sam,
- SPFlt(1)
- ),
- SPDiv(
- big,
- SPSub(
- little,
- SPFlt(suzie[sx][sy])
- )
- )
- )
- );
-
- lght = SPAdd(
- SPFlt(40),
- SPDiv(
- (new.l),
- SPMul(
- (new.y),
- SPMul(
- ieee_to_ffp(0.8),
- SPMul(
- shadow ( &(r -> org) ),
- sanity
- )
- )
- )
- )
- );
-
- } else {
- /* check to see if it hit lightsource */
- SV (ss.cent, ls.cent, r -> org);
- ss.rad = ls.rad;
- if (SPTst(find (&trans, &(ss.cent))) > 0)
- lght = SPFlt(255);
- else
- lght = SPFlt(0);
- }
- }
- }
- /* too many levels return 0 cause it shouldn't matter */
- else
- lght = SPFlt(0);
- level--;
-
- if (SPTst(lght) < 0)
- lght = SPFlt(0);
-
- if (SPCmp(lght, SPFlt(255) ) > 0 )
- lght = SPFlt(255);
-
-
- return ( SPFix(lght) );
- }
-