Added cg_atmospheric to the Linux Makefile and added a CVS header to

cg_atmospheric and indented it like the other files.
This commit is contained in:
Richard Allen 2002-08-25 19:19:49 +00:00
parent 2cea4d3acc
commit 50d562f7f9
2 changed files with 283 additions and 295 deletions

View file

@ -74,6 +74,7 @@ CGOBJ = \
$(CGDIRNAME)/cg_servercmds.o \ $(CGDIRNAME)/cg_servercmds.o \
$(CGDIRNAME)/cg_snapshot.o \ $(CGDIRNAME)/cg_snapshot.o \
$(CGDIRNAME)/cg_view.o \ $(CGDIRNAME)/cg_view.o \
$(CGDIRNAME)/cg_atmospheric.o \
$(CGDIRNAME)/cg_weapons.o $(CGDIRNAME)/cg_weapons.o
UIOBJ = \ UIOBJ = \

View file

@ -1,3 +1,16 @@
//-----------------------------------------------------------------------------
//
// $Id$
//
//-----------------------------------------------------------------------------
//
// $Log$
// Revision 1.2 2002/08/25 19:19:49 jbravo
// Added cg_atmospheric to the Linux Makefile and added a CVS header to
// cg_atmospheric and indented it like the other files.
//
//
//-----------------------------------------------------------------------------
/* /*
** Copyright (C) 2000, 2001 by the Q3F Development team ** Copyright (C) 2000, 2001 by the Q3F Development team
** All rights reserved. ** All rights reserved.
@ -11,20 +24,17 @@
#include "cg_local.h" #include "cg_local.h"
#define MAX_ATMOSPHERIC_PARTICLES 1000 // maximum # of particles #define MAX_ATMOSPHERIC_PARTICLES 1000 // maximum # of particles
#define MAX_ATMOSPHERIC_DISTANCE 1000 // maximum distance from refdef origin that particles are visible #define MAX_ATMOSPHERIC_DISTANCE 1000 // maximum distance from refdef origin that particles are visible
#define MAX_ATMOSPHERIC_HEIGHT 4096 // maximum world height (FIXME: since 1.27 this should be 65536) #define MAX_ATMOSPHERIC_HEIGHT 4096 // maximum world height (FIXME: since 1.27 this should be 65536)
#define MIN_ATMOSPHERIC_HEIGHT -4096 // minimum world height (FIXME: since 1.27 this should be -65536) #define MIN_ATMOSPHERIC_HEIGHT -4096 // minimum world height (FIXME: since 1.27 this should be -65536)
#define MAX_ATMOSPHERIC_EFFECTSHADERS 6 // maximum different effectshaders for an atmospheric effect #define MAX_ATMOSPHERIC_EFFECTSHADERS 6 // maximum different effectshaders for an atmospheric effect
#define ATMOSPHERIC_DROPDELAY 1000 #define ATMOSPHERIC_DROPDELAY 1000
#define ATMOSPHERIC_CUTHEIGHT 800 #define ATMOSPHERIC_CUTHEIGHT 800
#define ATMOSPHERIC_RAIN_SPEED 1.1f * DEFAULT_GRAVITY
#define ATMOSPHERIC_RAIN_HEIGHT 150
#define ATMOSPHERIC_RAIN_SPEED 1.1f * DEFAULT_GRAVITY #define ATMOSPHERIC_SNOW_SPEED 0.1f * DEFAULT_GRAVITY
#define ATMOSPHERIC_RAIN_HEIGHT 150 #define ATMOSPHERIC_SNOW_HEIGHT 10
#define ATMOSPHERIC_SNOW_SPEED 0.1f * DEFAULT_GRAVITY
#define ATMOSPHERIC_SNOW_HEIGHT 10
typedef struct cg_atmosphericParticle_s { typedef struct cg_atmosphericParticle_s {
vec3_t pos, delta, deltaNormalized, colour, surfacenormal; vec3_t pos, delta, deltaNormalized, colour, surfacenormal;
@ -38,21 +48,16 @@ typedef struct cg_atmosphericEffect_s {
cg_atmosphericParticle_t particles[MAX_ATMOSPHERIC_PARTICLES]; cg_atmosphericParticle_t particles[MAX_ATMOSPHERIC_PARTICLES];
qhandle_t effectshaders[MAX_ATMOSPHERIC_EFFECTSHADERS]; qhandle_t effectshaders[MAX_ATMOSPHERIC_EFFECTSHADERS];
qhandle_t effectwatershader, effectlandshader; qhandle_t effectwatershader, effectlandshader;
int lastRainTime, numDrops; int lastRainTime, numDrops, gustStartTime, gustEndTime;
int gustStartTime, gustEndTime; int baseStartTime, baseEndTime, gustMinTime, gustMaxTime;
int baseStartTime, baseEndTime; int changeMinTime, changeMaxTime, baseMinTime, baseMaxTime;
int gustMinTime, gustMaxTime;
int changeMinTime, changeMaxTime;
int baseMinTime, baseMaxTime;
float baseWeight, gustWeight; float baseWeight, gustWeight;
int baseDrops, gustDrops; int baseDrops, gustDrops, numEffectShaders;
int numEffectShaders;
qboolean waterSplash, landSplash; qboolean waterSplash, landSplash;
vec3_t baseVec, gustVec; vec3_t baseVec, gustVec;
qboolean(*ParticleCheckVisible) (cg_atmosphericParticle_t * particle);
qboolean (*ParticleCheckVisible)( cg_atmosphericParticle_t *particle ); qboolean(*ParticleGenerate) (cg_atmosphericParticle_t * particle, vec3_t currvec, float currweight);
qboolean (*ParticleGenerate)( cg_atmosphericParticle_t *particle, vec3_t currvec, float currweight ); void (*ParticleRender) (cg_atmosphericParticle_t * particle);
void (*ParticleRender)( cg_atmosphericParticle_t *particle );
} cg_atmosphericEffect_t; } cg_atmosphericEffect_t;
static cg_atmosphericEffect_t cg_atmFx; static cg_atmosphericEffect_t cg_atmFx;
@ -61,35 +66,33 @@ static cg_atmosphericEffect_t cg_atmFx;
** Render utility functions ** Render utility functions
*/ */
void CG_EffectMark( qhandle_t markShader, const vec3_t origin, const vec3_t dir, float alpha, float radius ) { void CG_EffectMark(qhandle_t markShader, const vec3_t origin, const vec3_t dir, float alpha, float radius)
{
// 'quick' version of the CG_ImpactMark function // 'quick' version of the CG_ImpactMark function
vec3_t axis[3]; vec3_t axis[3], originalPoints[4];
float texCoordScale; float texCoordScale;
vec3_t originalPoints[4]; byte colors[4];
byte colors[4]; int i;
int i; polyVert_t *v, verts[4];
polyVert_t *v;
polyVert_t verts[4];
if ( !cg_addMarks.integer ) { if (!cg_addMarks.integer) {
return; return;
} }
if ( radius <= 0 ) { if (radius <= 0) {
CG_Error( "CG_EffectMark called with <= 0 radius" ); CG_Error("CG_EffectMark called with <= 0 radius");
} }
// create the texture axis // create the texture axis
VectorNormalize2( dir, axis[0] ); VectorNormalize2(dir, axis[0]);
PerpendicularVector( axis[1], axis[0] ); PerpendicularVector(axis[1], axis[0]);
VectorSet( axis[2], 1, 0, 0 ); // This is _wrong_, but the function is for water anyway (i.e. usually flat) VectorSet(axis[2], 1, 0, 0); // This is _wrong_, but the function is for water anyway (i.e. usually flat)
CrossProduct( axis[0], axis[2], axis[1] ); CrossProduct(axis[0], axis[2], axis[1]);
texCoordScale = 0.5 * 1.0 / radius; texCoordScale = 0.5 * 1.0 / radius;
// create the full polygon // create the full polygon
for ( i = 0 ; i < 3 ; i++ ) { for (i = 0; i < 3; i++) {
originalPoints[0][i] = origin[i] - radius * axis[1][i] - radius * axis[2][i]; originalPoints[0][i] = origin[i] - radius * axis[1][i] - radius * axis[2][i];
originalPoints[1][i] = origin[i] + radius * axis[1][i] - radius * axis[2][i]; originalPoints[1][i] = origin[i] + radius * axis[1][i] - radius * axis[2][i];
originalPoints[2][i] = origin[i] + radius * axis[1][i] + radius * axis[2][i]; originalPoints[2][i] = origin[i] + radius * axis[1][i] + radius * axis[2][i];
@ -101,47 +104,46 @@ void CG_EffectMark( qhandle_t markShader, const vec3_t origin, const vec3_t di
colors[2] = 127; colors[2] = 127;
colors[3] = alpha * 255; colors[3] = alpha * 255;
for ( i = 0, v = verts ; i < 4 ; i++, v++ ) { for (i = 0, v = verts; i < 4; i++, v++) {
vec3_t delta; vec3_t delta;
VectorCopy( originalPoints[i], v->xyz ); VectorCopy(originalPoints[i], v->xyz);
VectorSubtract(v->xyz, origin, delta);
VectorSubtract( v->xyz, origin, delta ); v->st[0] = 0.5 + DotProduct(delta, axis[1]) * texCoordScale;
v->st[0] = 0.5 + DotProduct( delta, axis[1] ) * texCoordScale; v->st[1] = 0.5 + DotProduct(delta, axis[2]) * texCoordScale;
v->st[1] = 0.5 + DotProduct( delta, axis[2] ) * texCoordScale; *(int *) v->modulate = *(int *) colors;
*(int *)v->modulate = *(int *)colors;
} }
trap_R_AddPolyToScene( markShader, 4, verts ); trap_R_AddPolyToScene(markShader, 4, verts);
} }
/* /*
** Raindrop management functions ** Raindrop management functions
*/ */
static qboolean CG_RainParticleCheckVisible( cg_atmosphericParticle_t *particle ) static qboolean CG_RainParticleCheckVisible(cg_atmosphericParticle_t * particle)
{ {
// Check the raindrop is visible and still going, wrapping if necessary. // Check the raindrop is visible and still going, wrapping if necessary.
float moved; float moved;
vec3_t distance; vec3_t distance;
if( !particle || !particle->active ) if (!particle || !particle->active)
return( qfalse ); return (qfalse);
moved = (cg.time - cg_atmFx.lastRainTime) * 0.001; // Units moved since last frame moved = (cg.time - cg_atmFx.lastRainTime) * 0.001; // Units moved since last frame
VectorMA( particle->pos, moved, particle->delta, particle->pos ); VectorMA(particle->pos, moved, particle->delta, particle->pos);
if( particle->pos[2] + ATMOSPHERIC_CUTHEIGHT < particle->minz ) if (particle->pos[2] + ATMOSPHERIC_CUTHEIGHT < particle->minz)
return( particle->active = qfalse ); return (particle->active = qfalse);
VectorSubtract( cg.refdef.vieworg, particle->pos, distance ); VectorSubtract(cg.refdef.vieworg, particle->pos, distance);
if( sqrt( distance[0] * distance[0] + distance[1] * distance[1] ) > MAX_ATMOSPHERIC_DISTANCE ) if (sqrt(distance[0] * distance[0] + distance[1] * distance[1]) > MAX_ATMOSPHERIC_DISTANCE)
return( particle->active = qfalse ); return (particle->active = qfalse);
return( qtrue ); return (qtrue);
} }
static qboolean CG_RainParticleGenerate( cg_atmosphericParticle_t *particle, vec3_t currvec, float currweight ) static qboolean CG_RainParticleGenerate(cg_atmosphericParticle_t * particle, vec3_t currvec, float currweight)
{ {
// Attempt to 'spot' a raindrop somewhere below a sky texture. // Attempt to 'spot' a raindrop somewhere below a sky texture.
@ -149,7 +151,7 @@ static qboolean CG_RainParticleGenerate( cg_atmosphericParticle_t *particle, vec
vec3_t testpoint, testend; vec3_t testpoint, testend;
trace_t tr; trace_t tr;
angle = random() * 2*M_PI; angle = random() * 2 * M_PI;
distance = 20 + MAX_ATMOSPHERIC_DISTANCE * random(); distance = 20 + MAX_ATMOSPHERIC_DISTANCE * random();
testpoint[0] = testend[0] = cg.refdef.vieworg[0] + sin(angle) * distance; testpoint[0] = testend[0] = cg.refdef.vieworg[0] + sin(angle) * distance;
@ -157,104 +159,102 @@ static qboolean CG_RainParticleGenerate( cg_atmosphericParticle_t *particle, vec
testpoint[2] = origz = cg.refdef.vieworg[2]; testpoint[2] = origz = cg.refdef.vieworg[2];
testend[2] = testpoint[2] + MAX_ATMOSPHERIC_HEIGHT; testend[2] = testpoint[2] + MAX_ATMOSPHERIC_HEIGHT;
while( 1 ) while (1) {
{ if (testpoint[2] >= MAX_ATMOSPHERIC_HEIGHT)
if( testpoint[2] >= MAX_ATMOSPHERIC_HEIGHT ) return (qfalse);
return( qfalse ); if (testend[2] >= MAX_ATMOSPHERIC_HEIGHT)
if( testend[2] >= MAX_ATMOSPHERIC_HEIGHT )
testend[2] = MAX_ATMOSPHERIC_HEIGHT - 1; testend[2] = MAX_ATMOSPHERIC_HEIGHT - 1;
CG_Trace( &tr, testpoint, NULL, NULL, testend, ENTITYNUM_NONE, MASK_SOLID|MASK_WATER ); CG_Trace(&tr, testpoint, NULL, NULL, testend, ENTITYNUM_NONE, MASK_SOLID | MASK_WATER);
if( tr.startsolid ) // Stuck in something, skip over it. if (tr.startsolid) // Stuck in something, skip over it.
{ {
testpoint[2] += 64; testpoint[2] += 64;
testend[2] = testpoint[2] + MAX_ATMOSPHERIC_HEIGHT; testend[2] = testpoint[2] + MAX_ATMOSPHERIC_HEIGHT;
} } else if (tr.fraction == 1) // Didn't hit anything, we're (probably) outside the world
else if( tr.fraction == 1 ) // Didn't hit anything, we're (probably) outside the world return (qfalse);
return( qfalse ); else if (tr.surfaceFlags & SURF_SKY) // Hit sky, this is where we start.
else if( tr.surfaceFlags & SURF_SKY ) // Hit sky, this is where we start.
break; break;
else return( qfalse ); else
return (qfalse);
} }
particle->active = qtrue; particle->active = qtrue;
particle->colour[0] = 0.6 + 0.2 * random(); particle->colour[0] = 0.6 + 0.2 * random();
particle->colour[1] = 0.6 + 0.2 * random(); particle->colour[1] = 0.6 + 0.2 * random();
particle->colour[2] = 0.6 + 0.2 * random(); particle->colour[2] = 0.6 + 0.2 * random();
VectorCopy( tr.endpos, particle->pos ); VectorCopy(tr.endpos, particle->pos);
VectorCopy( currvec, particle->delta ); VectorCopy(currvec, particle->delta);
particle->delta[2] += crandom() * 100; particle->delta[2] += crandom() * 100;
VectorNormalize2( particle->delta, particle->deltaNormalized ); VectorNormalize2(particle->delta, particle->deltaNormalized);
particle->height = ATMOSPHERIC_RAIN_HEIGHT + crandom() * 100; particle->height = ATMOSPHERIC_RAIN_HEIGHT + crandom() * 100;
particle->weight = currweight; particle->weight = currweight;
particle->effectshader = &cg_atmFx.effectshaders[0]; particle->effectshader = &cg_atmFx.effectshaders[0];
distance = ((float)(tr.endpos[2] - MIN_ATMOSPHERIC_HEIGHT)) / -particle->delta[2]; distance = ((float) (tr.endpos[2] - MIN_ATMOSPHERIC_HEIGHT)) / -particle->delta[2];
VectorMA( tr.endpos, distance, particle->delta, testend ); VectorMA(tr.endpos, distance, particle->delta, testend);
CG_Trace( &tr, particle->pos, NULL, NULL, testend, ENTITYNUM_NONE, MASK_SOLID|MASK_WATER ); CG_Trace(&tr, particle->pos, NULL, NULL, testend, ENTITYNUM_NONE, MASK_SOLID | MASK_WATER);
particle->minz = tr.endpos[2]; particle->minz = tr.endpos[2];
tr.endpos[2]--; tr.endpos[2]--;
VectorCopy( tr.plane.normal, particle->surfacenormal ); VectorCopy(tr.plane.normal, particle->surfacenormal);
particle->surface = tr.surfaceFlags; particle->surface = tr.surfaceFlags;
particle->contents = CG_PointContents( tr.endpos, ENTITYNUM_NONE ); particle->contents = CG_PointContents(tr.endpos, ENTITYNUM_NONE);
return( qtrue ); return (qtrue);
} }
static void CG_RainParticleRender( cg_atmosphericParticle_t *particle ) static void CG_RainParticleRender(cg_atmosphericParticle_t * particle)
{ {
// Draw a raindrop // Draw a raindrop
vec3_t forward, right; vec3_t forward, right;
polyVert_t verts[4]; polyVert_t verts[4];
vec2_t line; vec2_t line;
float len, frac; float len, frac;
vec3_t start, finish; vec3_t start, finish;
if( !particle->active ) if (!particle->active)
return; return;
VectorCopy( particle->pos, start ); VectorCopy(particle->pos, start);
len = particle->height; len = particle->height;
if( start[2] <= particle->minz ) if (start[2] <= particle->minz) {
{
// Stop rain going through surfaces. // Stop rain going through surfaces.
len = particle->height - particle->minz + start[2]; len = particle->height - particle->minz + start[2];
frac = start[2]; frac = start[2];
VectorMA( start, len - particle->height, particle->deltaNormalized, start ); VectorMA(start, len - particle->height, particle->deltaNormalized, start);
if( !cg_lowEffects.integer ) if (!cg_lowEffects.integer) {
{
frac = (ATMOSPHERIC_CUTHEIGHT - particle->minz + frac) / (float) ATMOSPHERIC_CUTHEIGHT; frac = (ATMOSPHERIC_CUTHEIGHT - particle->minz + frac) / (float) ATMOSPHERIC_CUTHEIGHT;
// Splash effects on different surfaces // Splash effects on different surfaces
if( particle->contents & (CONTENTS_WATER|CONTENTS_SLIME) ) if (particle->contents & (CONTENTS_WATER | CONTENTS_SLIME)) {
{
// Water splash // Water splash
if( cg_atmFx.effectwatershader && frac > 0 && frac < 1 ) if (cg_atmFx.effectwatershader && frac > 0 && frac < 1)
CG_EffectMark( cg_atmFx.effectwatershader, start, particle->surfacenormal, frac * 0.5, 8 - frac * 8 ); CG_EffectMark(cg_atmFx.effectwatershader, start, particle->surfacenormal,
} frac * 0.5, 8 - frac * 8);
else if( !(particle->contents & CONTENTS_LAVA) && !(particle->surface & (SURF_NODAMAGE|SURF_NOIMPACT|SURF_NOMARKS|SURF_SKY)) ) } else if (!(particle->contents & CONTENTS_LAVA)
{ && !(particle->
surface & (SURF_NODAMAGE | SURF_NOIMPACT | SURF_NOMARKS | SURF_SKY))) {
// Solid splash // Solid splash
if( cg_atmFx.effectlandshader && frac > 0 && frac < 1 ) if (cg_atmFx.effectlandshader && frac > 0 && frac < 1)
CG_ImpactMark( cg_atmFx.effectlandshader, start, particle->surfacenormal, 0, 1, 1, 1, frac * 0.5, qfalse, 3 - frac * 2, qtrue ); CG_ImpactMark(cg_atmFx.effectlandshader, start, particle->surfacenormal, 0, 1,
1, 1, frac * 0.5, qfalse, 3 - frac * 2, qtrue);
} }
} }
} }
if( len <= 0 ) if (len <= 0)
return; return;
VectorCopy( particle->deltaNormalized, forward ); VectorCopy(particle->deltaNormalized, forward);
VectorMA( start, -len, forward, finish ); VectorMA(start, -len, forward, finish);
line[0] = DotProduct( forward, cg.refdef.viewaxis[1] ); line[0] = DotProduct(forward, cg.refdef.viewaxis[1]);
line[1] = DotProduct( forward, cg.refdef.viewaxis[2] ); line[1] = DotProduct(forward, cg.refdef.viewaxis[2]);
VectorScale( cg.refdef.viewaxis[1], line[1], right ); VectorScale(cg.refdef.viewaxis[1], line[1], right);
VectorMA( right, -line[0], cg.refdef.viewaxis[2], right ); VectorMA(right, -line[0], cg.refdef.viewaxis[2], right);
VectorNormalize( right ); VectorNormalize(right);
VectorMA( finish, particle->weight, right, verts[0].xyz ); VectorMA(finish, particle->weight, right, verts[0].xyz);
verts[0].st[0] = 1; verts[0].st[0] = 1;
verts[0].st[1] = 0; verts[0].st[1] = 0;
verts[0].modulate[0] = 255; verts[0].modulate[0] = 255;
@ -262,7 +262,7 @@ static void CG_RainParticleRender( cg_atmosphericParticle_t *particle )
verts[0].modulate[2] = 255; verts[0].modulate[2] = 255;
verts[0].modulate[3] = 0; verts[0].modulate[3] = 0;
VectorMA( finish, -particle->weight, right, verts[1].xyz ); VectorMA(finish, -particle->weight, right, verts[1].xyz);
verts[1].st[0] = 0; verts[1].st[0] = 0;
verts[1].st[1] = 0; verts[1].st[1] = 0;
verts[1].modulate[0] = 255; verts[1].modulate[0] = 255;
@ -270,7 +270,7 @@ static void CG_RainParticleRender( cg_atmosphericParticle_t *particle )
verts[1].modulate[2] = 255; verts[1].modulate[2] = 255;
verts[1].modulate[3] = 0; verts[1].modulate[3] = 0;
VectorMA( start, -particle->weight, right, verts[2].xyz ); VectorMA(start, -particle->weight, right, verts[2].xyz);
verts[2].st[0] = 0; verts[2].st[0] = 0;
verts[2].st[1] = 1; verts[2].st[1] = 1;
verts[2].modulate[0] = 255; verts[2].modulate[0] = 255;
@ -278,7 +278,7 @@ static void CG_RainParticleRender( cg_atmosphericParticle_t *particle )
verts[2].modulate[2] = 255; verts[2].modulate[2] = 255;
verts[2].modulate[3] = 127; verts[2].modulate[3] = 127;
VectorMA( start, particle->weight, right, verts[3].xyz ); VectorMA(start, particle->weight, right, verts[3].xyz);
verts[3].st[0] = 1; verts[3].st[0] = 1;
verts[3].st[1] = 1; verts[3].st[1] = 1;
verts[3].modulate[0] = 255; verts[3].modulate[0] = 255;
@ -286,14 +286,14 @@ static void CG_RainParticleRender( cg_atmosphericParticle_t *particle )
verts[3].modulate[2] = 255; verts[3].modulate[2] = 255;
verts[3].modulate[3] = 127; verts[3].modulate[3] = 127;
trap_R_AddPolyToScene( *particle->effectshader, 4, verts ); trap_R_AddPolyToScene(*particle->effectshader, 4, verts);
} }
/* /*
** Snow management functions ** Snow management functions
*/ */
static qboolean CG_SnowParticleGenerate( cg_atmosphericParticle_t *particle, vec3_t currvec, float currweight ) static qboolean CG_SnowParticleGenerate(cg_atmosphericParticle_t * particle, vec3_t currvec, float currweight)
{ {
// Attempt to 'spot' a raindrop somewhere below a sky texture. // Attempt to 'spot' a raindrop somewhere below a sky texture.
@ -301,7 +301,7 @@ static qboolean CG_SnowParticleGenerate( cg_atmosphericParticle_t *particle, vec
vec3_t testpoint, testend; vec3_t testpoint, testend;
trace_t tr; trace_t tr;
angle = random() * 2*M_PI; angle = random() * 2 * M_PI;
distance = 20 + MAX_ATMOSPHERIC_DISTANCE * random(); distance = 20 + MAX_ATMOSPHERIC_DISTANCE * random();
testpoint[0] = testend[0] = cg.refdef.vieworg[0] + sin(angle) * distance; testpoint[0] = testend[0] = cg.refdef.vieworg[0] + sin(angle) * distance;
@ -309,94 +309,92 @@ static qboolean CG_SnowParticleGenerate( cg_atmosphericParticle_t *particle, vec
testpoint[2] = origz = cg.refdef.vieworg[2]; testpoint[2] = origz = cg.refdef.vieworg[2];
testend[2] = testpoint[2] + MAX_ATMOSPHERIC_HEIGHT; testend[2] = testpoint[2] + MAX_ATMOSPHERIC_HEIGHT;
while( 1 ) while (1) {
{ if (testpoint[2] >= MAX_ATMOSPHERIC_HEIGHT)
if( testpoint[2] >= MAX_ATMOSPHERIC_HEIGHT ) return (qfalse);
return( qfalse ); if (testend[2] >= MAX_ATMOSPHERIC_HEIGHT)
if( testend[2] >= MAX_ATMOSPHERIC_HEIGHT )
testend[2] = MAX_ATMOSPHERIC_HEIGHT - 1; testend[2] = MAX_ATMOSPHERIC_HEIGHT - 1;
CG_Trace( &tr, testpoint, NULL, NULL, testend, ENTITYNUM_NONE, MASK_SOLID|MASK_WATER ); CG_Trace(&tr, testpoint, NULL, NULL, testend, ENTITYNUM_NONE, MASK_SOLID | MASK_WATER);
if( tr.startsolid ) // Stuck in something, skip over it. if (tr.startsolid) // Stuck in something, skip over it.
{ {
testpoint[2] += 64; testpoint[2] += 64;
testend[2] = testpoint[2] + MAX_ATMOSPHERIC_HEIGHT; testend[2] = testpoint[2] + MAX_ATMOSPHERIC_HEIGHT;
} } else if (tr.fraction == 1) // Didn't hit anything, we're (probably) outside the world
else if( tr.fraction == 1 ) // Didn't hit anything, we're (probably) outside the world return (qfalse);
return( qfalse ); else if (tr.surfaceFlags & SURF_SKY) // Hit sky, this is where we start.
else if( tr.surfaceFlags & SURF_SKY ) // Hit sky, this is where we start.
break; break;
else return( qfalse ); else
return (qfalse);
} }
particle->active = qtrue; particle->active = qtrue;
particle->colour[0] = 0.6 + 0.2 * random(); particle->colour[0] = 0.6 + 0.2 * random();
particle->colour[1] = 0.6 + 0.2 * random(); particle->colour[1] = 0.6 + 0.2 * random();
particle->colour[2] = 0.6 + 0.2 * random(); particle->colour[2] = 0.6 + 0.2 * random();
VectorCopy( tr.endpos, particle->pos ); VectorCopy(tr.endpos, particle->pos);
VectorCopy( currvec, particle->delta ); VectorCopy(currvec, particle->delta);
particle->delta[2] += crandom() * 25; particle->delta[2] += crandom() * 25;
VectorNormalize2( particle->delta, particle->deltaNormalized ); VectorNormalize2(particle->delta, particle->deltaNormalized);
particle->height = ATMOSPHERIC_SNOW_HEIGHT + crandom() * 8; particle->height = ATMOSPHERIC_SNOW_HEIGHT + crandom() * 8;
particle->weight = particle->height * 0.5f; particle->weight = particle->height * 0.5f;
particle->effectshader = &cg_atmFx.effectshaders[ (int) (random() * ( cg_atmFx.numEffectShaders - 1 )) ]; particle->effectshader = &cg_atmFx.effectshaders[(int) (random() * (cg_atmFx.numEffectShaders - 1))];
distance = ((float)(tr.endpos[2] - MIN_ATMOSPHERIC_HEIGHT)) / -particle->delta[2]; distance = ((float) (tr.endpos[2] - MIN_ATMOSPHERIC_HEIGHT)) / -particle->delta[2];
VectorMA( tr.endpos, distance, particle->delta, testend ); VectorMA(tr.endpos, distance, particle->delta, testend);
CG_Trace( &tr, particle->pos, NULL, NULL, testend, ENTITYNUM_NONE, MASK_SOLID|MASK_WATER ); CG_Trace(&tr, particle->pos, NULL, NULL, testend, ENTITYNUM_NONE, MASK_SOLID | MASK_WATER);
particle->minz = tr.endpos[2]; particle->minz = tr.endpos[2];
tr.endpos[2]--; tr.endpos[2]--;
VectorCopy( tr.plane.normal, particle->surfacenormal ); VectorCopy(tr.plane.normal, particle->surfacenormal);
particle->surface = tr.surfaceFlags; particle->surface = tr.surfaceFlags;
particle->contents = CG_PointContents( tr.endpos, ENTITYNUM_NONE ); particle->contents = CG_PointContents(tr.endpos, ENTITYNUM_NONE);
return( qtrue ); return (qtrue);
} }
static void CG_SnowParticleRender( cg_atmosphericParticle_t *particle ) static void CG_SnowParticleRender(cg_atmosphericParticle_t * particle)
{ {
// Draw a snowflake // Draw a snowflake
vec3_t forward, right; vec3_t forward, right;
polyVert_t verts[4]; polyVert_t verts[4];
vec2_t line; vec2_t line;
float len, frac, sinTumbling, cosTumbling, particleWidth; float len, frac, sinTumbling, cosTumbling, particleWidth;
vec3_t start, finish; vec3_t start, finish;
if( !particle->active ) if (!particle->active)
return; return;
VectorCopy( particle->pos, start ); VectorCopy(particle->pos, start);
sinTumbling = sin( particle->pos[2] * 0.03125f ); sinTumbling = sin(particle->pos[2] * 0.03125f);
cosTumbling = cos( ( particle->pos[2] + particle->pos[1] ) * 0.03125f ); cosTumbling = cos((particle->pos[2] + particle->pos[1]) * 0.03125f);
start[0] += 24 * ( 1 - particle->deltaNormalized[2] ) * sinTumbling; start[0] += 24 * (1 - particle->deltaNormalized[2]) * sinTumbling;
start[1] += 24 * ( 1 - particle->deltaNormalized[2] ) * cosTumbling; start[1] += 24 * (1 - particle->deltaNormalized[2]) * cosTumbling;
len = particle->height; len = particle->height;
if( start[2] <= particle->minz ) if (start[2] <= particle->minz) {
{
// Stop snow going through surfaces. // Stop snow going through surfaces.
len = particle->height - particle->minz + start[2]; len = particle->height - particle->minz + start[2];
frac = start[2]; frac = start[2];
VectorMA( start, len - particle->height, particle->deltaNormalized, start ); VectorMA(start, len - particle->height, particle->deltaNormalized, start);
} }
if( len <= 0 ) if (len <= 0)
return; return;
VectorCopy( particle->deltaNormalized, forward ); VectorCopy(particle->deltaNormalized, forward);
VectorMA( start, -( len * sinTumbling ), forward, finish ); VectorMA(start, -(len * sinTumbling), forward, finish);
line[0] = DotProduct( forward, cg.refdef.viewaxis[1] ); line[0] = DotProduct(forward, cg.refdef.viewaxis[1]);
line[1] = DotProduct( forward, cg.refdef.viewaxis[2] ); line[1] = DotProduct(forward, cg.refdef.viewaxis[2]);
VectorScale( cg.refdef.viewaxis[1], line[1], right ); VectorScale(cg.refdef.viewaxis[1], line[1], right);
VectorMA( right, -line[0], cg.refdef.viewaxis[2], right ); VectorMA(right, -line[0], cg.refdef.viewaxis[2], right);
VectorNormalize( right ); VectorNormalize(right);
particleWidth = cosTumbling * particle->weight; particleWidth = cosTumbling * particle->weight;
VectorMA( finish, particleWidth, right, verts[0].xyz ); VectorMA(finish, particleWidth, right, verts[0].xyz);
verts[0].st[0] = 1; verts[0].st[0] = 1;
verts[0].st[1] = 0; verts[0].st[1] = 0;
verts[0].modulate[0] = 255; verts[0].modulate[0] = 255;
@ -404,7 +402,7 @@ static void CG_SnowParticleRender( cg_atmosphericParticle_t *particle )
verts[0].modulate[2] = 255; verts[0].modulate[2] = 255;
verts[0].modulate[3] = 255; verts[0].modulate[3] = 255;
VectorMA( finish, -particleWidth, right, verts[1].xyz ); VectorMA(finish, -particleWidth, right, verts[1].xyz);
verts[1].st[0] = 0; verts[1].st[0] = 0;
verts[1].st[1] = 0; verts[1].st[1] = 0;
verts[1].modulate[0] = 255; verts[1].modulate[0] = 255;
@ -412,7 +410,7 @@ static void CG_SnowParticleRender( cg_atmosphericParticle_t *particle )
verts[1].modulate[2] = 255; verts[1].modulate[2] = 255;
verts[1].modulate[3] = 255; verts[1].modulate[3] = 255;
VectorMA( start, -particleWidth, right, verts[2].xyz ); VectorMA(start, -particleWidth, right, verts[2].xyz);
verts[2].st[0] = 0; verts[2].st[0] = 0;
verts[2].st[1] = 1; verts[2].st[1] = 1;
verts[2].modulate[0] = 255; verts[2].modulate[0] = 255;
@ -420,7 +418,7 @@ static void CG_SnowParticleRender( cg_atmosphericParticle_t *particle )
verts[2].modulate[2] = 255; verts[2].modulate[2] = 255;
verts[2].modulate[3] = 255; verts[2].modulate[3] = 255;
VectorMA( start, particleWidth, right, verts[3].xyz ); VectorMA(start, particleWidth, right, verts[3].xyz);
verts[3].st[0] = 1; verts[3].st[0] = 1;
verts[3].st[1] = 1; verts[3].st[1] = 1;
verts[3].modulate[0] = 255; verts[3].modulate[0] = 255;
@ -428,7 +426,7 @@ static void CG_SnowParticleRender( cg_atmosphericParticle_t *particle )
verts[3].modulate[2] = 255; verts[3].modulate[2] = 255;
verts[3].modulate[3] = 255; verts[3].modulate[3] = 255;
trap_R_AddPolyToScene( *particle->effectshader, 4, verts ); trap_R_AddPolyToScene(*particle->effectshader, 4, verts);
} }
/* /*
@ -441,76 +439,73 @@ static void CG_EffectGust()
int diff; int diff;
cg_atmFx.baseEndTime = cg.time + cg_atmFx.baseMinTime + (rand() % (cg_atmFx.baseMaxTime - cg_atmFx.baseMinTime)); cg_atmFx.baseEndTime =
diff = cg_atmFx.changeMaxTime - cg_atmFx.changeMinTime; cg.time + cg_atmFx.baseMinTime + (rand() % (cg_atmFx.baseMaxTime - cg_atmFx.baseMinTime));
cg_atmFx.gustStartTime = cg_atmFx.baseEndTime + cg_atmFx.changeMinTime + (diff ? (rand() % diff) : 0); diff = cg_atmFx.changeMaxTime - cg_atmFx.changeMinTime;
diff = cg_atmFx.gustMaxTime - cg_atmFx.gustMinTime; cg_atmFx.gustStartTime = cg_atmFx.baseEndTime + cg_atmFx.changeMinTime + (diff ? (rand() % diff) : 0);
cg_atmFx.gustEndTime = cg_atmFx.gustStartTime + cg_atmFx.gustMinTime + (diff ? (rand() % diff) : 0); diff = cg_atmFx.gustMaxTime - cg_atmFx.gustMinTime;
diff = cg_atmFx.changeMaxTime - cg_atmFx.changeMinTime; cg_atmFx.gustEndTime = cg_atmFx.gustStartTime + cg_atmFx.gustMinTime + (diff ? (rand() % diff) : 0);
cg_atmFx.baseStartTime = cg_atmFx.gustEndTime + cg_atmFx.changeMinTime + (diff ? (rand() % diff) : 0); diff = cg_atmFx.changeMaxTime - cg_atmFx.changeMinTime;
cg_atmFx.baseStartTime = cg_atmFx.gustEndTime + cg_atmFx.changeMinTime + (diff ? (rand() % diff) : 0);
} }
static qboolean CG_EffectGustCurrent( vec3_t curr, float *weight, int *num ) static qboolean CG_EffectGustCurrent(vec3_t curr, float *weight, int *num)
{ {
// Calculate direction for new drops. // Calculate direction for new drops.
vec3_t temp; vec3_t temp;
float frac; float frac;
if( cg.time < cg_atmFx.baseEndTime ) if (cg.time < cg_atmFx.baseEndTime) {
{ VectorCopy(cg_atmFx.baseVec, curr);
VectorCopy( cg_atmFx.baseVec, curr );
*weight = cg_atmFx.baseWeight; *weight = cg_atmFx.baseWeight;
*num = cg_atmFx.baseDrops; *num = cg_atmFx.baseDrops;
} } else {
else { VectorSubtract(cg_atmFx.gustVec, cg_atmFx.baseVec, temp);
VectorSubtract( cg_atmFx.gustVec, cg_atmFx.baseVec, temp ); if (cg.time < cg_atmFx.gustStartTime) {
if( cg.time < cg_atmFx.gustStartTime ) frac =
{ ((float) (cg.time - cg_atmFx.baseEndTime)) /
frac = ((float)(cg.time - cg_atmFx.baseEndTime))/((float)(cg_atmFx.gustStartTime - cg_atmFx.baseEndTime)); ((float) (cg_atmFx.gustStartTime - cg_atmFx.baseEndTime));
VectorMA( cg_atmFx.baseVec, frac, temp, curr ); VectorMA(cg_atmFx.baseVec, frac, temp, curr);
*weight = cg_atmFx.baseWeight + (cg_atmFx.gustWeight - cg_atmFx.baseWeight) * frac; *weight = cg_atmFx.baseWeight + (cg_atmFx.gustWeight - cg_atmFx.baseWeight) * frac;
*num = cg_atmFx.baseDrops + ((float)(cg_atmFx.gustDrops - cg_atmFx.baseDrops)) * frac; *num = cg_atmFx.baseDrops + ((float) (cg_atmFx.gustDrops - cg_atmFx.baseDrops)) * frac;
} } else if (cg.time < cg_atmFx.gustEndTime) {
else if( cg.time < cg_atmFx.gustEndTime ) VectorCopy(cg_atmFx.gustVec, curr);
{
VectorCopy( cg_atmFx.gustVec, curr );
*weight = cg_atmFx.gustWeight; *weight = cg_atmFx.gustWeight;
*num = cg_atmFx.gustDrops; *num = cg_atmFx.gustDrops;
} } else {
else frac =
{ 1.0 -
frac = 1.0 - ((float)(cg.time - cg_atmFx.gustEndTime))/((float)(cg_atmFx.baseStartTime - cg_atmFx.gustEndTime)); ((float) (cg.time - cg_atmFx.gustEndTime)) /
VectorMA( cg_atmFx.baseVec, frac, temp, curr ); ((float) (cg_atmFx.baseStartTime - cg_atmFx.gustEndTime));
VectorMA(cg_atmFx.baseVec, frac, temp, curr);
*weight = cg_atmFx.baseWeight + (cg_atmFx.gustWeight - cg_atmFx.baseWeight) * frac; *weight = cg_atmFx.baseWeight + (cg_atmFx.gustWeight - cg_atmFx.baseWeight) * frac;
*num = cg_atmFx.baseDrops + ((float)(cg_atmFx.gustDrops - cg_atmFx.baseDrops)) * frac; *num = cg_atmFx.baseDrops + ((float) (cg_atmFx.gustDrops - cg_atmFx.baseDrops)) * frac;
if( cg.time >= cg_atmFx.baseStartTime ) if (cg.time >= cg_atmFx.baseStartTime)
return( qtrue ); return (qtrue);
} }
} }
return( qfalse ); return (qfalse);
} }
static void CG_EP_ParseFloats( char *floatstr, float *f1, float *f2 ) static void CG_EP_ParseFloats(char *floatstr, float *f1, float *f2)
{ {
// Parse the float or floats // Parse the float or floats
char *middleptr; char *middleptr;
char buff[64]; char buff[64];
Q_strncpyz( buff, floatstr, sizeof(buff) ); Q_strncpyz(buff, floatstr, sizeof(buff));
for( middleptr = buff; *middleptr && *middleptr != ' '; middleptr++ ); for (middleptr = buff; *middleptr && *middleptr != ' '; middleptr++);
if( *middleptr ) if (*middleptr) {
{
*middleptr++ = 0; *middleptr++ = 0;
*f1 = atof( floatstr ); *f1 = atof(floatstr);
*f2 = atof( middleptr ); *f2 = atof(middleptr);
} } else {
else { *f1 = *f2 = atof(floatstr);
*f1 = *f2 = atof( floatstr );
} }
} }
void CG_EffectParse( const char *effectstr ) void CG_EffectParse(const char *effectstr)
{ {
// Split the string into it's component parts. // Split the string into it's component parts.
@ -519,7 +514,7 @@ void CG_EffectParse( const char *effectstr )
char *startptr, *eqptr, *endptr, *type; char *startptr, *eqptr, *endptr, *type;
char workbuff[128]; char workbuff[128];
if( CG_AtmosphericKludge() ) if (CG_AtmosphericKludge())
return; return;
// Set up some default values // Set up some default values
@ -539,73 +534,69 @@ void CG_EffectParse( const char *effectstr )
type = NULL; type = NULL;
// Parse the parameter string // Parse the parameter string
Q_strncpyz( workbuff, effectstr, sizeof(workbuff) ); Q_strncpyz(workbuff, effectstr, sizeof(workbuff));
for( startptr = workbuff; *startptr; ) for (startptr = workbuff; *startptr;) {
{ for (eqptr = startptr; *eqptr && *eqptr != '=' && *eqptr != ','; eqptr++);
for( eqptr = startptr; *eqptr && *eqptr != '=' && *eqptr != ','; eqptr++ ); if (!*eqptr)
if( !*eqptr ) break; // No more string
break; // No more string if (*eqptr == ',') {
if( *eqptr == ',' ) startptr = eqptr + 1; // Bad argument, continue
{
startptr = eqptr + 1; // Bad argument, continue
continue; continue;
} }
*eqptr++ = 0; *eqptr++ = 0;
for( endptr = eqptr; *endptr && *endptr != ','; endptr++ ); for (endptr = eqptr; *endptr && *endptr != ','; endptr++);
if( *endptr ) if (*endptr)
*endptr++ = 0; *endptr++ = 0;
if( !type ) if (!type) {
{ if (Q_stricmp(startptr, "T")) {
if( Q_stricmp( startptr, "T" ) ) {
cg_atmFx.numDrops = 0; cg_atmFx.numDrops = 0;
CG_Printf( "Atmospheric effect must start with a type.\n" ); CG_Printf("Atmospheric effect must start with a type.\n");
return; return;
} }
if( !Q_stricmp( eqptr, "RAIN" ) ) { if (!Q_stricmp(eqptr, "RAIN")) {
type = "rain"; type = "rain";
cg_atmFx.ParticleCheckVisible = &CG_RainParticleCheckVisible; cg_atmFx.ParticleCheckVisible = &CG_RainParticleCheckVisible;
cg_atmFx.ParticleGenerate = &CG_RainParticleGenerate; cg_atmFx.ParticleGenerate = &CG_RainParticleGenerate;
cg_atmFx.ParticleRender = &CG_RainParticleRender; cg_atmFx.ParticleRender = &CG_RainParticleRender;
cg_atmFx.baseVec[2] = cg_atmFx.gustVec[2] = - ATMOSPHERIC_RAIN_SPEED; cg_atmFx.baseVec[2] = cg_atmFx.gustVec[2] = -ATMOSPHERIC_RAIN_SPEED;
} else if( !Q_stricmp( eqptr, "SNOW" ) ) { } else if (!Q_stricmp(eqptr, "SNOW")) {
type = "snow"; type = "snow";
cg_atmFx.ParticleCheckVisible = &CG_RainParticleCheckVisible; cg_atmFx.ParticleCheckVisible = &CG_RainParticleCheckVisible;
cg_atmFx.ParticleGenerate = &CG_SnowParticleGenerate; cg_atmFx.ParticleGenerate = &CG_SnowParticleGenerate;
cg_atmFx.ParticleRender = &CG_SnowParticleRender; cg_atmFx.ParticleRender = &CG_SnowParticleRender;
cg_atmFx.baseVec[2] = cg_atmFx.gustVec[2] = - ATMOSPHERIC_SNOW_SPEED; cg_atmFx.baseVec[2] = cg_atmFx.gustVec[2] = -ATMOSPHERIC_SNOW_SPEED;
} else { } else {
cg_atmFx.numDrops = 0; cg_atmFx.numDrops = 0;
CG_Printf( "Only effect type 'rain' and 'snow' are supported.\n" ); CG_Printf("Only effect type 'rain' and 'snow' are supported.\n");
return; return;
} }
} } else {
else { if (!Q_stricmp(startptr, "B"))
if( !Q_stricmp( startptr, "B" ) ) CG_EP_ParseFloats(eqptr, &bmin, &bmax);
CG_EP_ParseFloats( eqptr, &bmin, &bmax ); else if (!Q_stricmp(startptr, "C"))
else if( !Q_stricmp( startptr, "C" ) ) CG_EP_ParseFloats(eqptr, &cmin, &cmax);
CG_EP_ParseFloats( eqptr, &cmin, &cmax ); else if (!Q_stricmp(startptr, "G"))
else if( !Q_stricmp( startptr, "G" ) ) CG_EP_ParseFloats(eqptr, &gmin, &gmax);
CG_EP_ParseFloats( eqptr, &gmin, &gmax ); else if (!Q_stricmp(startptr, "BV"))
else if( !Q_stricmp( startptr, "BV" ) ) CG_EP_ParseFloats(eqptr, &cg_atmFx.baseVec[0], &cg_atmFx.baseVec[1]);
CG_EP_ParseFloats( eqptr, &cg_atmFx.baseVec[0], &cg_atmFx.baseVec[1] ); else if (!Q_stricmp(startptr, "GV"))
else if( !Q_stricmp( startptr, "GV" ) ) CG_EP_ParseFloats(eqptr, &cg_atmFx.gustVec[0], &cg_atmFx.gustVec[1]);
CG_EP_ParseFloats( eqptr, &cg_atmFx.gustVec[0], &cg_atmFx.gustVec[1] ); else if (!Q_stricmp(startptr, "W"))
else if( !Q_stricmp( startptr, "W" ) ) CG_EP_ParseFloats(eqptr, &cg_atmFx.baseWeight, &cg_atmFx.gustWeight);
CG_EP_ParseFloats( eqptr, &cg_atmFx.baseWeight, &cg_atmFx.gustWeight ); else if (!Q_stricmp(startptr, "S"))
else if( !Q_stricmp( startptr, "S" ) ) CG_EP_ParseFloats(eqptr, &wsplash, &lsplash);
CG_EP_ParseFloats( eqptr, &wsplash, &lsplash ); else if (!Q_stricmp(startptr, "D"))
else if( !Q_stricmp( startptr, "D" ) ) CG_EP_ParseFloats(eqptr, &bdrop, &gdrop);
CG_EP_ParseFloats( eqptr, &bdrop, &gdrop ); else
else CG_Printf( "Unknown effect key '%s'.\n", startptr ); CG_Printf("Unknown effect key '%s'.\n", startptr);
} }
startptr = endptr; startptr = endptr;
} }
if( !type ) if (!type) {
{
// No effects // No effects
cg_atmFx.numDrops = -1; cg_atmFx.numDrops = -1;
@ -624,26 +615,28 @@ void CG_EffectParse( const char *effectstr )
cg_atmFx.landSplash = lsplash; cg_atmFx.landSplash = lsplash;
cg_atmFx.numDrops = (cg_atmFx.baseDrops > cg_atmFx.gustDrops) ? cg_atmFx.baseDrops : cg_atmFx.gustDrops; cg_atmFx.numDrops = (cg_atmFx.baseDrops > cg_atmFx.gustDrops) ? cg_atmFx.baseDrops : cg_atmFx.gustDrops;
if( cg_atmFx.numDrops > MAX_ATMOSPHERIC_PARTICLES ) if (cg_atmFx.numDrops > MAX_ATMOSPHERIC_PARTICLES)
cg_atmFx.numDrops = MAX_ATMOSPHERIC_PARTICLES; cg_atmFx.numDrops = MAX_ATMOSPHERIC_PARTICLES;
// Load graphics // Load graphics
// Rain // Rain
if( !Q_stricmp(type, "rain") ) { if (!Q_stricmp(type, "rain")) {
cg_atmFx.numEffectShaders = 1; cg_atmFx.numEffectShaders = 1;
if( !(cg_atmFx.effectshaders[0] = trap_R_RegisterShader( "gfx/atmosphere/raindrop" )) ) if (!(cg_atmFx.effectshaders[0] = trap_R_RegisterShader("gfx/atmosphere/raindrop")))
cg_atmFx.effectshaders[0] = -1; cg_atmFx.effectshaders[0] = -1;
if( cg_atmFx.waterSplash ) if (cg_atmFx.waterSplash)
cg_atmFx.effectwatershader = trap_R_RegisterShader( "gfx/atmosphere/raindropwater" ); cg_atmFx.effectwatershader = trap_R_RegisterShader("gfx/atmosphere/raindropwater");
if( cg_atmFx.landSplash ) if (cg_atmFx.landSplash)
cg_atmFx.effectlandshader = trap_R_RegisterShader( "gfx/atmosphere/raindropsolid" ); cg_atmFx.effectlandshader = trap_R_RegisterShader("gfx/atmosphere/raindropsolid");
// Snow // Snow
} else if( !Q_stricmp(type, "snow") ) { } else if (!Q_stricmp(type, "snow")) {
for( cg_atmFx.numEffectShaders = 0; cg_atmFx.numEffectShaders < 6; cg_atmFx.numEffectShaders++ ) { for (cg_atmFx.numEffectShaders = 0; cg_atmFx.numEffectShaders < 6; cg_atmFx.numEffectShaders++) {
if( !( cg_atmFx.effectshaders[cg_atmFx.numEffectShaders] = trap_R_RegisterShader( va("gfx/atmosphere/snowflake0%i", cg_atmFx.numEffectShaders ) ) ) ) if (!
cg_atmFx.effectshaders[cg_atmFx.numEffectShaders] = -1; // we had some kind of a problem (cg_atmFx.effectshaders[cg_atmFx.numEffectShaders] =
trap_R_RegisterShader(va("gfx/atmosphere/snowflake0%i", cg_atmFx.numEffectShaders))))
cg_atmFx.effectshaders[cg_atmFx.numEffectShaders] = -1; // we had some kind of a problem
} }
cg_atmFx.waterSplash = 0; cg_atmFx.waterSplash = 0;
cg_atmFx.landSplash = 0; cg_atmFx.landSplash = 0;
@ -653,7 +646,7 @@ void CG_EffectParse( const char *effectstr )
cg_atmFx.numEffectShaders = 0; cg_atmFx.numEffectShaders = 0;
// Initialise atmospheric effect to prevent all particles falling at the start // Initialise atmospheric effect to prevent all particles falling at the start
for( count = 0; count < cg_atmFx.numDrops; count++ ) for (count = 0; count < cg_atmFx.numDrops; count++)
cg_atmFx.particles[count].nextDropTime = ATMOSPHERIC_DROPDELAY + (rand() % ATMOSPHERIC_DROPDELAY); cg_atmFx.particles[count].nextDropTime = ATMOSPHERIC_DROPDELAY + (rand() % ATMOSPHERIC_DROPDELAY);
CG_EffectGust(); CG_EffectGust();
@ -672,28 +665,23 @@ void CG_AddAtmosphericEffects()
vec3_t currvec; vec3_t currvec;
float currweight; float currweight;
if( cg_atmFx.numDrops <= 0 || cg_atmFx.numEffectShaders == 0 ) if (cg_atmFx.numDrops <= 0 || cg_atmFx.numEffectShaders == 0)
return; return;
max = cg_lowEffects.integer ? (cg_atmFx.numDrops >> 1) : cg_atmFx.numDrops; max = cg_lowEffects.integer ? (cg_atmFx.numDrops >> 1) : cg_atmFx.numDrops;
if( CG_EffectGustCurrent( currvec, &currweight, &currnum ) ) if (CG_EffectGustCurrent(currvec, &currweight, &currnum))
CG_EffectGust(); // Recalculate gust parameters CG_EffectGust(); // Recalculate gust parameters
for( curr = 0; curr < max; curr++ ) for (curr = 0; curr < max; curr++) {
{
particle = &cg_atmFx.particles[curr]; particle = &cg_atmFx.particles[curr];
if( !cg_atmFx.ParticleCheckVisible( particle ) ) if (!cg_atmFx.ParticleCheckVisible(particle)) {
{
// Effect has terminated / fallen from screen view // Effect has terminated / fallen from screen view
if( !particle->nextDropTime ) if (!particle->nextDropTime) {
{
// Stop rain being synchronized // Stop rain being synchronized
particle->nextDropTime = rand() % ATMOSPHERIC_DROPDELAY; particle->nextDropTime = rand() % ATMOSPHERIC_DROPDELAY;
} } else if (currnum < curr || particle->nextDropTime > cg.time)
else if( currnum < curr || particle->nextDropTime > cg.time )
continue; continue;
if( !cg_atmFx.ParticleGenerate( particle, currvec, currweight ) ) if (!cg_atmFx.ParticleGenerate(particle, currvec, currweight)) {
{
// Ensure it doesn't attempt to generate every frame, to prevent // Ensure it doesn't attempt to generate every frame, to prevent
// 'clumping' when there's only a small sky area available. // 'clumping' when there's only a small sky area available.
particle->nextDropTime = cg.time + ATMOSPHERIC_DROPDELAY; particle->nextDropTime = cg.time + ATMOSPHERIC_DROPDELAY;
@ -701,13 +689,12 @@ void CG_AddAtmosphericEffects()
} }
} }
cg_atmFx.ParticleRender( particle ); cg_atmFx.ParticleRender(particle);
} }
cg_atmFx.lastRainTime = cg.time; cg_atmFx.lastRainTime = cg.time;
} }
/* /*
** G_AtmosphericKludge ** G_AtmosphericKludge
*/ */
@ -718,20 +705,20 @@ qboolean CG_AtmosphericKludge()
// Activate effects for specified kludge maps that don't // Activate effects for specified kludge maps that don't
// have it specified for them. // have it specified for them.
if( kludgeChecked ) if (kludgeChecked)
return( kludgeResult ); return (kludgeResult);
kludgeChecked = qtrue; kludgeChecked = qtrue;
kludgeResult = qfalse; kludgeResult = qfalse;
// NiceAss: apparently example code: // NiceAss: apparently example code:
// T=RAIN and T=SNOW are the two options // T=RAIN and T=SNOW are the two options
/* /*
if( !Q_stricmp( cgs.mapname, "maps/bank.bsp" ) ) if( !Q_stricmp( cgs.mapname, "maps/bank.bsp" ) )
{ {
CG_EffectParse( "T=RAIN" ); CG_EffectParse( "T=RAIN" );
return ( kludgeResult = qtrue ); return ( kludgeResult = qtrue );
} }
*/ */
return( kludgeResult = qfalse ); return (kludgeResult = qfalse);
} }