|
From: Roger H. <rog...@mi...> - 2008-12-19 13:05:16
|
Hi,
To fix the problem with spot lights:
In LibLight/spot.h
replace the lines:
#define LightSpotCreate(c,f,t,p,i,o) LightCreate( \
(LightRef)SpotCreate(f,t,p,i,o), SpotMethods(), c)
typedef struct {
Vector pos, dir;
Float coef, radius, falloff;
} Spotlight;
extern Spotlight *
SpotCreate(Vector *from,Vector *to,Float coef,Float in,Float out);
with:
#define LightSpotCreate(c,f,t,i,o,at,fo) LightCreate( \
(LightRef)SpotCreate(f,t,i,o,at,fo), SpotMethods(), c)
typedef struct {
Vector pos, dir;
Float hotAngle ;
Float outerAngle ;
Float cosHotAngle ;
Float cosOuterAngle ;
int attenuation ;
int fallOff ;
} Spotlight;
extern Spotlight *
SpotCreate ( Vector* from , Vector* dir , Float hotAngle , Float
outerAngle , int attenuation , int fallOff ) ;
Then in LibLight/spot.cpp replace:
static Float rampup(Float left,Float right,Float at);
static Float SpotAtten(Spotlight *lp, Vector *dir);
Spotlight *
SpotCreate(
Vector *from,
Vector *to,
Float coef,
Float in,
Float 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;
}
with:
static Float SpotAtten(Spotlight *lp, Vector *dir);
Spotlight *
SpotCreate(
Vector *from,
Vector *dir,
Float hotAngle,
Float outerAngle ,
int attenuation ,
int fallOff )
{
Spotlight *spot;
spot = (Spotlight *)share_malloc(sizeof(Spotlight));
spot->pos = *from;
spot->dir.x = dir->x ;
spot->dir.y = dir->y ;
spot->dir.z = dir->z ;
if (VecNormalize(&spot->dir) == 0. || hotAngle > outerAngle ) {
RLerror(RL_ABORT,"Invalid spotlight specification.\n");
return (Spotlight *)NULL;
}
spot->hotAngle = hotAngle ;
spot->outerAngle = outerAngle ;
spot->cosHotAngle = cos ( hotAngle ) ;
spot->cosOuterAngle = cos ( outerAngle ) ;
spot->attenuation = attenuation ;
spot->fallOff = fallOff ;
return spot;
}
and further down the same file replace:
/*
* Compute intensity of spotlight along 'dir'.
*/
static Float
SpotAtten(
Spotlight *lp,
Vector *dir)
{
Float costheta, atten;
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(Float left,Float right,Float 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;
}
with:
#define kQ3PiOver2 ((Float)
(3.1415926535898 / 2.0))
static const float eMinus1 = exp ( 1.0f ) - 1.0f ;
/*
* Compute intensity of spotlight along 'dir'.
*/
static Float
SpotAtten(
Spotlight *lp,
Vector *dir)
{
Float costheta, atten;
costheta = -dotp(dir, &lp->dir);
/*
* Behind spotlight.
*/
if (costheta <= 0.)
return 0.;
if ( costheta < lp->cosOuterAngle )
return 0.0 ;
atten = costheta ;
if (lp->cosHotAngle > 0.) // What is this all about ?
{
Float fallOffMultiplier = 1.0 ;
if ( lp->fallOff == 1 /*kQ3FallOffTypeLinear*/ )
{
if ( costheta < lp->cosHotAngle )
{
Float angle = acos ( costheta ) ;
fallOffMultiplier = ( lp->outerAngle - angle ) / ( lp->outerAngle
- lp->hotAngle ) ;
}
}
else
if ( lp->fallOff == 2/*kQ3FallOffTypeExponential*/ )
{
if ( costheta < lp->cosHotAngle )
{
Float angle = acos ( costheta ) ;
fallOffMultiplier = ( exp ( ( lp->outerAngle - angle ) / ( lp-
>outerAngle - lp->hotAngle ) ) - 1 ) / eMinus1 ;
}
}
else
if ( lp->fallOff == 3/*kQ3FallOffTypeCosine*/ )
{
if ( costheta < lp->cosHotAngle )
{
Float angle = acos ( costheta ) ;
fallOffMultiplier = cos ( ( angle - lp->hotAngle ) * kQ3PiOver2 /
( lp->outerAngle - lp->hotAngle ) ) ;
}
}
/*
This may be required some time but presently neither the attenuation
nor the world pixel position are available. Maybe it should go
somewhere else in the calculations
if ( lp->attenuation != kQ3AttenuationTypeNone )
{
switch ( lp->attenuation )
{
case kQ3AttenuationTypeInverseDistance :
{
fallOffMultiplier *= 1.0f / Distance ( pixelWorldPos - lp-
>pos ) ;
break ;
}
case kQ3AttenuationTypeInverseDistanceSquared :
{
fallOffMultiplier *= 1.0f / DistanceSquared ( pixelWorldPos -
lp->pos ) ;
break ;
}
}
}
*/
atten *= fallOffMultiplier ;
}
return atten;
}
Nearly there. In RT_Light.cpp, in subroutine RT_AddSpotLight replace:
theVector.x = -inDirection->x;
theVector.y = -inDirection->y;
theVector.z = -inDirection->z;
switch(inFallOffType)
{
case kQ3FallOffTypeNone:
theCoeff = 0.0f;
break;
case kQ3FallOffTypeLinear:
theCoeff = 1.0f;
break;
case kQ3FallOffTypeExponential:
theCoeff = 0.8f;
break;
case kQ3FallOffTypeCosine:
theCoeff = 2.0f;
break;
}
theLight = LightSpotCreate(&theColor,
&thePos,
&theVector,
theCoeff,
Q3Math_RadiansToDegrees(hotAngle),
Q3Math_RadiansToDegrees(outerAngle));
with:
theVector.x = inDirection->x;
theVector.y = inDirection->y;
theVector.z = inDirection->z;
theLight = LightSpotCreate(&theColor,
&thePos,
&theVector,
hotAngle ,
outerAngle ,
kQ3AttenuationTypeNone ,
inFallOffType ) ; // Use kQ3AttenuationTypeNone until we find we
need thee proper value
Thats it.
I tried including the file which defines kQ3FallOffTypeExponential etc
but had problems with multiply defined names, hence the slightly
questionable way I've used constants 1,2 and 3 in SpotAtten.
Roger.
|