Particle.cpp
资源名称:Direct3D.rar [点击查看]
上传用户:junlon
上传日期:2022-01-05
资源大小:39075k
文件大小:12k
源码类别:
DirextX编程
开发平台:
Visual C++
- #include "dxstdafx.h"
- #include <list>
- #include "d3dUtility.h"
- #include "Particle.h"
- using namespace ParticleSystem;
- //using namespace myd3d;
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //Imenpletation of CParticleSystem
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- const DWORD ParticleVertex::FVF = D3DFVF_XYZ|D3DFVF_PSIZE|D3DFVF_DIFFUSE;
- CParticleSystem::CParticleSystem()
- {
- _vbSize = 2000;
- _vbOffset = 0;
- _vbBatchSize = 500;
- }
- CParticleSystem::~CParticleSystem()
- {
- Release<IDirect3DTexture9*>(_tex);
- Release<IDirect3DVertexBuffer9*>(_vb);
- }
- bool CParticleSystem::init(IDirect3DDevice9* device, LPCTSTR texFileName)
- {
- _device = device;
- HRESULT hr;
- hr = D3DXCreateTextureFromFile( _device, texFileName, &_tex );
- if(FAILED(hr))
- {
- ::MessageBoxA(NULL, "Create Texture Failed!", "ParticleSystem", 0);
- return false;
- }
- hr = _device->CreateVertexBuffer( _vbSize * sizeof( ParticleVertex ), D3DUSAGE_DYNAMIC|D3DUSAGE_POINTS|D3DUSAGE_WRITEONLY,
- ParticleVertex::FVF, D3DPOOL_DEFAULT, &_vb, NULL );
- if(FAILED(hr))
- {
- ::MessageBoxA(NULL, "Create VertexBuffer Failed!", "ParticleSystem", 0);
- return false;
- }
- return true;
- }
- void CParticleSystem::reset()
- {
- std::list<Particle>::iterator particleIter;
- for(particleIter = _particleList.begin(); particleIter != _particleList.end(); particleIter++)
- {
- resetParticle( &(*particleIter));
- }
- }
- void CParticleSystem::addParticle()
- {
- Particle newParticle;
- resetParticle(&newParticle);
- _particleList.push_back(newParticle);
- }
- void CParticleSystem::preRender()
- {
- _device->SetRenderState(D3DRS_LIGHTING, false);
- _device->SetRenderState(D3DRS_POINTSPRITEENABLE, true);
- _device->SetRenderState(D3DRS_POINTSCALEENABLE, true);
- _device->SetRenderState(D3DRS_POINTSIZE, FtoDw(_size));
- _device->SetRenderState(D3DRS_POINTSIZE_MIN, FtoDw(0.0f));
- // control the size of the particle relative to distance
- _device->SetRenderState(D3DRS_POINTSCALE_A, FtoDw(0.0f));
- _device->SetRenderState(D3DRS_POINTSCALE_B, FtoDw(0.0f));
- _device->SetRenderState(D3DRS_POINTSCALE_C, FtoDw(1.0f));
- // use alpha from texture
- _device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
- _device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
- _device->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
- _device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
- _device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_DESTALPHA);
- }
- void CParticleSystem::render()
- {
- //
- // Remarks: The render method works by filling a section of the vertex buffer with data,
- // then we render that section. While that section is rendering we lock a new
- // section and begin to fill that section. Once that sections filled we render it.
- // This process continues until all the particles have been drawn. The benifit
- // of this method is that we keep the video card and the CPU busy.
- if( !_particleList.empty() )
- {
- // set render states
- preRender();
- _device->SetTexture(0, _tex);
- _device->SetFVF(ParticleVertex::FVF);
- _device->SetStreamSource(0, _vb, 0, sizeof(ParticleVertex));
- // render batches one by one
- // start at beginning if we're at the end of the vb
- if(_vbOffset >= _vbSize)
- _vbOffset = 0;
- ParticleVertex* v = 0;
- _vb->Lock(
- _vbOffset * sizeof( ParticleVertex ),
- _vbBatchSize * sizeof( ParticleVertex ),
- (void**)&v,
- _vbOffset ? D3DLOCK_NOOVERWRITE : D3DLOCK_DISCARD);
- DWORD numParticlesInBatch = 0;
- //
- // Until all particles have been rendered.
- //
- std::list<Particle>::iterator i;
- for(i = _particleList.begin(); i != _particleList.end(); i++)
- {
- if( i->_isAlive )
- {
- //
- // Copy a batch of the living particles to the
- // next vertex buffer segment
- //
- v->_position = i->_position;
- v->_size = i->_size;
- v->_color = (D3DCOLOR)i->_color;
- v++; // next element;
- numParticlesInBatch++; //increase batch counter
- // if this batch full?
- if(numParticlesInBatch == _vbBatchSize)
- {
- //
- // Draw the last batch of particles that was
- // copied to the vertex buffer.
- //
- _vb->Unlock();
- _device->DrawPrimitive(
- D3DPT_POINTLIST,
- _vbOffset,
- _vbBatchSize);
- //
- // While that batch is drawing, start filling the
- // next batch with particles.
- //
- // move the offset to the start of the next batch
- _vbOffset += _vbBatchSize;
- // don't offset into memory thats outside the vb's range.
- // If we're at the end, start at the beginning.
- if(_vbOffset >= _vbSize)
- _vbOffset = 0;
- _vb->Lock(
- _vbOffset * sizeof( ParticleVertex ),
- _vbBatchSize * sizeof( ParticleVertex ),
- (void**)&v,
- _vbOffset ? D3DLOCK_NOOVERWRITE : D3DLOCK_DISCARD);
- numParticlesInBatch = 0; // reset for new batch
- }
- }
- }
- _vb->Unlock();
- // its possible that the LAST batch being filled never
- // got rendered because the condition
- // (numParticlesInBatch == _vbBatchSize) would not have
- // been satisfied. We draw the last partially filled batch now.
- if( numParticlesInBatch )
- {
- _device->DrawPrimitive(
- D3DPT_POINTLIST,
- _vbOffset,
- numParticlesInBatch);
- }
- // next block
- _vbOffset += _vbBatchSize;
- // reset render states
- postRender();
- }
- }
- void CParticleSystem::postRender()
- {
- _device->SetRenderState(D3DRS_LIGHTING, true);
- _device->SetRenderState(D3DRS_POINTSPRITEENABLE, false);
- _device->SetRenderState(D3DRS_POINTSCALEENABLE, false);
- _device->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
- }
- int CParticleSystem::getParticleNum()
- {
- return (int)_particleList.size();
- }
- bool CParticleSystem::isDead()
- {
- if( isEmpty() )
- return true;
- std::list<Particle>::iterator i;
- for( i = _particleList.begin(); i != _particleList.end(); i++ )
- {
- if( i->_isAlive )
- return false;
- }
- return true;
- }
- bool CParticleSystem::isEmpty()
- {
- return _particleList.empty();
- }
- void CParticleSystem::removeDeadParticles()
- {
- if( isEmpty() )
- return;
- std::list<Particle>::iterator i;
- for( i = _particleList.begin(); i != _particleList.end(); i++ )
- {
- if( i->_isAlive == false )
- _particleList.erase(i);
- }
- }
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //Imenpletation of CSnowSystem
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- CSnowSystem::CSnowSystem(int numParticles):CParticleSystem()
- {
- _size = 0.15f;
- m_yVelocity = -0.25f;
- m_xzVel_max = 0.5f;
- m_yAcceleration = -0.98f;
- m_xzAcc_max = 5.0f;
- _boundingBox._maxPoint = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
- _boundingBox._minPoint = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
- for(int i=0; i<numParticles; i++)
- addParticle();
- }
- CSnowSystem::CSnowSystem(BoundingBox* pBoundingBox, int numParticles):CParticleSystem()
- {
- _size = 0.15f;
- m_yVelocity = -0.25f;
- m_xzVel_max = 0.5f;
- m_yAcceleration = -0.98f;
- m_xzAcc_max = 5.0f;
- _boundingBox._maxPoint = pBoundingBox->_maxPoint;
- _boundingBox._minPoint = pBoundingBox->_minPoint;
- for(int i=0; i<numParticles; i++)
- addParticle();
- }
- CSnowSystem::~CSnowSystem()
- {
- }
- void CSnowSystem::resetBoundingBox(BoundingBox& boundingBox)
- {
- _boundingBox = boundingBox;
- }
- void CSnowSystem::resetParticle(Particle* pParticle)
- {
- pParticle->_isAlive = true;
- //init snow's position
- GetRandomVector( &pParticle->_position, &_boundingBox._minPoint, &_boundingBox._maxPoint );
- pParticle->_position.y = _boundingBox._maxPoint.y;
- //init snow's size and color
- pParticle->_size = _size;
- pParticle->_color = WHITE;
- //init snow's velocity
- pParticle->_velocity.x = GetRandomFloat( -m_xzVel_max, m_xzVel_max );
- pParticle->_velocity.z = GetRandomFloat( -m_xzVel_max, m_xzVel_max );
- pParticle->_velocity.y = m_yVelocity;
- //init snow's acceleration
- pParticle->_acceleration.x = GetRandomFloat( -m_xzAcc_max, m_xzAcc_max );
- pParticle->_acceleration.z = GetRandomFloat( -m_xzAcc_max, m_xzAcc_max );
- pParticle->_acceleration.y = m_yAcceleration;
- }
- void CSnowSystem::update(float timeDelta)
- {
- std::list<Particle>::iterator i;
- //update every snow particle in the particleList
- for(i = _particleList.begin(); i != _particleList.end(); i++)
- {
- i->_position += i->_velocity * timeDelta;
- i->_velocity += i->_acceleration * timeDelta;
- //update the snow particle's acceleration
- i->_acceleration.x = GetRandomFloat( -m_xzAcc_max, m_xzAcc_max );
- i->_acceleration.z = GetRandomFloat( -m_xzAcc_max, m_xzAcc_max );
- i->_acceleration.y = m_yAcceleration;
- //update the snow particle's _isAlive attribute
- // i->_isAlive = _boundingBox.isPointInside( i->_position );
- //reset particle that's dead
- if( !_boundingBox.isPointInside( i->_position ) )
- resetParticle( &(*i) );
- }
- }
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- //Imenpletation of CRainSystem
- //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- CRainSystem::CRainSystem(int numParticles):CParticleSystem()
- {
- _size = GetRandomFloat(0.01f, 0.1f);
- m_yVelocity = -5.0f;
- m_xzVel_max = 0.25f;
- m_yAcceleration = -0.98f;
- m_xzAcc_max = 1.0f;
- _boundingBox._maxPoint = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
- _boundingBox._minPoint = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
- for(int i=0; i<numParticles; i++)
- addParticle();
- }
- CRainSystem::CRainSystem(BoundingBox* pBoundingBox, int numParticles):CParticleSystem()
- {
- _size = GetRandomFloat(0.2f, 0.4f);
- m_yVelocity = -5.0f;
- m_xzVel_max = 0.25f;
- m_yAcceleration = -0.98f;
- m_xzAcc_max = 1.0f;
- _boundingBox._maxPoint = pBoundingBox->_maxPoint;
- _boundingBox._minPoint = pBoundingBox->_minPoint;
- for(int i=0; i<numParticles; i++)
- addParticle();
- }
- CRainSystem::~CRainSystem()
- {
- }
- void CRainSystem::resetBoundingBox(BoundingBox& boundingBox)
- {
- _boundingBox = boundingBox;
- }
- void CRainSystem::resetParticle(Particle* pParticle)
- {
- pParticle->_isAlive = true;
- //init rain's position
- GetRandomVector( &pParticle->_position, &_boundingBox._minPoint, &_boundingBox._maxPoint );
- pParticle->_position.y = GetRandomFloat(0.0f, _boundingBox._maxPoint.y);
- //init rain's size and color
- pParticle->_size = _size;
- pParticle->_color = D3DXCOLOR(0.5f, 0.5f, 0.5f, 0.5f);
- //init rain's velocity
- pParticle->_velocity.x = GetRandomFloat( -m_xzVel_max, m_xzVel_max );
- pParticle->_velocity.z = GetRandomFloat( -m_xzVel_max, m_xzVel_max );
- pParticle->_velocity.y = m_yVelocity;
- //init rain's acceleration
- pParticle->_acceleration.x = GetRandomFloat( -m_xzAcc_max, m_xzAcc_max );
- pParticle->_acceleration.z = GetRandomFloat( -m_xzAcc_max, m_xzAcc_max );
- pParticle->_acceleration.y = m_yAcceleration;
- }
- void CRainSystem::update(float timeDelta)
- {
- std::list<Particle>::iterator i;
- //update every rain particle in the particleList
- for(i = _particleList.begin(); i != _particleList.end(); i++)
- {
- i->_position += i->_velocity * timeDelta;
- i->_velocity += i->_acceleration * timeDelta;
- //update the rain particle's acceleration
- i->_acceleration.x = GetRandomFloat( -m_xzAcc_max, m_xzAcc_max );
- i->_acceleration.z = GetRandomFloat( -m_xzAcc_max, m_xzAcc_max );
- i->_acceleration.y = m_yAcceleration;
- //update the rain particle's _isAlive attribute
- // i->_isAlive = _boundingBox.isPointInside( i->_position );
- //reset particle that's dead
- if( !_boundingBox.isPointInside( i->_position ) )
- resetParticle( &(*i) );
- }
- }