home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / zip / graphics / utility / raymovi2.lzh / RAYMOVI2 / SHADE.C (.txt) < prev    next >
C/C++ Source or Header  |  1988-12-21  |  8KB  |  268 lines

  1. /*
  2. From harvard!husc6!caip!nike!ucbcad!ucbvax!sdcsvax!net1!fritzz 25 Jul 86 21:35:59 GMT
  3. Article 2915 of net.sources:
  4. Relay-Version: version B 2.10.2 9/18/84; site bbnccv.UUCP
  5. Path: bbnccv!harvard!husc6!caip!nike!ucbcad!ucbvax!sdcsvax!net1!fritzz
  6. >From: fritzz@net1.UCSD.EDU (Friedrich Knauss)
  7. Newsgroups: net.sources
  8. Subject: basic ray tracing: part 1 (tracer.c)
  9. Message-ID: <190@net1.UCSD.EDU>
  10. Date: 25 Jul 86 21:35:59 GMT
  11. Date-Received: 27 Jul 86 01:07:29 GMT
  12. Reply-To: fritzz@net1.UUCP (Friedrich Knauss)
  13. Organization: University of California, San Diego
  14. */
  15. /*
  16.  * this subroutine does all the gritty work- it calculates 
  17.  * what shade each pixel should be. I like recursion.
  18.  */
  19.  
  20. #include <math.h>
  21. #include "rtd.h"
  22. #include "extern.h"
  23. #define time(x) 0
  24.  
  25. /* LEVEL defines number of levels of recursion */
  26. #define LEVEL 5
  27. int debug;
  28. #define dprintf if (debug) printf
  29.  
  30. shade (r, red, green, blue)
  31. struct ray *r;
  32. double *red, *green, *blue;
  33. {   int     i, c,
  34.             refract ();
  35.     struct ray  refr;
  36.     double  rd, gn, blu, tmp;
  37.     double  lght_red, lght_green, lght_blue,
  38.             x, y, z,
  39.             l, k,
  40.             dot (), find (), findo ();
  41.     struct vector   new, norm;
  42.     struct mat  trans;
  43.     struct sphere   ss;
  44.  
  45.     if (++level <= LEVEL)
  46.     {    c = -1;
  47.     l = HUGE;
  48.  
  49.     dprintf("LEVEL %d: ", level);
  50.         /* get vector length and xz component for mt() */
  51.     vecl (&r->dir);
  52.     vexzl (&r->dir);
  53.  
  54.         /* make a transform matrix that rotates something in space so
  55.             that the ray will be aligned with the x axis */
  56.  
  57.     mt (&r->dir, &trans);
  58.  
  59.         /* for starters we find out whether we hit anything. */
  60.  
  61.     for (i = 0; i < nob; i++)
  62.     {   ss.rad = bl[i].s.rad;
  63.         sv (&ss.cent, &bl[i].s.cent, &r->org);
  64.         if ((k = find (&trans, &ss)) > 0.0 && k < l)
  65.         {    c = i;
  66.         l = k;
  67.         }
  68.     }
  69.     if (c >= 0.0)         /* WE HIT SOMETHING */
  70.     {   x = l * trans.x.x;
  71.         y = l * trans.x.y;
  72.         z = l * trans.x.z;
  73.         mv (x, y, z, &new);
  74.  
  75.         /* move the new orgin of the ray to the intersection */
  76.  
  77.         av (&refr.org, &new, &r->org);
  78.         av (&r->org, &new, &r->org);
  79.         mv (r->dir.x, r->dir.y, r->dir.z, &refr.dir);
  80.  
  81.         /* get a normal vector for the intersection point */
  82.  
  83.         sv (&norm, &r->org, &bl[c].s.cent);
  84.         vecl (&norm); 
  85.  
  86.         /* ambient lighting */
  87.  
  88.         tmp = 255.0 * bl[c].amb;
  89.         lght_red = tmp * bl[c].red;
  90.         lght_green = tmp * bl[c].green;
  91.         lght_blue = tmp * bl[c].blue;
  92.         dprintf(" ball[%d]", c);
  93.         dprintf(", ambient=%d,%d,%d\n",
  94.         (int)lght_red, (int)lght_green, (int)lght_blue);
  95.  
  96.         /* shaded lighting (diffuse). subroutine shadow is in find.c */
  97.  
  98.         if (bl[c].dif != 0.0)
  99.         {    sv (&new, &ls.cent, &r->org);
  100.         vecl (&new); 
  101.         if ((k = dot (&new, &norm)) > 0.0)
  102.         {   shadow (&r->org, &rd, &gn, &blu);
  103.             dprintf("diffuse = %d, %d, %d\n",(int)rd,(int)gn,(int)blu);
  104.             tmp = bl[c].dif * k / (new.l * norm.l);
  105.             lght_red   += tmp * rd * bl[c].red;
  106.             lght_green += tmp * rd * bl[c].green;
  107.             lght_blue  += tmp * rd * bl[c].blue;
  108.         }   }
  109.  
  110.         /*reflection... easy */
  111.  
  112.         if (bl[c].rfl != 0.0)
  113.         {    vecl (&norm); 
  114.           /* make the normal unit length */
  115.         scamult ((1.0 / norm.l), &norm);
  116.         /* get the length of the ray's component in the normal direction */
  117.          x = 2.0 * dot (&norm, &r->dir);
  118.         scamult (x, &norm);
  119.         /* subtract double the normal component- !reflection! */
  120.         sv (&r->dir, &r->dir, &norm);
  121.         shade (r, &rd, &gn, &blu);
  122.         dprintf("reflection = %d, %d, %d, tmp=%d\n", 
  123.             (int)rd, (int)gn, (int)blu, (int)tmp);
  124.         tmp = bl[c].rfl;
  125.         lght_red   += tmp * rd;
  126.         lght_green += tmp * gn;
  127.         lght_blue  += tmp * blu;
  128.         }
  129.  
  130.         /* refraction. this is ugly, which is why I choose to deal with
  131.            it in it's own subroutine which comes after this one */
  132.  
  133.         if (bl[c].rfr != 0.0)
  134.         {    dprintf(" refraction\n");
  135.             refract (&refr, &bl[c], &rd, &gn, &blu);
  136.         tmp = bl[c].rfr;
  137.         dprintf("refraction = %d, %d, %d\n",(int)rd,(int)gn,(int)blu);
  138.         lght_red   += tmp * rd;
  139.         lght_green += tmp * gn;
  140.         lght_blue  += tmp * blu;
  141.     }   }
  142.     else             /* hit no objects... */
  143.     {   if ((r->dir.y) < 0.0) /* crosses floor */
  144.         {    z = -(r->org.y) / (r->dir.y);
  145.         (r->org.x) += z * (r->dir.x);
  146.         (r->org.z) += z * (r->dir.z);
  147.         (r->org.y) = 0.0;
  148.         dprintf("floor (%d, %d): ", (int)r->org.x, (int)r->org.z);
  149.         if (  ((int) ((r->org.x) / 9.0) % 8 == 0) 
  150.            || ((int) ((r->org.z) / 9.0) % 8 == 0))
  151.         {   lght_red = lght_green = lght_blue = 0.0;
  152.             dprintf("black. 0,0,0\n"); 
  153.         }        /* this is for texture, grid on the ground */
  154.         else         /* get shading for the squares... */
  155.         {   sv (&new, &ls.cent, &r->org);
  156.             vecl (&new); 
  157.             shadow (&r->org, &rd, &gn, &blu);
  158.             tmp = 0.6 * new.y / new.l;
  159.             lght_blue   = tmp * blu + 100.0;     /* tile pattern: */
  160.             if ((int)r->org.x/72 & (int)r->org.z/72 & 0x15)
  161.             {    lght_red = lght_green = 0.0;        /* blue */
  162.                 dprintf("blue. %d, %d, %d\n", 
  163.                 (int)lght_red, (int)lght_green, (int)lght_blue);
  164.             }
  165.             else
  166.             {    lght_red   = tmp * rd + 100.0;        /* white */
  167.             lght_green = tmp * gn + 100.0;
  168.             dprintf("white. %d,%d,%d\n", 
  169.                 (int)lght_red, (int)lght_green, (int)lght_blue);
  170.         }    }   }
  171.         else    /* didn't hit ground... sky */
  172.         {    lght_red = lght_green = lght_blue = 0.0;
  173.         dprintf("sky. %d,%d,%d\n", 
  174.             (int)lght_red, (int)lght_green, (int)lght_blue);
  175.         }
  176.         dprintf("lght_= %d,%d,%d\n", 
  177.         (int)lght_red, (int)lght_green, (int)lght_blue);
  178.     }    }   
  179.     /* to many levels return 0 cause it shouldn't matter */
  180.     else
  181.     {    lght_red = lght_green = lght_blue = 0.0;
  182.     dprintf(">5 levels. 0, 0, 0\n");
  183.     }
  184.     level--;
  185.  
  186.     if (lght_red < 0.0)     lght_red = 0.0;
  187.     if (lght_red > 255.0)    lght_red = 255.0;
  188.  
  189.     if (lght_green < 0.0)     lght_green = 0.0;
  190.     if (lght_green > 255.0)    lght_green = 255.0;
  191.  
  192.     if (lght_blue < 0.0)     lght_blue = 0.0;
  193.     if (lght_blue > 255.0)    lght_blue = 255.0;
  194.  
  195.     *red = lght_red;
  196.     *green = lght_green;
  197.     *blue = lght_blue;
  198.  
  199.     dprintf("returned: %d, %d, %d\n", (int)*red, (int)*green, (int)*blue);
  200. }
  201.  
  202. int     refract (r, bll, red, green, blue)
  203. struct ray *r;
  204. struct ball *bll;
  205. double *red, *green, *blue;
  206. {
  207.     struct vector   new, norm;
  208.     struct mat  trans;
  209.     double  l,
  210.             refk ();
  211.     struct sphere   ss;
  212.  
  213.     sv (&norm, &r->org, &bll->s.cent);
  214.     vecl (&norm);
  215.     vecl (&r->dir);
  216.  
  217.     /* get the addition factor for the normal */
  218.  
  219.     scamult (refk (&norm, &r->dir, bll->ior), &norm);
  220.     av (&r->dir, &r->dir, &norm);
  221.  
  222.     /* find the point where the ray leaves the sphere. just like shade. */
  223.  
  224.     vexzl (&r->dir);
  225.     vecl (&r->dir);
  226.     mt (&r->dir, &trans);
  227.     ss.rad = bll->s.rad;
  228.     sv (&ss.cent, &bll->s.cent, &r->org);
  229.     l = findo (&trans, &ss);
  230.     mv (l * trans.x.x, l * trans.x.y, l * trans.x.z, &new);
  231.     av (&r->org, &r->org, &new);
  232.  
  233.     /* redirect the ray and continue tracing */
  234.  
  235.     sv (&norm, &r->org, &bll->s.cent);
  236.     vecl (&norm);
  237.     vecl (&r->dir);
  238.     scamult (refk (&norm, &r->dir, 1.0 / bll->ior), &norm);
  239.     av (&r->dir, &r->dir, &norm);
  240.  
  241.     shade (r, red, green, blue);
  242. }
  243.  
  244.  
  245. double  refk (nrm, in, ior)
  246. struct vector  *nrm, *in;
  247. double  ior;
  248. {   double  dt, ln, li, ret;
  249.  
  250.     dt = dot (nrm, in);
  251.     ln = nrm->x * nrm->x + nrm->y * nrm->y + nrm->z * nrm->z;
  252.     li = in->x * in->x + in->y * in->y + in->z * in->z;
  253.     ret = dt * dt - ln * li * (1 - ior);
  254.     if (ret < 0.0)
  255.     ret = 0.0;
  256.     if (dt < 0)
  257.     ret = (-dt - sqrt (ret)) / ln;
  258.     else
  259.     ret = (-dt + sqrt (ret)) / ln;
  260.     return (ret);
  261. }
  262.  
  263. printv(s, v)
  264. char *s;
  265. struct vector *v;
  266. {    printf("%s.x = %f, .y = %f, .z = %f\n", s, v->x, v->y, v->z);
  267. }
  268.