This is extended.c in view mode; [Download] [Up]
/*
* extended.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$
*
* $Log$
*/
#include "light.h"
#include "libcommon/sampling.h"
#include "extended.h"
static LightMethods *iExtendedMethods = NULL;
Extended *
ExtendedCreate(r, pos)
Float r;
Vector *pos;
{
Extended *e;
e = (Extended *)share_malloc(sizeof(Extended));
e->pos = *pos;
e->radius = r;
return e;
}
LightMethods *
ExtendedMethods()
{
if (iExtendedMethods == (LightMethods *)NULL) {
iExtendedMethods = LightMethodsCreate();
iExtendedMethods->intens = ExtendedIntens;
iExtendedMethods->dir = ExtendedDirection;
}
return iExtendedMethods;
}
/*
* Compute intensity ('color') of extended light source 'lp' from 'pos'.
*/
static int
ExtendedIntens(lp, lcolor, cache, ray, dist, noshadow, color)
Extended *lp;
Color *lcolor, *color;
ShadowCache *cache;
Ray *ray;
Float dist;
int noshadow;
{
int uSample, vSample, islit;
Float jit, vbase, ubase, vpos, upos, lightdist;
Color newcol;
Ray newray;
Vector Uaxis, Vaxis, ldir;
if (noshadow) {
*color = *lcolor;
return TRUE;
}
newray = *ray;
/*
* Determinte two orthoganal vectors that lay in the plane
* whose normal is defined by the vector from the center
* of the light source to the point of intersection and
* passes through the center of the light source.
*/
VecSub(lp->pos, ray->pos, &ldir);
VecCoordSys(&ldir, &Uaxis, &Vaxis);
jit = 2. * lp->radius * Sampling.spacing;
/*
* If sample # is >= 0, then take that numbered sample
* of the disc.
*/
if (ray->sample >= 0) {
/*
* Sample a single point, determined by SampleNumber,
* on the extended source.
*/
vpos = -lp->radius + (ray->sample % Sampling.sidesamples)*jit;
upos = -lp->radius + (ray->sample / Sampling.sidesamples)*jit;
vpos += nrand() * jit;
upos += nrand() * jit;
VecComb(upos, Uaxis, vpos, Vaxis, &newray.dir);
VecAdd(ldir, newray.dir, &newray.dir);
lightdist = VecNormalize(&newray.dir);
return !Shadowed(color, lcolor, cache, &newray,
lightdist, noshadow);
}
/*
* Else have to sample the entire disc using
* Sampling.totsamples samples.
*/
color->r = color->g = color->b = 0.;
islit = FALSE;
/*
* Sample Samples.totsamples points arranged in a square lying on the
* plane calculated above. The size of the square is equal to
* the diameter of the light source. We sample the square at equal
* intervals in the U and V direction, with 'jitter'.
*/
ubase = -lp->radius;
for (uSample = 0; uSample < Sampling.sidesamples;
uSample++, ubase += jit) {
vbase = -lp->radius;
for (vSample = 0; vSample < Sampling.sidesamples;
vSample++, vbase += jit) {
vpos = vbase + nrand() * jit;
upos = ubase + nrand() * jit;
VecComb(upos, Uaxis, vpos, Vaxis, &newray.dir);
VecAdd(ldir, newray.dir, &newray.dir);
lightdist = VecNormalize(&newray.dir);
if (!Shadowed(&newcol, lcolor, cache, &newray,
lightdist, noshadow)) {
islit = TRUE;
color->r += newcol.r;
color->g += newcol.g;
color->b += newcol.b;
}
}
}
ColorScale(Sampling.weight, *color, color);
return islit;
}
void
ExtendedDirection(lp, pos, dir, dist)
Extended *lp;
Vector *pos, *dir;
Float *dist;
{
/*
* Calculate dir from position to center of
* light source.
*/
VecSub(lp->pos, *pos, dir);
*dist = VecNormalize(dir);
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.