home *** CD-ROM | disk | FTP | other *** search
/ Amiga Tools 3 / Amiga Tools 3.iso / grafik / raytracing / rayshade-4.0.6.3 / libray / liblight / spot.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-09  |  3.4 KB  |  166 lines

  1. /*
  2.  * spot.c
  3.  *
  4.  * Copyright (C) 1989, 1991, Craig E. Kolb
  5.  * All rights reserved.
  6.  *
  7.  * This software may be freely copied, modified, and redistributed
  8.  * provided that this copyright notice is preserved on all copies.
  9.  *
  10.  * You may not distribute this software, in whole or in part, as part of
  11.  * any commercial product without the express consent of the authors.
  12.  *
  13.  * There is no warranty or other guarantee of fitness of this software
  14.  * for any purpose.  It is provided solely "as is".
  15.  *
  16.  * spot.c,v 4.1 1994/08/09 07:57:21 explorer Exp
  17.  *
  18.  * spot.c,v
  19.  * Revision 4.1  1994/08/09  07:57:21  explorer
  20.  * Bump version to 4.1
  21.  *
  22.  * Revision 1.1.1.1  1994/08/08  04:52:04  explorer
  23.  * Initial import.  This is a prerelease of 4.0.6enh3, or 4.1 possibly.
  24.  *
  25.  * Revision 4.0  91/07/17  14:35:42  kolb
  26.  * Initial version.
  27.  * 
  28.  */
  29. #include "light.h"
  30. #include "spot.h"
  31.  
  32. static LightMethods *iSpotMethods = NULL;
  33.  
  34. Spotlight *
  35. SpotCreate(from, to, coef, in, out)
  36. Vector *from, *to;
  37. Float coef, in, out;
  38. {
  39.     Spotlight *spot;
  40.  
  41.     spot = (Spotlight *)share_malloc(sizeof(Spotlight));
  42.     spot->pos = *from;
  43.     VecSub(*to, *from, &spot->dir);
  44.     if (VecNormalize(&spot->dir) == 0. || in > out) {
  45.         RLerror(RL_ABORT,"Invalid spotlight specification.\n");
  46.         return (Spotlight *)NULL;
  47.     }
  48.     spot->coef = coef;
  49.     spot->radius = cos(deg2rad(in));
  50.     spot->falloff = cos(deg2rad(out));
  51.  
  52.     return spot;
  53. }
  54.  
  55. LightMethods *
  56. SpotMethods()
  57. {
  58.     if (iSpotMethods == (LightMethods *)NULL) {
  59.         iSpotMethods = LightMethodsCreate();
  60.         iSpotMethods->intens = SpotIntens;
  61.         iSpotMethods->dir = SpotDirection;
  62.     }
  63.     return iSpotMethods;
  64. }
  65.  
  66. /*
  67.  * Calculate intensity ('color') of light reaching 'pos' from light 'lp'.
  68.  * The spotlight is 'dist' units from 'pos' along 'dir'.
  69.  *
  70.  * Returns TRUE if non-zero illumination, FALSE otherwise.
  71.  */
  72. int
  73. SpotIntens(spot, lcolor, cache, ray, dist, noshadow, color)
  74. Spotlight *spot;
  75. ShadowCache *cache;
  76. Ray *ray;
  77. Color *lcolor, *color;
  78. int noshadow;
  79. Float dist;
  80. {
  81.     Float atten;
  82.     extern Float SpotAtten();
  83.  
  84.     /*
  85.      * Compute spotlight color
  86.      */
  87.     atten = SpotAtten(spot, &ray->dir);
  88.     /*
  89.      * If outside of spot, return FALSE.
  90.      */
  91.     if (atten == 0.)
  92.         return FALSE;
  93.     if (Shadowed(color, lcolor, cache, ray, dist, noshadow))
  94.         return FALSE;
  95.     ColorScale(atten, *color, color);
  96.     return TRUE;
  97. }
  98.  
  99. /*
  100.  * Compute intensity of spotlight along 'dir'.
  101.  */
  102. Float
  103. SpotAtten(lp, dir)
  104. Spotlight *lp;
  105. Vector *dir;
  106. {
  107.     Float costheta, atten;
  108.     extern Float rampup();
  109.  
  110.     costheta = -dotp(dir, &lp->dir);
  111.     /*
  112.      * Behind spotlight.
  113.      */
  114.     if (costheta <= 0.)
  115.         return 0.;
  116.     /*
  117.      * Intensity is the product of costheta raised to lp->coef and
  118.      * a function that smoothly interpolates from 0 at
  119.      * costheta=lp->falloff to 1 at costheta=lp->radius.
  120.      */
  121.     atten = pow(costheta, lp->coef);
  122.     if (lp->radius > 0.)
  123.         atten *= rampup(lp->falloff, lp->radius, costheta);
  124.     return atten;
  125. }
  126.  
  127. /*
  128.  * Cubic interpolation between 0 at left and 1 at right, sampled at 'at'
  129.  * It is assumed that right >= left.
  130.  */
  131. Float
  132. rampup(left, right, at)
  133. Float left, right, at;
  134. {
  135.     if (at < left)
  136.         return 0.;
  137.     else if (at > right)
  138.         return 1.;
  139.  
  140.     if (right == left)
  141.         return 0.;
  142.  
  143.     at = (at - left) / (right - left);
  144.     return (3 - 2*at)*at*at;
  145. }
  146.  
  147. void
  148. SpotDirection(lp, pos, dir, dist)
  149. Spotlight *lp;
  150. Vector *pos, *dir;
  151. Float *dist;
  152. {
  153.     /*
  154.      * Calculate dir from position to center of light source.
  155.      */
  156.     VecSub(lp->pos, *pos, dir);
  157.     *dist = VecNormalize(dir);
  158. }
  159.  
  160. SpotMethodRegister(meth)
  161. UserMethodType meth;
  162. {
  163.     if (iSpotMethods)
  164.         iSpotMethods->user = meth;
  165. }
  166.