//----------------------------------------------------------------------------- // 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; } } } } }
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); }
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; } } } } }
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; } } } } } }