476 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			476 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
//========= Copyright Valve Corporation, All rights reserved. ============//
 | 
						|
//
 | 
						|
// Purpose: 
 | 
						|
//
 | 
						|
//=============================================================================//
 | 
						|
 | 
						|
#include "cbase.h"
 | 
						|
#include "particlemgr.h"
 | 
						|
#include "particle_prototype.h"
 | 
						|
#include "particle_util.h"
 | 
						|
#include "surfinfo.h"
 | 
						|
#include "baseparticleentity.h"
 | 
						|
#include "materialsystem/imaterialsystemhardwareconfig.h"
 | 
						|
 | 
						|
// memdbgon must be the last include file in a .cpp file!!!
 | 
						|
#include "tier0/memdbgon.h"
 | 
						|
 | 
						|
// ------------------------------------------------------------------------- //
 | 
						|
// Definitions
 | 
						|
// ------------------------------------------------------------------------- //
 | 
						|
 | 
						|
#define NUM_AR2_EXPLOSION_PARTICLES	70
 | 
						|
#define AR2_DUST_RADIUS				240 // 340
 | 
						|
#define AR2_DUST_LIFETIME			4
 | 
						|
#define AR2_DUST_LIFETIME_DELTA		6
 | 
						|
#define AR2_DUST_SPEED				10000
 | 
						|
#define AR2_DUST_STARTSIZE			8
 | 
						|
#define AR2_DUST_ENDSIZE			32
 | 
						|
#define	AR2_DUST_ALPHA				0.5f
 | 
						|
#define	AR2_DUST_FADE_IN_TIME		0.25f
 | 
						|
 | 
						|
static Vector g_AR2DustColor1(0.35, 0.345, 0.33 );
 | 
						|
static Vector g_AR2DustColor2(0.75, 0.75, 0.7);
 | 
						|
 | 
						|
 | 
						|
// ------------------------------------------------------------------------- //
 | 
						|
// Classes
 | 
						|
// ------------------------------------------------------------------------- //
 | 
						|
 | 
						|
class C_AR2Explosion : public C_BaseParticleEntity, public IPrototypeAppEffect
 | 
						|
{
 | 
						|
public:
 | 
						|
	DECLARE_CLASS( C_AR2Explosion, C_BaseParticleEntity );
 | 
						|
	DECLARE_CLIENTCLASS();
 | 
						|
 | 
						|
					C_AR2Explosion();
 | 
						|
					~C_AR2Explosion();
 | 
						|
 | 
						|
private:
 | 
						|
	
 | 
						|
	class AR2ExplosionParticle : public StandardParticle_t
 | 
						|
	{
 | 
						|
	public:
 | 
						|
		float				m_Dist;
 | 
						|
		Vector				m_Start;
 | 
						|
		float				m_Roll;
 | 
						|
		float				m_RollSpeed;
 | 
						|
		float				m_Dwell;
 | 
						|
	};
 | 
						|
 | 
						|
// C_BaseEntity.
 | 
						|
public:
 | 
						|
	virtual void	OnDataChanged(DataUpdateType_t updateType);
 | 
						|
 | 
						|
// IPrototypeAppEffect.
 | 
						|
public:
 | 
						|
	virtual void	Start(CParticleMgr *pParticleMgr, IPrototypeArgAccess *pArgs);
 | 
						|
 | 
						|
// IParticleEffect.
 | 
						|
public:
 | 
						|
	virtual void	Update(float fTimeDelta);
 | 
						|
	
 | 
						|
	virtual void RenderParticles( CParticleRenderIterator *pIterator );
 | 
						|
	virtual void SimulateParticles( CParticleSimulateIterator *pIterator );
 | 
						|
 | 
						|
 | 
						|
public:
 | 
						|
	CParticleMgr		*m_pParticleMgr;
 | 
						|
	PMaterialHandle	m_MaterialHandle;
 | 
						|
 | 
						|
private:
 | 
						|
 | 
						|
	char m_szMaterialName[255];
 | 
						|
 | 
						|
	C_AR2Explosion( const C_AR2Explosion & );
 | 
						|
};
 | 
						|
 | 
						|
