Exemplo n.º 1
0
void ImageInterpolatedValue(unsigned char *data, int w, double x, double y, unsigned char c[3])
{
    int x0 = floor(x), x1 = ceil(x), y0 = floor(y), y1 = ceil(y);
    unsigned char nc[4][3], xc[2][3];
    ImageValue(data, w, x0, y0, nc[0]);
    ImageValue(data, w, x1, y0, nc[1]);
    ImageValue(data, w, x0, y1, nc[2]);
    ImageValue(data, w, x1, y1, nc[3]);

    double d0 = x - x0, d1 = y - y0;
    InterpColor(nc[0], nc[1], d0, xc[0]);
    InterpColor(nc[2], nc[3], d0, xc[1]);
    InterpColor(xc[0], xc[1], d1, c);
}
inline void C_ParticleSmokeGrenade::UpdateParticleDuringTrade( int iParticle, float fTimeDelta )
{
	SmokeParticleInfo *pInfo = &m_SmokeParticleInfos[iParticle];
	SmokeParticleInfo *pOther = &m_SmokeParticleInfos[pInfo->m_TradeIndex];
	Assert(pOther->m_TradeIndex == iParticle);
	
	// 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(iParticle, x, y, z);
		Vector myPos = GetSmokeParticlePos(x, y, z) - m_SmokeBasePos;
		
		int otherX, otherY, otherZ;
		GetParticleInfoXYZ(pInfo->m_TradeIndex, otherX, otherY, otherZ);
		Vector otherPos = GetSmokeParticlePos(otherX, otherY, otherZ) - m_SmokeBasePos;

		// 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;
		}
	}
}
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;
				}
			}
		}
	}
}
Exemplo n.º 4
0
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;
				}
			}
		}
	}
}
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;
					}
				}
			}
		}
	}
}