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

  1. /*
  2.  * this subroutine does all the gritty work- it calculates 
  3.  * what shade each pixel should be. I like recursion.
  4.  */
  5. #include <math.h>
  6. #include "rtd.h"
  7. #include "macros.h"
  8. #include "extern.h"
  9.  
  10. int     shade (r)
  11. struct ray *r;
  12. {
  13.     int     i,
  14.             c,
  15.             refract ();
  16.     struct ray  refr;
  17.     double  lght,
  18.             x,
  19.             y,
  20.             z,
  21.             l,
  22.             k,
  23.             dot (), find (), shadow ();
  24.     int     sx,
  25.             sy;
  26.     double  stupid;
  27.     struct vector   new,
  28.                     norm;
  29.     struct mat  trans;
  30.     struct sphere   ss;
  31.     if (++level <= LEVEL) {
  32.     c = -1;
  33.     l = HUGE;
  34. /* get vector length and xz component for mt() */
  35.     r -> dir.l = LEN (r -> dir);
  36.     r -> dir.xzl = XZL (r -> dir);
  37. /* make a transform matrix that rotates something in space so
  38.    that the ray will be aligned with the x axis */
  39.     mt (&(r -> dir), &trans);
  40.  
  41. /* for starters we find out whether we hit anything. */
  42.     for (i = 0; i < nob; i++) {
  43.         ss.rad = bl[i] -> s.rad;
  44.         SV (ss.cent, bl[i] -> s.cent, r -> org);
  45.         if ((k = find (&trans, &ss)) > 0.0 && k < l) {
  46.         c = i;
  47.         l = k;
  48.         }
  49.     }
  50.     if (c >= 0 && (l * trans.x.y + r -> org.y) > 0.0) {
  51.                 /* WE HIT SOMETHING */
  52.         MV (l * trans.x.x, l * trans.x.y, l * trans.x.z, new);
  53.         new.l=l;
  54. /* move the new orgin of the ray to the intersection */
  55.         AV (refr.org, new, r -> org);
  56.         AV (r -> org, new, r -> org);
  57.         MV (r -> dir.x, r -> dir.y, r -> dir.z, refr.dir);
  58. /* get a normal vector for the intersection point */
  59.         SV (norm, r -> org, bl[c] -> s.cent);
  60.         norm.l=bl[c] ->s.rad;
  61.  
  62. /* ambient lighting */
  63.         lght = 200.0 * bl[c] -> amb;
  64.  
  65. /* shaded lighting (diffuse). subroutine shadow is in find.c */
  66.         if (bl[c] -> dif != 0.0) {
  67.         SV (new, ls.cent, r -> org);
  68.         new.l = LEN(new);
  69.         if ((k = DOT (new, norm)) > 0.0)
  70.             lght += bl[c] -> dif * shadow (&(r -> org)) * k / (new.l) / (norm.l);
  71.         }
  72.  
  73. /*reflection... easy */
  74.         if (bl[c] -> rfl != 0.0) {
  75. /* make the normal unit length */
  76.         SCMLT ((1.0 / norm.l), norm);
  77. /* get the length of the ray's component in the normal direction */
  78.         stupid = 2.0 * DOT (norm, r -> dir);
  79.         SCMLT (stupid, norm);
  80. /* subtract double the normal component- !reflection! */
  81.         SV (r -> dir, r -> dir, norm);
  82.         lght += bl[c] -> rfl * (double) shade (r);
  83.         }
  84.  
  85. /* refraction. this is ugly, which is why I choose to deal with
  86.    it in it's own subroutine which comes after this one */
  87.         if (bl[c] -> rfr != 0.0) {
  88.         lght += bl[c] -> rfr * (double) refract (&refr, bl[c]);
  89.         }
  90.  
  91.  
  92.  
  93.     }
  94.     else {            /* hit no objects... */
  95.         if ((r -> dir.y) < 0.0) {/* crosses floor */
  96.         z = -(r -> org.y) / (r -> dir.y);
  97.         (r -> org.x) += z * (r -> dir.x);
  98.         (r -> org.z) += z * (r -> dir.z);
  99.         (r -> org.y) = 0.0;
  100.  
  101.         SV (new, ls.cent, r -> org);
  102.         new.l = LEN(new);
  103.         sx = (int) (r -> org.x / 1.5) % xsue;
  104.         if (sx < 0)
  105.             sx += xsue;
  106.         sy = -(int) (r -> org.z / 1.5) % ysue;
  107.         if (sy < 0)
  108.             sy += ysue;
  109.         lght = (sam * suzie[sx][sy] + 1.0 - sam) * (0.8 *
  110.             shadow (&(r -> org)) * (new.y) / (new.l) + 40.0);
  111.  
  112.  
  113.         }
  114.         else {        /* check to see if it hit lightsource */
  115.         SV (ss.cent, ls.cent, r -> org);
  116.         ss.rad = ls.rad;
  117.         if (find (&trans, &(ss.cent)) > 0.0)
  118.             lght = 255;
  119.         else
  120.             lght = 0;
  121.         }
  122.     }
  123.     }
  124. /* to many levels return 0 cause it shouldn't matter */
  125.     else
  126.     lght = 0;
  127.     level--;
  128.     if (lght < 0.0)
  129.     lght = 0.0;
  130.     if (lght > 255.0)
  131.     lght = 255.0;
  132.     return ((int) lght);
  133. }
  134.