// Expose to the particle app.
 | 
						|
EXPOSE_PROTOTYPE_EFFECT(AR2Explosion, C_AR2Explosion);
 | 
						|
 | 
						|
IMPLEMENT_CLIENTCLASS_DT(C_AR2Explosion, DT_AR2Explosion, AR2Explosion)
 | 
						|
	RecvPropString( RECVINFO( m_szMaterialName ) ),
 | 
						|
END_RECV_TABLE()
 | 
						|
 | 
						|
 | 
						|
 | 
						|
// ------------------------------------------------------------------------- //
 | 
						|
// Helpers.
 | 
						|
// ------------------------------------------------------------------------- //
 | 
						|
 | 
						|
// Given a line segment from vStart to vEnd
 | 
						|
// and a list of convex polygons in pSurfInfos and nSurfInfos, 
 | 
						|
// fill in the list of which polygons the segment intersects.
 | 
						|
// Returns the number of intersected surfaces.
 | 
						|
static int IntersectSegmentWithSurfInfos(
 | 
						|
	const Vector &vStart,
 | 
						|
	const Vector &vEnd,
 | 
						|
	SurfInfo *pSurfInfos,
 | 
						|
	const int nSurfInfos,
 | 
						|
	SurfInfo ** pIntersections,
 | 
						|
	Vector *pIntersectionPositions,
 | 
						|
	int nMaxIntersections)
 | 
						|
{
 | 
						|
	if(nMaxIntersections == 0)
 | 
						|
		return 0;
 | 
						|
 | 
						|
	int nIntersections = 0;
 | 
						|
	for(int i=0; i < nSurfInfos; i++)
 | 
						|
	{
 | 
						|
		SurfInfo *pSurf = &pSurfInfos[i];
 | 
						|
 | 
						|
		// Does it intersect the plane?
 | 
						|
		float dot1 = pSurf->m_Plane.DistTo(vStart);
 | 
						|
		float dot2 = pSurf->m_Plane.DistTo(vEnd);
 | 
						|
		if((dot1 > 0) != (dot2 > 0))
 | 
						|
		{
 | 
						|
			float t = dot1 / (dot1 - dot2);
 | 
						|
			Vector vIntersection = vStart + (vEnd - vStart) * t;
 | 
						|
			
 | 
						|
			// If the intersection is behind any edge plane, then it's not inside the polygon.
 | 
						|
			unsigned long iEdge;
 | 
						|
			for(iEdge=0; iEdge < pSurf->m_nVerts; iEdge++)
 | 
						|
			{
 | 
						|
				VPlane edgePlane;
 | 
						|
				edgePlane.m_Normal = pSurf->m_Plane.m_Normal.Cross(pSurf->m_Verts[iEdge] - pSurf->m_Verts[(iEdge+1)%pSurf->m_nVerts]);
 | 
						|
				VectorNormalize( edgePlane.m_Normal );
 | 
						|
				edgePlane.m_Dist = edgePlane.m_Normal.Dot(pSurf->m_Verts[iEdge]);
 | 
						|
 | 
						|
				if(edgePlane.DistTo(vIntersection) < 0.0f)
 | 
						|
					break;
 | 
						|
			}
 | 
						|
 | 
						|
			if(iEdge == pSurf->m_nVerts)
 | 
						|
			{
 | 
						|
				pIntersections[nIntersections] = pSurf;
 | 
						|
				pIntersectionPositions[nIntersections] = vIntersection;
 | 
						|
				++nIntersections;
 | 
						|
				if(nIntersections >= nMaxIntersections)
 | 
						|
					break;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return nIntersections;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
// ------------------------------------------------------------------------- //
 | 
						|
// C_AR2Explosion
 | 
						|
// ------------------------------------------------------------------------- //
 | 
						|
C_AR2Explosion::C_AR2Explosion()
 | 
						|
{
 | 
						|
	m_pParticleMgr = NULL;
 | 
						|
	m_MaterialHandle = INVALID_MATERIAL_HANDLE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
C_AR2Explosion::~C_AR2Explosion()
 | 
						|
{
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void C_AR2Explosion::OnDataChanged(DataUpdateType_t updateType)
 | 
						|
{
 | 
						|
	C_BaseEntity::OnDataChanged(updateType);
 | 
						|
 | 
						|
	if(updateType == DATA_UPDATE_CREATED)
 | 
						|
	{
 | 
						|
		Start(ParticleMgr(), NULL);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
static ConVar mat_reduceparticles( "mat_reduceparticles", "0" );
 | 
						|
 | 
						|
void C_AR2Explosion::Start(CParticleMgr *pParticleMgr, IPrototypeArgAccess *pArgs)
 | 
						|
{
 | 
						|
	m_pParticleMgr = pParticleMgr;
 | 
						|
	if(!pParticleMgr->AddEffect(&m_ParticleEffect, this))
 | 
						|
		return;
 | 
						|
 | 
						|
	if (!m_szMaterialName[0])
 | 
						|
	{
 | 
						|
		Q_strncpy(m_szMaterialName, "particle/particle_noisesphere", sizeof( m_szMaterialName ) );
 | 
						|
	}
 | 
						|
 | 
						|
	m_MaterialHandle = m_ParticleEffect.FindOrAddMaterial(m_szMaterialName);
 | 
						|
 | 
						|
	// Precalculate stuff for the particle spawning..
 | 
						|
	#define NUM_DUSTEMITTER_SURFINFOS	128
 | 
						|
	SurfInfo surfInfos[NUM_DUSTEMITTER_SURFINFOS];
 | 
						|
	int nSurfInfos;
 | 
						|
 | 
						|
	// Center of explosion.
 | 
						|
	Vector vCenter = GetAbsOrigin(); // HACKHACK.. when the engine bug is fixed, use origin.
 | 
						|
 | 
						|
	if ( IsXbox() )
 | 
						|
	{
 | 
						|
		m_ParticleEffect.SetBBox( vCenter-Vector(300,300,300), vCenter+Vector(300,300,300) );
 | 
						|
	}
 | 
						|
 | 
						|
	#ifdef PARTICLEPROTOTYPE_APP
 | 
						|
		float surfSize = 10000;
 | 
						|
		nSurfInfos = 1;
 | 
						|
		surfInfos[0].m_Verts[0].Init(-surfSize,-surfSize,0);
 | 
						|
		surfInfos[0].m_Verts[1].Init(-surfSize,surfSize,0);
 | 
						|
		surfInfos[0].m_Verts[2].Init(surfSize, surfSize,0);
 | 
						|
		surfInfos[0].m_Verts[3].Init(surfSize,-surfSize,0);
 | 
						|
		surfInfos[0].m_nVerts = 4;
 | 
						|
		surfInfos[0].m_Plane.m_Normal.Init(0,0,1);
 | 
						|
		surfInfos[0].m_Plane.m_Dist = -3;
 | 
						|
	#else
 | 
						|
		{
 | 
						|
			nSurfInfos = 0;
 | 
						|
			C_BaseEntity *ent = cl_entitylist->GetEnt( 0 );
 | 
						|
			if ( ent )
 | 
						|
			{
 | 
						|
				nSurfInfos = engine->GetIntersectingSurfaces(
 | 
						|
					ent->GetModel(),
 | 
						|
					vCenter,
 | 
						|
					AR2_DUST_RADIUS,
 | 
						|
					true,
 | 
						|
					surfInfos,
 | 
						|
					NUM_DUSTEMITTER_SURFINFOS);
 | 
						|
			}
 | 
						|
		}
 | 
						|
	#endif
 | 
						|
 | 
						|
	int nParticles = 0;
 | 
						|
 | 
						|
	int iParticlesToSpawn = NUM_AR2_EXPLOSION_PARTICLES;
 | 
						|
 | 
						|
	// In DX7, much fewer particles
 | 
						|
	if ( g_pMaterialSystemHardwareConfig->GetDXSupportLevel() < 80 )
 | 
						|
	{
 | 
						|
		iParticlesToSpawn *= 0.25;
 | 
						|
	}
 | 
						|
	else if ( mat_reduceparticles.GetBool() )
 | 
						|
	{
 | 
						|
		iParticlesToSpawn *= 0.025;
 | 
						|
	}
 | 
						|
 | 
						|
	if( nSurfInfos > 0 )
 | 
						|
	{
 | 
						|
		// For nParticles*N, generate a ray and cast it out. If it hits anything, spawn a particle there.
 | 
						|
		int nTestsPerParticle=3;
 | 
						|
		for(int i=0; i < iParticlesToSpawn; i++)
 | 
						|
		{
 | 
						|
			for(int iTest=0; iTest < nTestsPerParticle; iTest++)
 | 
						|
			{
 | 
						|
				Vector randVec = RandomVector(-1,1);
 | 
						|
				VectorNormalize( randVec );
 | 
						|
				Vector startPos = vCenter + randVec * AR2_DUST_RADIUS;
 | 
						|
 | 
						|
				randVec = RandomVector(-1,1);
 | 
						|
				VectorNormalize( randVec );
 | 
						|
				Vector endPos = vCenter + randVec * AR2_DUST_RADIUS;
 | 
						|
 | 
						|
				#define MAX_SURFINFO_INTERSECTIONS	4
 | 
						|
				SurfInfo *pIntersected[MAX_SURFINFO_INTERSECTIONS];
 | 
						|
				Vector vIntersections[MAX_SURFINFO_INTERSECTIONS];
 | 
						|
				int nIntersections;
 | 
						|
				nIntersections = IntersectSegmentWithSurfInfos(
 | 
						|
					startPos, 
 | 
						|
					endPos, 
 | 
						|
					surfInfos, 
 | 
						|
					nSurfInfos, 
 | 
						|
					pIntersected,
 | 
						|
					vIntersections,
 | 
						|
					MAX_SURFINFO_INTERSECTIONS);
 | 
						|
				
 | 
						|
				if(nIntersections)
 | 
						|
				{
 | 
						|
					int iIntersection = rand() % nIntersections;
 | 
						|
 | 
						|
					Vector velocity;
 | 
						|
					//velocity.Init(-1.0f + ((float)rand()/VALVE_RAND_MAX) * 2.0f, -1.0f + ((float)rand()/VALVE_RAND_MAX) * 2.0f, -1.0f + ((float)rand()/VALVE_RAND_MAX) * 2.0f);
 | 
						|
					//velocity = velocity * FRand(m_MinSpeed, m_MaxSpeed);
 | 
						|
					Vector direction = (vIntersections[iIntersection] - vCenter );
 | 
						|
					float dist = VectorNormalize( direction );
 | 
						|
					if(dist > AR2_DUST_RADIUS)
 | 
						|
						dist = AR2_DUST_RADIUS;
 | 
						|
 | 
						|
					static float power = 2.0f;
 | 
						|
					float falloffMul = pow(1.0f - dist / AR2_DUST_RADIUS, power);
 | 
						|
 | 
						|
					Vector reflection = direction - 2 * DotProduct( direction, pIntersected[iIntersection]->m_Plane.m_Normal ) * pIntersected[iIntersection]->m_Plane.m_Normal;
 | 
						|
					VectorNormalize( reflection );
 | 
						|
 | 
						|
					velocity = reflection * AR2_DUST_SPEED * falloffMul;
 | 
						|
					// velocity = velocity + (vIntersections[iIntersection] - vCenter) * falloffMul;
 | 
						|
 | 
						|
					
 | 
						|
					/*
 | 
						|
					debugoverlay->AddLineOverlay( vIntersections[iIntersection], 
 | 
						|
												  vIntersections[iIntersection] + reflection * 64,
 | 
						|
												  128, 128, 255, false, 15.0 );
 | 
						|
					*/
 | 
						|
#if 1
 | 
						|
					AR2ExplosionParticle *pParticle = 
 | 
						|
						(AR2ExplosionParticle*)m_ParticleEffect.AddParticle( sizeof(AR2ExplosionParticle), m_MaterialHandle );
 | 
						|
 | 
						|
					if(pParticle)
 | 
						|
					{
 | 
						|
						pParticle->m_Pos = vIntersections[iIntersection];
 | 
						|
						pParticle->m_Start = pParticle->m_Pos;
 | 
						|
						pParticle->m_Dist = 8.0;
 | 
						|
						pParticle->m_Velocity = velocity;
 | 
						|
						// sound == 13031.496062992125984251968503937ips
 | 
						|
						pParticle->m_Lifetime = -dist / 13031.5f - 0.1;
 | 
						|
						pParticle->m_Roll = FRand( 0, M_PI * 2 );
 | 
						|
						pParticle->m_RollSpeed = FRand( -1, 1 ) * 0.4;
 | 
						|
						pParticle->m_Dwell = AR2_DUST_LIFETIME + random->RandomFloat( 0, AR2_DUST_LIFETIME_DELTA );
 | 
						|
						nParticles++;
 | 
						|
						break;
 | 
						|
					}
 | 
						|
#endif
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}	
 | 
						|
 | 
						|
	// build interior smoke particles
 | 
						|
	for(int i=nParticles; i < iParticlesToSpawn; i++)
 | 
						|
	{
 | 
						|
		Vector randVec = RandomVector(-1,1);
 | 
						|
		VectorNormalize( randVec );
 | 
						|
		Vector endPos = vCenter + randVec * AR2_DUST_RADIUS / 4.0;
 | 
						|
 | 
						|
		Vector direction = (endPos - vCenter );
 | 
						|
		float dist = VectorNormalize( direction ) + random->RandomFloat( 0, AR2_DUST_RADIUS / 4.0 );
 | 
						|
		if(dist > AR2_DUST_RADIUS)
 | 
						|
			dist = AR2_DUST_RADIUS;
 | 
						|
 | 
						|
		static float power = 2.0f;
 | 
						|
		float falloffMul = pow(1.0f - dist / (AR2_DUST_RADIUS / 2), power);
 | 
						|
 | 
						|
		Vector velocity = direction * AR2_DUST_SPEED * falloffMul;
 | 
						|
		AR2ExplosionParticle *pParticle = 
 | 
						|
			(AR2ExplosionParticle*)m_ParticleEffect.AddParticle( sizeof(AR2ExplosionParticle), m_MaterialHandle );
 | 
						|
 | 
						|
		if(pParticle)
 | 
						|
		{
 | 
						|
			pParticle->m_Pos = endPos;
 | 
						|
			pParticle->m_Start = pParticle->m_Pos;
 | 
						|
			pParticle->m_Dist = 8.0;
 | 
						|
			pParticle->m_Velocity = velocity;
 | 
						|
			// sound == 13031.496062992125984251968503937ips
 | 
						|
			pParticle->m_Lifetime = -dist / 13031.5f - 0.1;
 | 
						|
			pParticle->m_Roll = FRand( 0, M_PI * 2 );
 | 
						|
			pParticle->m_RollSpeed = FRand( -1, 1 ) * 4.0;
 | 
						|
			pParticle->m_Dwell = 0.5 * (AR2_DUST_LIFETIME + random->RandomFloat( 0, AR2_DUST_LIFETIME_DELTA ));
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void C_AR2Explosion::Update(float fTimeDelta)
 | 
						|
{
 | 
						|
	if(!m_pParticleMgr)
 | 
						|
		return;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void C_AR2Explosion::SimulateParticles( CParticleSimulateIterator *pIterator )
 | 
						|
{
 | 
						|
	float dt = pIterator->GetTimeDelta();
 | 
						|
 | 
						|
	AR2ExplosionParticle *pParticle = (AR2ExplosionParticle*)pIterator->GetFirst();
 | 
						|
	while ( pParticle )
 | 
						|
	{
 | 
						|
		if (dt > 0.05)
 | 
						|
			dt = 0.05; // yuck, air resistance function craps out at less then 20fps
 | 
						|
 | 
						|
		// Update its lifetime.
 | 
						|
		pParticle->m_Lifetime += dt; // pDraw->GetTimeDelta();
 | 
						|
		if(pParticle->m_Lifetime > pParticle->m_Dwell)
 | 
						|
		{
 | 
						|
			// faded to nothing....
 | 
						|
			pIterator->RemoveParticle( pParticle );
 | 
						|
		}
 | 
						|
		else
 | 
						|
		{
 | 
						|
			// Spin the thing
 | 
						|
			pParticle->m_Roll += pParticle->m_RollSpeed * pIterator->GetTimeDelta();
 | 
						|
 | 
						|
			// delayed?
 | 
						|
			if ( pParticle->m_Lifetime >= 0.0f )
 | 
						|
			{
 | 
						|
				// Move it (this comes after rendering to make it clear that moving the particle here won't change
 | 
						|
				// its rendering for this frame since m_TransformedPos has already been set).
 | 
						|
				pParticle->m_Pos = pParticle->m_Pos + pParticle->m_Velocity * dt;
 | 
						|
 | 
						|
				// keep track of distance traveled
 | 
						|
				pParticle->m_Dist = pParticle->m_Dist + pParticle->m_Velocity.Length() * dt;
 | 
						|
 | 
						|
				// Dampen velocity.
 | 
						|
				float dist = pParticle->m_Velocity.Length()	* dt;
 | 
						|
				float r = dist * dist;
 | 
						|
				// FIXME: this is a really screwy air-resistance function....
 | 
						|
				pParticle->m_Velocity = pParticle->m_Velocity * (100 / (100 + r )); 
 | 
						|
 | 
						|
				// dampen roll
 | 
						|
				static float dtime;
 | 
						|
				static float decay;
 | 
						|
				if (dtime != dt)
 | 
						|
				{
 | 
						|
					dtime = dt;
 | 
						|
					decay = ExponentialDecay( 0.3, 1.0, dtime );
 | 
						|
				}
 | 
						|
				if (fabs(pParticle->m_RollSpeed) > 0.2)
 | 
						|
					pParticle->m_RollSpeed = pParticle->m_RollSpeed * decay;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		pParticle = (AR2ExplosionParticle*)pIterator->GetNext();
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void C_AR2Explosion::RenderParticles( CParticleRenderIterator *pIterator )
 | 
						|
{
 | 
						|
	const AR2ExplosionParticle *pParticle = (const AR2ExplosionParticle *)pIterator->GetFirst();
 | 
						|
	while ( pParticle )
 | 
						|
	{
 | 
						|
		float sortKey = 0;
 | 
						|
		if ( pParticle->m_Lifetime >= 0.0f )
 | 
						|
		{
 | 
						|
			// Draw.
 | 
						|
			float lifetimePercent = ( pParticle->m_Lifetime - AR2_DUST_FADE_IN_TIME ) / pParticle->m_Dwell;
 | 
						|
 | 
						|
			// FIXME: base color should be a dirty version of the material color
 | 
						|
			Vector color = g_AR2DustColor1 * (1.0 - lifetimePercent) + g_AR2DustColor2 * lifetimePercent;
 | 
						|
			
 | 
						|
			Vector tPos;
 | 
						|
			TransformParticle(m_pParticleMgr->GetModelView(), pParticle->m_Pos, tPos);
 | 
						|
			sortKey = tPos.z;
 | 
						|
			
 | 
						|
			float	alpha;
 | 
						|
 | 
						|
			if ( pParticle->m_Lifetime < AR2_DUST_FADE_IN_TIME )
 | 
						|
			{
 | 
						|
				alpha = AR2_DUST_ALPHA * ( pParticle->m_Lifetime / AR2_DUST_FADE_IN_TIME );
 | 
						|
			}
 | 
						|
			else
 | 
						|
			{
 | 
						|
				alpha = AR2_DUST_ALPHA * ( 1.0f - lifetimePercent );
 | 
						|
			}
 | 
						|
 | 
						|
			alpha *= GetAlphaDistanceFade( tPos, IsXbox() ? 100 : 50, IsXbox() ? 200 : 150 );
 | 
						|
 | 
						|
			RenderParticle_ColorSizeAngle(
 | 
						|
				pIterator->GetParticleDraw(),
 | 
						|
				tPos,
 | 
						|
				color,
 | 
						|
				alpha,
 | 
						|
				pParticle->m_Dist, // size based on how far it's traveled
 | 
						|
				pParticle->m_Roll);
 | 
						|
		}
 | 
						|
 | 
						|
		pParticle = (const AR2ExplosionParticle *)pIterator->GetNext( sortKey );
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 |