예제 #1
0
/**
 * @brief Add atmospheric effects
 * @details Add atmospheric effects (e.g. rain, snow etc.) to view]
 */
void CG_AddAtmosphericEffects()
{
    int                      curr, max, currnum;
    cg_atmosphericParticle_t *particle;
    vec3_t                   currvec;
    float                    currweight;

    if (cg_atmFx.numDrops <= 0 || cg_atmFx.numEffectShaders == 0 || cg_atmosphericEffects.value <= 0)
    {
        return;
    }

    max = cg_atmosphericEffects.value < 1 ? cg_atmosphericEffects.value * cg_atmFx.numDrops : cg_atmFx.numDrops;

    if (CG_EffectGustCurrent(currvec, &currweight, &currnum))
    {
        // recalculate gust parameters
        CG_EffectGust();
    }

    // allow parametric management of drop count for swelling/waning precip
    cg_atmFx.oldDropsActive = cg_atmFx.dropsActive;
    cg_atmFx.dropsActive    = 0;
    cg_atmFx.dropsCreated   = 0;

    VectorSet(cg_atmFx.viewDir, cg.refdef_current->viewaxis[0][0], cg.refdef_current->viewaxis[0][1], 0.f);

    for (curr = 0; curr < max; curr++)
    {
        particle = &cg_atmFx.particles[curr];

        if (!cg_atmFx.ParticleCheckVisible(particle))
        {
            // effect has terminated or fallen from screen view
            if (!cg_atmFx.ParticleGenerate(particle, currvec, currweight))
            {
                continue;
            }
            else
            {
                cg_atmFx.dropsCreated++;
            }
        }

        cg_atmFx.ParticleRender(particle);
        cg_atmFx.dropsActive++;
    }

    cg_atmFx.lastRainTime = cg.time;
}
예제 #2
0
void CG_AddAtmosphericEffects()
{
	// Add atmospheric effects (e.g. rain, snow etc.) to view

	int curr, max, currnum;
	cg_atmosphericParticle_t *particle;
	vec3_t currvec;
	float currweight;

	if (cg_atmFx.numDrops <= 0 || cg_atmFx.numEffectShaders == 0)
		return;

	max = cg_lowEffects.integer ? (cg_atmFx.numDrops >> 1) : cg_atmFx.numDrops;
	if (CG_EffectGustCurrent(currvec, &currweight, &currnum))
		CG_EffectGust();	// Recalculate gust parameters
	for (curr = 0; curr < max; curr++) {
		particle = &cg_atmFx.particles[curr];
		if (!cg_atmFx.ParticleCheckVisible(particle)) {
			// Effect has terminated / fallen from screen view

			if (!particle->nextDropTime) {
				// Stop rain being synchronized 
				particle->nextDropTime = rand() % ATMOSPHERIC_DROPDELAY;
			} else if (currnum < curr || particle->nextDropTime > cg.time)
				continue;
			if (!cg_atmFx.ParticleGenerate(particle, currvec, currweight)) {
				// Ensure it doesn't attempt to generate every frame, to prevent
				// 'clumping' when there's only a small sky area available.
				particle->nextDropTime = cg.time + ATMOSPHERIC_DROPDELAY;
				continue;
			}
		}

		cg_atmFx.ParticleRender(particle);
	}

	cg_atmFx.lastRainTime = cg.time;
}
예제 #3
0
void CG_EffectParse(const char *effectstr)
{
	// Split the string into it's component parts.

	float bmin, bmax, cmin, cmax, gmin, gmax, bdrop, gdrop, wsplash, lsplash;
	int count;
	char *startptr, *eqptr, *endptr, *type;
	char workbuff[128];

	if (CG_AtmosphericKludge())
		return;

	// Set up some default values
	cg_atmFx.baseVec[0] = cg_atmFx.baseVec[1] = 0;
	cg_atmFx.gustVec[0] = cg_atmFx.gustVec[1] = 100;
	bmin = 5;
	bmax = 10;
	cmin = 1;
	cmax = 1;
	gmin = 0;
	gmax = 2;
	bdrop = gdrop = 300;
	cg_atmFx.baseWeight = 0.7f;
	cg_atmFx.gustWeight = 1.5f;
	wsplash = 1;
	lsplash = 1;
	type = NULL;

	// Parse the parameter string
	Q_strncpyz(workbuff, effectstr, sizeof(workbuff));
	for (startptr = workbuff; *startptr;) {
		for (eqptr = startptr; *eqptr && *eqptr != '=' && *eqptr != ','; eqptr++);
		if (!*eqptr)
			break;	// No more string
		if (*eqptr == ',') {
			startptr = eqptr + 1;	// Bad argument, continue
			continue;
		}
		*eqptr++ = 0;
		for (endptr = eqptr; *endptr && *endptr != ','; endptr++);
		if (*endptr)
			*endptr++ = 0;

		if (!type) {
			if (Q_stricmp(startptr, "T")) {
				cg_atmFx.numDrops = 0;
				CG_Printf("Atmospheric effect must start with a type.\n");
				return;
			}
			if (!Q_stricmp(eqptr, "RAIN")) {
				type = "rain";
				cg_atmFx.ParticleCheckVisible = &CG_RainParticleCheckVisible;
				cg_atmFx.ParticleGenerate = &CG_RainParticleGenerate;
				cg_atmFx.ParticleRender = &CG_RainParticleRender;

				cg_atmFx.baseVec[2] = cg_atmFx.gustVec[2] = -ATMOSPHERIC_RAIN_SPEED;
			} else if (!Q_stricmp(eqptr, "SNOW")) {
				type = "snow";
				cg_atmFx.ParticleCheckVisible = &CG_RainParticleCheckVisible;
				cg_atmFx.ParticleGenerate = &CG_SnowParticleGenerate;
				cg_atmFx.ParticleRender = &CG_SnowParticleRender;

				cg_atmFx.baseVec[2] = cg_atmFx.gustVec[2] = -ATMOSPHERIC_SNOW_SPEED;
			} else {
				cg_atmFx.numDrops = 0;
				CG_Printf("Only effect type 'rain' and 'snow' are supported.\n");
				return;
			}
		} else {
			if (!Q_stricmp(startptr, "B"))
				CG_EP_ParseFloats(eqptr, &bmin, &bmax);
			else if (!Q_stricmp(startptr, "C"))
				CG_EP_ParseFloats(eqptr, &cmin, &cmax);
			else if (!Q_stricmp(startptr, "G"))
				CG_EP_ParseFloats(eqptr, &gmin, &gmax);
			else if (!Q_stricmp(startptr, "BV"))
				CG_EP_ParseFloats(eqptr, &cg_atmFx.baseVec[0], &cg_atmFx.baseVec[1]);
			else if (!Q_stricmp(startptr, "GV"))
				CG_EP_ParseFloats(eqptr, &cg_atmFx.gustVec[0], &cg_atmFx.gustVec[1]);
			else if (!Q_stricmp(startptr, "W"))
				CG_EP_ParseFloats(eqptr, &cg_atmFx.baseWeight, &cg_atmFx.gustWeight);
			else if (!Q_stricmp(startptr, "S"))
				CG_EP_ParseFloats(eqptr, &wsplash, &lsplash);
			else if (!Q_stricmp(startptr, "D"))
				CG_EP_ParseFloats(eqptr, &bdrop, &gdrop);
			else
				CG_Printf("Unknown effect key '%s'.\n", startptr);
		}
		startptr = endptr;
	}

	if (!type) {
		// No effects

		cg_atmFx.numDrops = -1;
		return;
	}

	cg_atmFx.baseMinTime = 1000 * bmin;
	cg_atmFx.baseMaxTime = 1000 * bmax;
	cg_atmFx.changeMinTime = 1000 * cmin;
	cg_atmFx.changeMaxTime = 1000 * cmax;
	cg_atmFx.gustMinTime = 1000 * gmin;
	cg_atmFx.gustMaxTime = 1000 * gmax;
	cg_atmFx.baseDrops = bdrop;
	cg_atmFx.gustDrops = gdrop;
	cg_atmFx.waterSplash = wsplash;
	cg_atmFx.landSplash = lsplash;

	cg_atmFx.numDrops = (cg_atmFx.baseDrops > cg_atmFx.gustDrops) ? cg_atmFx.baseDrops : cg_atmFx.gustDrops;
	if (cg_atmFx.numDrops > MAX_ATMOSPHERIC_PARTICLES)
		cg_atmFx.numDrops = MAX_ATMOSPHERIC_PARTICLES;

	// Load graphics

	// Rain
	if (!Q_stricmp(type, "rain")) {
		cg_atmFx.numEffectShaders = 1;
		if (!(cg_atmFx.effectshaders[0] = trap_R_RegisterShader("gfx/atmosphere/raindrop")))
			cg_atmFx.effectshaders[0] = -1;
		if (cg_atmFx.waterSplash)
			cg_atmFx.effectwatershader = trap_R_RegisterShader("gfx/atmosphere/raindropwater");
		if (cg_atmFx.landSplash)
			cg_atmFx.effectlandshader = trap_R_RegisterShader("gfx/atmosphere/raindropsolid");

		// Snow
	} else if (!Q_stricmp(type, "snow")) {
		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))))
				cg_atmFx.effectshaders[cg_atmFx.numEffectShaders] = -1;	// we had some kind of a problem
		}
		cg_atmFx.waterSplash = 0;
		cg_atmFx.landSplash = 0;

		// This really should never happen
	} else
		cg_atmFx.numEffectShaders = 0;

	// Initialise atmospheric effect to prevent all particles falling at the start
	for (count = 0; count < cg_atmFx.numDrops; count++)
		cg_atmFx.particles[count].nextDropTime = ATMOSPHERIC_DROPDELAY + (rand() % ATMOSPHERIC_DROPDELAY);

	CG_EffectGust();
}
예제 #4
0
/**
 * @brief Parse effect
 * @details Split the string into it's component parts.
 */
