Example #1
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : fTimeDelta - 
//-----------------------------------------------------------------------------
void C_SmokeStack::Update(float fTimeDelta)
{
    if (!m_pParticleMgr)
    {
        assert(false);
        return;
    }

    // Don't spawn particles unless we're visible.
    if (m_bEmit && (m_ParticleEffect.WasDrawnPrevFrame() || m_ParticleEffect.GetAlwaysSimulate()))
    {
        // Add new particles.																	
        Vector forward, right, up;
        AngleVectors(GetAbsAngles(), &forward, &right, &up);

        float tempDelta = fTimeDelta;
        while (m_ParticleSpawn.NextEvent(tempDelta))
        {
            int iRandomFrame = random->RandomInt(0, m_iMaxFrames);

            iRandomFrame = 0;

            // Make a new particle.
            if (SmokeStackParticle *pParticle = (SmokeStackParticle*) m_ParticleEffect.AddParticle(sizeof(SmokeStackParticle), m_MaterialHandle[iRandomFrame]))
            {
                float angle = FRand(0, 2.0f*M_PI_F);

                pParticle->m_Pos = GetAbsOrigin() +
                    right * (cos(angle) * m_flBaseSpread) +
                    forward * (sin(angle) * m_flBaseSpread);

                pParticle->m_Velocity =
                    FRand(-m_SpreadSpeed, m_SpreadSpeed) * right +
                    FRand(-m_SpreadSpeed, m_SpreadSpeed) * forward +
                    m_Speed * up;

                pParticle->m_vAccel = m_vWind;
                pParticle->m_Lifetime = 0;
                pParticle->m_flAngle = 0.0f;

                pParticle->m_flRollDelta = random->RandomFloat(-m_flRollSpeed, m_flRollSpeed);
                pParticle->m_flSortPos = pParticle->m_Pos.z;
            }
        }
    }

    // Setup the twist matrix.
    float flTwist = (m_flTwist * (M_PI_F * 2.f) / 360.0f) * Helper_GetFrameTime();
    if ((m_bTwist = !!flTwist))
    {
        m_TwistMat[0][0] = cos(flTwist);
        m_TwistMat[0][1] = sin(flTwist);
        m_TwistMat[1][0] = -sin(flTwist);
        m_TwistMat[1][1] = cos(flTwist);
    }

    QueueLightParametersInRenderer();
}
void NoiseGenerator::GenerateShiftNoise(std::vector<double>& out_serie)
{
	srand( static_cast<unsigned>( time(0) ) );
	double rand_one = rand();

	double range_value_min = 1000.;
	double range_value_max = 10000.;
	rand_one = FRand(rand_one);
	double r = rand_one * range_value_max + range_value_min;
	out_serie.assign(SerieSettings::SerieSize(),r);
}
//-----------------------------------------------------------------------------
// Purpose: Starts the effect
// Input  : *pParticleMgr - 
//			*pArgs - 
//-----------------------------------------------------------------------------
void C_PerfTest::Start(CParticleMgr *pParticleMgr, IPrototypeArgAccess *pArgs)
{
	pParticleMgr->AddEffect( &m_ParticleEffect, this );
	m_MaterialHandle = m_ParticleEffect.FindOrAddMaterial("particle/particle_sphere");

	m_pParticleMgr = pParticleMgr;

	// Make a bunch of particles.
	srand( 0 );
	for( int i=0; i < m_nParticles; i++ )
	{
		PerfTestParticle *pParticle = (PerfTestParticle*)m_ParticleEffect.AddParticle( sizeof(PerfTestParticle), m_MaterialHandle );

		static float spread=30;
		pParticle->m_Pos = Vector(
			FRand(-spread, spread),
			FRand(-spread, spread),
			FRand(-spread, spread));
	}
}
void C_ParticleSmokeGrenade::UpdateParticleAndFindTrade( int iParticle, float fTimeDelta )
{
	SmokeParticleInfo *pInfo = &m_SmokeParticleInfos[iParticle];

	pInfo->m_pParticle->m_FadeAlpha = pInfo->m_FadeAlpha;
	pInfo->m_pParticle->m_Color[0] = pInfo->m_Color[0];
	pInfo->m_pParticle->m_Color[1] = pInfo->m_Color[1];
	pInfo->m_pParticle->m_Color[2] = pInfo->m_Color[2];

	// Is there an adjacent one that's not trading?
	int x, y, z;
	GetParticleInfoXYZ(iParticle, x, y, z);

	int xCountOffset = rand();
	int yCountOffset = rand();
	int zCountOffset = rand();

	bool bFound = false;
	for(int xCount=0; xCount < 3 && !bFound; xCount++)
	{
		for(int yCount=0; yCount < 3 && !bFound; yCount++)
		{
			for(int zCount=0; zCount < 3; zCount++)
			{
				int testX = x + g_OffsetLookup[(xCount+xCountOffset) % 3];
				int testY = y + g_OffsetLookup[(yCount+yCountOffset) % 3];
				int testZ = z + g_OffsetLookup[(zCount+zCountOffset) % 3];

				if(testX == x && testY == y && testZ == z)
					continue;

				if(IsValidXYZCoords(testX, testY, testZ))
				{
					SmokeParticleInfo *pOther = GetSmokeParticleInfo(testX, testY, testZ);
					if(pOther->m_pParticle && pOther->m_TradeIndex == -1)
					{
						// Ok, this one is looking to trade also.
						pInfo->m_TradeIndex = GetSmokeParticleIndex(testX, testY, testZ);
						pOther->m_TradeIndex = iParticle;
						pInfo->m_TradeClock = pOther->m_TradeClock = 0;
						pInfo->m_TradeDuration = FRand(TRADE_DURATION_MIN, TRADE_DURATION_MAX);
						
						bFound = true;
						break;
					}
				}
			}
		}
	}
}
void NoiseGenerator::GenerateJumpNoise(std::vector<double>& out_serie)
{
	std::vector<double> x_points;
	std::vector<double> jump_values;

	srand( static_cast<unsigned>( time(0) ) );
	double rand_one = rand();
	
	double range_value_min = 1.;
	double range_value_max = 100.;

	for( int i = 0 ; i < SerieSettings::SerieSize() ; i++ )
	{
		rand_one = FRand(rand_one);
		if( rand_one <= 0.01 )
		{
			rand_one = FRand(rand_one);
			double r = rand_one * range_value_max + range_value_min;
			out_serie.push_back(r);
		}
		else
			out_serie.push_back(0.);
	}
}
void NoiseGenerator::GenerateWhiteNoise(std::vector<double>& out_serie)
{
	srand( static_cast<unsigned>( time(0) ) );
	out_serie.clear();
	double RANGE_MIN = -10.;
	double RANGE_MAX = 10.;
	double rand_one = rand();
	for( int i = 0 ; i < SerieSettings::SerieSize() ; i++ )
	{
		rand_one = FRand(rand_one);
		double rand100 = rand_one * RANGE_MAX + RANGE_MIN;
		out_serie.push_back(rand100);
	}
	UINT addr = -1;
}
void C_AR2Explosion::Start(CParticleMgr *pParticleMgr, IPrototypeArgAccess *pArgs)
{
	m_pParticleMgr = pParticleMgr;
	if(!pParticleMgr->AddEffect(&m_ParticleEffect, this))
		return;

	if (!m_szMaterialName[0])
	{
		strcpy(m_szMaterialName, "particle/particle_noisesphere");
	}

	m_MaterialHandle = m_ParticleEffect.FindOrAddMaterial(m_szMaterialName);

	// Precalculate stuff for the particle spawning..
	#define NUM_DUSTEMITTER_SURFINFOS	128
	SurfInfo surfInfos[NUM_DUSTEMITTER_SURFINFOS];
	int nSurfInfos;

	// Center of explosion.
	Vector vCenter = GetAbsOrigin(); // HACKHACK.. when the engine bug is fixed, use origin.

	
	#ifdef PARTICLEPROTOTYPE_APP
		float surfSize = 10000;
		nSurfInfos = 1;
		surfInfos[0].m_Verts[0].Init(-surfSize,-surfSize,0);
		surfInfos[0].m_Verts[1].Init(-surfSize,surfSize,0);
		surfInfos[0].m_Verts[2].Init(surfSize, surfSize,0);
		surfInfos[0].m_Verts[3].Init(surfSize,-surfSize,0);
		surfInfos[0].m_nVerts = 4;
		surfInfos[0].m_Plane.m_Normal.Init(0,0,1);
		surfInfos[0].m_Plane.m_Dist = -3;
	#else
		{
			nSurfInfos = 0;
			C_BaseEntity *ent = cl_entitylist->GetEnt( 0 );
			if ( ent )
			{
				nSurfInfos = engine->GetIntersectingSurfaces(
					ent->GetModel(),
					vCenter,
					AR2_DUST_RADIUS,
					true,
					surfInfos,
					NUM_DUSTEMITTER_SURFINFOS);
			}
		}
	#endif

	int nParticles = 0;

	if(nSurfInfos > 0)
	{
		// For nParticles*N, generate a ray and cast it out. If it hits anything, spawn a particle there.
		int nTestsPerParticle=3;
		for(int i=0; i < NUM_AR2_EXPLOSION_PARTICLES; i++)
		{
			for(int iTest=0; iTest < nTestsPerParticle; iTest++)
			{
				Vector randVec = RandomVector(-1,1);
				VectorNormalize( randVec );
				Vector startPos = vCenter + randVec * AR2_DUST_RADIUS;

				randVec = RandomVector(-1,1);
				VectorNormalize( randVec );
				Vector endPos = vCenter + randVec * AR2_DUST_RADIUS;

				#define MAX_SURFINFO_INTERSECTIONS	4
				SurfInfo *pIntersected[MAX_SURFINFO_INTERSECTIONS];
				Vector vIntersections[MAX_SURFINFO_INTERSECTIONS];
				int nIntersections;
				nIntersections = IntersectSegmentWithSurfInfos(
					startPos, 
					endPos, 
					surfInfos, 
					nSurfInfos, 
					pIntersected,
					vIntersections,
					MAX_SURFINFO_INTERSECTIONS);
				
				if(nIntersections)
				{
					int iIntersection = rand() % nIntersections;

					Vector velocity;
					//velocity.Init(-1.0f + ((float)rand()/RAND_MAX) * 2.0f, -1.0f + ((float)rand()/RAND_MAX) * 2.0f, -1.0f + ((float)rand()/RAND_MAX) * 2.0f);
					//velocity = velocity * FRand(m_MinSpeed, m_MaxSpeed);
					Vector direction = (vIntersections[iIntersection] - vCenter );
					float dist = VectorNormalize( direction );
					if(dist > AR2_DUST_RADIUS)
						dist = AR2_DUST_RADIUS;

					static float power = 2.0f;
					float falloffMul = pow(1.0f - dist / AR2_DUST_RADIUS, power);

					Vector reflection = direction - 2 * DotProduct( direction, pIntersected[iIntersection]->m_Plane.m_Normal ) * pIntersected[iIntersection]->m_Plane.m_Normal;
					VectorNormalize( reflection );

					velocity = reflection * AR2_DUST_SPEED * falloffMul;
					// velocity = velocity + (vIntersections[iIntersection] - vCenter) * falloffMul;

					
					/*
					debugoverlay->AddLineOverlay( vIntersections[iIntersection], 
												  vIntersections[iIntersection] + reflection * 64,
												  128, 128, 255, false, 15.0 );
					*/
#if 1
					AR2ExplosionParticle *pParticle = 
						(AR2ExplosionParticle*)m_ParticleEffect.AddParticle( sizeof(AR2ExplosionParticle), m_MaterialHandle );

					if(pParticle)
					{
						pParticle->m_Pos = vIntersections[iIntersection];
						pParticle->m_Start = pParticle->m_Pos;
						pParticle->m_Dist = 8.0;
						pParticle->m_Velocity = velocity;
						// sound == 13031.496062992125984251968503937ips
						pParticle->m_Lifetime = -dist / 13031.5f - 0.1;
						pParticle->m_Roll = FRand( 0, M_PI * 2 );
						pParticle->m_RollSpeed = FRand( -1, 1 ) * 0.4;
						pParticle->m_Dwell = AR2_DUST_LIFETIME + random->RandomFloat( 0, AR2_DUST_LIFETIME_DELTA );
						nParticles++;
						break;
					}
#endif
				}
			}
		}
	}	

	// build interior smoke particles
	for(int i=nParticles; i < NUM_AR2_EXPLOSION_PARTICLES; i++)
	{
		Vector randVec = RandomVector(-1,1);
		VectorNormalize( randVec );
		Vector endPos = vCenter + randVec * AR2_DUST_RADIUS / 4.0;

		Vector direction = (endPos - vCenter );
		float dist = VectorNormalize( direction ) + random->RandomFloat( 0, AR2_DUST_RADIUS / 4.0 );
		if(dist > AR2_DUST_RADIUS)
			dist = AR2_DUST_RADIUS;

		static float power = 2.0f;
		float falloffMul = pow(1.0f - dist / (AR2_DUST_RADIUS / 2), power);

		Vector velocity = direction * AR2_DUST_SPEED * falloffMul;
		AR2ExplosionParticle *pParticle = 
			(AR2ExplosionParticle*)m_ParticleEffect.AddParticle( sizeof(AR2ExplosionParticle), m_MaterialHandle );

		if(pParticle)
		{
			pParticle->m_Pos = endPos;
			pParticle->m_Start = pParticle->m_Pos;
			pParticle->m_Dist = 8.0;
			pParticle->m_Velocity = velocity;
			// sound == 13031.496062992125984251968503937ips
			pParticle->m_Lifetime = -dist / 13031.5f - 0.1;
			pParticle->m_Roll = FRand( 0, M_PI * 2 );
			pParticle->m_RollSpeed = FRand( -1, 1 ) * 4.0;
			pParticle->m_Dwell = 0.5 * (AR2_DUST_LIFETIME + random->RandomFloat( 0, AR2_DUST_LIFETIME_DELTA ));
		}
	}
}
void C_FuncSmokeVolume::FillVolume()
{
	Vector vPos;
	for(int x=0; x < m_xCount; x++)
	{
		for(int y=0; y < m_yCount; y++)
		{
			for(int z=0; z < m_zCount; z++)
			{
				vPos = GetSmokeParticlePos( x, y, z );
				if(SmokeParticleInfo *pInfo = GetSmokeParticleInfo(x,y,z))
				{
					int contents = GetWorldPointContents(vPos);
					if(contents & CONTENTS_SOLID)
					{
						pInfo->m_pParticle = NULL;
					}
					else
					{
						SmokeGrenadeParticle *pParticle = 
							(SmokeGrenadeParticle*)m_ParticleEffect.AddParticle(sizeof(SmokeGrenadeParticle), m_MaterialHandle);

						if(pParticle)
						{
							pParticle->m_Pos = vPos;
							pParticle->m_ColorInterp = (unsigned char)((rand() * 255) / RAND_MAX);
							pParticle->m_RotationFactor = FRand( -1.0f, 1.0f ); // Rotation factor.
							pParticle->m_CurRotation = FRand( -m_RotationSpeed, m_RotationSpeed );
						}

#ifdef _DEBUG
						int testX, testY, testZ;
						int index = GetSmokeParticleIndex(x,y,z);
						GetParticleInfoXYZ(index, testX, testY, testZ);
						assert(testX == x && testY == y && testZ == z);
#endif

						Vector vColor = EngineGetLightForPoint(vPos);
						pInfo->m_Color[0] = LinearToTexture( vColor.x );
						pInfo->m_Color[1] = LinearToTexture( vColor.y );
						pInfo->m_Color[2] = LinearToTexture( vColor.z );

						// Cast some rays and if it's too close to anything, fade its alpha down.
						pInfo->m_FadeAlpha = 1;

						for(int i=0; i < NUM_FADE_PLANES; i++)
						{
							trace_t trace;
							WorldTraceLine(vPos, vPos + s_FadePlaneDirections[i] * 100, MASK_SOLID_BRUSHONLY, &trace);
							if(trace.fraction < 1.0f)
							{
								float dist = DotProduct(trace.plane.normal, vPos) - trace.plane.dist;
								if(dist < 0)
								{
									pInfo->m_FadeAlpha = 0;
								}
								else if(dist < m_ParticleRadius)
								{
									float alphaScale = dist / m_ParticleRadius;
									alphaScale *= alphaScale * alphaScale;
									pInfo->m_FadeAlpha *= alphaScale;
								}
							}
						}

						pInfo->m_pParticle = pParticle;
						pInfo->m_TradeIndex = -1;
					}
				}
			}
		}
	}
}
void C_FuncSmokeVolume::Update( float fTimeDelta )
{
	// lerp m_CurrentDensity towards m_Density at a rate of m_DensityRampSpeed
	if( m_CurrentDensity < m_Density )
	{
		m_CurrentDensity += m_DensityRampSpeed * fTimeDelta;
		if( m_CurrentDensity > m_Density )
		{
			m_CurrentDensity = m_Density;
		}
	}
	else if( m_CurrentDensity > m_Density )
	{
		m_CurrentDensity -= m_DensityRampSpeed * fTimeDelta;
		if( m_CurrentDensity < m_Density )
		{
			m_CurrentDensity = m_Density;
		}
	}

	if( m_CurrentDensity == 0.0f )
	{
		return;
	}
	
	// This is used to randomize the direction it chooses to move a particle in.
	int offsetLookup[3] = {-1,0,1};

	float tradeDurationMax = m_ParticleSpacingDistance / m_MovementSpeed;
	float tradeDurationMin = tradeDurationMax * 0.5f;
//	Warning( "tradeDuration: [%f,%f]\n", tradeDurationMin, tradeDurationMax );
	
	// Update all the moving traders and establish new ones.
	int nTotal = m_xCount * m_yCount * m_zCount;
	for( int i=0; i < nTotal; i++ )
	{
		SmokeParticleInfo *pInfo = &m_pSmokeParticleInfos[i];

		if(!pInfo->m_pParticle)
			continue;
	
		if(pInfo->m_TradeIndex == -1)
		{
			pInfo->m_pParticle->m_FadeAlpha = pInfo->m_FadeAlpha;
			pInfo->m_pParticle->m_Color[0] = pInfo->m_Color[0];
			pInfo->m_pParticle->m_Color[1] = pInfo->m_Color[1];
			pInfo->m_pParticle->m_Color[2] = pInfo->m_Color[2];

			// Is there an adjacent one that's not trading?
			int x, y, z;
			GetParticleInfoXYZ(i, x, y, z);

			int xCountOffset = rand();
			int yCountOffset = rand();
			int zCountOffset = rand();

			bool bFound = false;
			for(int xCount=0; xCount < 3 && !bFound; xCount++)
			{
				for(int yCount=0; yCount < 3 && !bFound; yCount++)
				{
					for(int zCount=0; zCount < 3; zCount++)
					{
						int testX = x + offsetLookup[(xCount+xCountOffset) % 3];
						int testY = y + offsetLookup[(yCount+yCountOffset) % 3];
						int testZ = z + offsetLookup[(zCount+zCountOffset) % 3];

						if(testX == x && testY == y && testZ == z)
							continue;

						if(IsValidXYZCoords(testX, testY, testZ))
						{
							SmokeParticleInfo *pOther = GetSmokeParticleInfo(testX, testY, testZ);
							if(pOther->m_pParticle && pOther->m_TradeIndex == -1)
							{
								// Ok, this one is looking to trade also.
								pInfo->m_TradeIndex = GetSmokeParticleIndex(testX, testY, testZ);
								pOther->m_TradeIndex = i;
								pInfo->m_TradeClock = pOther->m_TradeClock = 0;
								pOther->m_TradeDuration = pInfo->m_TradeDuration = FRand( tradeDurationMin, tradeDurationMax );
								
								bFound = true;
								break;
							}
						}
					}
				}
			}
		}
		else
		{
			SmokeParticleInfo *pOther = &m_pSmokeParticleInfos[pInfo->m_TradeIndex];
			assert(pOther->m_TradeIndex == i);
			
			// This makes sure the trade only gets updated once per frame.
			if(pInfo < pOther)
			{
				// Increment the trade clock..
				pInfo->m_TradeClock = (pOther->m_TradeClock += fTimeDelta);
				int x, y, z;
				GetParticleInfoXYZ(i, x, y, z);
				Vector myPos = GetSmokeParticlePos(x, y, z);
				
				int otherX, otherY, otherZ;
				GetParticleInfoXYZ(pInfo->m_TradeIndex, otherX, otherY, otherZ);
				Vector otherPos = GetSmokeParticlePos(otherX, otherY, otherZ);

				// Is the trade finished?
				if(pInfo->m_TradeClock >= pInfo->m_TradeDuration)
				{
					pInfo->m_TradeIndex = pOther->m_TradeIndex = -1;
					
					pInfo->m_pParticle->m_Pos = otherPos;
					pOther->m_pParticle->m_Pos = myPos;

					SmokeGrenadeParticle *temp = pInfo->m_pParticle;
					pInfo->m_pParticle = pOther->m_pParticle;
					pOther->m_pParticle = temp;
				}
				else
				{			
					// Ok, move them closer.
					float percent = (float)cos(pInfo->m_TradeClock * 2 * 1.57079632f / pInfo->m_TradeDuration);
					percent = percent * 0.5 + 0.5;
					
					pInfo->m_pParticle->m_FadeAlpha  = pInfo->m_FadeAlpha + (pOther->m_FadeAlpha - pInfo->m_FadeAlpha) * (1 - percent);
					pOther->m_pParticle->m_FadeAlpha = pInfo->m_FadeAlpha + (pOther->m_FadeAlpha - pInfo->m_FadeAlpha) * percent;

					InterpColor(pInfo->m_pParticle->m_Color,  pInfo->m_Color, pOther->m_Color, 1-percent);
					InterpColor(pOther->m_pParticle->m_Color, pInfo->m_Color, pOther->m_Color, percent);

					pInfo->m_pParticle->m_Pos  = myPos + (otherPos - myPos) * (1 - percent);
					pOther->m_pParticle->m_Pos = myPos + (otherPos - myPos) * percent;
				}
			}
		}
	}
}
Example #10
0
void RandomlyChangeVector(DTTestServer *pServer)
{
	pServer->m_Vector.x = FRand(-500000, 500000);
	pServer->m_Vector.y = FRand(-500000, 500000);
	pServer->m_Vector.z = FRand(-500000, 500000);
}
Example #11
0
void RandomlyChangeFloat(DTTestServer *pServer)
{
	pServer->m_Float = FRand(-500000, 500000);
}
void C_FuncSmokeVolume::Update( float fTimeDelta )
{
	// Update our world space bbox if we've moved at all.
	// We do this manually because sometimes people make HUGE bboxes, and if they're constantly changing because their
	// particles wander outside the current bounds sometimes, it'll be linking them into all the leaves repeatedly.
	const Vector &curOrigin = GetAbsOrigin();
	const QAngle &curAngles = GetAbsAngles();
	if ( !VectorsAreEqual( curOrigin, m_vLastOrigin, 0.1 ) || 
		fabs( curAngles.x - m_vLastAngles.x ) > 0.1 || 
		fabs( curAngles.y - m_vLastAngles.y ) > 0.1 || 
		fabs( curAngles.z - m_vLastAngles.z ) > 0.1 ||
		m_bFirstUpdate )
	{
		m_bFirstUpdate = false;
		m_vLastAngles = curAngles;
		m_vLastOrigin = curOrigin;

		Vector vWorldMins, vWorldMaxs;
		CollisionProp()->WorldSpaceAABB( &vWorldMins, &vWorldMaxs );
		vWorldMins -= Vector( m_ParticleRadius, m_ParticleRadius, m_ParticleRadius );
		vWorldMaxs += Vector( m_ParticleRadius, m_ParticleRadius, m_ParticleRadius );

		m_ParticleEffect.SetBBox( vWorldMins, vWorldMaxs );
	}
		
	// lerp m_CurrentDensity towards m_Density at a rate of m_DensityRampSpeed
	if( m_CurrentDensity < m_Density )
	{
		m_CurrentDensity += m_DensityRampSpeed * fTimeDelta;
		if( m_CurrentDensity > m_Density )
		{
			m_CurrentDensity = m_Density;
		}
	}
	else if( m_CurrentDensity > m_Density )
	{
		m_CurrentDensity -= m_DensityRampSpeed * fTimeDelta;
		if( m_CurrentDensity < m_Density )
		{
			m_CurrentDensity = m_Density;
		}
	}

	if( m_CurrentDensity == 0.0f )
	{
		return;
	}
	
	// This is used to randomize the direction it chooses to move a particle in.

	int offsetLookup[3] = {-1,0,1};

	float tradeDurationMax = m_ParticleSpacingDistance / ( m_MovementSpeed + 0.1f );
	float tradeDurationMin = tradeDurationMax * 0.5f;

	if ( IS_NAN( tradeDurationMax ) || IS_NAN( tradeDurationMin ) )
		return;

//	Warning( "tradeDuration: [%f,%f]\n", tradeDurationMin, tradeDurationMax );
	
	// Update all the moving traders and establish new ones.
	int nTotal = m_xCount * m_yCount * m_zCount;
	for( int i=0; i < nTotal; i++ )
	{
		SmokeParticleInfo *pInfo = &m_pSmokeParticleInfos[i];

		if(!pInfo->m_pParticle)
			continue;
	
		if(pInfo->m_TradeIndex == -1)
		{
			pInfo->m_pParticle->m_FadeAlpha = pInfo->m_FadeAlpha;
			pInfo->m_pParticle->m_Color[0] = pInfo->m_Color[0];
			pInfo->m_pParticle->m_Color[1] = pInfo->m_Color[1];
			pInfo->m_pParticle->m_Color[2] = pInfo->m_Color[2];

			// Is there an adjacent one that's not trading?
			int x, y, z;
			GetParticleInfoXYZ(i, x, y, z);

			int xCountOffset = rand();
			int yCountOffset = rand();
			int zCountOffset = rand();

			bool bFound = false;
			for(int xCount=0; xCount < 3 && !bFound; xCount++)
			{
				for(int yCount=0; yCount < 3 && !bFound; yCount++)
				{
					for(int zCount=0; zCount < 3; zCount++)
					{
						int testX = x + offsetLookup[(xCount+xCountOffset) % 3];
						int testY = y + offsetLookup[(yCount+yCountOffset) % 3];
						int testZ = z + offsetLookup[(zCount+zCountOffset) % 3];

						if(testX == x && testY == y && testZ == z)
							continue;

						if(IsValidXYZCoords(testX, testY, testZ))
						{
							SmokeParticleInfo *pOther = GetSmokeParticleInfo(testX, testY, testZ);
							if(pOther->m_pParticle && pOther->m_TradeIndex == -1)
							{
								// Ok, this one is looking to trade also.
								pInfo->m_TradeIndex = GetSmokeParticleIndex(testX, testY, testZ);
								pOther->m_TradeIndex = i;
								pInfo->m_TradeClock = pOther->m_TradeClock = 0;
								pOther->m_TradeDuration = pInfo->m_TradeDuration = FRand( tradeDurationMin, tradeDurationMax );
								
								bFound = true;
								break;
							}
						}
					}
				}
			}
		}
		else
		{
			SmokeParticleInfo *pOther = &m_pSmokeParticleInfos[pInfo->m_TradeIndex];
			assert(pOther->m_TradeIndex == i);
			
			// This makes sure the trade only gets updated once per frame.
			if(pInfo < pOther)
			{
				// Increment the trade clock..
				pInfo->m_TradeClock = (pOther->m_TradeClock += fTimeDelta);
				int x, y, z;
				GetParticleInfoXYZ(i, x, y, z);
				Vector myPos = GetSmokeParticlePos(x, y, z);
				
				int otherX, otherY, otherZ;
				GetParticleInfoXYZ(pInfo->m_TradeIndex, otherX, otherY, otherZ);
				Vector otherPos = GetSmokeParticlePos(otherX, otherY, otherZ);

				// Is the trade finished?
				if(pInfo->m_TradeClock >= pInfo->m_TradeDuration)
				{
					pInfo->m_TradeIndex = pOther->m_TradeIndex = -1;
					
					pInfo->m_pParticle->m_Pos = otherPos;
					pOther->m_pParticle->m_Pos = myPos;

					SmokeGrenadeParticle *temp = pInfo->m_pParticle;
					pInfo->m_pParticle = pOther->m_pParticle;
					pOther->m_pParticle = temp;
				}
				else
				{			
					// Ok, move them closer.
					float percent = (float)cos(pInfo->m_TradeClock * 2 * 1.57079632f / pInfo->m_TradeDuration);
					percent = percent * 0.5 + 0.5;
					
					pInfo->m_pParticle->m_FadeAlpha  = pInfo->m_FadeAlpha + (pOther->m_FadeAlpha - pInfo->m_FadeAlpha) * (1 - percent);
					pOther->m_pParticle->m_FadeAlpha = pInfo->m_FadeAlpha + (pOther->m_FadeAlpha - pInfo->m_FadeAlpha) * percent;

					InterpColor(pInfo->m_pParticle->m_Color,  pInfo->m_Color, pOther->m_Color, 1-percent);
					InterpColor(pOther->m_pParticle->m_Color, pInfo->m_Color, pOther->m_Color, percent);

					pInfo->m_pParticle->m_Pos  = myPos + (otherPos - myPos) * (1 - percent);
					pOther->m_pParticle->m_Pos = myPos + (otherPos - myPos) * percent;
				}
			}
		}
	}
}
Example #13
0
void C_SteamJet::Update(float fTimeDelta)
{
	if(!m_pParticleMgr)
	{
		assert(false);
		return;
	}

	if( m_bEmit )
	{
		// Add new particles.
		int nToEmit = 0;
		float tempDelta = fTimeDelta;
		while( m_ParticleSpawn.NextEvent(tempDelta) )
			++nToEmit;

		if ( nToEmit > 0 )
		{
			Vector forward, right, up;
			AngleVectors(GetAbsAngles(), &forward, &right, &up);			

			// Legacy env_steamjet entities faced left instead of forward.
			if (m_bFaceLeft)
			{
				Vector temp = forward;
				forward = -right;
				right = temp;
			}

			// EVIL: Ideally, we could tell the renderer our OBB, and let it build a big box that encloses
			// the entity with its parent so it doesn't have to setup its parent's bones here.
			Vector vEndPoint = GetAbsOrigin() + forward * m_Speed;
			Vector vMin, vMax;
			VectorMin( GetAbsOrigin(), vEndPoint, vMin );
			VectorMax( GetAbsOrigin(), vEndPoint, vMax );
			m_ParticleEffect.SetBBox( vMin, vMax );

			if ( m_ParticleEffect.WasDrawnPrevFrame() )
			{
				while ( nToEmit-- )
				{
					// Make a new particle.
					if( SteamJetParticle *pParticle = (SteamJetParticle*) m_ParticleEffect.AddParticle( sizeof(SteamJetParticle), m_MaterialHandle ) )
					{
						pParticle->m_Pos = GetAbsOrigin();
						
						pParticle->m_Velocity = 
							FRand(-m_SpreadSpeed,m_SpreadSpeed) * right +
							FRand(-m_SpreadSpeed,m_SpreadSpeed) * up +
							m_Speed * forward;
						
						pParticle->m_Lifetime	= 0;
						pParticle->m_DieTime	= m_Lifetime;

						pParticle->m_uchStartSize	= m_StartSize;
						pParticle->m_uchEndSize		= m_EndSize;

						pParticle->m_flRoll = random->RandomFloat( 0, 360 );
						pParticle->m_flRollDelta = random->RandomFloat( -m_flRollSpeed, m_flRollSpeed );
					}
				}
			}

			UpdateLightingRamp();
		}	
	}
}
void C_ParticleSmokeGrenade::FillVolume()
{
	m_CurrentStage = 1;
	m_SmokeBasePos = GetPos();
	m_SmokeTrail.SetEmit(false);
	m_ExpandTimeCounter = m_ExpandRadius = 0;
	m_bVolumeFilled = true;

	// Spawn all of our particles.
	float overlap = SMOKEPARTICLE_OVERLAP;

	m_SpacingRadius = (SMOKEGRENADE_PARTICLERADIUS - overlap) * NUM_PARTICLES_PER_DIMENSION * 0.5f;
	m_xCount = m_yCount = m_zCount = NUM_PARTICLES_PER_DIMENSION;

	float invNumPerDimX = 1.0f / (m_xCount-1);
	float invNumPerDimY = 1.0f / (m_yCount-1);
	float invNumPerDimZ = 1.0f / (m_zCount-1);

	Vector vPos;
	for(int x=0; x < m_xCount; x++)
	{
		vPos.x = m_SmokeBasePos.x + ((float)x * invNumPerDimX) * m_SpacingRadius * 2 - m_SpacingRadius;

		for(int y=0; y < m_yCount; y++)
		{
			vPos.y = m_SmokeBasePos.y + ((float)y * invNumPerDimY) * m_SpacingRadius * 2 - m_SpacingRadius;
							  
			for(int z=0; z < m_zCount; z++)
			{
				vPos.z = m_SmokeBasePos.z + ((float)z * invNumPerDimZ) * m_SpacingRadius * 2 - m_SpacingRadius;

				// Don't spawn and simulate particles that are inside a wall
				int contents = enginetrace->GetPointContents( vPos );

				if( contents & CONTENTS_SOLID )
				{
					continue;
				}

				if(SmokeParticleInfo *pInfo = GetSmokeParticleInfo(x,y,z))
				{
					// MD 11/10/03: disabled this because we weren't getting coverage near the ground.
					// If we want it back in certain cases, we can make it a flag.
					/*int contents = GetWorldPointContents(vPos);
					if(false && (contents & CONTENTS_SOLID))
					{
						pInfo->m_pParticle = NULL;
					}
					else
					*/
					{
						SmokeGrenadeParticle *pParticle = 
							(SmokeGrenadeParticle*)m_ParticleEffect.AddParticle(sizeof(SmokeGrenadeParticle), m_MaterialHandles[rand() % NUM_MATERIAL_HANDLES]);

						if(pParticle)
						{
							pParticle->m_Pos = vPos - m_SmokeBasePos; // store its position in local space
							pParticle->m_ColorInterp = (unsigned char)((rand() * 255) / RAND_MAX);
							pParticle->m_RotationSpeed = FRand(-ROTATION_SPEED, ROTATION_SPEED); // Rotation speed.
							pParticle->m_CurRotation = FRand(-6, 6);
						}

						#ifdef _DEBUG
							int testX, testY, testZ;
							int index = GetSmokeParticleIndex(x,y,z);
							GetParticleInfoXYZ(index, testX, testY, testZ);
							assert(testX == x && testY == y && testZ == z);
						#endif

						Vector vColor = EngineGetLightForPoint(vPos);
						pInfo->m_Color[0] = (unsigned char)(vColor.x * 255.9f);
						pInfo->m_Color[1] = (unsigned char)(vColor.y * 255.9f);
						pInfo->m_Color[2] = (unsigned char)(vColor.z * 255.9f);

						// Cast some rays and if it's too close to anything, fade its alpha down.
						pInfo->m_FadeAlpha = 1;

						/*for(int i=0; i < NUM_FADE_PLANES; i++)
						{
							trace_t trace;
							WorldTraceLine(vPos, vPos + s_FadePlaneDirections[i] * 100, MASK_SOLID_BRUSHONLY, &trace);
							if(trace.fraction < 1.0f)
							{
								float dist = DotProduct(trace.plane.normal, vPos) - trace.plane.dist;
								if(dist < 0)
								{
									pInfo->m_FadeAlpha = 0;
								}
								else if(dist < SMOKEPARTICLE_SIZE)
								{
									float alphaScale = dist / SMOKEPARTICLE_SIZE;
									alphaScale *= alphaScale * alphaScale;
									pInfo->m_FadeAlpha *= alphaScale;
								}
							}
						}*/

						pInfo->m_pParticle = pParticle;
						pInfo->m_TradeIndex = -1;
					}
				}
			}
		}
	}
}
void C_ParticleSmokeGrenade::Update(float fTimeDelta)
{
	m_LifetimeCounter += fTimeDelta;
	
	// Update the smoke trail.
	C_BaseEntity *pAimEnt = GetFollowedEntity();
	if ( pAimEnt )
	{
		Vector forward, right, up;

		// Update the smoke particle color.
		if(m_CurrentStage == 0)
		{
			m_SmokeTrail.m_StartColor = EngineGetLightForPoint(GetAbsOrigin()) * 0.5f;
			m_SmokeTrail.m_EndColor = m_SmokeTrail.m_StartColor;
		}

		// Spin the smoke trail.
		AngleVectors(pAimEnt->GetAbsAngles(), &forward, &right, &up);
		m_SmokeTrail.m_VelocityOffset = forward * 30 + GetAbsVelocity();

		m_SmokeTrail.SetLocalOrigin( GetAbsOrigin() );
		m_SmokeTrail.Update(fTimeDelta);
	}	
	
	
	// Update our fade alpha.
	if(m_LifetimeCounter < m_FadeStartTime)
	{
		m_FadeAlpha = 1;
	}
	else if(m_LifetimeCounter < m_FadeEndTime)
	{
		float fadePercent = (m_LifetimeCounter - m_FadeStartTime) / (m_FadeEndTime - m_FadeStartTime);
		m_FadeAlpha = cos(fadePercent * 3.14159) * 0.5 + 0.5;
	}
	else
	{
		m_FadeAlpha = 0;
	}

	// Scale by the amount the sphere has grown.
	m_FadeAlpha *= m_ExpandRadius / SMOKESPHERE_MAX_RADIUS;

	if(m_CurrentStage == 1)
	{
		// Update the expanding sphere.
		m_ExpandTimeCounter += fTimeDelta;
		if(m_ExpandTimeCounter > SMOKESPHERE_EXPAND_TIME)
			m_ExpandTimeCounter = SMOKESPHERE_EXPAND_TIME;

		m_ExpandRadius = SMOKESPHERE_MAX_RADIUS * (float)sin(m_ExpandTimeCounter * 3.14159265358 * 0.5 / SMOKESPHERE_EXPAND_TIME);

		// Add our influence to the global smoke fog alpha.
		float testDist = (EngineGetVecRenderOrigin() - m_SmokeBasePos).Length();
		float fadeEnd = m_ExpandRadius * 0.75;
		if(testDist < fadeEnd)
		{
			EngineGetSmokeFogOverlayAlpha() += 1 - testDist / fadeEnd;
		}	


		// This is used to randomize the direction it chooses to move a particle in.
		int offsetLookup[3] = {-1,0,1};

		// Update all the moving traders and establish new ones.
		int nTotal = m_xCount * m_yCount * m_zCount;
		for(int i=0; i < nTotal; i++)
		{
			SmokeParticleInfo *pInfo = &m_SmokeParticleInfos[i];

			if(!pInfo->m_pParticle)
				continue;
		
			if(pInfo->m_TradeIndex == -1)
			{
				pInfo->m_pParticle->m_FadeAlpha = pInfo->m_FadeAlpha;
				pInfo->m_pParticle->m_Color[0] = pInfo->m_Color[0];
				pInfo->m_pParticle->m_Color[1] = pInfo->m_Color[1];
				pInfo->m_pParticle->m_Color[2] = pInfo->m_Color[2];

				// Is there an adjacent one that's not trading?
				int x, y, z;
				GetParticleInfoXYZ(i, x, y, z);

				int xCountOffset = rand();
				int yCountOffset = rand();
				int zCountOffset = rand();

				bool bFound = false;
				for(int xCount=0; xCount < 3 && !bFound; xCount++)
				{
					for(int yCount=0; yCount < 3 && !bFound; yCount++)
					{
						for(int zCount=0; zCount < 3; zCount++)
						{
							int testX = x + offsetLookup[(xCount+xCountOffset) % 3];
							int testY = y + offsetLookup[(yCount+yCountOffset) % 3];
							int testZ = z + offsetLookup[(zCount+zCountOffset) % 3];

							if(testX == x && testY == y && testZ == z)
								continue;

							if(IsValidXYZCoords(testX, testY, testZ))
							{
								SmokeParticleInfo *pOther = GetSmokeParticleInfo(testX, testY, testZ);
								if(pOther->m_pParticle && pOther->m_TradeIndex == -1)
								{
									// Ok, this one is looking to trade also.
									pInfo->m_TradeIndex = GetSmokeParticleIndex(testX, testY, testZ);
									pOther->m_TradeIndex = i;
									pInfo->m_TradeClock = pOther->m_TradeClock = 0;
									pInfo->m_TradeDuration = FRand(TRADE_DURATION_MIN, TRADE_DURATION_MAX);
									
									bFound = true;
									break;
								}
							}
						}
					}
				}
			}
			else
			{
				SmokeParticleInfo *pOther = &m_SmokeParticleInfos[pInfo->m_TradeIndex];
				assert(pOther->m_TradeIndex == i);
				
				// This makes sure the trade only gets updated once per frame.
				if(pInfo < pOther)
				{
					// Increment the trade clock..
					pInfo->m_TradeClock = (pOther->m_TradeClock += fTimeDelta);
					int x, y, z;
					GetParticleInfoXYZ(i, x, y, z);
					Vector myPos = GetSmokeParticlePos(x, y, z);
					
					int otherX, otherY, otherZ;
					GetParticleInfoXYZ(pInfo->m_TradeIndex, otherX, otherY, otherZ);
					Vector otherPos = GetSmokeParticlePos(otherX, otherY, otherZ);

					// Is the trade finished?
					if(pInfo->m_TradeClock >= pInfo->m_TradeDuration)
					{
						pInfo->m_TradeIndex = pOther->m_TradeIndex = -1;
						
						pInfo->m_pParticle->m_Pos = otherPos;
						pOther->m_pParticle->m_Pos = myPos;

						SmokeGrenadeParticle *temp = pInfo->m_pParticle;
						pInfo->m_pParticle = pOther->m_pParticle;
						pOther->m_pParticle = temp;
					}
					else
					{			
						// Ok, move them closer.
						float percent = (float)cos(pInfo->m_TradeClock * 2 * 1.57079632f / pInfo->m_TradeDuration);
						percent = percent * 0.5 + 0.5;
						
						pInfo->m_pParticle->m_FadeAlpha  = pInfo->m_FadeAlpha + (pOther->m_FadeAlpha - pInfo->m_FadeAlpha) * (1 - percent);
						pOther->m_pParticle->m_FadeAlpha = pInfo->m_FadeAlpha + (pOther->m_FadeAlpha - pInfo->m_FadeAlpha) * percent;

						InterpColor(pInfo->m_pParticle->m_Color,  pInfo->m_Color, pOther->m_Color, 1-percent);
						InterpColor(pOther->m_pParticle->m_Color, pInfo->m_Color, pOther->m_Color, percent);

						pInfo->m_pParticle->m_Pos  = myPos + (otherPos - myPos) * (1 - percent);
						pOther->m_pParticle->m_Pos = myPos + (otherPos - myPos) * percent;
					}
				}
			}
		}
	}
}