📄 ch18p1_particleemitter.cpp
字号:
#include "Ch18p1_ParticleEmitter.h"
CParticleEmitter::CParticleEmitter()
{
// default particle system configuration - boring!
SetGravity(D3DXVECTOR3(0.0f,0.0f,0.0f));
SetPos(D3DXVECTOR3(0.0f,0.0f,0.0f));
SetMinEmitRate(30.0f);
SetMaxEmitRate(30.0f);
SetColor1(D3DXCOLOR(1.0f,1.0f,1.0f,1.0f));
SetColor2(D3DXCOLOR(1.0f,1.0f,1.0f,1.0f));
SetMinSize(1.0f);
SetMaxSize(1.0f);
SetSpawnDir1(D3DXVECTOR3(-1.0f, -1.0f, -1.0f));
SetSpawnDir2(D3DXVECTOR3(1.0f, 1.0f, 1.0f));
// initialize misc. other things
m_pd3dDevice = NULL;
SetVBSize(NUMPARTICLES / 10);
m_fNumNewPartsExcess = 0.0f;
}
CParticleEmitter::~CParticleEmitter()
{
}
HRESULT CParticleEmitter::RestoreDeviceObjects(LPDIRECT3DDEVICE8 pDev, const char *strTextureFilename)
{
HRESULT hr;
m_pd3dDevice = pDev;
m_Particles.DeleteAll();
// load up the particle system texture
if (FAILED(hr = D3DXCreateTextureFromFile(m_pd3dDevice,
strTextureFilename, &m_texParticle))) {
return(hr);
}
// create vertex buffer
if(FAILED(hr = m_pd3dDevice->CreateVertexBuffer(m_iVBSize * sizeof(VERTEX_PARTICLE),
D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY | D3DUSAGE_POINTS,
D3DFVF_PARTICLE, D3DPOOL_DEFAULT, &m_vbParticles))) {
return(hr);
}
return S_OK;
}
void CParticleEmitter::InvalidateDeviceObjects()
{
SAFE_RELEASE(m_texParticle);
SAFE_RELEASE(m_vbParticles);
}
void CParticleEmitter::Update(float fElapsedTime, float fTimeDelta)
{
// update existing particles
{
for (int q=0; q < m_Particles.GetTotalElements(); q++) {
if (m_Particles.IsAlive(q)) {
CParticle &part = m_Particles.GetAt(q);
if (!part.Update(fTimeDelta)) {
m_Particles.Delete(&part);
}
} // is alive
} // next particle
}
// create new particles
{
// determine the number of particles we need to create
float fEmitRateThisFrame = RandomNumber(m_fMinEmitRate, m_fMaxEmitRate);
int iNumNewParts = fEmitRateThisFrame * fTimeDelta;
m_fNumNewPartsExcess += (float)(fEmitRateThisFrame * fTimeDelta)-iNumNewParts;
if (m_fNumNewPartsExcess > 1.0f) {
iNumNewParts += (int)m_fNumNewPartsExcess;
m_fNumNewPartsExcess -= (int)m_fNumNewPartsExcess;
}
for (int q=0; q < iNumNewParts; q++) {
try {
CParticle *part = m_Particles.New();
// determine a random vector between dir1 and dir2
float fRandX = RandomNumber(m_vSpawnDir1.x, m_vSpawnDir2.x);
float fRandY = RandomNumber(m_vSpawnDir1.y, m_vSpawnDir2.y);
float fRandZ = RandomNumber(m_vSpawnDir1.z, m_vSpawnDir2.z);
part->m_vDir = D3DXVECTOR3(fRandX, fRandY, fRandZ);
part->m_vPos = m_vPos;
float fRandR = RandomNumber(m_Color1.r, m_Color2.r);
float fRandG = RandomNumber(m_Color1.g, m_Color2.g);
float fRandB = RandomNumber(m_Color1.b, m_Color2.b);
float fRandA = RandomNumber(m_Color1.a, m_Color2.a);
part->m_Color = D3DXCOLOR(fRandR, fRandG, fRandB, fRandA);
} catch(...) { q = iNumNewParts; }
}
}
}
HRESULT CParticleEmitter::Render()
{
HRESULT hr;
// Set the render states for using point sprites
m_pd3dDevice->SetRenderState( D3DRS_POINTSPRITEENABLE, TRUE );
m_pd3dDevice->SetRenderState( D3DRS_POINTSCALEENABLE, TRUE );
m_pd3dDevice->SetRenderState( D3DRS_POINTSIZE, FtoDW(100.0f) );
m_pd3dDevice->SetRenderState( D3DRS_POINTSIZE_MIN, FtoDW(0.00f) );
m_pd3dDevice->SetRenderState( D3DRS_POINTSIZE_MAX, FtoDW(1000.00f) );
m_pd3dDevice->SetRenderState( D3DRS_POINTSCALE_A, FtoDW(0.00f) );
m_pd3dDevice->SetRenderState( D3DRS_POINTSCALE_B, FtoDW(0.00f) );
m_pd3dDevice->SetRenderState( D3DRS_POINTSCALE_C, FtoDW(1.00f) );
// Set up the vertex buffer to be rendered
m_pd3dDevice->SetStreamSource( 0, m_vbParticles, sizeof(VERTEX_PARTICLE) );
m_pd3dDevice->SetVertexShader( D3DFVF_PARTICLE );
m_pd3dDevice->SetTexture(0, m_texParticle);
VERTEX_PARTICLE *pVertices;
DWORD dwNumParticlesToRender = 0;
if(FAILED(hr = m_vbParticles->Lock(0, m_iVBSize * sizeof(VERTEX_PARTICLE),
(BYTE **) &pVertices, D3DLOCK_DISCARD)))
{
return hr;
}
// Render each particle
for (int q=0; q < NUMPARTICLES; q++) {
// Render each particle a bunch of times to get a blurring effect
if (m_Particles.IsAlive(q)) {
CParticle &part = m_Particles.GetAt(q);
pVertices->position = part.m_vPos;
pVertices->pointsize = 1.0f;
pVertices->color = (DWORD)part.m_Color;
pVertices++;
if( ++dwNumParticlesToRender == m_iVBSize ) {
// Done filling this chunk of the vertex buffer. Lets unlock and
// draw this portion so we can begin filling the next chunk.
m_vbParticles->Unlock();
if(FAILED(hr = m_pd3dDevice->DrawPrimitive(
D3DPT_POINTLIST, 0, dwNumParticlesToRender)))
return hr;
if(FAILED(hr = m_vbParticles->Lock(0, m_iVBSize * sizeof(VERTEX_PARTICLE),
(BYTE **) &pVertices, D3DLOCK_DISCARD)))
return hr;
dwNumParticlesToRender = 0;
}
}
}
// Unlock the vertex buffer
m_vbParticles->Unlock();
// Render any remaining particles
if( dwNumParticlesToRender )
{
if(FAILED(hr = m_pd3dDevice->DrawPrimitive( D3DPT_POINTLIST, 0, dwNumParticlesToRender )))
return hr;
}
// Reset render states
m_pd3dDevice->SetRenderState( D3DRS_POINTSPRITEENABLE, FALSE );
m_pd3dDevice->SetRenderState( D3DRS_POINTSCALEENABLE, FALSE );
return S_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -