DirectX粒子--雪花

创建Particle父类,Snow子类。

Class Particle

 

#include <cstdlib>
#include "pSystem.h"

using namespace psys;

const DWORD Particle::FVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;

PSystem::PSystem()
{
 _device = 0;
 _vb     = 0;
 _tex    = 0;
}

PSystem::~PSystem()
{
 d3d::Release<IDirect3DVertexBuffer9*>(_vb);
 d3d::Release<IDirect3DTexture9*>(_tex);
}

bool PSystem::init(IDirect3DDevice9* device, char* texFileName)
{
  _device = device;

 HRESULT hr = 0;

 hr = device->CreateVertexBuffer(
  _vbSize * sizeof(Particle),
  D3DUSAGE_DYNAMIC | D3DUSAGE_POINTS | D3DUSAGE_WRITEONLY,
  Particle::FVF,
  D3DPOOL_DEFAULT, 
  &_vb,
  0);
 
 if(FAILED(hr))
 {
  ::MessageBox(0, "CreateVertexBuffer() - FAILED", "PSystem", 0);
  return false;
 }

 hr = D3DXCreateTextureFromFile(
  device,
  texFileName,
  &_tex);

 if(FAILED(hr))
 {
  ::MessageBox(0, "D3DXCreateTextureFromFile() - FAILED", "PSystem", 0);
  return false;
 }

 return true;
}

void PSystem::reset()
{
 std::list<Attribute>::iterator i;
 for(i = _particles.begin(); i != _particles.end(); i++)
 {
  resetParticle( &(*i) );
 }
}

void PSystem::addParticle()
{
 Attribute attribute;

 resetParticle(&attribute);

 _particles.push_back(attribute);
}

void PSystem::preRender()
{
 _device->SetRenderState(D3DRS_LIGHTING, false);
 _device->SetRenderState(D3DRS_POINTSPRITEENABLE, true);
 _device->SetRenderState(D3DRS_POINTSCALEENABLE, true);
 _device->SetRenderState(D3DRS_POINTSIZE, d3d::FtoDw(_size));
 _device->SetRenderState(D3DRS_POINTSIZE_MIN, d3d::FtoDw(0.0f));


 _device->SetRenderState(D3DRS_POINTSCALE_A, d3d::FtoDw(0.0f));
 _device->SetRenderState(D3DRS_POINTSCALE_B, d3d::FtoDw(0.0f));
 _device->SetRenderState(D3DRS_POINTSCALE_C, d3d::FtoDw(1.0f));
  
  _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_INVSRCALPHA);
}

void PSystem::postRender()
{
 _device->SetRenderState(D3DRS_LIGHTING,          true);
 _device->SetRenderState(D3DRS_POINTSPRITEENABLE, false);
 _device->SetRenderState(D3DRS_POINTSCALEENABLE,  false);
 _device->SetRenderState(D3DRS_ALPHABLENDENABLE,  false);
}

void PSystem::render()
{
  if( !_particles.empty() )
 {
  preRender();
  
  _device->SetTexture(0, _tex);
  _device->SetFVF(Particle::FVF);
  _device->SetStreamSource(0, _vb, 0, sizeof(Particle));

 

   if(_vbOffset >= _vbSize)
   _vbOffset = 0;

  Particle* v = 0;

  _vb->Lock(
   _vbOffset    * sizeof( Particle ),
   _vbBatchSize * sizeof( Particle ),
   (void**)&v,
   _vbOffset ? D3DLOCK_NOOVERWRITE : D3DLOCK_DISCARD);

  DWORD numParticlesInBatch = 0;

 

   std::list<Attribute>::iterator i;
  for(i = _particles.begin(); i != _particles.end(); i++)
  {
   if( i->_isAlive )
   {
        v->_position = i->_position;
    v->_color    = (D3DCOLOR)i->_color;
    v++; // next element;

    numParticlesInBatch++; //increase batch counter

    

    if(numParticlesInBatch == _vbBatchSize)
    {
         _vb->Unlock();

     _device->DrawPrimitive(
      D3DPT_POINTLIST,
      _vbOffset,
      _vbBatchSize);

   

     _vbOffset += _vbBatchSize;

    

     if(_vbOffset >= _vbSize)
      _vbOffset = 0;      

     _vb->Lock(
      _vbOffset    * sizeof( Particle ),
      _vbBatchSize * sizeof( Particle ),
      (void**)&v,
      _vbOffset ? D3DLOCK_NOOVERWRITE : D3DLOCK_DISCARD);

     numParticlesInBatch = 0; 
    } 
   }
  }

  _vb->Unlock();

  
  if( numParticlesInBatch )
  {
   _device->DrawPrimitive(
    D3DPT_POINTLIST,
    _vbOffset,
    numParticlesInBatch);
  }

  

  _vbOffset += _vbBatchSize;

  

  postRender();

 }
}

bool PSystem::isEmpty()
{
 return _particles.empty();
}

bool PSystem::isDead()
{
 std::list<Attribute>::iterator i;
 for(i = _particles.begin(); i != _particles.end(); i++)
 {
   if( i->_isAlive )
   return false;
 }
  return true;
}

