diff options
-rw-r--r-- | src/cgame/cg_ents.c | 202 | ||||
-rw-r--r-- | src/cgame/cg_local.h | 8 |
2 files changed, 113 insertions, 97 deletions
diff --git a/src/cgame/cg_ents.c b/src/cgame/cg_ents.c index 6283e7ff..5c7c6cab 100644 --- a/src/cgame/cg_ents.c +++ b/src/cgame/cg_ents.c @@ -542,7 +542,7 @@ static void CG_LightFlare( centity_t *cent ) float len; trace_t tr; float maxAngle; - vec3_t mins, maxs, dir, start, end; + vec3_t mins, maxs, start, end; float srcRadius, srLocal, ratio = 1.0f; es = ¢->currentState; @@ -565,13 +565,6 @@ static void CG_LightFlare( centity_t *cent ) memset( &flare, 0, sizeof( flare ) ); - //bunch of geometry - AngleVectors( es->angles, forward, NULL, NULL ); - VectorCopy( cent->lerpOrigin, flare.origin ); - VectorSubtract( flare.origin, cg.refdef.vieworg, delta ); - len = VectorLength( delta ); - VectorNormalize( delta ); - flare.reType = RT_SPRITE; flare.customShader = cgs.gameShaders[ es->modelindex ]; flare.shaderRGBA[ 0 ] = 0xFF; @@ -582,115 +575,136 @@ static void CG_LightFlare( centity_t *cent ) //flares always drawn before the rest of the scene flare.renderfx |= RF_DEPTHHACK; - //can only see the flare when in front of it - flare.radius = len / es->origin2[ 0 ]; + //bunch of geometry + AngleVectors( es->angles, forward, NULL, NULL ); + VectorCopy( cent->lerpOrigin, flare.origin ); + VectorSubtract( flare.origin, cg.refdef.vieworg, delta ); + len = VectorLength( delta ); + VectorNormalize( delta ); - if( es->origin2[ 2 ] == 0 ) - srcRadius = srLocal = flare.radius / 2.0f; - else - srcRadius = srLocal = len / es->origin2[ 2 ]; - - maxAngle = es->origin2[ 1 ]; + //don't bother for flares behind the view plane + if( DotProduct( delta, cg.refdef.viewaxis[ 0 ] ) < 0.0 ) + return; - if( maxAngle > 0.0f ) + //only recalculate radius and ratio every three frames + if( !( cg.clientFrame % 3 ) ) { - float radiusMod = 1.0f - ( 180.0f - RAD2DEG( - acos( DotProduct( delta, forward ) ) ) ) / maxAngle; - - if( es->eFlags & EF_NODRAW ) - flare.radius *= radiusMod; - else if( radiusMod < 0.0f ) - flare.radius = 0.0f; - } + //can only see the flare when in front of it + flare.radius = len / es->origin2[ 0 ]; - if( flare.radius < 0.0f ) - flare.radius = 0.0f; - - VectorSubtract( cg.refdef.vieworg, flare.origin, dir ); - VectorNormalize( dir ); - VectorMA( flare.origin, flare.radius, dir, end ); - VectorMA( cg.refdef.vieworg, -flare.radius, dir, start ); - - if( cg_lightFlare.integer == FLARE_REALFADE ) - { - //draw "correct" albeit inefficient flares - srLocal = cent->lastFlareRadius; + if( es->origin2[ 2 ] == 0 ) + srcRadius = srLocal = flare.radius / 2.0f; + else + srcRadius = srLocal = len / es->origin2[ 2 ]; - //flare radius is likely to be the same as last frame so start with it - do + maxAngle = es->origin2[ 1 ]; + + if( maxAngle > 0.0f ) { - srLocal += RADIUSSTEP; - SETBOUNDS( mins, maxs, srLocal ); - CG_Trace( &tr, start, mins, maxs, end, - cg.predictedPlayerState.clientNum, MASK_SHOT ); + float radiusMod = 1.0f - ( 180.0f - RAD2DEG( + acos( DotProduct( delta, forward ) ) ) ) / maxAngle; + + if( es->eFlags & EF_NODRAW ) + flare.radius *= radiusMod; + else if( radiusMod < 0.0f ) + flare.radius = 0.0f; + } - } while( ( tr.fraction == 1.0f && !tr.startsolid ) && ( srLocal < srcRadius ) ); + if( flare.radius < 0.0f ) + flare.radius = 0.0f; - srLocal -= RADIUSSTEP; + VectorMA( flare.origin, -flare.radius, delta, end ); + VectorMA( cg.refdef.vieworg, flare.radius, delta, start ); - //shink the flare until there is a los - do + if( cg_lightFlare.integer == FLARE_REALFADE ) { - SETBOUNDS( mins, maxs, srLocal ); - CG_Trace( &tr, start, mins, maxs, end, - cg.predictedPlayerState.clientNum, MASK_SHOT ); + //draw "correct" albeit inefficient flares + srLocal = cent->lastFlareSrcRadius; + + //flare radius is likely to be the same as last frame so start with it + do + { + srLocal += RADIUSSTEP; + SETBOUNDS( mins, maxs, srLocal ); + CG_Trace( &tr, start, mins, maxs, end, + cg.predictedPlayerState.clientNum, MASK_SHOT ); + } while( ( tr.fraction == 1.0f && !tr.startsolid ) && ( srLocal < srcRadius ) ); + srLocal -= RADIUSSTEP; - } while( ( tr.fraction < 1.0f || tr.startsolid ) && ( srLocal > 0.0f ) ); - - ratio = srLocal / srcRadius; + + //shink the flare until there is a los + do + { + SETBOUNDS( mins, maxs, srLocal ); + CG_Trace( &tr, start, mins, maxs, end, + cg.predictedPlayerState.clientNum, MASK_SHOT ); - cent->lastFlareRadius = srLocal; - } - else if( cg_lightFlare.integer == FLARE_TIMEFADE ) - { - //draw timed flares - SETBOUNDS( mins, maxs, srcRadius ); - CG_Trace( &tr, start, mins, maxs, end, - cg.predictedPlayerState.clientNum, MASK_SHOT ); + srLocal -= RADIUSSTEP; + } while( ( tr.fraction < 1.0f || tr.startsolid ) && ( srLocal > 0.0f ) ); + + ratio = srLocal / srcRadius; - if( ( tr.fraction < 1.0f || tr.startsolid ) && cent->flareStatus ) - { - cent->flareStatus = qfalse; - cent->lastFlareTime = cg.time; + cent->lastFlareSrcRadius = srLocal; } - else if( ( tr.fraction == 1.0f && !tr.startsolid ) && !cent->flareStatus ) + else if( cg_lightFlare.integer == FLARE_TIMEFADE ) { - cent->flareStatus = qtrue; - cent->lastFlareTime = cg.time; - } + //draw timed flares + SETBOUNDS( mins, maxs, srcRadius ); + CG_Trace( &tr, start, mins, maxs, end, + cg.predictedPlayerState.clientNum, MASK_SHOT ); - //fade flare up - if( cent->flareStatus ) - { - if( cent->lastFlareTime + es->time > cg.time ) - ratio = (float)( cg.time - cent->lastFlareTime ) / es->time; - } - - //fade flare down - if( !cent->flareStatus ) - { - if( cent->lastFlareTime + es->time > cg.time ) + if( ( tr.fraction < 1.0f || tr.startsolid ) && cent->flareStatus ) { - ratio = (float)( cg.time - cent->lastFlareTime ) / es->time; - ratio = 1.0f - ratio; + cent->flareStatus = qfalse; + cent->lastFlareTime = cg.time; } - else - return; + else if( ( tr.fraction == 1.0f && !tr.startsolid ) && !cent->flareStatus ) + { + cent->flareStatus = qtrue; + cent->lastFlareTime = cg.time; + } + + //fade flare up + if( cent->flareStatus ) + { + if( cent->lastFlareTime + es->time > cg.time ) + ratio = (float)( cg.time - cent->lastFlareTime ) / es->time; + } + + //fade flare down + if( !cent->flareStatus ) + { + if( cent->lastFlareTime + es->time > cg.time ) + { + ratio = (float)( cg.time - cent->lastFlareTime ) / es->time; + ratio = 1.0f - ratio; + } + else + ratio = 0.0f; + } + } + else if( cg_lightFlare.integer == FLARE_NOFADE ) + { + //draw nofade flares + SETBOUNDS( mins, maxs, srcRadius ); + CG_Trace( &tr, start, mins, maxs, end, + cg.predictedPlayerState.clientNum, MASK_SHOT ); + + //flare source occluded + if( ( tr.fraction < 1.0f || tr.startsolid ) ) + ratio = 0.0f; } } - else if( cg_lightFlare.integer == FLARE_NOFADE ) + else { - //draw nofade flares - SETBOUNDS( mins, maxs, srcRadius ); - CG_Trace( &tr, start, mins, maxs, end, - cg.predictedPlayerState.clientNum, MASK_SHOT ); - - //flare source occluded - if( ( tr.fraction < 1.0f || tr.startsolid ) ) - return; + ratio = cent->lastFlareRatio; + flare.radius = cent->lastFlareRadius; } - + + cent->lastFlareRatio = ratio; + cent->lastFlareRadius = flare.radius; + if( ratio < 1.0f ) { flare.radius *= ratio; diff --git a/src/cgame/cg_local.h b/src/cgame/cg_local.h index cf125215..05783824 100644 --- a/src/cgame/cg_local.h +++ b/src/cgame/cg_local.h @@ -217,9 +217,11 @@ typedef struct centity_s int buildableSparkTime; int buildableBleedTime; - float lastFlareRadius; //caching of likely flare radius - int lastFlareTime; //last time flare was visible/occluded - qboolean flareStatus; //flare is visble? + float lastFlareSrcRadius; //caching of likely flare source radius + float lastFlareRadius; //caching of likely flare radius + float lastFlareRatio; //caching of likely flare ratio + int lastFlareTime; //last time flare was visible/occluded + qboolean flareStatus; //flare is visble? } centity_t; |