www.pudn.com > 3D_Tank.rar > Particle.cpp


#include "Particle.h" 
 
CParticleSystem::CParticleSystem() 
{ 
	m_dwVBSize = 500; 
	m_fSize = 1; 
	m_vOrigin = D3DXVECTOR3(0, 0, 20); 
	m_vInitVelocity = D3DXVECTOR3(1, 1, 500); 
	m_InitColor = D3DCOLOR_XRGB(255, 0, 0); 
	m_BoundingBox.m_vMin = D3DXVECTOR3(0, 0, 0); 
	m_BoundingBox.m_vMax = D3DXVECTOR3(0.0f, 0.0f, 0.0f); 
} 
 
CParticleSystem::~CParticleSystem() 
{} 
 
BOOL CParticleSystem::Init(const CComPtr &device, LPCTSTR pTextureFile) 
{ 
	m_pDevice = device; 
 
	HRESULT hr; 
 
	IDirect3DVertexBuffer9 *VB; 
 
	hr = m_pDevice->CreateVertexBuffer(	m_dwVBSize * sizeof(Particle), 	 
		D3DUSAGE_DYNAMIC | D3DUSAGE_POINTS | D3DUSAGE_WRITEONLY, Particle::FVF, 
		D3DPOOL_DEFAULT, &VB, 0); 
 
	if (FAILED(hr)) 
	{	HrError(hr);} 
 
	m_pVB.Reset(VB); 
 
	if (pTextureFile != 0) 
	{ 
		IDirect3DTexture9 *tex; 
		hr = D3DXCreateTextureFromFile(m_pDevice.Get(), pTextureFile, &tex); 
 
		if (FAILED(hr)) 
			; 
		else 
			m_pTexture.Reset(tex); 
 
		return TRUE; 
	} 
	else 
	{	return FALSE;} 
} 
 
VOID CParticleSystem::ResetParticle(Attribute *attribute) 
{ 
	attribute->m_bIsAlive = TRUE; 
	attribute->m_vPosition = m_vOrigin; 
	attribute->m_vVelocity = m_vInitVelocity; 
	attribute->m_Color = m_InitColor; 
} 
 
VOID CParticleSystem::Reset() 
{ 
	std::list::iterator iter; 
	for (iter = m_listParticle.begin(); iter != m_listParticle.end(); ++iter) 
		ResetParticle( &(*iter) ); 
} 
 
VOID CParticleSystem::AddPartile() 
{ 
	Attribute attribute; 
	ResetParticle(&attribute); 
	m_listParticle.push_back(attribute); 
} 
 
VOID CParticleSystem::Update(float fTimeDelta) 
{ 
	std::list::iterator i; 
	for (i = m_listParticle.begin(); i != m_listParticle.end(); ++i) 
	{ 
		if (i->m_bIsAlive) 
		{ 
			i->m_vPosition += i->m_vVelocity * fTimeDelta; 
			if (!IsPointInBox(i->m_vPosition, m_BoundingBox)) 
				i->m_bIsAlive = FALSE; 
		} 
	} 
} 
 
VOID CParticleSystem::RemoveDeadParticle() 
{ 
	std::list::iterator i; 
 
	i = m_listParticle.begin(); 
 
	while( i != m_listParticle.end()) 
	{ 
		if ( i->m_bIsAlive == FALSE) 
			i = m_listParticle.erase(i); 
		else 
			++i; 
	} 
 
} 
 
VOID CParticleSystem::PrepareRenderState() 
{ 
	m_pDevice->SetRenderState(D3DRS_LIGHTING, FALSE); 
	m_pDevice->SetTexture(0, m_pTexture.Get()); 
	m_pDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE); 
	m_pDevice->SetRenderState(D3DRS_POINTSCALEENABLE, TRUE); 
	m_pDevice->SetRenderState(D3DRS_POINTSIZE, FtoDw(m_fSize)); 
	m_pDevice->SetRenderState(D3DRS_POINTSIZE_MIN, FtoDw(0.0f)); 
 
	m_pDevice->SetRenderState(D3DRS_POINTSCALE_A, FtoDw(0.0f)); 
	m_pDevice->SetRenderState(D3DRS_POINTSCALE_B, FtoDw(0.0f)); 
	m_pDevice->SetRenderState(D3DRS_POINTSCALE_C, FtoDw(1.0f)); 
 
	m_pDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); 
	m_pDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); 
 
	m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); 
	m_pDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); 
	m_pDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); 
} 
 