void PSystem::removeDeadParticles()
{
 std::list<Attribute>::iterator i;

 i = _particles.begin();

 while( i != _particles.end() )
 {
  if( i->_isAlive == false )
  {
      i = _particles.erase(i);
  }
  else
  {
   i++; // next in list
  }
 }
}

*****************************************************************************
Class Snow

 

 

Snow::Snow(d3d::BoundingBox* boundingBox, int numParticles)
{
 _boundingBox   = *boundingBox;
 _size          = 0.25f;
 _vbSize        = 2048;
 _vbOffset      = 0;
 _vbBatchSize   = 512;
 
 for(int i = 0; i < numParticles; i++)
  addParticle();
}

void Snow::resetParticle(Attribute* attribute)
{
 attribute->_isAlive  = true;

 d3d::GetRandomVector(
  &attribute->_position,
  &_boundingBox._min,
  &_boundingBox._max);

 

  attribute->_position.y = _boundingBox._max.y;

 attribute->_velocity.x = d3d::GetRandomFloat(0.0f, 1.0f) * -3.0f;
 attribute->_velocity.y = d3d::GetRandomFloat(0.0f, 1.0f) * -10.0f;
 attribute->_velocity.z = 0.0f;

 
 attribute->_color = d3d::WHITE;
}

void Snow::update(float timeDelta)
{
 std::list<Attribute>::iterator i;
 for(i = _particles.begin(); i != _particles.end(); i++)
 {
  i->_position += i->_velocity * timeDelta;

  // is the point outside bounds?
  if( _boundingBox.isPointInside( i->_position ) == false )
  {
   // nope so kill it, but we want to recycle dead
   // particles, so respawn it instead.
   resetParticle( &(*i) );
  }
 }
}

 }
 _device->SetRenderState(D3DRS_ZWRITEENABLE, true);
}

 

 

Render Snow

 

 

#include "d3dUtility.h"
#include "psystem.h"
#include "camera.h"
#include <cstdlib>
#include <ctime>

 

IDirect3DDevice9*     Device = 0;

const int Width  = 640;
const int Height = 480;

psys::PSystem* Sno = 0;

Camera TheCamera(Camera::AIRCRAFT);

 

bool Setup()
{
 
 srand((unsigned int)time(0));

 

 d3d::BoundingBox boundingBox;
 boundingBox._min = D3DXVECTOR3(-10.0f, -10.0f, -10.0f);
 boundingBox._max = D3DXVECTOR3( 10.0f,  10.0f,  10.0f);
 Sno = new psys::Snow(&boundingBox, 5000);
 Sno->init(Device, "snowflake.dds");

 

 d3d::DrawBasicScene(Device, 1.0f);

 

 D3DXMATRIX proj;
 D3DXMatrixPerspectiveFovLH(
   &proj,
   D3DX_PI / 4.0f, // 45 - degree
   (float)Width / (float)Height,
   1.0f,
   5000.0f);
 Device->SetTransform(D3DTS_PROJECTION, &proj);

 return true;
}

void Cleanup()
{
 d3d::Delete<psys::PSystem*>( Sno );
 d3d::DrawBasicScene(0, 1.0f);
}

bool Display(float timeDelta)
{
 if( Device )
 {

  if( ::GetAsyncKeyState(VK_UP) & 0x8000f )
   TheCamera.walk(4.0f * timeDelta);

  if( ::GetAsyncKeyState(VK_DOWN) & 0x8000f )
   TheCamera.walk(-4.0f * timeDelta);

  if( ::GetAsyncKeyState(VK_LEFT) & 0x8000f )
   TheCamera.yaw(-1.0f * timeDelta);
  
  if( ::GetAsyncKeyState(VK_RIGHT) & 0x8000f )
   TheCamera.yaw(1.0f * timeDelta);

  if( ::GetAsyncKeyState('A') & 0x8000f )
   TheCamera.strafe(-4.0f * timeDelta);

  if( ::GetAsyncKeyState('D') & 0x8000f )
   TheCamera.strafe(4.0f * timeDelta);

  if( ::GetAsyncKeyState('W') & 0x8000f )
   TheCamera.pitch(1.0f * timeDelta);

  if( ::GetAsyncKeyState('S') & 0x8000f )
   TheCamera.pitch(-1.0f * timeDelta);

  D3DXMATRIX V;
  TheCamera.getViewMatrix(&V);
  Device->SetTransform(D3DTS_VIEW, &V);

  Sno->update(timeDelta);

  

  Device->Clear(0, 0, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0);
  Device->BeginScene();

  D3DXMATRIX I;
  D3DXMatrixIdentity(&I);
  Device->SetTransform(D3DTS_WORLD, &I);

  d3d::DrawBasicScene(Device, 1.0f);

  

  Device->SetTransform(D3DTS_WORLD, &I);
  Sno->render();

  Device->EndScene();
  Device->Present(0, 0, 0, 0);
 }
 return true;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值