Particle.cpp
上传用户:junlon
上传日期:2022-01-05
资源大小:39075k
文件大小:12k
源码类别:

DirextX编程

开发平台:

Visual C++

  1. #include "stdafx.h"
  2. #include "d3dUtility.h"
  3. #include "Particle.h"
  4. using namespace ParticleSystem;
  5. //using namespace myd3d;
  6. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  7. //Imenpletation of CParticleSystem
  8. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  9. const DWORD ParticleVertex::FVF = D3DFVF_XYZ|D3DFVF_PSIZE|D3DFVF_DIFFUSE;
  10. CParticleSystem::CParticleSystem()
  11. {
  12. _vbSize = 2000;
  13. _vbOffset = 0;
  14. _vbBatchSize = 500;
  15. }
  16. CParticleSystem::~CParticleSystem()
  17. {
  18. Release<IDirect3DTexture9*>(_tex);
  19. Release<IDirect3DVertexBuffer9*>(_vb);
  20. }
  21. bool CParticleSystem::init(IDirect3DDevice9* device, LPCTSTR texFileName)
  22. {
  23. _device = device;
  24. HRESULT hr;
  25. hr = D3DXCreateTextureFromFile( _device, texFileName, &_tex );
  26. if(FAILED(hr))
  27. {
  28. ::MessageBoxA(NULL, "Create Texture Failed!", "ParticleSystem", 0);
  29. return false;
  30. }
  31. hr = _device->CreateVertexBuffer( _vbSize * sizeof( ParticleVertex ), D3DUSAGE_DYNAMIC|D3DUSAGE_POINTS|D3DUSAGE_WRITEONLY,
  32. ParticleVertex::FVF, D3DPOOL_DEFAULT, &_vb, NULL );
  33. if(FAILED(hr))
  34. {
  35. ::MessageBoxA(NULL, "Create VertexBuffer Failed!", "ParticleSystem", 0);
  36. return false;
  37. }
  38. return true;
  39. }
  40. void CParticleSystem::reset()
  41. {
  42. std::list<Particle>::iterator particleIter;
  43. for(particleIter = _particleList.begin(); particleIter != _particleList.end(); particleIter++)
  44. {
  45. resetParticle( &(*particleIter));
  46. }
  47. }
  48. void CParticleSystem::addParticle()
  49. {
  50. Particle newParticle;
  51. resetParticle(&newParticle);
  52. _particleList.push_back(newParticle);
  53. }
  54. void CParticleSystem::preRender()
  55. {
  56. D3DXMATRIX matWorld;
  57. D3DXMatrixIdentity(&matWorld);
  58. _device->SetTransform(D3DTS_WORLD, &matWorld);
  59. _device->SetRenderState(D3DRS_POINTSPRITEENABLE, true);
  60. _device->SetRenderState(D3DRS_POINTSCALEENABLE, true); 
  61. _device->SetRenderState(D3DRS_POINTSIZE, FtoDw(_size));
  62. _device->SetRenderState(D3DRS_POINTSIZE_MIN, FtoDw(5.0f));
  63. _device->SetRenderState(D3DRS_POINTSIZE_MAX, FtoDw(20.0f));
  64. // control the size of the particle relative to distance
  65. _device->SetRenderState(D3DRS_POINTSCALE_A, FtoDw(0.0f));
  66. _device->SetRenderState(D3DRS_POINTSCALE_B, FtoDw(0.0f));
  67. _device->SetRenderState(D3DRS_POINTSCALE_C, FtoDw(1.0f));
  68. _device->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
  69. _device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  70.     _device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_DESTALPHA);
  71. _device->SetRenderState(D3DRS_LIGHTING, false);
  72. }
  73. void CParticleSystem::render()
  74. {
  75. //
  76. // Remarks:  The render method works by filling a section of the vertex buffer with data,
  77. //           then we render that section.  While that section is rendering we lock a new
  78. //           section and begin to fill that section.  Once that sections filled we render it.
  79. //           This process continues until all the particles have been drawn.  The benifit
  80. //           of this method is that we keep the video card and the CPU busy.  
  81. if( !_particleList.empty() )
  82. {
  83. // set render states
  84. preRender();
  85. _device->SetTexture(0, _tex);
  86. _device->SetFVF(ParticleVertex::FVF);
  87. _device->SetStreamSource(0, _vb, 0, sizeof(ParticleVertex));
  88. // render batches one by one
  89. // start at beginning if we're at the end of the vb
  90. if(_vbOffset >= _vbSize)
  91. _vbOffset = 0;
  92. ParticleVertex* v = 0;
  93. _vb->Lock(
  94. _vbOffset    * sizeof( ParticleVertex ),
  95. _vbBatchSize * sizeof( ParticleVertex ),
  96. (void**)&v,
  97. _vbOffset ? D3DLOCK_NOOVERWRITE : D3DLOCK_DISCARD);
  98. DWORD numParticlesInBatch = 0;
  99. //
  100. // Until all particles have been rendered.
  101. //
  102. std::list<Particle>::iterator i;
  103. for(i = _particleList.begin(); i != _particleList.end(); i++)
  104. {
  105. if( i->_isAlive )
  106. {
  107. //
  108. // Copy a batch of the living particles to the
  109. // next vertex buffer segment
  110. //
  111. v->_position = i->_position;
  112. v->_size     = i->_size;
  113. v->_color    = (D3DCOLOR)i->_color;
  114. v++; // next element;
  115. numParticlesInBatch++; //increase batch counter
  116. // if this batch full?
  117. if(numParticlesInBatch == _vbBatchSize) 
  118. {
  119. //
  120. // Draw the last batch of particles that was
  121. // copied to the vertex buffer. 
  122. //
  123. _vb->Unlock();
  124. _device->DrawPrimitive(
  125. D3DPT_POINTLIST,
  126. _vbOffset,
  127. _vbBatchSize);
  128. //
  129. // While that batch is drawing, start filling the
  130. // next batch with particles.
  131. //
  132. // move the offset to the start of the next batch
  133. _vbOffset += _vbBatchSize;
  134. // don't offset into memory thats outside the vb's range.
  135. // If we're at the end, start at the beginning.
  136. if(_vbOffset >= _vbSize) 
  137. _vbOffset = 0;       
  138. _vb->Lock(
  139. _vbOffset    * sizeof( ParticleVertex ),
  140. _vbBatchSize * sizeof( ParticleVertex ),
  141. (void**)&v,
  142. _vbOffset ? D3DLOCK_NOOVERWRITE : D3DLOCK_DISCARD);
  143. numParticlesInBatch = 0; // reset for new batch
  144. }
  145. }
  146. }
  147. _vb->Unlock();
  148. // its possible that the LAST batch being filled never 
  149. // got rendered because the condition 
  150. // (numParticlesInBatch == _vbBatchSize) would not have
  151. // been satisfied.  We draw the last partially filled batch now.
  152. if( numParticlesInBatch )
  153. {
  154. _device->DrawPrimitive(
  155. D3DPT_POINTLIST,
  156. _vbOffset,
  157. numParticlesInBatch);
  158. }
  159. // next block
  160. _vbOffset += _vbBatchSize; 
  161. // reset render states
  162. postRender();
  163. }
  164. }
  165. void CParticleSystem::postRender()
  166. {
  167. _device->SetRenderState(D3DRS_LIGHTING, true);
  168. _device->SetRenderState(D3DRS_POINTSPRITEENABLE, false);
  169. _device->SetRenderState(D3DRS_POINTSCALEENABLE,  false);
  170. _device->SetRenderState(D3DRS_ALPHABLENDENABLE,  false);
  171. _device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
  172.     _device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
  173. }
  174. int CParticleSystem::getParticleNum()
  175. {
  176. return (int)_particleList.size();
  177. }
  178. bool CParticleSystem::isDead()
  179. {
  180. if( isEmpty() )
  181. return true;
  182. std::list<Particle>::iterator i;
  183. for( i = _particleList.begin(); i != _particleList.end(); i++ )
  184. {
  185. if( i->_isAlive )
  186. return false;
  187. }
  188. return true;
  189. }
  190. bool CParticleSystem::isEmpty()
  191. {
  192. return _particleList.empty();
  193. }
  194. void CParticleSystem::removeDeadParticles()
  195. {
  196. if( isEmpty() )
  197. return;
  198. std::list<Particle>::iterator i;
  199. for( i = _particleList.begin(); i != _particleList.end(); i++ )
  200. {
  201. if( i->_isAlive == false )
  202. _particleList.erase(i);
  203. }
  204. }
  205. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  206. //Imenpletation of CSnowSystem
  207. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  208. CSnowSystem::CSnowSystem(int numParticles, float size):CParticleSystem()
  209. {
  210. //_size = 0.15f;
  211. _size = size;
  212. m_yVelocity = -0.25f;
  213. m_xzVel_max = 0.5f;
  214. m_yAcceleration = -0.98f;
  215. m_xzAcc_max = 5.0f;
  216. _boundingBox._maxPoint = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
  217. _boundingBox._minPoint = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
  218. for(int i=0; i<numParticles; i++)
  219. addParticle();
  220. }
  221. CSnowSystem::CSnowSystem(BoundingBox* pBoundingBox, int numParticles, float size):CParticleSystem()
  222. {
  223. //_size = 0.15f;
  224. _size = size;
  225. m_yVelocity = -0.25f;
  226. m_xzVel_max = 0.5f;
  227. m_yAcceleration = -0.98f;
  228. m_xzAcc_max = 5.0f;
  229. _boundingBox._maxPoint = pBoundingBox->_maxPoint;
  230. _boundingBox._minPoint = pBoundingBox->_minPoint;
  231. for(int i=0; i<numParticles; i++)
  232. addParticle();
  233. }
  234. CSnowSystem::~CSnowSystem()
  235. {
  236. }
  237. void CSnowSystem::resetBoundingBox(BoundingBox& boundingBox)
  238. {
  239. _boundingBox = boundingBox;
  240. }
  241. void CSnowSystem::resetParticle(Particle* pParticle)
  242. {
  243. pParticle->_isAlive = true;
  244. //init snow's position
  245. GetRandomVector( &pParticle->_position, &_boundingBox._minPoint, &_boundingBox._maxPoint );
  246. pParticle->_position.y = _boundingBox._maxPoint.y;
  247. //init snow's size and color
  248. pParticle->_size = _size;
  249. pParticle->_color = WHITE;
  250. //init snow's velocity
  251. pParticle->_velocity.x = GetRandomFloat( -m_xzVel_max, m_xzVel_max );
  252. pParticle->_velocity.z = GetRandomFloat( -m_xzVel_max, m_xzVel_max );
  253. pParticle->_velocity.y = m_yVelocity;
  254. //init snow's acceleration
  255. pParticle->_acceleration.x = GetRandomFloat( -m_xzAcc_max, m_xzAcc_max );
  256. pParticle->_acceleration.z = GetRandomFloat( -m_xzAcc_max, m_xzAcc_max );
  257. pParticle->_acceleration.y = m_yAcceleration;
  258. }
  259. void CSnowSystem::update(float timeDelta)
  260. {
  261. std::list<Particle>::iterator i;
  262. //update every snow particle in the particleList
  263. for(i = _particleList.begin(); i != _particleList.end(); i++)
  264. {
  265. i->_position += i->_velocity * timeDelta;
  266. i->_velocity += i->_acceleration * timeDelta;
  267. //update the snow particle's acceleration
  268. i->_acceleration.x = GetRandomFloat( -m_xzAcc_max, m_xzAcc_max );
  269. i->_acceleration.z = GetRandomFloat( -m_xzAcc_max, m_xzAcc_max );
  270. i->_acceleration.y = m_yAcceleration;
  271. //update the snow particle's _isAlive attribute
  272. // i->_isAlive = _boundingBox.isPointInside( i->_position );
  273. //reset particle that's dead
  274. if( !_boundingBox.isPointInside( i->_position ) )
  275. resetParticle( &(*i) );
  276. }
  277. }
  278. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  279. //Imenpletation of CRainSystem
  280. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  281. CRainSystem::CRainSystem(int numParticles, float size):CParticleSystem()
  282. {
  283. //_size = GetRandomFloat(0.2f, 0.4f);
  284. _size = size;
  285. m_yVelocity = -5.0f;
  286. m_xzVel_max = 0.25f;
  287. m_yAcceleration = -0.98f;
  288. m_xzAcc_max = 1.0f;
  289. _boundingBox._maxPoint = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
  290. _boundingBox._minPoint = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
  291. for(int i=0; i<numParticles; i++)
  292. addParticle();
  293. }
  294. CRainSystem::CRainSystem(BoundingBox* pBoundingBox, int numParticles, float size):CParticleSystem()
  295. {
  296. //_size = GetRandomFloat(0.2f, 0.4f);
  297. _size = size;
  298. m_yVelocity = -5.0f;
  299. m_xzVel_max = 0.25f;
  300. m_yAcceleration = -0.98f;
  301. m_xzAcc_max = 1.0f;
  302. _boundingBox._maxPoint = pBoundingBox->_maxPoint;
  303. _boundingBox._minPoint = pBoundingBox->_minPoint;
  304. for(int i=0; i<numParticles; i++)
  305. addParticle();
  306. }
  307. CRainSystem::~CRainSystem()
  308. {
  309. }
  310. void CRainSystem::resetBoundingBox(BoundingBox& boundingBox)
  311. {
  312. _boundingBox = boundingBox;
  313. }
  314. void CRainSystem::resetParticle(Particle* pParticle)
  315. {
  316. pParticle->_isAlive = true;
  317. //init rain's position
  318. GetRandomVector( &pParticle->_position, &_boundingBox._minPoint, &_boundingBox._maxPoint );
  319. pParticle->_position.y = GetRandomFloat(0.0f, _boundingBox._maxPoint.y);
  320. //init rain's size and color
  321. pParticle->_size = _size;
  322. pParticle->_color = D3DXCOLOR(0.5f, 0.5f, 0.5f, 0.5f);
  323. //init rain's velocity
  324. pParticle->_velocity.x = GetRandomFloat( -m_xzVel_max, m_xzVel_max );
  325. pParticle->_velocity.z = GetRandomFloat( -m_xzVel_max, m_xzVel_max );
  326. pParticle->_velocity.y = m_yVelocity;
  327. //init rain's acceleration
  328. pParticle->_acceleration.x = GetRandomFloat( -m_xzAcc_max, m_xzAcc_max );
  329. pParticle->_acceleration.z = GetRandomFloat( -m_xzAcc_max, m_xzAcc_max );
  330. pParticle->_acceleration.y = m_yAcceleration;
  331. }
  332. void CRainSystem::update(float timeDelta)
  333. {
  334. std::list<Particle>::iterator i;
  335. //update every rain particle in the particleList
  336. for(i = _particleList.begin(); i != _particleList.end(); i++)
  337. {
  338. i->_position += i->_velocity * timeDelta;
  339. i->_velocity += i->_acceleration * timeDelta;
  340. //update the rain particle's acceleration
  341. i->_acceleration.x = GetRandomFloat( -m_xzAcc_max, m_xzAcc_max );
  342. i->_acceleration.z = GetRandomFloat( -m_xzAcc_max, m_xzAcc_max );
  343. i->_acceleration.y = m_yAcceleration;
  344. //update the rain particle's _isAlive attribute
  345. // i->_isAlive = _boundingBox.isPointInside( i->_position );
  346. //reset particle that's dead
  347. if( !_boundingBox.isPointInside( i->_position ) )
  348. resetParticle( &(*i) );
  349. }
  350. }