VOID CParticleSystem::Render() 
{ 
	if (!IsEmpty()) 
	{ 
		PrepareRenderState(); 
 
		m_pDevice->SetTexture(0, m_pTexture.Get()); 
		m_pDevice->SetFVF(Particle::FVF); 
 
		IDirect3DVertexBuffer9 *VB = m_pVB.Get(); 
		m_pDevice->SetStreamSource(0, VB, 0, sizeof(Particle) );  
 
		if (m_dwVBOffset > m_dwVBSize) 
			m_dwVBOffset = 0; 
 
		Particle *pParticle; 
 
		m_pVB->Lock(m_dwVBOffset * sizeof(Particle), m_dwBatchSize * sizeof(Particle), 
			(VOID **)&pParticle,  
			m_dwVBOffset ? D3DLOCK_NOOVERWRITE : D3DLOCK_DISCARD); 
 
		DWORD dwParticleInBatch = 0; 
 
		std::list::iterator i; 
		for (i = m_listParticle.begin(); i != m_listParticle.end(); ++i) 
		{ 
			if ( i->m_bIsAlive ) 
			{ 
				pParticle->m_vPosition = i->m_vPosition; 
				pParticle->m_Color = i->m_Color; 
				++pParticle; 
 
				++dwParticleInBatch; 
 
				if (dwParticleInBatch == m_dwBatchSize) 
				{ 
					m_pVB->Unlock(); 
 
					m_pDevice->DrawPrimitive(	D3DPT_POINTLIST, m_dwVBOffset,  
						m_dwBatchSize); 
 
					m_dwVBOffset += m_dwBatchSize; 
 
					if(m_dwVBOffset > m_dwVBSize) 
						m_dwVBOffset = 0; 
 
					m_pVB->Lock(m_dwVBOffset * sizeof(Particle),  
						m_dwBatchSize * sizeof(Particle), 
						(VOID **)&pParticle,  
						m_dwVBOffset ? D3DLOCK_NOOVERWRITE : D3DLOCK_DISCARD); 
 
					dwParticleInBatch = 0; 
				} 
			} 
		} 
 
		m_pVB->Unlock(); 
 
		if (dwParticleInBatch) 
			m_pDevice->DrawPrimitive(D3DPT_POINTLIST, m_dwVBOffset, dwParticleInBatch); 
 
		m_dwVBOffset += m_dwBatchSize; 
 
		ResetRenderState(); 
	} 
} 
 
VOID CParticleSystem::ResetRenderState() 
{ 
	m_pDevice->SetRenderState(D3DRS_LIGHTING, TRUE); 
	m_pDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, FALSE); 
	m_pDevice->SetRenderState(D3DRS_POINTSCALEENABLE, FALSE); 
	m_pDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); 
} 
 
BOOL CParticleSystem::IsEmpty() 
{ 
	if (m_listParticle.size() == 0) 
		return TRUE; 
	else 
		return FALSE; 
} 
 
VOID CParticleSystem::GetBoundingBox(D3DXVECTOR3 *min, D3DXVECTOR3 *max) 
{ 
	*min = m_BoundingBox.m_vMin; 
	*max = m_BoundingBox.m_vMax; 
} 
 
VOID CParticleSystem::SetOrigin(const D3DXVECTOR3 &origin) 
{ 
	m_vOrigin = origin; 
} 
 
VOID CParticleSystem::SetVelocity(const D3DXVECTOR3 &velocity) 
{ 
	m_vInitVelocity = velocity; 
} 
 
VOID CParticleSystem::SetInitColor(const D3DCOLOR &color) 
{ 
	m_InitColor = color; 
} 
 
VOID CParticleSystem::SetBoundingBox(const D3DXVECTOR3 &min, const D3DXVECTOR3 &max) 
{ 
	m_BoundingBox.m_vMin = min; 
	m_BoundingBox.m_vMax = max; 
}