You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
270 lines
6.0 KiB
270 lines
6.0 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: Client side CTFTeam class |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
|
|
#ifndef PARTICLE_ITERATORS_H |
|
#define PARTICLE_ITERATORS_H |
|
#ifdef _WIN32 |
|
#pragma once |
|
#endif |
|
|
|
|
|
#include "materialsystem/imesh.h" |
|
#include "particledraw.h" |
|
|
|
|
|
#define NUM_PARTICLES_PER_BATCH 200 |
|
#ifndef _XBOX |
|
#define MAX_TOTAL_PARTICLES 2048 // Max particles in the world |
|
#else |
|
#define MAX_TOTAL_PARTICLES 1024 |
|
#endif |
|
|
|
|
|
// |
|
// Iterate the particles like this: |
|
// |
|
// Particle *pCur = pIterator->GetFirst(); |
|
// while ( pCur ) |
|
// { |
|
// ... render the particle here and figure out the sort key and position |
|
// pCur = pIterator->GetNext( sortKey, pCur->m_Pos ); |
|
// } |
|
// |
|
class CParticleRenderIterator |
|
{ |
|
friend class CParticleMgr; |
|
friend class CParticleEffectBinding; |
|
public: |
|
CParticleRenderIterator(); |
|
|
|
// The sort key is used to sort the particles incrementally as they're rendered. |
|
// They only get sorted in the main rendered view (ie: not in reflections or monitors). |
|
// These return const because you should only modify particles during their simulation. |
|
const Particle* GetFirst(); |
|
const Particle* GetNext( float sortKey ); |
|
|
|
// Use this to render. This can return NULL, in which case you shouldn't render. |
|
// This being NULL is a carryover from when particles rendered and simulated together and |
|
// it should GO AWAY SOON! |
|
ParticleDraw* GetParticleDraw() const; |
|
|
|
|
|
private: |
|
|
|
void TestFlushBatch(); |
|
|
|
|
|
private: |
|
// Set by CParticleMgr. |
|
CParticleEffectBinding *m_pEffectBinding; |
|
CEffectMaterial *m_pMaterial; |
|
ParticleDraw *m_pParticleDraw; |
|
CMeshBuilder *m_pMeshBuilder; |
|
IMesh *m_pMesh; |
|
bool m_bBucketSort; |
|
|
|
// Output after rendering. |
|
float m_MinZ; |
|
float m_MaxZ; |
|
float m_zCoords[MAX_TOTAL_PARTICLES]; |
|
int m_nZCoords; |
|
|
|
Particle *m_pCur; |
|
bool m_bGotFirst; |
|
float m_flPrevZ; |
|
int m_nParticlesInCurrentBatch; |
|
}; |
|
|
|
|
|
// |
|
// Iterate the particles like this: |
|
// |
|
// Particle *pCur = pIterator->GetFirst(); |
|
// while ( pCur ) |
|
// { |
|
// ... simulate here.. call pIterator->RemoveParticle if you want the particle to go away |
|
// pCur = pIterator->GetNext(); |
|
// } |
|
// |
|
class CParticleSimulateIterator |
|
{ |
|
friend class CParticleMgr; |
|
friend class CParticleEffectBinding; |
|
public: |
|
CParticleSimulateIterator(); |
|
|
|
// Iterate through the particles, simulate them, and remove them if necessary. |
|
Particle* GetFirst(); |
|
Particle* GetNext(); |
|
float GetTimeDelta() const; |
|
|
|
void RemoveParticle( Particle *pParticle ); |
|
void RemoveAllParticles(); |
|
|
|
private: |
|
CParticleEffectBinding *m_pEffectBinding; |
|
CEffectMaterial *m_pMaterial; |
|
float m_flTimeDelta; |
|
|
|
bool m_bGotFirst; |
|
Particle *m_pNextParticle; |
|
}; |
|
|
|
|
|
// -------------------------------------------------------------------------------------------------------- // |
|
// CParticleRenderIterator inlines |
|
// -------------------------------------------------------------------------------------------------------- // |
|
|
|
inline CParticleRenderIterator::CParticleRenderIterator() |
|
{ |
|
m_pCur = NULL; |
|
m_bGotFirst = false; |
|
m_flPrevZ = 0; |
|
m_nParticlesInCurrentBatch = 0; |
|
m_MinZ = 1e24; |
|
m_MaxZ = -1e24; |
|
m_nZCoords = 0; |
|
} |
|
|
|
inline const Particle* CParticleRenderIterator::GetFirst() |
|
{ |
|
Assert( !m_bGotFirst ); |
|
m_bGotFirst = true; |
|
|
|
m_pCur = m_pMaterial->m_Particles.m_pNext; |
|
if ( m_pCur == &m_pMaterial->m_Particles ) |
|
return NULL; |
|
|
|
m_pParticleDraw->m_pSubTexture = m_pCur->m_pSubTexture; |
|
return m_pCur; |
|
} |
|
|
|
inline void CParticleRenderIterator::TestFlushBatch() |
|
{ |
|
++m_nParticlesInCurrentBatch; |
|
if( m_nParticlesInCurrentBatch >= NUM_PARTICLES_PER_BATCH ) |
|
{ |
|
m_pMeshBuilder->End( false, true ); |
|
m_pMeshBuilder->Begin( m_pMesh, MATERIAL_QUADS, NUM_PARTICLES_PER_BATCH * 4 ); |
|
|
|
m_nParticlesInCurrentBatch = 0; |
|
} |
|
} |
|
|
|
inline const Particle* CParticleRenderIterator::GetNext( float sortKey ) |
|
{ |
|
Assert( m_bGotFirst ); |
|
Assert( m_pCur ); |
|
|
|
TestFlushBatch(); |
|
|
|
Particle *pNext = m_pCur->m_pNext; |
|
|
|
// Update the incremental sort. |
|
if( m_bBucketSort ) |
|
{ |
|
m_MinZ = MIN( sortKey, m_MinZ ); |
|
m_MaxZ = MAX( sortKey, m_MaxZ ); |
|
|
|
m_zCoords[m_nZCoords] = sortKey; |
|
++m_nZCoords; |
|
} |
|
else |
|
{ |
|
// Swap with the previous particle (incremental sort)? |
|
if( m_pCur != m_pMaterial->m_Particles.m_pNext && m_flPrevZ > sortKey ) |
|
{ |
|
SwapParticles( m_pCur->m_pPrev, m_pCur ); |
|
} |
|
else |
|
{ |
|
m_flPrevZ = sortKey; |
|
} |
|
} |
|
|
|
m_pCur = pNext; |
|
if ( m_pCur == &m_pMaterial->m_Particles ) |
|
return NULL; |
|
|
|
m_pParticleDraw->m_pSubTexture = m_pCur->m_pSubTexture; |
|
return m_pCur; |
|
} |
|
|
|
inline ParticleDraw* CParticleRenderIterator::GetParticleDraw() const |
|
{ |
|
return m_pParticleDraw; |
|
} |
|
|
|
|
|
// -------------------------------------------------------------------------------------------------------- // |
|
// CParticleSimulateIterator inlines |
|
// -------------------------------------------------------------------------------------------------------- // |
|
|
|
inline CParticleSimulateIterator::CParticleSimulateIterator() |
|
{ |
|
m_pNextParticle = NULL; |
|
#ifdef _DEBUG |
|
m_bGotFirst = false; |
|
#endif |
|
} |
|
|
|
inline Particle* CParticleSimulateIterator::GetFirst() |
|
{ |
|
#ifdef _DEBUG |
|
// Make sure they're either starting out fresh or that the previous guy iterated through all the particles. |
|
if ( m_bGotFirst ) |
|
{ |
|
Assert( m_pNextParticle == &m_pMaterial->m_Particles ); |
|
} |
|
#endif |
|
|
|
Particle *pRet = m_pMaterial->m_Particles.m_pNext; |
|
if ( pRet == &m_pMaterial->m_Particles ) |
|
return NULL; |
|
|
|
#ifdef _DEBUG |
|
m_bGotFirst = true; |
|
#endif |
|
|
|
m_pNextParticle = pRet->m_pNext; |
|
return pRet; |
|
} |
|
|
|
inline Particle* CParticleSimulateIterator::GetNext() |
|
{ |
|
Particle *pRet = m_pNextParticle; |
|
|
|
if ( pRet == &m_pMaterial->m_Particles ) |
|
return NULL; |
|
|
|
m_pNextParticle = pRet->m_pNext; |
|
return pRet; |
|
} |
|
|
|
inline void CParticleSimulateIterator::RemoveParticle( Particle *pParticle ) |
|
{ |
|
m_pEffectBinding->RemoveParticle( pParticle ); |
|
} |
|
|
|
inline void CParticleSimulateIterator::RemoveAllParticles() |
|
{ |
|
Particle *pParticle = GetFirst(); |
|
while ( pParticle ) |
|
{ |
|
RemoveParticle( pParticle ); |
|
pParticle = GetNext(); |
|
} |
|
} |
|
|
|
inline float CParticleSimulateIterator::GetTimeDelta() const |
|
{ |
|
return m_flTimeDelta; |
|
} |
|
|
|
|
|
#endif // PARTICLE_ITERATORS_H |
|
|
|
|