home *** CD-ROM | disk | FTP | other *** search
/ Resource Library: Graphics / graphics-16000.iso / msdos / raytrace / rayshade / src / spot.c < prev    next >
C/C++ Source or Header  |  1991-07-18  |  3KB  |  160 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.  * $Id: spot.c,v 4.0 91/07/17 14:35:42 kolb Exp Locker: kolb $
  17.  *
  18.  * $Log:    spot.c,v $
  19.  * Revision 4.0  91/07/17  14:35:42  kolb
  20.  * Initial version.
  21.  * 
  22.  */
  23. #include "light.h"
  24. #include "spot.h"
  25.  
  26. static LightMethods *iSpotMethods = NULL;
  27.  
  28. Spotlight *
  29. SpotCreate(from, to, coef, in, out)
  30. Vector *from, *to;
  31. Float coef, in, out;
  32. {
  33.     Spotlight *spot;
  34.  
  35.     spot = (Spotlight *)share_malloc(sizeof(Spotlight));
  36.     spot->pos = *from;
  37.     VecSub(*to, *from, &spot->dir);
  38.     if (VecNormalize(&spot->dir) == 0. || in > out) {
  39.         RLerror(RL_ABORT,"Invalid spotlight specification.\n");
  40.         return (Spotlight *)NULL;
  41.     }
  42.     spot->coef = coef;
  43.     spot->radius = cos(deg2rad(in));
  44.     spot->falloff = cos(deg2rad(out));
  45.  
  46.     return spot;
  47. }
  48.  
  49. LightMethods *
  50. SpotMethods()
  51. {
  52.     if (iSpotMethods == (LightMethods *)NULL) {
  53.         iSpotMethods = LightMethodsCreate();
  54.         iSpotMethods->intens = SpotIntens;
  55.         iSpotMethods->dir = SpotDirection;
  56.     }
  57.     return iSpotMethods;
  58. }
  59.  
  60. /*
  61.  * Calculate intensity ('color') of light reaching 'pos' from light 'lp'.
  62.  * The spotlight is 'dist' units from 'pos' along 'dir'.
  63.  *
  64.  * Returns TRUE if non-zero illumination, FALSE otherwise.
  65.  */
  66. int
  67. SpotIntens(spot, lcolor, cache, ray, dist, noshadow, color)
  68. Spotlight *spot;
  69. ShadowCache *cache;
  70. Ray *ray;
  71. Color *lcolor, *color;
  72. int noshadow;
  73. Float dist;
  74. {
  75.     Float atten;
  76.     extern Float SpotAtten();
  77.  
  78.     /*
  79.      * Compute spotlight color
  80.      */
  81.     atten = SpotAtten(spot, &ray->dir);
  82.     /*
  83.      * If outside of spot, return FALSE.
  84.      */
  85.     if (atten == 0.)
  86.         return FALSE;
  87.     if (Shadowed(color, lcolor, cache, ray, dist, noshadow))
  88.         return FALSE;
  89.     ColorScale(atten, *color, color);
  90.     return TRUE;
  91. }
  92.  
  93. /*
  94.  * Compute intensity of spotlight along 'dir'.
  95.  */
  96. Float
  97. SpotAtten(lp, dir)
  98. Spotlight *lp;
  99. Vector *dir;
  100. {
  101.     Float costheta, atten;
  102.     extern Float rampup();
  103.  
  104.     costheta = -dotp(dir, &lp->dir);
  105.     /*
  106.      * Behind spotlight.
  107.      */
  108.     if (costheta <= 0.)
  109.         return 0.;
  110.     /*
  111.      * Intensity is the product of costheta raised to lp->coef and
  112.      * a function that smoothly interpolates from 0 at
  113.      * costheta=lp->falloff to 1 at costheta=lp->radius.
  114.      */
  115.     atten = pow(costheta, lp->coef);
  116.     if (lp->radius > 0.)
  117.         atten *= rampup(lp->falloff, lp->radius, costheta);
  118.     return atten;
  119. }
  120.  
  121. /*
  122.  * Cubic interpolation between 0 at left and 1 at right, sampled at 'at'
  123.  * It is assumed that right >= left.
  124.  */
  125. Float
  126. rampup(left, right, at)
  127. Float left, right, at;
  128. {
  129.     if (at < left)
  130.         return 0.;
  131.     else if (at > right)
  132.         return 1.;
  133.  
  134.     if (right == left)
  135.         return 0.;
  136.  
  137.     at = (at - left) / (right - left);
  138.     return (3 - 2*at)*at*at;
  139. }
  140.  
  141. void
  142. SpotDirection(lp, pos, dir, dist)
  143. Spotlight *lp;
  144. Vector *pos, *dir;
  145. Float *dist;
  146. {
  147.     /*
  148.      * Calculate dir from position to center of light source.
  149.      */
  150.     VecSub(lp->pos, *pos, dir);
  151.     *dist = VecNormalize(dir);
  152. }
  153.  
  154. SpotMethodRegister(meth)
  155. UserMethodType meth;
  156. {
  157.     if (iSpotMethods)
  158.         iSpotMethods->user = meth;
  159. }
  160.