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;
}