home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2214 / shade.c < prev   
Encoding:
C/C++ Source or Header  |  1990-12-28  |  5.1 KB  |  260 lines

  1. /*
  2.  * shade.c - This module contains the illumination model.
  3.  * 
  4.  * Copyright (C) 1990, Kory Hamzeh
  5.  */
  6.  
  7. #include <stdio.h>
  8. #include <math.h>
  9.  
  10. #include "rt.h"
  11. #include "externs.h"
  12.  
  13.  
  14.  
  15. COLOR           Illuminate(), Trace_a_ray();
  16.  
  17. /*
  18.  * Illuminate()
  19.  * 
  20.  * Apply the proper illumination model to determine the color of the object at
  21.  * the given point.
  22.  */
  23.  
  24.  
  25. COLOR 
  26. Illuminate(inter, ray, ip, n)
  27. INTERSECT      *inter;
  28. RAY            *ray;
  29. VECTOR         *ip;
  30. int             n;        /* Level of recursion */
  31. {
  32.     COLOR           col, c;
  33.     OBJECT         *obj, *scache;
  34.     SURFACE        *surf, *surf2;
  35.     VECTOR          normal, l_dir, h, refl;
  36.     INTERSECT       test_inter;
  37.     RAY             ray2;
  38.     double          t, l_dist, incident, spec;
  39.     double          n1, n2, intensity;
  40.     int             in_shadow, l;
  41.  
  42.     /*
  43.      * If the maximum level of recusion has been reached, then return
  44.      * peacefully.
  45.      */
  46.  
  47.     if (n >= MAX_LEVEL)
  48.     {
  49.         col.r = col.g = col.b = 0;
  50.         return (col);
  51.     }
  52.  
  53.     obj = inter->obj;
  54.     surf = obj->surf;
  55.     t = inter->t;
  56.  
  57.     /* get the surface normal */
  58.     (*obj->normal) (obj->obj, ray, ip, &normal);
  59.  
  60.     /* first set the color to ambient color */
  61.     col = surf->c_ambient;
  62.  
  63.     /* foreach light source */
  64.     for (l = 0; l < nlights; l++)
  65.     {
  66.         /*
  67.          * get the vector from the light source to the intersection
  68.          * point
  69.          */
  70.         VecSub(lights[l]->pos, *ip, l_dir);
  71.  
  72.         intensity = lights[l]->intensity;
  73.  
  74.         /*
  75.          * Calculate the angle of incident.
  76.          */
  77.  
  78.         if (VecDot(normal, l_dir) >= 0)
  79.         {
  80.             /*
  81.              * Test to see if any object is casting a shadow on
  82.              * this point by firing a test ray from the light
  83.              * source to this spot. If there is a hit and the
  84.              * object is not the current object, then a shadow is
  85.              * casted. In such a case, we don't need to calculate
  86.              * the diffuse color.
  87.              */
  88.  
  89.             l_dist = VecNormalize(&l_dir);
  90.             in_shadow = 0;
  91.             if (shadow)
  92.             {
  93.                 ray2.pos = *ip;
  94.                 ray2.dir = l_dir;
  95.                 ++n_shadows;
  96.  
  97.                 /*
  98.                  * If we do have a shadow cache entry for
  99.                  * this light at this level, try that first.
  100.                  * If it hits, then a shadow is casted. If it
  101.                  * doesn't hit, then try all of the other
  102.                  * primitives.
  103.                  */
  104.  
  105.                 if ((scache = lights[l]->cache[n]) != NULL)
  106.                 {
  107.                     if ((*scache->inter) (scache, &ray2, &test_inter) &&
  108.                         inter->obj != test_inter.obj &&
  109.                         test_inter.t < l_dist - MIN_T)
  110.                     {
  111.                         ++n_shadinter;
  112.                         continue;
  113.                     }
  114.                 }
  115.  
  116.                 if (Intersect(&ray2, &test_inter) &&
  117.                     inter->obj != test_inter.obj &&
  118.                     test_inter.t < l_dist - MIN_T)
  119.                 {
  120.                     lights[l]->cache[n] = test_inter.obj;
  121.                     ++n_shadinter;
  122.                     continue;
  123.                 }
  124.                 else
  125.                 {
  126.                     lights[l]->cache[n] = NULL;
  127.                 }
  128.             }
  129.  
  130.             incident = VecDot(normal, l_dir);
  131.             /* calculate the diffuse color */
  132.             col.r += incident * surf->c_diffuse.r * intensity;
  133.             col.g += incident * surf->c_diffuse.g * intensity;
  134.             col.b += incident * surf->c_diffuse.b * intensity;
  135.  
  136.             /*
  137.              * Add some specular highlights. This is accomplished
  138.              * by calculating the angle of reflection and getting
  139.              * the dot product of it with the ray direction.
  140.              */
  141.  
  142.             if (surf->spec_width != 0.0)
  143.             {
  144.                 Reflect(&ray->dir, &normal, &ray2.dir);
  145.                 spec = pow(VecDot(l_dir, ray2.dir), surf->spec_width);
  146.  
  147.                 col.r += spec * surf->c_specular.r * intensity;
  148.                 col.g += spec * surf->c_specular.g * intensity;
  149.                 col.b += spec * surf->c_specular.b * intensity;
  150.             }
  151.         }
  152.     }
  153.  
  154.     /*
  155.      * If reflections are enabled, calculat the reflection color.
  156.      */
  157.  
  158.     if (reflect && surf->p_reflect != 0.0)
  159.     {
  160.         ++n_reflect;
  161.         ray2.pos = *ip;
  162.         Reflect(&ray->dir, &normal, &ray2.dir);
  163.  
  164.         /*
  165.          * Send out reflection ray.
  166.          */
  167.  
  168.         c = Trace_a_ray(&ray2, n + 1);
  169.         col.r += c.r * surf->p_reflect * surf->c_reflect.r;
  170.         col.g += c.g * surf->p_reflect * surf->c_reflect.g;
  171.         col.b += c.b * surf->p_reflect * surf->c_reflect.b;
  172.     }
  173.  
  174.     /*
  175.      * If refraction are enable, calculate the refracted color.
  176.      */
  177.  
  178.     if (refract && surf->p_refract != 0.0)
  179.     {
  180.         /*
  181.          * determine the this ray is inside or outside the object so
  182.          * that we can determine the proper index of refraction to
  183.          * use.
  184.          */
  185.  
  186.         if (inter->inside)
  187.         {
  188.             n1 = surf->i_refraction;
  189.             n2 = 1.0;
  190.         }
  191.         else
  192.         {
  193.             n1 = 1.0;
  194.             n2 = surf->i_refraction;
  195.         }
  196.  
  197.         ray2.pos = *ip;
  198.         if (Refract(n1, n2, &ray->dir, &normal, &ray2.dir))
  199.         {
  200.             ++n_refract;
  201.             c = Trace_a_ray(&ray2, n + 1);
  202.  
  203.             col.r += c.r * surf->p_refract * surf->c_refract.r;
  204.             col.g += c.g * surf->p_refract * surf->c_refract.g;
  205.             col.b += c.b * surf->p_refract * surf->c_refract.b;
  206.         }
  207.     }
  208.  
  209.     /* return that color */
  210.     return (col);
  211.  
  212. }
  213.  
  214.  
  215. /*
  216.  * Reflect()
  217.  * 
  218.  * Calculate the reflected vector.
  219.  */
  220.  
  221. Reflect(v, norm, refl)
  222. VECTOR         *v;
  223. VECTOR         *norm;
  224. VECTOR         *refl;
  225. {
  226.     double          nl;
  227.  
  228.     nl = 1 / fabs(VecDot(*v, *norm));
  229.  
  230.     VecComb(nl, *v, 2.0, *norm, *refl);
  231.     VecNormalize(refl);
  232. }
  233.  
  234. /*
  235.  * Refract()
  236.  * 
  237.  * Calculate the refraction vector.
  238.  */
  239.  
  240. Refract(n1, n2, i, n, r)
  241. double          n1;
  242. double          n2;
  243. VECTOR         *i;
  244. VECTOR         *n;
  245. VECTOR         *r;
  246. {
  247.     double          eta, c1, c2, c3;
  248.  
  249.     eta = n1 / n2;
  250.     c1 = -VecDot(*i, *n);
  251.     c2 = 1.0 - eta * eta * (1.0 - (c1 * c1));
  252.     if (c2 < 0.0)
  253.         return (0);    /* total internal reflection */
  254.  
  255.     c3 = (eta * c1) - sqrt(c2);
  256.  
  257.     VecComb(eta, *i, c3, *n, *r);
  258.     return (1);
  259. }
  260.