home *** CD-ROM | disk | FTP | other *** search
- #define _MC68881_
-
- /*
- * 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);
- }
-
- CallStdEvent();
- /*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);
- }