Team Fortress 2 Source Code as on 22/4/2020
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

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Client side CTFTeam class
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #ifndef PARTICLE_ITERATORS_H
  8. #define PARTICLE_ITERATORS_H
  9. #ifdef _WIN32
  10. #pragma once
  11. #endif
  12. #include "materialsystem/imesh.h"
  13. #include "particledraw.h"
  14. #define NUM_PARTICLES_PER_BATCH 200
  15. #ifndef _XBOX
  16. #define MAX_TOTAL_PARTICLES 2048 // Max particles in the world
  17. #else
  18. #define MAX_TOTAL_PARTICLES 1024
  19. #endif
  20. //
  21. // Iterate the particles like this:
  22. //
  23. // Particle *pCur = pIterator->GetFirst();
  24. // while ( pCur )
  25. // {
  26. // ... render the particle here and figure out the sort key and position
  27. // pCur = pIterator->GetNext( sortKey, pCur->m_Pos );
  28. // }
  29. //
  30. class CParticleRenderIterator
  31. {
  32. friend class CParticleMgr;
  33. friend class CParticleEffectBinding;
  34. public:
  35. CParticleRenderIterator();
  36. // The sort key is used to sort the particles incrementally as they're rendered.
  37. // They only get sorted in the main rendered view (ie: not in reflections or monitors).
  38. // These return const because you should only modify particles during their simulation.
  39. const Particle* GetFirst();
  40. const Particle* GetNext( float sortKey );
  41. // Use this to render. This can return NULL, in which case you shouldn't render.
  42. // This being NULL is a carryover from when particles rendered and simulated together and
  43. // it should GO AWAY SOON!
  44. ParticleDraw* GetParticleDraw() const;
  45. private:
  46. void TestFlushBatch();
  47. private:
  48. // Set by CParticleMgr.
  49. CParticleEffectBinding *m_pEffectBinding;
  50. CEffectMaterial *m_pMaterial;
  51. ParticleDraw *m_pParticleDraw;
  52. CMeshBuilder *m_pMeshBuilder;
  53. IMesh *m_pMesh;
  54. bool m_bBucketSort;
  55. // Output after rendering.
  56. float m_MinZ;
  57. float m_MaxZ;
  58. float m_zCoords[MAX_TOTAL_PARTICLES];
  59. int m_nZCoords;
  60. Particle *m_pCur;
  61. bool m_bGotFirst;
  62. float m_flPrevZ;
  63. int m_nParticlesInCurrentBatch;
  64. };
  65. //
  66. // Iterate the particles like this:
  67. //
  68. // Particle *pCur = pIterator->GetFirst();
  69. // while ( pCur )
  70. // {
  71. // ... simulate here.. call pIterator->RemoveParticle if you want the particle to go away
  72. // pCur = pIterator->GetNext();
  73. // }
  74. //
  75. class CParticleSimulateIterator
  76. {
  77. friend class CParticleMgr;
  78. friend class CParticleEffectBinding;
  79. public:
  80. CParticleSimulateIterator();
  81. // Iterate through the particles, simulate them, and remove them if necessary.
  82. Particle* GetFirst();
  83. Particle* GetNext();
  84. float GetTimeDelta() const;
  85. void RemoveParticle( Particle *pParticle );
  86. void RemoveAllParticles();
  87. private:
  88. CParticleEffectBinding *m_pEffectBinding;
  89. CEffectMaterial *m_pMaterial;
  90. float m_flTimeDelta;
  91. bool m_bGotFirst;
  92. Particle *m_pNextParticle;
  93. };
  94. // -------------------------------------------------------------------------------------------------------- //
  95. // CParticleRenderIterator inlines
  96. // -------------------------------------------------------------------------------------------------------- //
  97. inline CParticleRenderIterator::CParticleRenderIterator()
  98. {
  99. m_pCur = NULL;
  100. m_bGotFirst = false;
  101. m_flPrevZ = 0;
  102. m_nParticlesInCurrentBatch = 0;
  103. m_MinZ = 1e24;
  104. m_MaxZ = -1e24;
  105. m_nZCoords = 0;
  106. }
  107. inline const Particle* CParticleRenderIterator::GetFirst()
  108. {
  109. Assert( !m_bGotFirst );
  110. m_bGotFirst = true;
  111. m_pCur = m_pMaterial->m_Particles.m_pNext;
  112. if ( m_pCur == &m_pMaterial->m_Particles )
  113. return NULL;
  114. m_pParticleDraw->m_pSubTexture = m_pCur->m_pSubTexture;
  115. return m_pCur;
  116. }
  117. inline void CParticleRenderIterator::TestFlushBatch()
  118. {
  119. ++m_nParticlesInCurrentBatch;
  120. if( m_nParticlesInCurrentBatch >= NUM_PARTICLES_PER_BATCH )
  121. {
  122. m_pMeshBuilder->End( false, true );
  123. m_pMeshBuilder->Begin( m_pMesh, MATERIAL_QUADS, NUM_PARTICLES_PER_BATCH * 4 );
  124. m_nParticlesInCurrentBatch = 0;
  125. }
  126. }
  127. inline const Particle* CParticleRenderIterator::GetNext( float sortKey )
  128. {
  129. Assert( m_bGotFirst );
  130. Assert( m_pCur );
  131. TestFlushBatch();
  132. Particle *pNext = m_pCur->m_pNext;
  133. // Update the incremental sort.
  134. if( m_bBucketSort )
  135. {
  136. m_MinZ = MIN( sortKey, m_MinZ );
  137. m_MaxZ = MAX( sortKey, m_MaxZ );
  138. m_zCoords[m_nZCoords] = sortKey;
  139. ++m_nZCoords;
  140. }
  141. else
  142. {
  143. // Swap with the previous particle (incremental sort)?
  144. if( m_pCur != m_pMaterial->m_Particles.m_pNext && m_flPrevZ > sortKey )
  145. {
  146. SwapParticles( m_pCur->m_pPrev, m_pCur );
  147. }
  148. else
  149. {
  150. m_flPrevZ = sortKey;
  151. }
  152. }
  153. m_pCur = pNext;
  154. if ( m_pCur == &m_pMaterial->m_Particles )
  155. return NULL;
  156. m_pParticleDraw->m_pSubTexture = m_pCur->m_pSubTexture;
  157. return m_pCur;
  158. }
  159. inline ParticleDraw* CParticleRenderIterator::GetParticleDraw() const
  160. {
  161. return m_pParticleDraw;
  162. }
  163. // -------------------------------------------------------------------------------------------------------- //
  164. // CParticleSimulateIterator inlines
  165. // -------------------------------------------------------------------------------------------------------- //
  166. inline CParticleSimulateIterator::CParticleSimulateIterator()
  167. {
  168. m_pNextParticle = NULL;
  169. #ifdef _DEBUG
  170. m_bGotFirst = false;
  171. #endif
  172. }
  173. inline Particle* CParticleSimulateIterator::GetFirst()
  174. {
  175. #ifdef _DEBUG
  176. // Make sure they're either starting out fresh or that the previous guy iterated through all the particles.
  177. if ( m_bGotFirst )
  178. {
  179. Assert( m_pNextParticle == &m_pMaterial->m_Particles );
  180. }
  181. #endif
  182. Particle *pRet = m_pMaterial->m_Particles.m_pNext;
  183. if ( pRet == &m_pMaterial->m_Particles )
  184. return NULL;
  185. #ifdef _DEBUG
  186. m_bGotFirst = true;
  187. #endif
  188. m_pNextParticle = pRet->m_pNext;
  189. return pRet;
  190. }
  191. inline Particle* CParticleSimulateIterator::GetNext()
  192. {
  193. Particle *pRet = m_pNextParticle;
  194. if ( pRet == &m_pMaterial->m_Particles )
  195. return NULL;
  196. m_pNextParticle = pRet->m_pNext;
  197. return pRet;
  198. }
  199. inline void CParticleSimulateIterator::RemoveParticle( Particle *pParticle )
  200. {
  201. m_pEffectBinding->RemoveParticle( pParticle );
  202. }
  203. inline void CParticleSimulateIterator::RemoveAllParticles()
  204. {
  205. Particle *pParticle = GetFirst();
  206. while ( pParticle )
  207. {
  208. RemoveParticle( pParticle );
  209. pParticle = GetNext();
  210. }
  211. }
  212. inline float CParticleSimulateIterator::GetTimeDelta() const
  213. {
  214. return m_flTimeDelta;
  215. }
  216. #endif // PARTICLE_ITERATORS_H