void CG_EffectParse(const char *effectstr)
{
    float       bmin, bmax, cmin, cmax, gmin, gmax, bdrop, gdrop /*, wsplash, lsplash*/;
    int         bheight;
    char        *startptr, *eqptr, *endptr;
    char        workbuff[128];
    atmFXType_t atmFXType = ATM_NONE;

    if (CG_AtmosphericKludge())
    {
        return;
    }

    // set up some default values
    cg_atmFx.baseVec[0] = cg_atmFx.baseVec[1] = 0;
    cg_atmFx.gustVec[0] = cg_atmFx.gustVec[1] = 100;
    bmin                = 5;
    bmax                = 10;
    cmin                = 1;
    cmax                = 1;
    gmin                = 0;
    gmax                = 2;
    bdrop               = gdrop = 300;
    cg_atmFx.baseWeight = 0.7f;
    cg_atmFx.gustWeight = 1.5f;
    bheight             = 0;

    // parse the parameter string
    Q_strncpyz(workbuff, effectstr, sizeof(workbuff));

    for (startptr = workbuff; *startptr; )
    {
        for (eqptr = startptr; *eqptr && *eqptr != '=' && *eqptr != ','; eqptr++)
            ;
        if (!*eqptr)
        {
            break;          // No more string
        }
        if (*eqptr == ',')
        {
            startptr = eqptr + 1;   // Bad argument, continue
            continue;
        }

        *eqptr++ = 0;

        for (endptr = eqptr; *endptr && *endptr != ','; endptr++)
            ;
        if (*endptr)
        {
            *endptr++ = 0;
        }

        if (atmFXType == ATM_NONE)
        {
            if (Q_stricmp(startptr, "T"))
            {
                cg_atmFx.numDrops = 0;
                CG_Printf("Atmospheric effect must start with a type.\n");
                return;
            }

            if (!Q_stricmp(eqptr, "RAIN"))
            {
                atmFXType                     = ATM_RAIN;
                cg_atmFx.ParticleCheckVisible = &CG_RainParticleCheckVisible;
                cg_atmFx.ParticleGenerate     = &CG_RainParticleGenerate;
                cg_atmFx.ParticleRender       = &CG_RainParticleRender;

                cg_atmFx.baseVec[2] = cg_atmFx.gustVec[2] = -ATMOSPHERIC_RAIN_SPEED;
            }
            else if (!Q_stricmp(eqptr, "SNOW"))
            {
                atmFXType                     = ATM_SNOW;
                cg_atmFx.ParticleCheckVisible = &CG_SnowParticleCheckVisible;
                cg_atmFx.ParticleGenerate     = &CG_SnowParticleGenerate;
                cg_atmFx.ParticleRender       = &CG_SnowParticleRender;

                cg_atmFx.baseVec[2] = cg_atmFx.gustVec[2] = -ATMOSPHERIC_SNOW_SPEED;
            }
            else
            {
                cg_atmFx.numDrops = 0;
                CG_Printf("Only effect type 'rain' and 'snow' are supported.\n");
                return;
            }
        }
        else
        {
            if (!Q_stricmp(startptr, "B"))
            {
                CG_EP_ParseFloats(eqptr, &bmin, &bmax);
            }
            else if (!Q_stricmp(startptr, "C"))
            {
                CG_EP_ParseFloats(eqptr, &cmin, &cmax);
            }
            else if (!Q_stricmp(startptr, "G"))
            {
                CG_EP_ParseFloats(eqptr, &gmin, &gmax);
            }
            else if (!Q_stricmp(startptr, "BV"))
            {
                CG_EP_ParseFloats(eqptr, &cg_atmFx.baseVec[0], &cg_atmFx.baseVec[1]);
            }
            else if (!Q_stricmp(startptr, "GV"))
            {
                CG_EP_ParseFloats(eqptr, &cg_atmFx.gustVec[0], &cg_atmFx.gustVec[1]);
            }
            else if (!Q_stricmp(startptr, "W"))
            {
                CG_EP_ParseFloats(eqptr, &cg_atmFx.baseWeight, &cg_atmFx.gustWeight);
            }
            else if (!Q_stricmp(startptr, "D"))
            {
                CG_EP_ParseFloats(eqptr, &bdrop, &gdrop);
            }
            else if (!Q_stricmp(startptr, "H"))
            {
                CG_EP_ParseInts(eqptr, &bheight, &bheight);
            }
            else
            {
                CG_Printf("Unknown effect key '%s'.\n", startptr);
            }
        }
        startptr = endptr;
    }

    if (atmFXType == ATM_NONE || !BG_LoadTraceMap(cgs.rawmapname, cg.mapcoordsMins, cg.mapcoordsMaxs))
    {
        // no effects
        cg_atmFx.numDrops = -1;
        return;
    }

    cg_atmFx.baseHeightOffset = bheight;

    if (cg_atmFx.baseHeightOffset < 0)
    {
        cg_atmFx.baseHeightOffset = 0;
    }

    cg_atmFx.baseMinTime   = 1000 * bmin;
    cg_atmFx.baseMaxTime   = 1000 * bmax;
    cg_atmFx.changeMinTime = 1000 * cmin;
    cg_atmFx.changeMaxTime = 1000 * cmax;
    cg_atmFx.gustMinTime   = 1000 * gmin;
    cg_atmFx.gustMaxTime   = 1000 * gmax;
    cg_atmFx.baseDrops     = bdrop;
    cg_atmFx.gustDrops     = gdrop;

    cg_atmFx.numDrops = (cg_atmFx.baseDrops > cg_atmFx.gustDrops) ? cg_atmFx.baseDrops : cg_atmFx.gustDrops;

    if (cg_atmFx.numDrops > MAX_ATMOSPHERIC_PARTICLES)
    {
        cg_atmFx.numDrops = MAX_ATMOSPHERIC_PARTICLES;
    }

    // load graphics
    if (atmFXType == ATM_RAIN)      // rain
    {
        cg_atmFx.numEffectShaders = 1;
        cg_atmFx.effectshaders[0] = trap_R_RegisterShader("gfx/misc/raindrop");

        if (!(cg_atmFx.effectshaders[0]))
        {
            cg_atmFx.effectshaders[0] = -1;
            cg_atmFx.numEffectShaders = 0;
        }
    }
    else if (atmFXType == ATM_SNOW) // snow
    {
        cg_atmFx.numEffectShaders = 1;
        cg_atmFx.effectshaders[0] = trap_R_RegisterShader("gfx/misc/snow");
    }
    else
    {
        // this really should never happen
        cg_atmFx.numEffectShaders = 0;
    }

    CG_EffectGust();
}
예제 #5
0
void CG_AddAtmosphericEffects()
{
	// Add atmospheric effects (e.g. rain, snow etc.) to view

	int curr, max, currnum;
	cg_atmosphericParticle_t *particle;
	vec3_t currvec;
	float currweight;

	if( cg_atmFx.numDrops <= 0 || cg_atmFx.numEffectShaders == 0 || cg_atmosphericEffects.value <= 0 )
		return;

#ifndef ATM_NEW
	CG_ClearPolyPool();
#endif // ATM_NEW

	max = cg_atmosphericEffects.value < 1 ? cg_atmosphericEffects.value * cg_atmFx.numDrops : cg_atmFx.numDrops;
	if( CG_EffectGustCurrent( currvec, &currweight, &currnum ) )
		CG_EffectGust();			// Recalculate gust parameters

	// ydnar: allow parametric management of drop count for swelling/waning precip
	cg_atmFx.oldDropsActive = cg_atmFx.dropsActive;
	cg_atmFx.dropsActive = 0;
	
	cg_atmFx.dropsRendered = cg_atmFx.dropsCreated = cg_atmFx.dropsSkipped = 0;

//	getgroundtime = getskytime = rendertime = checkvisibletime = generatetime = 0;
//	n_getgroundtime = n_getskytime = n_rendertime = n_checkvisibletime = n_generatetime = 0;

	VectorSet( cg_atmFx.viewDir, cg.refdef_current->viewaxis[0][0], cg.refdef_current->viewaxis[0][1], 0.f );

	for( curr = 0; curr < max; curr++ )
	{
		particle = &cg_atmFx.particles[curr];
		//%	if( !CG_SnowParticleCheckVisible( particle ) )
		if( !cg_atmFx.ParticleCheckVisible( particle ) )
		{
			// Effect has terminated / fallen from screen view
			/*
			if( !particle->nextDropTime )
			{
				// Stop rain being synchronized 
				particle->nextDropTime = cg.time + rand() % ATMOSPHERIC_DROPDELAY;
			}
			if( currnum < curr || particle->nextDropTime > cg.time )
			{
				cg_atmFx.dropsRendered++;
				continue;
			} */
			//%	if( !CG_SnowParticleGenerate( particle, currvec, currweight ) )
			if( !cg_atmFx.ParticleGenerate( particle, currvec, currweight ) )
			{
				// Ensure it doesn't attempt to generate every frame, to prevent
				// 'clumping' when there's only a small sky area available.
				particle->nextDropTime = cg.time + ATMOSPHERIC_DROPDELAY;
				continue;
			}
			else
			{
				cg_atmFx.dropsCreated++;
			}
		}
		
		//%	CG_RainParticleRender( particle );
		cg_atmFx.ParticleRender( particle );
		cg_atmFx.dropsActive++;
	}

//	CG_RenderPolyPool();

	cg_atmFx.lastRainTime = cg.time;
	
//	CG_Printf( "Active: %d Generated: %d Rendered: %d Skipped: %d\n", cg_atmFx.dropsActive, cg_atmFx.dropsCreated, cg_atmFx.dropsRendered, cg_atmFx.dropsSkipped );
//	CG_Printf( "gg: %i gs: %i rt: %i cv: %i ge: %i\n", getgroundtime, getskytime, rendertime, checkvisibletime, generatetime );
//	CG_Printf( "\\-> %i \\-> %i \\-> %i \\-> %i \\-> %i\n", n_getgroundtime, n_getskytime, n_rendertime, n_checkvisibletime, n_generatetime );
}