void CParticleSystemManager :: UpdateSystems( void ) { float frametime; static int framecount = -1; AURSTATE state; // HACKHACK: don't evaluate particles when executes many times at same frame // e.g. mirror rendering if( framecount != tr.realframecount ) { frametime = RI.refdef.frametime; framecount = tr.realframecount; } else frametime = 0.0f; CParticleSystem *pSystem; CParticleSystem *pLast = NULL; pSystem = m_pFirstSystem; while( pSystem ) { state = pSystem->UpdateSystem( frametime ); if( state != AURORA_REMOVE ) { if( state == AURORA_DRAW ) pSystem->DrawSystem(); pLast = pSystem; pSystem = pSystem->m_pNextSystem; } else { // delete this system if( pLast ) { pLast->m_pNextSystem = pSystem->m_pNextSystem; delete pSystem; pSystem = pLast->m_pNextSystem; } else { // deleting the first system m_pFirstSystem = pSystem->m_pNextSystem; delete pSystem; pSystem = m_pFirstSystem; } } } gEngfuncs.pTriAPI->RenderMode(kRenderNormal); }
// updates all systems void CParticleSystemManager::UpdateSystems( void ) { CParticleSystem *pSystem = NULL; signed int i = 0; signed int iSystems = (signed)m_pParticleSystems.size(); // iterate through all the particle systems, drawing each for (; i < iSystems; i++) { pSystem = m_pParticleSystems[i]; // remove the system if the system requests it if( pSystem && pSystem->DrawSystem() == false) { delete pSystem; m_pParticleSystems.erase((m_pParticleSystems.begin() + i)); i--; iSystems--; } } // we couldn't return earlier as we need to have the sorting before the ps updating // however no sorting when we can't see the particles if(CheckDrawSystem() == false) return; int iParticles = m_pParticles.size(); if(iParticles > 1) { // calculate the fraction of a second between sorts float flTimeSinceLastSort = (gEngfuncs.GetClientTime() - m_flLastSort); // 1 / time between sorts will give us a number like 5 // if it is less than the particlesorts cvar then it is a small value // and therefore a long time since last sort if((((int)(1 / flTimeSinceLastSort)) < g_ParticleSorts->value)) { m_flLastSort = gEngfuncs.GetClientTime(); std::sort(m_pParticles.begin(), m_pParticles.end(), less_than); } } if(iParticles > 0) { // prepare opengl Particle_InitOpenGL(); float flTimeSinceLastDraw = TimeSinceLastDraw(); // loop through all particles drawing them // they have already been tested and updated in their pss' draw sys func // we've reversed the greater than order, so that oldest particles are at 0 // further away particles and recently added particles get drawn first CParticle *pParticle = NULL; for(i = 0; i < iParticles ; i++) { if(m_pParticles[i]) { pParticle = m_pParticles[i]; if(pParticle && pParticle->Test()) { pParticle->Update(flTimeSinceLastDraw); if(g_iUser1 != OBS_MAP_FREE && g_iUser1 != OBS_MAP_CHASE) { // unfortunately we have to prepare every particle now // as we can't prepare for a batch of the same type anymore pParticle->Prepare(); pParticle->Draw(); } } else { RemoveParticle(pParticle); i--; iParticles--; } } } Particle_FinishOpenGL(); } // print out how fast we've been drawing the systems in debug mode if (g_ParticleDebug->value != 0 && ((m_flLastSort + 0.5) <= gEngfuncs.GetClientTime())) { gEngfuncs.Con_Printf("%i Particles Drawn this pass in %i systems ", m_pParticles.size(), m_pParticleSystems.size()); gEngfuncs.Con_Printf("%i Textures in Cache\n\0", m_pTextures.size()); } m_flLastDraw = gEngfuncs.GetClientTime(); }