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 >
Wrap
Text File
|
1990-05-08
|
4KB
|
160 lines
/*
* light.c
*
* Copyright (C) 1989, Craig E. Kolb
*
* This software may be freely copied, modified, and redistributed,
* provided that this copyright notice is preserved on all copies.
*
* There is no warranty or other guarantee of fitness for this software,
* it is provided solely . Bug reports or fixes may be sent
* to the author, who may or may not act on them as he desires.
*
* You may not include this software in a program or other software product
* without supplying the source, or without informing the end-user that the
* source is available for no extra charge.
*
* If you modify this software, you should include a notice giving the
* name of the person performing the modification, the date of modification,
* and the reason for such modification.
*
* $Id: light.c,v 3.0.1.1 90/03/07 21:28:21 craig Exp $
*
* $Log: light.c,v $
* Revision 3.0.1.1 90/03/07 21:28:21 craig
* patch4: Removed LightCoordSys().
*
* Revision 3.0 89/10/27 16:17:22 craig
* Baseline for first official release.
*
*/
#include <stdio.h>
#include <math.h>
#include "typedefs.h"
#include "funcdefs.h"
#include "constants.h"
int nlight; /* # of lights defined */
int NoShadows; /* Don't trace shadow rays */
int Cache = TRUE; /* Use shadow-caching */
int ClearShadows; /* Shadow rays pass through transp. objects */
Light light[LIGHTS]; /* array of lights */
double lightdist; /* distance to light */
unsigned long CacheWorked, CacheFailed, ShadowHits;
/*
* Calculate ray from position to light # lnum.
*/
lightray(lp, objpos, lray)
Light *lp;
Vector *objpos, *lray;
{
if(lp->type == DIRECTIONAL) {
/*
* Directional sources only have direction.
*/
*lray = lp->pos;
lightdist = FAR_AWAY;
} else {
/*
* Calculate ray from position to center of
* light source.
*/
vecsub(lp->pos, *objpos, lray);
lightdist = normalize(lray);
}
}
/*
* Trace ray from point of intersection to a light. If an intersection
* occurs at a distance less than "lightdist" (the distance to the
* light source), then the point is in shadow, and 0 is returned.
* Otherwise, the brightness (color) of the light is returned. This
* color may be modulated by any translucent objects which fall between
* the point of intersection and the light source.
*/
inshadow(result, source, lp, pos, ray)
Color *result;
Primitive *source;
Light *lp;
Vector *pos, *ray;
{
double s;
Ray tmpray, tray;
HitInfo hitinfo;
double atten, totaldist, TransformRay();
extern int level;
extern unsigned long ShadowRays;
extern double TraceRay();
if (NoShadows) {
*result = lp->color;
return FALSE;
}
ShadowRays++;
tmpray.pos = *pos;
tmpray.dir = *ray; /* Medium not needed. */
tmpray.shadow = TRUE;
hitinfo.totaltrans = &lp->trans[level];
/*
* Check shadow cache if necessary. (The following implies
* ... && Cache)
*/
if (lp->cache[level]) {
tray = tmpray;
s = TransformRay(&tray, &lp->trans[level]);
s = int_primitive(lp->cache[level], source, &tray, &hitinfo)/s;
if (s > EPSILON && s < lightdist) {
CacheWorked++;
return TRUE;
}
CacheFailed++;
lp->cache[level] = (Primitive *)0;
}
if (Cache)
init_trans(hitinfo.totaltrans);
s = TraceRay(source, &tmpray, &hitinfo);
if (s < EPSILON || s > lightdist) {
*result = lp->color;
return FALSE; /* Not in shadow. */
}
/*
* Otherwise, we've hit something.
*/
ShadowHits++;
if (!ClearShadows || hitinfo.surf.transp == 0.) {
if (Cache)
lp->cache[level] = hitinfo.prim;
return TRUE;
}
/*
* We've hit a transparent object. Attenuate the color
* of the light source and continue the ray until
* we hit background or a non-transparent object.
* Note that this is incorrect if any of the surfaces hit (or
* DefIndex) have differing indices of refraction.
*/
atten = 1.;
totaldist = s;
do {
atten *= hitinfo.surf.transp;
if (atten < EPSILON)
return TRUE;
addscaledvec(tmpray.pos, s, tmpray.dir, &tmpray.pos);
/*
* Trace ray starting at new origin and in the
* same direction.
*/
s = TraceRay(hitinfo.prim, &tmpray, &hitinfo);
totaldist += s;
} while (s > EPSILON && totaldist < lightdist);
ScaleColor(atten, lp->color, result);
return FALSE;
}