Counter Strike : Global Offensive Source Code
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.

239 lines
7.2 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $Workfile: $
  6. // $NoKeywords: $
  7. //=============================================================================//
  8. #include "cbase.h"
  9. #include "fx_fleck.h"
  10. // memdbgon must be the last include file in a .cpp file!!!
  11. #include "tier0/memdbgon.h"
  12. // enable this to have the fleck_merge cvar as well as the current system count displayed as it changes (for profiling)
  13. #define REPORT_MERGED_FLECKS 0
  14. //
  15. // class PARTICLE_MERGE
  16. //{
  17. //public:
  18. // bool MergeParticleSystems( CFleckParticles *pSystem, const char *pEffectName, const Vector &center, const Vector &extents )
  19. // { merge; return true; }
  20. //};
  21. // a singly linked list through all particle effects of a specific type
  22. // with a specific rule for sharing them.
  23. // Needs a hook to the particle effect's constructor/destructor and factory method
  24. // The factory needs to support optionally merging the new particles into a previously built particle effect
  25. // this cuts down on lots of scene management overhead as well as rendering/batch overhead
  26. template< class PARTICLE_EFFECT, class PARTICLE_MERGE >
  27. class CParticleMergeList
  28. {
  29. public:
  30. CParticleMergeList() : m_pHead(NULL) {}
  31. void AddParticleSystem( PARTICLE_EFFECT *pSystem );
  32. void RemoveParticleSystem( PARTICLE_EFFECT *pRemove );
  33. PARTICLE_EFFECT *FindAndMergeParticleSystem( const char *pEffectName, const Vector &center, const Vector &extents );
  34. bool MergeParticleSystems( PARTICLE_EFFECT *pSystem, const char *pEffectName, const Vector &center, const Vector &extents );
  35. private:
  36. PARTICLE_EFFECT *m_pHead;
  37. PARTICLE_MERGE m_merge;
  38. };
  39. #if REPORT_MERGED_FLECKS
  40. ConVar fleck_merge("fleck_merge","1");
  41. int g_PCount = 0;
  42. #endif
  43. template< class PARTICLE_EFFECT, class PARTICLE_MERGE >
  44. void CParticleMergeList<PARTICLE_EFFECT,PARTICLE_MERGE>::AddParticleSystem( PARTICLE_EFFECT *pSystem )
  45. {
  46. #if REPORT_MERGED_FLECKS
  47. g_PCount++;
  48. Msg("PS: %d\n", g_PCount);
  49. #endif
  50. pSystem->m_pNextParticleSystem = m_pHead;
  51. m_pHead = pSystem;
  52. }
  53. template< class PARTICLE_EFFECT, class PARTICLE_MERGE >
  54. void CParticleMergeList<PARTICLE_EFFECT,PARTICLE_MERGE>::RemoveParticleSystem( PARTICLE_EFFECT *pRemove )
  55. {
  56. #if REPORT_MERGED_FLECKS
  57. g_PCount--;
  58. Msg("PS: %d\n", g_PCount);
  59. #endif
  60. PARTICLE_EFFECT **pPrev = &m_pHead;
  61. PARTICLE_EFFECT *pCur = *pPrev;
  62. while ( pCur )
  63. {
  64. if ( pCur == pRemove )
  65. {
  66. *pPrev = pCur->m_pNextParticleSystem;
  67. return;
  68. }
  69. pPrev = &pCur->m_pNextParticleSystem;
  70. pCur = *pPrev;
  71. }
  72. }
  73. template< class PARTICLE_EFFECT, class PARTICLE_MERGE >
  74. PARTICLE_EFFECT *CParticleMergeList<PARTICLE_EFFECT,PARTICLE_MERGE>::FindAndMergeParticleSystem( const char *pEffectName, const Vector &center, const Vector &extents )
  75. {
  76. #if REPORT_MERGED_FLECKS
  77. if ( !fleck_merge.GetBool() )
  78. return NULL;
  79. #endif
  80. for ( PARTICLE_EFFECT *pMerge = m_pHead; pMerge != NULL; pMerge = pMerge->m_pNextParticleSystem )
  81. {
  82. if ( m_merge.MergeParticleSystems( pMerge, pEffectName, center, extents ) )
  83. return pMerge;
  84. }
  85. return NULL;
  86. }
  87. // merge anything within 10 feet
  88. const float MAX_RADIUS_BBOX_MERGE = 120.0f;
  89. template< class PARTICLE_EFFECT >
  90. class CMergeSameNameBbox
  91. {
  92. public:
  93. bool MergeParticleSystems( PARTICLE_EFFECT *pSystem, const char *pEffectName, const Vector &center, const Vector &extents )
  94. {
  95. // by default, match names
  96. if ( !Q_stricmp(pSystem->GetEffectName(), pEffectName) )
  97. {
  98. Vector mins, maxs;
  99. pSystem->GetBinding().GetWorldspaceBounds( &mins, &maxs );
  100. AddPointToBounds( center - extents, mins, maxs );
  101. AddPointToBounds( center + extents, mins, maxs );
  102. Vector size = maxs - mins;
  103. float radius = size.Length();
  104. if ( radius < MAX_RADIUS_BBOX_MERGE )
  105. {
  106. pSystem->GetBinding().SetBBox( mins, maxs );
  107. // put sort origin at center of the new box
  108. Vector sortOrigin = 0.5f * (mins+maxs);
  109. pSystem->SetSortOrigin(sortOrigin);
  110. return true;
  111. }
  112. }
  113. return false;
  114. }
  115. };
  116. CParticleMergeList< CFleckParticles, CMergeSameNameBbox<CFleckParticles> > g_FleckMergeList;
  117. //
  118. // CFleckParticles
  119. //
  120. CSmartPtr<CFleckParticles> CFleckParticles::Create( const char *pDebugName, const Vector &vCenter, const Vector &extents )
  121. {
  122. CFleckParticles *pMerge = g_FleckMergeList.FindAndMergeParticleSystem( pDebugName, vCenter, extents );
  123. if ( pMerge )
  124. return pMerge;
  125. CFleckParticles *pRet = new CFleckParticles( pDebugName );
  126. if ( pRet )
  127. {
  128. pRet->GetBinding().SetBBox( vCenter - extents, vCenter + extents );
  129. pRet->SetSortOrigin(vCenter);
  130. }
  131. return pRet;
  132. }
  133. CFleckParticles::CFleckParticles( const char *pDebugName ) : CSimpleEmitter( pDebugName ), m_pNextParticleSystem(NULL)
  134. {
  135. g_FleckMergeList.AddParticleSystem(this);
  136. }
  137. CFleckParticles::~CFleckParticles()
  138. {
  139. g_FleckMergeList.RemoveParticleSystem(this);
  140. }
  141. //-----------------------------------------------------------------------------
  142. // Purpose: Test for surrounding collision surfaces for quick collision testing for the particle system
  143. // Input : &origin - starting position
  144. // *dir - direction of movement (if NULL, will do a point emission test in four directions)
  145. // angularSpread - looseness of the spread
  146. // minSpeed - minimum speed
  147. // maxSpeed - maximum speed
  148. // gravity - particle gravity for the sytem
  149. // dampen - dampening amount on collisions
  150. // flags - extra information
  151. //-----------------------------------------------------------------------------
  152. void CFleckParticles::Setup( const Vector &origin, const Vector *direction, float angularSpread, float minSpeed, float maxSpeed, float gravity, float dampen, int flags )
  153. {
  154. //See if we've specified a direction
  155. m_ParticleCollision.Setup( origin, direction, angularSpread, minSpeed, maxSpeed, gravity, dampen );
  156. }
  157. void CFleckParticles::RenderParticles( CParticleRenderIterator *pIterator )
  158. {
  159. const FleckParticle *pParticle = (const FleckParticle*)pIterator->GetFirst();
  160. while ( pParticle )
  161. {
  162. Vector tPos;
  163. TransformParticle( ParticleMgr()->GetModelView(), pParticle->m_Pos, tPos );
  164. float sortKey = (int) tPos.z;
  165. Vector color;
  166. color[0] = pParticle->m_uchColor[0] / 255.0f;
  167. color[1] = pParticle->m_uchColor[1] / 255.0f;
  168. color[2] = pParticle->m_uchColor[2] / 255.0f;
  169. //Render it
  170. RenderParticle_ColorSizeAngle(
  171. pIterator->GetParticleDraw(),
  172. tPos,
  173. color,
  174. 1.0f - (pParticle->m_flLifetime / pParticle->m_flDieTime),
  175. pParticle->m_uchSize,
  176. pParticle->m_flRoll );
  177. pParticle = (const FleckParticle*)pIterator->GetNext( sortKey );
  178. }
  179. }
  180. void CFleckParticles::SimulateParticles( CParticleSimulateIterator *pIterator )
  181. {
  182. FleckParticle *pParticle = (FleckParticle*)pIterator->GetFirst();
  183. while ( pParticle )
  184. {
  185. const float timeDelta = pIterator->GetTimeDelta();
  186. //Should this particle die?
  187. pParticle->m_flLifetime += timeDelta;
  188. if ( pParticle->m_flLifetime >= pParticle->m_flDieTime )
  189. {
  190. pIterator->RemoveParticle( pParticle );
  191. }
  192. else
  193. {
  194. pParticle->m_flRoll += pParticle->m_flRollDelta * timeDelta;
  195. //Simulate the movement with collision
  196. trace_t trace;
  197. m_ParticleCollision.MoveParticle( pParticle->m_Pos, pParticle->m_vecVelocity, &pParticle->m_flRollDelta, timeDelta, &trace );
  198. // If we're in solid, then stop moving
  199. if ( trace.allsolid )
  200. {
  201. pParticle->m_vecVelocity = vec3_origin;
  202. pParticle->m_flRollDelta = 0.0f;
  203. }
  204. }
  205. pParticle = (FleckParticle*)pIterator->GetNext();
  206. }
  207. }