diff options
| author | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
|---|---|---|
| committer | Joe Ludwig <[email protected]> | 2013-06-26 15:22:04 -0700 |
| commit | 39ed87570bdb2f86969d4be821c94b722dc71179 (patch) | |
| tree | abc53757f75f40c80278e87650ea92808274aa59 /mp/src/game/client/fx_fleck.cpp | |
| download | source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.tar.xz source-sdk-2013-39ed87570bdb2f86969d4be821c94b722dc71179.zip | |
First version of the SOurce SDK 2013
Diffstat (limited to 'mp/src/game/client/fx_fleck.cpp')
| -rw-r--r-- | mp/src/game/client/fx_fleck.cpp | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/mp/src/game/client/fx_fleck.cpp b/mp/src/game/client/fx_fleck.cpp new file mode 100644 index 00000000..47e8b645 --- /dev/null +++ b/mp/src/game/client/fx_fleck.cpp @@ -0,0 +1,239 @@ +//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $Workfile: $
+// $NoKeywords: $
+//=============================================================================//
+#include "cbase.h"
+#include "fx_fleck.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+
+// enable this to have the fleck_merge cvar as well as the current system count displayed as it changes (for profiling)
+#define REPORT_MERGED_FLECKS 0
+
+//
+// class PARTICLE_MERGE
+//{
+//public:
+// bool MergeParticleSystems( CFleckParticles *pSystem, const char *pEffectName, const Vector ¢er, const Vector &extents )
+// { merge; return true; }
+//};
+
+// a singly linked list through all particle effects of a specific type
+// with a specific rule for sharing them.
+// Needs a hook to the particle effect's constructor/destructor and factory method
+// The factory needs to support optionally merging the new particles into a previously built particle effect
+// this cuts down on lots of scene management overhead as well as rendering/batch overhead
+template< class PARTICLE_EFFECT, class PARTICLE_MERGE >
+class CParticleMergeList
+{
+public:
+ CParticleMergeList() : m_pHead(NULL) {}
+ void AddParticleSystem( PARTICLE_EFFECT *pSystem );
+ void RemoveParticleSystem( PARTICLE_EFFECT *pRemove );
+ PARTICLE_EFFECT *FindAndMergeParticleSystem( const char *pEffectName, const Vector ¢er, const Vector &extents );
+ bool MergeParticleSystems( PARTICLE_EFFECT *pSystem, const char *pEffectName, const Vector ¢er, const Vector &extents );
+private:
+ PARTICLE_EFFECT *m_pHead;
+ PARTICLE_MERGE m_merge;
+};
+
+#if REPORT_MERGED_FLECKS
+ConVar fleck_merge("fleck_merge","1");
+int g_PCount = 0;
+#endif
+
+template< class PARTICLE_EFFECT, class PARTICLE_MERGE >
+void CParticleMergeList<PARTICLE_EFFECT,PARTICLE_MERGE>::AddParticleSystem( PARTICLE_EFFECT *pSystem )
+{
+#if REPORT_MERGED_FLECKS
+ g_PCount++;
+ Msg("PS: %d\n", g_PCount);
+#endif
+ pSystem->m_pNextParticleSystem = m_pHead;
+ m_pHead = pSystem;
+}
+
+template< class PARTICLE_EFFECT, class PARTICLE_MERGE >
+void CParticleMergeList<PARTICLE_EFFECT,PARTICLE_MERGE>::RemoveParticleSystem( PARTICLE_EFFECT *pRemove )
+{
+#if REPORT_MERGED_FLECKS
+ g_PCount--;
+ Msg("PS: %d\n", g_PCount);
+#endif
+ PARTICLE_EFFECT **pPrev = &m_pHead;
+ PARTICLE_EFFECT *pCur = *pPrev;
+ while ( pCur )
+ {
+ if ( pCur == pRemove )
+ {
+ *pPrev = pCur->m_pNextParticleSystem;
+ return;
+ }
+ pPrev = &pCur->m_pNextParticleSystem;
+ pCur = *pPrev;
+ }
+}
+
+template< class PARTICLE_EFFECT, class PARTICLE_MERGE >
+PARTICLE_EFFECT *CParticleMergeList<PARTICLE_EFFECT,PARTICLE_MERGE>::FindAndMergeParticleSystem( const char *pEffectName, const Vector ¢er, const Vector &extents )
+{
+#if REPORT_MERGED_FLECKS
+ if ( !fleck_merge.GetBool() )
+ return NULL;
+#endif
+
+ for ( PARTICLE_EFFECT *pMerge = m_pHead; pMerge != NULL; pMerge = pMerge->m_pNextParticleSystem )
+ {
+ if ( m_merge.MergeParticleSystems( pMerge, pEffectName, center, extents ) )
+ return pMerge;
+ }
+ return NULL;
+}
+
+// merge anything within 10 feet
+const float MAX_RADIUS_BBOX_MERGE = 120.0f;
+
+template< class PARTICLE_EFFECT >
+class CMergeSameNameBbox
+{
+public:
+ bool MergeParticleSystems( PARTICLE_EFFECT *pSystem, const char *pEffectName, const Vector ¢er, const Vector &extents )
+ {
+ // by default, match names
+ if ( !Q_stricmp(pSystem->GetEffectName(), pEffectName) )
+ {
+ Vector mins, maxs;
+ pSystem->GetBinding().GetWorldspaceBounds( &mins, &maxs );
+ AddPointToBounds( center - extents, mins, maxs );
+ AddPointToBounds( center + extents, mins, maxs );
+ Vector size = maxs - mins;
+ float radius = size.Length();
+ if ( radius < MAX_RADIUS_BBOX_MERGE )
+ {
+ pSystem->GetBinding().SetBBox( mins, maxs );
+ // put sort origin at center of the new box
+ Vector sortOrigin = 0.5f * (mins+maxs);
+ pSystem->SetSortOrigin(sortOrigin);
+ return true;
+ }
+ }
+ return false;
+ }
+};
+
+CParticleMergeList< CFleckParticles, CMergeSameNameBbox<CFleckParticles> > g_FleckMergeList;
+
+//
+// CFleckParticles
+//
+CSmartPtr<CFleckParticles> CFleckParticles::Create( const char *pDebugName, const Vector &vCenter, const Vector &extents )
+{
+ CFleckParticles *pMerge = g_FleckMergeList.FindAndMergeParticleSystem( pDebugName, vCenter, extents );
+ if ( pMerge )
+ return pMerge;
+
+ CFleckParticles *pRet = new CFleckParticles( pDebugName );
+ if ( pRet )
+ {
+ pRet->GetBinding().SetBBox( vCenter - extents, vCenter + extents );
+ pRet->SetSortOrigin(vCenter);
+ }
+ return pRet;
+}
+
+
+CFleckParticles::CFleckParticles( const char *pDebugName ) : CSimpleEmitter( pDebugName ), m_pNextParticleSystem(NULL)
+{
+ g_FleckMergeList.AddParticleSystem(this);
+}
+
+CFleckParticles::~CFleckParticles()
+{
+ g_FleckMergeList.RemoveParticleSystem(this);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Test for surrounding collision surfaces for quick collision testing for the particle system
+// Input : &origin - starting position
+// *dir - direction of movement (if NULL, will do a point emission test in four directions)
+// angularSpread - looseness of the spread
+// minSpeed - minimum speed
+// maxSpeed - maximum speed
+// gravity - particle gravity for the sytem
+// dampen - dampening amount on collisions
+// flags - extra information
+//-----------------------------------------------------------------------------
+void CFleckParticles::Setup( const Vector &origin, const Vector *direction, float angularSpread, float minSpeed, float maxSpeed, float gravity, float dampen, int flags )
+{
+ //See if we've specified a direction
+ m_ParticleCollision.Setup( origin, direction, angularSpread, minSpeed, maxSpeed, gravity, dampen );
+}
+
+
+void CFleckParticles::RenderParticles( CParticleRenderIterator *pIterator )
+{
+ const FleckParticle *pParticle = (const FleckParticle*)pIterator->GetFirst();
+ while ( pParticle )
+ {
+ Vector tPos;
+ TransformParticle( ParticleMgr()->GetModelView(), pParticle->m_Pos, tPos );
+ float 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;
+ //Render it
+ RenderParticle_ColorSizeAngle(
+ pIterator->GetParticleDraw(),
+ tPos,
+ color,
+ 1.0f - (pParticle->m_flLifetime / pParticle->m_flDieTime),
+ pParticle->m_uchSize,
+ pParticle->m_flRoll );
+
+ pParticle = (const FleckParticle*)pIterator->GetNext( sortKey );
+ }
+}
+
+
+void CFleckParticles::SimulateParticles( CParticleSimulateIterator *pIterator )
+{
+ FleckParticle *pParticle = (FleckParticle*)pIterator->GetFirst();
+ while ( pParticle )
+ {
+ const float timeDelta = pIterator->GetTimeDelta();
+
+ //Should this particle die?
+ pParticle->m_flLifetime += timeDelta;
+
+ if ( pParticle->m_flLifetime >= pParticle->m_flDieTime )
+ {
+ pIterator->RemoveParticle( pParticle );
+ }
+ else
+ {
+ pParticle->m_flRoll += pParticle->m_flRollDelta * timeDelta;
+
+ //Simulate the movement with collision
+ trace_t trace;
+ m_ParticleCollision.MoveParticle( pParticle->m_Pos, pParticle->m_vecVelocity, &pParticle->m_flRollDelta, timeDelta, &trace );
+
+ // If we're in solid, then stop moving
+ if ( trace.allsolid )
+ {
+ pParticle->m_vecVelocity = vec3_origin;
+ pParticle->m_flRollDelta = 0.0f;
+ }
+ }
+
+ pParticle = (FleckParticle*)pIterator->GetNext();
+ }
+}
+
+
|