home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Resource Library: Graphics
/
graphics-16000.iso
/
msdos
/
raytrace
/
rayshade
/
src
/
spot.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-07-18
|
3KB
|
160 lines
/*
* spot.c
*
* Copyright (C) 1989, 1991, Craig E. Kolb
* All rights reserved.
*
* This software may be freely copied, modified, and redistributed
* provided that this copyright notice is preserved on all copies.
*
* You may not distribute this software, in whole or in part, as part of
* any commercial product without the express consent of the authors.
*
* There is no warranty or other guarantee of fitness of this software
* for any purpose. It is provided solely "as is".
*
* $Id: spot.c,v 4.0 91/07/17 14:35:42 kolb Exp Locker: kolb $
*
* $Log: spot.c,v $
* Revision 4.0 91/07/17 14:35:42 kolb
* Initial version.
*
*/
#include "light.h"
#include "spot.h"
static LightMethods *iSpotMethods = NULL;
Spotlight *
SpotCreate(from, to, coef, in, out)
Vector *from, *to;
Float coef, in, out;
{
Spotlight *spot;
spot = (Spotlight *)share_malloc(sizeof(Spotlight));
spot->pos = *from;
VecSub(*to, *from, &spot->dir);
if (VecNormalize(&spot->dir) == 0. || in > out) {
RLerror(RL_ABORT,"Invalid spotlight specification.\n");
return (Spotlight *)NULL;
}
spot->coef = coef;
spot->radius = cos(deg2rad(in));
spot->falloff = cos(deg2rad(out));
return spot;
}
LightMethods *
SpotMethods()
{
if (iSpotMethods == (LightMethods *)NULL) {
iSpotMethods = LightMethodsCreate();
iSpotMethods->intens = SpotIntens;
iSpotMethods->dir = SpotDirection;
}
return iSpotMethods;
}
/*
* Calculate intensity ('color') of light reaching 'pos' from light 'lp'.
* The spotlight is 'dist' units from 'pos' along 'dir'.
*
* Returns TRUE if non-zero illumination, FALSE otherwise.
*/
int
SpotIntens(spot, lcolor, cache, ray, dist, noshadow, color)
Spotlight *spot;
ShadowCache *cache;
Ray *ray;
Color *lcolor, *color;
int noshadow;
Float dist;
{
Float atten;
extern Float SpotAtten();
/*
* Compute spotlight color
*/
atten = SpotAtten(spot, &ray->dir);
/*
* If outside of spot, return FALSE.
*/
if (atten == 0.)
return FALSE;
if (Shadowed(color, lcolor, cache, ray, dist, noshadow))
return FALSE;
ColorScale(atten, *color, color);
return TRUE;
}
/*
* Compute intensity of spotlight along 'dir'.
*/
Float
SpotAtten(lp, dir)
Spotlight *lp;
Vector *dir;
{
Float costheta, atten;
extern Float rampup();
costheta = -dotp(dir, &lp->dir);
/*
* Behind spotlight.
*/
if (costheta <= 0.)
return 0.;
/*
* Intensity is the product of costheta raised to lp->coef and
* a function that smoothly interpolates from 0 at
* costheta=lp->falloff to 1 at costheta=lp->radius.
*/
atten = pow(costheta, lp->coef);
if (lp->radius > 0.)
atten *= rampup(lp->falloff, lp->radius, costheta);
return atten;
}
/*
* Cubic interpolation between 0 at left and 1 at right, sampled at 'at'
* It is assumed that right >= left.
*/
Float
rampup(left, right, at)
Float left, right, at;
{
if (at < left)
return 0.;
else if (at > right)
return 1.;
if (right == left)
return 0.;
at = (at - left) / (right - left);
return (3 - 2*at)*at*at;
}
void
SpotDirection(lp, pos, dir, dist)
Spotlight *lp;
Vector *pos, *dir;
Float *dist;
{
/*
* Calculate dir from position to center of light source.
*/
VecSub(lp->pos, *pos, dir);
*dist = VecNormalize(dir);
}
SpotMethodRegister(meth)
UserMethodType meth;
{
if (iSpotMethods)
iSpotMethods->user = meth;
}