bool C_ParticleFire::SimulateAndRender(Particle *pInParticle, ParticleDraw *pDraw, float &sortKey) { FireParticle *pParticle = (FireParticle*)pInParticle; // Should this particle die? pParticle->m_Lifetime += pDraw->GetTimeDelta(); if(pParticle->m_Lifetime > FIRE_PARTICLE_LIFETIME) return false; float smooth01 = 1 - (cos(pParticle->m_Lifetime * 3.14159 / FIRE_PARTICLE_LIFETIME) * 0.5 + 0.5); float smooth00 = 1 - (cos(pParticle->m_Lifetime * 3.14159 * 2 / FIRE_PARTICLE_LIFETIME) * 0.5 + 0.5); pParticle->m_Pos = pParticle->m_StartPos + pParticle->m_Direction * smooth01; FireRamp *pRamp = &g_FireRamps[pParticle->m_iRamp]; Vector curColor = pRamp->m_Start + (pRamp->m_End - pRamp->m_Start) * smooth01; // Render. Vector tPos; TransformParticle(m_pParticleMgr->GetModelView(), pParticle->m_Pos, tPos); sortKey = (int)tPos.z; RenderParticle_ColorSize( pDraw, tPos, curColor, smooth00, size); return true; }
void CLitSmokeEmitter::RenderParticles( CParticleRenderIterator *pIterator ) { const LitSmokeParticle *pParticle = (const LitSmokeParticle*)pIterator->GetFirst(); while ( pParticle ) { float tLifetime = pParticle->m_flLifetime / pParticle->m_flDieTime; // Transform. Vector tPos; TransformParticle( ParticleMgr()->GetModelView(), pParticle->m_Pos, tPos ); float sortKey = tPos.z; float alpha255 = ( ( (float) pParticle->m_uchColor[3]/255.0f ) * sin( M_PI_F * tLifetime ) ) * 255.0f; Vector color01 = Vector( pParticle->m_uchColor[0], pParticle->m_uchColor[1], pParticle->m_uchColor[2] ) * (tLifetime / 255.0f); m_Renderer.RenderParticle_AddColor ( pIterator->GetParticleDraw(), pParticle->m_Pos, tPos, alpha255, FLerp( pParticle->m_uchStartSize, pParticle->m_uchEndSize, tLifetime ), color01 ); pParticle = (const LitSmokeParticle*)pIterator->GetNext( sortKey ); } }
void C_SmokeStack::RenderParticles( CParticleRenderIterator *pIterator ) { const SmokeStackParticle *pParticle = (const SmokeStackParticle*)pIterator->GetFirst(); while ( pParticle ) { // Transform. Vector tPos; TransformParticle( m_pParticleMgr->GetModelView(), pParticle->m_Pos, tPos ); // Figure out its alpha. Squaring it after it gets halfway through its lifetime // makes it get translucent and fade out for a longer time. //float alpha = cosf( -M_PI_F + tLifetime * M_PI_F * 2.f ) * 0.5f + 0.5f; float tLifetime = pParticle->m_Lifetime * m_InvLifetime; float alpha = TableCos( -M_PI_F + tLifetime * M_PI_F * 2.f ) * 0.5f + 0.5f; if( tLifetime > 0.5f ) alpha *= alpha; m_Renderer.RenderParticle( pIterator->GetParticleDraw(), pParticle->m_Pos, tPos, alpha * m_flAlphaScale, FLerp(m_StartSize, m_EndSize, tLifetime), DEG2RAD( pParticle->m_flAngle ) ); pParticle = (const SmokeStackParticle*)pIterator->GetNext( pParticle->m_flSortPos ); } }
void CLocalSpaceEmitter::RenderParticles( CParticleRenderIterator *pIterator ) { const matrix3x4_t &mLocalToWorld = GetTransformMatrix(); const VMatrix &mModelView = ParticleMgr()->GetModelView(); const SimpleParticle *pParticle = (const SimpleParticle *)pIterator->GetFirst(); while ( pParticle ) { // Transform it Vector screenPos, worldPos; VectorTransform( pParticle->m_Pos, mLocalToWorld, worldPos ); // Correct viewmodel squashing if ( m_fFlags & FLE_VIEWMODEL ) { FormatViewModelAttachment( NULL, worldPos, false ); } TransformParticle( mModelView, worldPos, screenPos ); float sortKey = (int) screenPos.z; // Render it RenderParticle_ColorSizeAngle( pIterator->GetParticleDraw(), screenPos, UpdateColor( pParticle ), UpdateAlpha( pParticle ) * GetAlphaDistanceFade( screenPos, m_flNearClipMin, m_flNearClipMax ), UpdateScale( pParticle ), pParticle->m_flRoll ); pParticle = (const SimpleParticle *)pIterator->GetNext( sortKey ); } }
//----------------------------------------------------------------------------- // Purpose: // Input : *pInParticle - // *pDraw - // &sortKey - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool C_PerfTest::SimulateAndRender(Particle *pInParticle, ParticleDraw *pDraw, float &sortKey) { PerfTestParticle *pParticle = (PerfTestParticle*)pInParticle; // Render. Vector tPos; TransformParticle(m_pParticleMgr->GetModelView(), pParticle->m_Pos, tPos); sortKey = tPos.z; Vector vColor( 0, 0, 0 ); for( int i=0; i < NUM_LIGHTS; i++ ) { float fDist = pParticle->m_Pos.DistToSqr( m_LightPos[i] ); float fAmt; if( fDist > 0.0001f ) fAmt = m_LightIntensity[i] / fDist; else fAmt = 1000; vColor += m_LightColor[i] * fAmt; } vColor = vColor.Min( Vector(255.1,255.1,255.1) ); RenderParticle_Color255Size( pDraw, tPos, vColor, // color 255, // alpha 1 // size ); return true; }
//----------------------------------------------------------------------------- // Purpose: Simulate motion and render all child particles // Input : *pInParticle - // *pDraw - // &sortKey - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool CSimpleEmitter::SimulateAndRender( Particle *pInParticle, ParticleDraw *pDraw, float &sortKey) { SimpleParticle *pParticle = (SimpleParticle *) pInParticle; float timeDelta = pDraw->GetTimeDelta(); //Render Vector tPos; TransformParticle( g_ParticleMgr.GetModelView(), pParticle->m_Pos, tPos ); sortKey = (int) tPos.z; //Render it RenderParticle_ColorSizeAngle( pDraw, tPos, UpdateColor( pParticle, timeDelta ), UpdateAlpha( pParticle, timeDelta ) * GetAlphaDistanceFade( tPos, m_flNearClipMin, m_flNearClipMax ), UpdateScale( pParticle, timeDelta ), UpdateRoll( pParticle, timeDelta ) ); //Update velocity UpdateVelocity( pParticle, timeDelta ); pParticle->m_Pos += pParticle->m_vecVelocity * timeDelta; //Should this particle die? pParticle->m_flLifetime += timeDelta; if ( pParticle->m_flLifetime >= pParticle->m_flDieTime ) return false; return true; }
void C_MovieExplosion::RenderParticles( CParticleRenderIterator *pIterator ) { const StandardParticle_t *pParticle = (const StandardParticle_t*)pIterator->GetFirst(); while ( pParticle ) { // Draw. Vector tPos; TransformParticle(m_pParticleMgr->GetModelView(), pParticle->m_Pos, tPos); float sortKey = tPos.z; float lifetimePercent = pParticle->m_Lifetime / EMITTED_PARTICLE_LIFETIME; Vector color; color.x = sin(lifetimePercent * 3.14159); color.y = color.x * 0.5f; color.z = 0; RenderParticle_ColorSize( pIterator->GetParticleDraw(), tPos, color, m_EmitterAlpha * sin(3.14159 * lifetimePercent), 10); pParticle = (const StandardParticle_t*)pIterator->GetNext( sortKey ); } }
void C_SteamJet::RenderParticles( CParticleRenderIterator *pIterator ) { const SteamJetParticle *pParticle = (const SteamJetParticle*)pIterator->GetFirst(); while ( pParticle ) { // Render. Vector tPos; TransformParticle(m_pParticleMgr->GetModelView(), pParticle->m_Pos, tPos); float sortKey = tPos.z; float lifetimeT = pParticle->m_Lifetime / (pParticle->m_DieTime + 0.001); float fRamp = lifetimeT * (STEAMJET_NUMRAMPS-1); int iRamp = (int)fRamp; float fraction = fRamp - iRamp; Vector vRampColor = m_Ramps[iRamp] + (m_Ramps[iRamp+1] - m_Ramps[iRamp]) * fraction; vRampColor[0] = min( 1.0f, vRampColor[0] ); vRampColor[1] = min( 1.0f, vRampColor[1] ); vRampColor[2] = min( 1.0f, vRampColor[2] ); #ifdef GE_DLL // Determine a linear alpha falloff based on our limits float alphamod = 1.0f; float fadetime = gpGlobals->curtime - m_flStartFadeTime; if ( m_bIsForExplosion && fadetime > 0 && m_flStartFadeTime > 0 ) alphamod = RemapValClamped( fadetime, 0, m_flFadeDuration, 1.0f, 0 ); float sinLifetime = sin(pParticle->m_Lifetime * 3.14159f / pParticle->m_DieTime) * alphamod; #else float sinLifetime = sin(pParticle->m_Lifetime * 3.14159f / pParticle->m_DieTime); #endif if ( m_nType == STEAM_HEATWAVE ) { RenderParticle_ColorSizePerturbNormal( pIterator->GetParticleDraw(), tPos, vRampColor, sinLifetime * (m_clrRender->a/255.0f), FLerp(m_StartSize, m_EndSize, pParticle->m_Lifetime)); } else { RenderParticle_ColorSizeAngle( pIterator->GetParticleDraw(), tPos, vRampColor, sinLifetime * (m_clrRender->a/255.0f), FLerp(pParticle->m_uchStartSize, pParticle->m_uchEndSize, pParticle->m_Lifetime), pParticle->m_flRoll ); } pParticle = (const SteamJetParticle*)pIterator->GetNext( sortKey ); } }
void C_FuncSmokeVolume::RenderParticles( CParticleRenderIterator *pIterator ) { if ( m_CurrentDensity == 0 ) return; const SmokeGrenadeParticle *pParticle = (const SmokeGrenadeParticle*)pIterator->GetFirst(); while ( pParticle ) { Vector renderPos = pParticle->m_Pos; // Fade out globally. float alpha = m_CurrentDensity; // Apply the precalculated fade alpha from world geometry. alpha *= pParticle->m_FadeAlpha; // TODO: optimize this whole routine! Vector color = m_MinColor + (m_MaxColor - m_MinColor) * (pParticle->m_ColorInterp / 255.1f); if ( IsEmissive() ) { color.x += pParticle->m_Color[0] / 255.0f; color.y += pParticle->m_Color[1] / 255.0f; color.z += pParticle->m_Color[2] / 255.0f; color.x = clamp( color.x, 0.0f, 1.0f ); color.y = clamp( color.y, 0.0f, 1.0f ); color.z = clamp( color.z, 0.0f, 1.0f ); } else { color.x *= pParticle->m_Color[0] / 255.0f; color.y *= pParticle->m_Color[1] / 255.0f; color.z *= pParticle->m_Color[2] / 255.0f; } Vector tRenderPos; TransformParticle( ParticleMgr()->GetModelView(), renderPos, tRenderPos ); float sortKey = 1;//tRenderPos.z; RenderParticle_ColorSizeAngle( pIterator->GetParticleDraw(), tRenderPos, color, alpha * GetAlphaDistanceFade(tRenderPos, 10, 30), // Alpha m_ParticleRadius, pParticle->m_CurRotation ); pParticle = (const SmokeGrenadeParticle*)pIterator->GetNext( sortKey ); } }
//----------------------------------------------------------------------------- // Simulate the particles //----------------------------------------------------------------------------- void C_EnvParticleScript::RenderParticles( CParticleRenderIterator *pIterator ) { const ParticleScriptParticle_t* pParticle = (const ParticleScriptParticle_t*)pIterator->GetFirst(); while ( pParticle ) { Vector vecRenderPos; TransformParticle( ParticleMgr()->GetModelView(), pParticle->m_Pos, vecRenderPos ); float sortKey = vecRenderPos.z; Vector color( 1, 1, 1 ); RenderParticle_ColorSize( pIterator->GetParticleDraw(), vecRenderPos, color, 1.0f, pParticle->m_flSize ); pParticle = (const ParticleScriptParticle_t*)pIterator->GetNext( sortKey ); } }
void CTrailParticles::RenderParticles(CParticleRenderIterator *pIterator) { const TrailParticle *pParticle = (const TrailParticle*) pIterator->GetFirst(); while (pParticle) { //Get our remaining time float lifePerc = 1.0f - (pParticle->m_flLifetime / pParticle->m_flDieTime); float scale = (pParticle->m_flLength*lifePerc); if (scale < 0.01f) scale = 0.01f; Vector start, delta; //NOTE: We need to do everything in screen space TransformParticle(ParticleMgr()->GetModelView(), pParticle->m_Pos, start); float sortKey = start.z; Vector3DMultiply(ParticleMgr()->GetModelView(), pParticle->m_vecVelocity, delta); float color[4]; float ramp = 1.0; // Fade in for the first few frames if (pParticle->m_flLifetime <= 0.3 && m_fFlags & bitsPARTICLE_TRAIL_FADE_IN) { ramp = pParticle->m_flLifetime; } else if (m_fFlags & bitsPARTICLE_TRAIL_FADE) { ramp = (1.0f - (pParticle->m_flLifetime / pParticle->m_flDieTime)); } color[0] = pParticle->m_color.r * ramp * (1.0f / 255.0f); color[1] = pParticle->m_color.g * ramp * (1.0f / 255.0f); color[2] = pParticle->m_color.b * ramp * (1.0f / 255.0f); color[3] = pParticle->m_color.a * ramp * (1.0f / 255.0f); float flLength = (pParticle->m_vecVelocity * scale).Length();//( delta - pos ).Length(); float flWidth = (flLength < pParticle->m_flWidth) ? flLength : pParticle->m_flWidth; //See if we should fade Vector vecScaledDelta = (delta*scale); Tracer_Draw(pIterator->GetParticleDraw(), start, vecScaledDelta, flWidth, color); pParticle = (const TrailParticle*) pIterator->GetNext(sortKey); } }
void C_SteamJet::RenderParticles( CParticleRenderIterator *pIterator ) { const SteamJetParticle *pParticle = (const SteamJetParticle*)pIterator->GetFirst(); while ( pParticle ) { // Render. Vector tPos; TransformParticle(m_pParticleMgr->GetModelView(), pParticle->m_Pos, tPos); float sortKey = tPos.z; float lifetimeT = pParticle->m_Lifetime / (pParticle->m_DieTime + 0.001); float fRamp = lifetimeT * (STEAMJET_NUMRAMPS-1); int iRamp = (int)fRamp; float fraction = fRamp - iRamp; Vector vRampColor = m_Ramps[iRamp] + (m_Ramps[iRamp+1] - m_Ramps[iRamp]) * fraction; vRampColor[0] = min( 1.0f, vRampColor[0] ); vRampColor[1] = min( 1.0f, vRampColor[1] ); vRampColor[2] = min( 1.0f, vRampColor[2] ); float sinLifetime = sin(pParticle->m_Lifetime * 3.14159f / pParticle->m_DieTime); if ( m_nType == STEAM_HEATWAVE ) { RenderParticle_ColorSizePerturbNormal( pIterator->GetParticleDraw(), tPos, vRampColor, sinLifetime * (m_clrRender->a/255.0f), FLerp(m_StartSize, m_EndSize, pParticle->m_Lifetime)); } else { RenderParticle_ColorSizeAngle( pIterator->GetParticleDraw(), tPos, vRampColor, sinLifetime * (m_clrRender->a/255.0f), FLerp(pParticle->m_uchStartSize, pParticle->m_uchEndSize, pParticle->m_Lifetime), pParticle->m_flRoll ); } pParticle = (const SteamJetParticle*)pIterator->GetNext( sortKey ); } }
void C_AR2Explosion::RenderParticles( CParticleRenderIterator *pIterator ) { const AR2ExplosionParticle *pParticle = (const AR2ExplosionParticle *)pIterator->GetFirst(); while ( pParticle ) { float sortKey = 0; if ( pParticle->m_Lifetime >= 0.0f ) { // Draw. float lifetimePercent = ( pParticle->m_Lifetime - AR2_DUST_FADE_IN_TIME ) / pParticle->m_Dwell; // FIXME: base color should be a dirty version of the material color Vector color = g_AR2DustColor1 * (1.0 - lifetimePercent) + g_AR2DustColor2 * lifetimePercent; Vector tPos; TransformParticle(m_pParticleMgr->GetModelView(), pParticle->m_Pos, tPos); sortKey = tPos.z; float alpha; if ( pParticle->m_Lifetime < AR2_DUST_FADE_IN_TIME ) { alpha = AR2_DUST_ALPHA * ( pParticle->m_Lifetime / AR2_DUST_FADE_IN_TIME ); } else { alpha = AR2_DUST_ALPHA * ( 1.0f - lifetimePercent ); } alpha *= GetAlphaDistanceFade( tPos, IsXbox() ? 100 : 50, IsXbox() ? 200 : 150 ); RenderParticle_ColorSizeAngle( pIterator->GetParticleDraw(), tPos, color, alpha, pParticle->m_Dist, // size based on how far it's traveled pParticle->m_Roll); } pParticle = (const AR2ExplosionParticle *)pIterator->GetNext( sortKey ); } }
void CDustEffect::RenderParticles( CParticleRenderIterator *pIterator ) { const CFuncDustParticle *pParticle = (const CFuncDustParticle*)pIterator->GetFirst(); while ( pParticle ) { // Velocity. float flAlpha; if( m_pDust->m_DustFlags & DUSTFLAGS_FROZEN ) { flAlpha = 1; } else { // Alpha. float flAngle = (pParticle->m_flLifetime / pParticle->m_flDieTime) * M_PI * 2; flAlpha = sin( flAngle - (M_PI * 0.5f) ) * 0.5f + 0.5f; } Vector tPos; TransformParticle( ParticleMgr()->GetModelView(), pParticle->m_Pos, tPos ); float sortKey = (int) tPos.z; if( -tPos.z <= m_pDust->m_DistMax ) { flAlpha *= 1 + (tPos.z / m_pDust->m_DistMax); // Draw it. float flSize = pParticle->m_flSize; if( m_pDust->m_DustFlags & DUSTFLAGS_SCALEMOTES ) flSize *= -tPos.z; RenderParticle_Color255Size( pIterator->GetParticleDraw(), tPos, Vector( m_pDust->m_Color.r, m_pDust->m_Color.g, m_pDust->m_Color.b ), flAlpha * m_pDust->m_Color.a, flSize ); } pParticle = (const CFuncDustParticle*)pIterator->GetNext( sortKey ); } }
//------------------------------------------------------------------------------ // Purpose : // Input : // Output : //------------------------------------------------------------------------------ bool CPlasmaSpray::SimulateAndRender(Particle *pParticle, ParticleDraw *pDraw, float &sortDist ) { SimpleParticle* pSimpleParticle = (SimpleParticle*)pParticle; //Should this particle die? pSimpleParticle->m_flLifetime += pDraw->GetTimeDelta(); C_PlasmaBeamNode* pNode = (C_PlasmaBeamNode*)((C_BaseEntity*)m_pOwner); if ( pSimpleParticle->m_flLifetime >= pSimpleParticle->m_flDieTime ) { return false; } // If owner is gone or spray off remove me else if (pNode == NULL || !pNode->m_bSprayOn) { return false; } float scale = random->RandomFloat( 0.02, 0.08 ); // NOTE: We need to do everything in screen space Vector delta; Vector start; TransformParticle(g_ParticleMgr.GetModelView(), pSimpleParticle->m_Pos, start); Vector3DMultiply( CurrentWorldToViewMatrix(), pSimpleParticle->m_vecVelocity, delta ); delta[0] *= scale; delta[1] *= scale; delta[2] *= scale; // See c_tracer.* for this method Tracer_Draw( pDraw, start, delta, random->RandomInt( 2, 8 ), 0 ); //Simulate the movement with collision trace_t trace; float timeDelta = pDraw->GetTimeDelta(); m_ParticleCollision.MoveParticle( pSimpleParticle->m_Pos, pSimpleParticle->m_vecVelocity, NULL, timeDelta, &trace ); return true; }
void CTEParticleRenderer::RenderParticles( CParticleRenderIterator *pIterator ) { const StandardParticle_t *pParticle = (const StandardParticle_t*)pIterator->GetFirst(); while ( pParticle ) { // Render. Vector tPos; TransformParticle(ParticleMgr()->GetModelView(), pParticle->m_Pos, tPos); float sortKey = tPos.z; Vector vColor(pParticle->m_Color[0]/255.9f, pParticle->m_Color[1]/255.9f, pParticle->m_Color[2]/255.9f); RenderParticle_ColorSize( pIterator->GetParticleDraw(), tPos, vColor, pParticle->m_Color[3]/255.9f, m_ParticleSize); pParticle = (const StandardParticle_t*)pIterator->GetNext( sortKey ); } }
//----------------------------------------------------------------------------- // Purpose: Simulate and render the particle in this system // Input : *pInParticle - particle to consider // *pDraw - drawing utilities // &sortKey - sorting key // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool CFleckParticles::SimulateAndRender( Particle *pInParticle, ParticleDraw *pDraw, float &sortKey ) { FleckParticle *pParticle = (FleckParticle *) pInParticle; const float timeDelta = pDraw->GetTimeDelta(); //Should this particle die? pParticle->m_flLifetime += timeDelta; if ( pParticle->m_flLifetime >= pParticle->m_flDieTime ) return false; //Render Vector tPos; TransformParticle( g_ParticleMgr.GetModelView(), pParticle->m_Pos, tPos ); sortKey = (int) tPos.z; Vector color; color[0] = pParticle->m_uchColor[0] / 255.0f; color[1] = pParticle->m_uchColor[1] / 255.0f; color[2] = pParticle->m_uchColor[2] / 255.0f; pParticle->m_flRoll += pParticle->m_flRollDelta * timeDelta; //Render it RenderParticle_ColorSizeAngle( pDraw, tPos, color, 1.0f - (pParticle->m_flLifetime / pParticle->m_flDieTime), pParticle->m_uchSize, pParticle->m_flRoll ); //Simulate the movement with collision trace_t trace; m_ParticleCollision.MoveParticle( pParticle->m_Pos, pParticle->m_vecVelocity, &pParticle->m_flRollDelta, timeDelta, &trace ); return true; }
inline void C_EntityParticleTrail::RenderParticles( CParticleRenderIterator *pIterator ) { const SimpleParticle *pParticle = (const SimpleParticle*)pIterator->GetFirst(); while ( pParticle ) { float t = pParticle->m_flLifetime / pParticle->m_flDieTime; // Render Vector tPos; TransformParticle( ParticleMgr()->GetModelView(), pParticle->m_Pos, tPos ); float sortKey = tPos.z; Vector color = Vector( pParticle->m_uchColor[0] / 255.0f, pParticle->m_uchColor[1] / 255.0f, pParticle->m_uchColor[2] / 255.0f ); float alpha = Lerp( t, pParticle->m_uchStartAlpha / 255.0f, pParticle->m_uchEndAlpha / 255.0f ); float flSize = Lerp( t, pParticle->m_uchStartSize, pParticle->m_uchEndSize ); // Render it RenderParticle_ColorSize( pIterator->GetParticleDraw(), tPos, color, alpha, flSize ); pParticle = (const SimpleParticle*)pIterator->GetNext( sortKey ); } }
bool C_FuncSmokeVolume::SimulateAndRender( Particle *pBaseParticle, ParticleDraw *pDraw, float &sortKey ) { if( m_CurrentDensity == 0.0f ) { return true; } SmokeGrenadeParticle* pParticle = (SmokeGrenadeParticle*)pBaseParticle; Vector renderPos = pParticle->m_Pos; // Fade out globally. float alpha = m_CurrentDensity; pParticle->m_CurRotation += pParticle->m_RotationFactor * ( M_PI / 180.0f ) * m_RotationSpeed * pDraw->GetTimeDelta(); // Apply the precalculated fade alpha from world geometry. alpha *= pParticle->m_FadeAlpha; // TODO: optimize this whole routine! Vector color = m_MinColor + (m_MaxColor - m_MinColor) * (pParticle->m_ColorInterp / 255.1f); color.x *= pParticle->m_Color[0] / 255.0f; color.y *= pParticle->m_Color[1] / 255.0f; color.z *= pParticle->m_Color[2] / 255.0f; Vector tRenderPos; TransformParticle( g_ParticleMgr.GetModelView(), renderPos, tRenderPos ); sortKey = tRenderPos.z; RenderParticle_ColorSizeAngle( pDraw, tRenderPos, color, alpha * GetAlphaDistanceFade(tRenderPos, 10, 30), // Alpha m_ParticleRadius, pParticle->m_CurRotation ); return true; }
void CSimpleEmitter::RenderParticles( CParticleRenderIterator *pIterator ) { const SimpleParticle *pParticle = (const SimpleParticle *)pIterator->GetFirst(); while ( pParticle ) { //Render Vector tPos; TransformParticle( ParticleMgr()->GetModelView(), pParticle->m_Pos, tPos ); float sortKey = (int) tPos.z; //Render it RenderParticle_ColorSizeAngle( pIterator->GetParticleDraw(), tPos, UpdateColor( pParticle ), UpdateAlpha( pParticle ) * GetAlphaDistanceFade( tPos, m_flNearClipMin, m_flNearClipMax ), UpdateScale( pParticle ), pParticle->m_flRoll ); pParticle = (const SimpleParticle *)pIterator->GetNext( sortKey ); } }
bool C_AR2Explosion::SimulateAndRender(Particle *pBaseParticle, ParticleDraw *pDraw, float &sortKey) { AR2ExplosionParticle* pParticle = (AR2ExplosionParticle*)pBaseParticle; float dt = pDraw->GetTimeDelta(); if (dt > 0.05) dt = 0.05; // yuck, air resistance function craps out at less then 20fps // Update its lifetime. pParticle->m_Lifetime += dt; // pDraw->GetTimeDelta(); if(pParticle->m_Lifetime > pParticle->m_Dwell) { // faded to nothing.... return false; } // Spin the thing pParticle->m_Roll += pParticle->m_RollSpeed * pDraw->GetTimeDelta(); // delayed? if(pParticle->m_Lifetime < 0.0f) { // not alive yet return true; } // Draw. float lifetimePercent = ( pParticle->m_Lifetime - AR2_DUST_FADE_IN_TIME ) / pParticle->m_Dwell; // FIXME: base color should be a dirty version of the material color Vector color = g_AR2DustColor1 * (1.0 - lifetimePercent) + g_AR2DustColor2 * lifetimePercent; Vector tPos; TransformParticle(m_pParticleMgr->GetModelView(), pParticle->m_Pos, tPos); // sortKey = tPos.z; float alpha; if ( pParticle->m_Lifetime < AR2_DUST_FADE_IN_TIME ) { alpha = AR2_DUST_ALPHA * ( pParticle->m_Lifetime / AR2_DUST_FADE_IN_TIME ); } else { alpha = AR2_DUST_ALPHA * ( 1.0f - lifetimePercent ); } alpha *= GetAlphaDistanceFade( tPos, 50, 150 ); RenderParticle_ColorSizeAngle( pDraw, tPos, color, alpha, pParticle->m_Dist, // size based on how far it's traveled pParticle->m_Roll); // Move it (this comes after rendering to make it clear that moving the particle here won't change // its rendering for this frame since m_TransformedPos has already been set). pParticle->m_Pos = pParticle->m_Pos + pParticle->m_Velocity * dt; // keep track of distance traveled pParticle->m_Dist = pParticle->m_Dist + pParticle->m_Velocity.Length() * dt; // Dampen velocity. float dist = pParticle->m_Velocity.Length() * dt; float r = dist * dist; // FIXME: this is a really screwy air-resistance function.... pParticle->m_Velocity = pParticle->m_Velocity * (100 / (100 + r )); // dampen roll static float dtime; static float decay; if (dtime != dt) { dtime = dt; decay = ExponentialDecay( 0.3, 1.0, dtime ); } if (fabs(pParticle->m_RollSpeed) > 0.2) pParticle->m_RollSpeed = pParticle->m_RollSpeed * decay; return true; }
void C_ParticleSmokeGrenade::RenderParticles( CParticleRenderIterator *pIterator ) { const SmokeGrenadeParticle *pParticle = (const SmokeGrenadeParticle*)pIterator->GetFirst(); while ( pParticle ) { Vector vWorldSpacePos = m_SmokeBasePos + pParticle->m_Pos; float sortKey; // Draw. float len = pParticle->m_Pos.Length(); if ( len > m_ExpandRadius ) { Vector vTemp; TransformParticle(ParticleMgr()->GetModelView(), vWorldSpacePos, vTemp); sortKey = vTemp.z; } else { // This smooths out the growing sphere. Rather than having particles appear in one spot as the sphere // expands, they stay at the borders. Vector renderPos; if(len > m_ExpandRadius * 0.5f) { renderPos = m_SmokeBasePos + (pParticle->m_Pos * (m_ExpandRadius * 0.5f)) / len; } else { renderPos = vWorldSpacePos; } // Figure out the alpha based on where it is in the sphere. float alpha = 1 - len / m_ExpandRadius; // This changes the ramp to be very solid in the core, then taper off. static float testCutoff=0.7; if(alpha > testCutoff) { alpha = 1; } else { // at testCutoff it's 1, at 0, it's 0 alpha = alpha / testCutoff; } // Fade out globally. alpha *= m_FadeAlpha; // Apply the precalculated fade alpha from world geometry. alpha *= pParticle->m_FadeAlpha; // TODO: optimize this whole routine! Vector color = m_MinColor + (m_MaxColor - m_MinColor) * (pParticle->m_ColorInterp / 255.1f); color.x *= pParticle->m_Color[0] / 255.0f; color.y *= pParticle->m_Color[1] / 255.0f; color.z *= pParticle->m_Color[2] / 255.0f; // Lighting. ApplyDynamicLight( renderPos, color ); Vector tRenderPos; TransformParticle(ParticleMgr()->GetModelView(), renderPos, tRenderPos); sortKey = tRenderPos.z; RenderParticle_ColorSizeAngle( pIterator->GetParticleDraw(), tRenderPos, color, alpha * GetAlphaDistanceFade(tRenderPos, 100, 200), // Alpha SMOKEPARTICLE_SIZE, pParticle->m_CurRotation ); } pParticle = (SmokeGrenadeParticle*)pIterator->GetNext( sortKey ); } }
void C_SmokeStack::SimulateParticles( CParticleSimulateIterator *pIterator ) { bool bSortNow = true; // Change this to false if we see sorting issues. bool bQuickTest = false; bool bDrawn = m_ParticleEffect.WasDrawnPrevFrame(); if ( bDrawn == true && m_bInView == false ) { bSortNow = true; } if ( bDrawn == false && m_bInView == true ) { bQuickTest = true; } if( bQuickTest == false && m_bEmit && (!m_ParticleEffect.WasDrawnPrevFrame() && !m_ParticleEffect.GetAlwaysSimulate()) ) return; SmokeStackParticle *pParticle = (SmokeStackParticle*)pIterator->GetFirst(); while ( pParticle ) { // Should this particle die? pParticle->m_Lifetime += pIterator->GetTimeDelta(); float tLifetime = pParticle->m_Lifetime * m_InvLifetime; if( tLifetime >= 1 ) { pIterator->RemoveParticle( pParticle ); } else { // Transform. Vector tPos; if( m_bTwist ) { Vector vTwist( pParticle->m_Pos.x - GetAbsOrigin().x, pParticle->m_Pos.y - GetAbsOrigin().y, 0); pParticle->m_Pos.x = vTwist.x * m_TwistMat[0][0] + vTwist.y * m_TwistMat[0][1] + GetAbsOrigin().x; pParticle->m_Pos.y = vTwist.x * m_TwistMat[1][0] + vTwist.y * m_TwistMat[1][1] + GetAbsOrigin().y; } pParticle->m_Pos = pParticle->m_Pos + pParticle->m_Velocity * pIterator->GetTimeDelta() + pParticle->m_vAccel * pIterator->GetTimeDelta(); pParticle->m_flAngle += pParticle->m_flRollDelta * pIterator->GetTimeDelta(); if ( bSortNow == true ) { Vector tPos; TransformParticle( m_pParticleMgr->GetModelView(), pParticle->m_Pos, tPos ); pParticle->m_flSortPos = tPos.z; } } pParticle = (SmokeStackParticle*)pIterator->GetNext(); } m_bInView = bDrawn; }
bool C_ParticleSmokeGrenade::SimulateAndRender(Particle *pBaseParticle, ParticleDraw *pDraw, float &sortKey) { SmokeGrenadeParticle* pParticle = (SmokeGrenadeParticle*)pBaseParticle; // Draw. float len = (pParticle->m_Pos - m_SmokeBasePos).Length(); if(len > m_ExpandRadius) { Vector vTemp; TransformParticle(g_ParticleMgr.GetModelView(), pParticle->m_Pos, vTemp); sortKey = vTemp.z; return true; } // This smooths out the growing sphere. Rather than having particles appear in one spot as the sphere // expands, they stay at the borders. Vector renderPos; if(len > m_ExpandRadius * 0.5f) { renderPos = m_SmokeBasePos + ((pParticle->m_Pos - m_SmokeBasePos) * (m_ExpandRadius * 0.5f)) / len; } else { renderPos = pParticle->m_Pos; } // Figure out the alpha based on where it is in the sphere. float alpha = 1 - len / m_ExpandRadius; // This changes the ramp to be very solid in the core, then taper off. static float testCutoff=0.7; if(alpha > testCutoff) { alpha = 1; } else { // at testCutoff it's 1, at 0, it's 0 alpha = alpha / testCutoff; } // Fade out globally. alpha *= m_FadeAlpha; pParticle->m_CurRotation += pParticle->m_RotationSpeed * pDraw->GetTimeDelta(); // Apply the precalculated fade alpha from world geometry. alpha *= pParticle->m_FadeAlpha; // TODO: optimize this whole routine! Vector color = m_MinColor + (m_MaxColor - m_MinColor) * (pParticle->m_ColorInterp / 255.1f); color.x *= pParticle->m_Color[0] / 255.0f; color.y *= pParticle->m_Color[1] / 255.0f; color.z *= pParticle->m_Color[2] / 255.0f; Vector tRenderPos; TransformParticle(g_ParticleMgr.GetModelView(), renderPos, tRenderPos); sortKey = tRenderPos.z; RenderParticle_ColorSizeAngle( pDraw, tRenderPos, color, alpha * GetAlphaDistanceFade(tRenderPos, 10, 30), // Alpha SMOKEPARTICLE_SIZE, pParticle->m_CurRotation ); return true; }
//----------------------------------------------------------------------------- // Purpose: Update state + render //----------------------------------------------------------------------------- bool CBasePlasmaProjectile::SimulateAndRender(Particle *pInParticle, ParticleDraw *pDraw, float &sortKey) { if ( IsDormantPredictable() ) return true; if ( GetMoveType() == MOVETYPE_NONE ) return true; // Update the particle position pInParticle->m_Pos = GetAbsOrigin(); // Add our blended offset if ( gpGlobals->curtime < m_Shared.GetSpawnTime() + REMAP_BLEND_TIME ) { float frac = ( gpGlobals->curtime - m_Shared.GetSpawnTime() ) / REMAP_BLEND_TIME; frac = 1.0f - clamp( frac, 0.0f, 1.0f ); Vector scaledOffset; VectorScale( m_vecGunOriginOffset, frac, scaledOffset ); pInParticle->m_Pos += scaledOffset; } float timeDelta = pDraw->GetTimeDelta(); // Render the head particle if ( pInParticle == m_pHeadParticle ) { SimpleParticle *pParticle = (SimpleParticle *) pInParticle; pParticle->m_flLifetime += timeDelta; // Render Vector tPos, vecOrigin; RemapPosition( m_pPreviousPositions[MAX_HISTORY-1].m_Position, m_pPreviousPositions[MAX_HISTORY-1].m_Time, vecOrigin ); TransformParticle( ParticleMgr()->GetModelView(), vecOrigin, tPos ); sortKey = (int) tPos.z; //Render it RenderParticle_ColorSizeAngle( pDraw, tPos, UpdateColor( pParticle, timeDelta ), UpdateAlpha( pParticle, timeDelta ) * GetAlphaDistanceFade( tPos, 16, 64 ), UpdateScale( pParticle, timeDelta ), UpdateRoll( pParticle, timeDelta ) ); /* if ( m_flNextSparkEffect < gpGlobals->curtime ) { // Drop sparks? if ( GetTeamNumber() == TEAM_HUMANS ) { g_pEffects->Sparks( pInParticle->m_Pos, 1, 3 ); } else { g_pEffects->EnergySplash( pInParticle->m_Pos, vec3_origin ); } m_flNextSparkEffect = gpGlobals->curtime + RandomFloat( 0.5, 2 ); } */ return true; } // Render the trail TrailParticle *pParticle = (TrailParticle *) pInParticle; pParticle->m_flLifetime += timeDelta; Vector vecScreenStart, vecScreenDelta; sortKey = pParticle->m_Pos.z; // NOTE: We need to do everything in screen space float flFragmentLength = (MAX_HISTORY > 1) ? 1.0 / (float)(MAX_HISTORY-1) : 1.0; for ( int i = 0; i < (MAX_HISTORY-1); i++ ) { Vector vecWorldStart, vecWorldEnd, vecScreenEnd; float flStartV, flEndV; // Did we just appear? if ( m_pPreviousPositions[i].m_Time == 0 ) continue; RemapPosition( m_pPreviousPositions[i+1].m_Position, m_pPreviousPositions[i+1].m_Time, vecWorldStart ); RemapPosition( m_pPreviousPositions[i].m_Position, m_pPreviousPositions[i].m_Time, vecWorldEnd ); // Texture wrapping flStartV = (flFragmentLength * (i+1)); flEndV = (flFragmentLength * i); TransformParticle( ParticleMgr()->GetModelView(), vecWorldStart, vecScreenStart ); TransformParticle( ParticleMgr()->GetModelView(), vecWorldEnd, vecScreenEnd ); Vector vecScreenDelta = (vecScreenEnd - vecScreenStart); if ( vecScreenDelta == vec3_origin ) continue; /* Vector vecForward, vecRight; AngleVectors( MainViewAngles(), &vecForward, &vecRight, NULL ); Vector vecWorldDelta = ( vecWorldEnd - vecWorldStart ); VectorNormalize( vecWorldDelta ); float flDot = fabs(DotProduct( vecWorldDelta, vecForward )); if ( flDot > 0.99 ) { // Remap alpha pParticle->m_flColor[3] = 1.0 - min( 1.0, RemapVal( flDot, 0.99, 1.0, 0, 1 ) ); } */ // See if we should fade float color[4]; Color32ToFloat4( color, pParticle->m_color ); Tracer_Draw( pDraw, vecScreenStart, vecScreenDelta, pParticle->m_flWidth, color, flStartV, flEndV ); } return true; }