home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / GRAPHICS / rayshade.lzh / light.c < prev    next >
Text File  |  1990-05-08  |  4KB  |  160 lines

  1. /*
  2.  * light.c
  3.  *
  4.  * Copyright (C) 1989, Craig E. Kolb
  5.  *
  6.  * This software may be freely copied, modified, and redistributed,
  7.  * provided that this copyright notice is preserved on all copies.
  8.  *
  9.  * There is no warranty or other guarantee of fitness for this software,
  10.  * it is provided solely .  Bug reports or fixes may be sent
  11.  * to the author, who may or may not act on them as he desires.
  12.  *
  13.  * You may not include this software in a program or other software product
  14.  * without supplying the source, or without informing the end-user that the
  15.  * source is available for no extra charge.
  16.  *
  17.  * If you modify this software, you should include a notice giving the
  18.  * name of the person performing the modification, the date of modification,
  19.  * and the reason for such modification.
  20.  *
  21.  * $Id: light.c,v 3.0.1.1 90/03/07 21:28:21 craig Exp $
  22.  *
  23.  * $Log:    light.c,v $
  24.  * Revision 3.0.1.1  90/03/07  21:28:21  craig
  25.  * patch4: Removed LightCoordSys().
  26.  * 
  27.  * Revision 3.0  89/10/27  16:17:22  craig
  28.  * Baseline for first official release.
  29.  * 
  30.  */
  31. #include <stdio.h>
  32. #include <math.h>
  33. #include "typedefs.h"
  34. #include "funcdefs.h"
  35. #include "constants.h"
  36.  
  37. int    nlight;            /* # of lights defined */
  38. int    NoShadows;        /* Don't trace shadow rays */
  39. int    Cache = TRUE;        /* Use shadow-caching */
  40. int    ClearShadows;        /* Shadow rays pass through transp. objects */
  41. Light    light[LIGHTS];        /* array of lights */
  42. double    lightdist;        /* distance to light */
  43. unsigned long CacheWorked, CacheFailed, ShadowHits;
  44. /*
  45.  * Calculate ray from position to light # lnum.
  46.  */
  47. lightray(lp, objpos, lray)
  48. Light *lp;
  49. Vector *objpos, *lray;
  50. {
  51.     if(lp->type == DIRECTIONAL) {
  52.         /*
  53.          * Directional sources only have direction.
  54.          */
  55.         *lray = lp->pos;
  56.         lightdist = FAR_AWAY;
  57.     } else {
  58.         /*
  59.          * Calculate ray from position to center of
  60.          * light source.
  61.          */
  62.         vecsub(lp->pos, *objpos, lray);
  63.         lightdist = normalize(lray);
  64.     }
  65. }
  66.  
  67. /*
  68.  * Trace ray from point of intersection to a light.  If an intersection
  69.  * occurs at a distance less than "lightdist" (the distance to the
  70.  * light source), then the point is in shadow, and 0 is returned.
  71.  * Otherwise, the brightness (color) of the light is returned.  This
  72.  * color may be modulated by any translucent objects which fall between
  73.  * the point of intersection and the light source.
  74.  */
  75. inshadow(result, source, lp, pos, ray)
  76. Color *result;
  77. Primitive *source;
  78. Light *lp;
  79. Vector *pos, *ray;
  80. {
  81.     double s;
  82.     Ray tmpray, tray;
  83.     HitInfo hitinfo;
  84.     double atten, totaldist, TransformRay();
  85.     extern int level;
  86.     extern unsigned long ShadowRays;
  87.     extern double TraceRay();
  88.  
  89.     if (NoShadows) {
  90.         *result = lp->color;
  91.         return FALSE;
  92.     }
  93.  
  94.     ShadowRays++;
  95.     tmpray.pos = *pos;
  96.     tmpray.dir = *ray;    /* Medium not needed. */
  97.     tmpray.shadow = TRUE;
  98.     hitinfo.totaltrans = &lp->trans[level];
  99.  
  100.     /*
  101.      * Check shadow cache if necessary.  (The following implies
  102.      * ... && Cache)
  103.      */
  104.     if (lp->cache[level]) {
  105.         tray = tmpray;
  106.         s = TransformRay(&tray, &lp->trans[level]);
  107.         s = int_primitive(lp->cache[level], source, &tray, &hitinfo)/s;
  108.         if (s > EPSILON && s < lightdist) {
  109.             CacheWorked++;
  110.             return TRUE;
  111.         }
  112.         CacheFailed++;
  113.         lp->cache[level] = (Primitive *)0;
  114.     }
  115.  
  116.     if (Cache)
  117.         init_trans(hitinfo.totaltrans);
  118.  
  119.     s = TraceRay(source, &tmpray, &hitinfo);
  120.  
  121.     if (s < EPSILON || s > lightdist) {
  122.         *result = lp->color;
  123.         return FALSE;        /* Not in shadow. */
  124.     }
  125.  
  126.     /*
  127.      * Otherwise, we've hit something.
  128.      */
  129.     ShadowHits++;
  130.     if (!ClearShadows || hitinfo.surf.transp == 0.) {
  131.         if (Cache)
  132.             lp->cache[level] = hitinfo.prim;
  133.         return TRUE;
  134.     }
  135.     /*
  136.      * We've hit a transparent object.  Attenuate the color
  137.      * of the light source and continue the ray until
  138.      * we hit background or a non-transparent object.
  139.      * Note that this is incorrect if any of the surfaces hit (or
  140.      * DefIndex) have differing indices of refraction.
  141.      */
  142.     atten = 1.;
  143.     totaldist = s;
  144.     do {
  145.         atten *= hitinfo.surf.transp;
  146.         if (atten < EPSILON)
  147.             return TRUE;
  148.         addscaledvec(tmpray.pos, s, tmpray.dir, &tmpray.pos);
  149.         /*
  150.          * Trace ray starting at new origin and in the
  151.          * same direction.
  152.          */
  153.         s = TraceRay(hitinfo.prim, &tmpray, &hitinfo);
  154.         totaldist += s;
  155.     } while (s > EPSILON && totaldist < lightdist);
  156.  
  157.     ScaleColor(atten, lp->color, result);
  158.     return FALSE;
  159. }
  160.