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

DirextX编程

开发平台:

Visual C++

  1. #include "dxstdafx.h"
  2. #include <list>
  3. #include "d3dUtility.h"
  4. #include "Particle.h"
  5. using namespace ParticleSystem;
  6. //using namespace myd3d;
  7. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  8. //Imenpletation of CParticleSystem
  9. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  10. const DWORD ParticleVertex::FVF = D3DFVF_XYZ|D3DFVF_PSIZE|D3DFVF_DIFFUSE;
  11. CParticleSystem::CParticleSystem()
  12. {
  13. _vbSize = 2000;
  14. _vbOffset = 0;
  15. _vbBatchSize = 500;
  16. }
  17. CParticleSystem::~CParticleSystem()
  18. {
  19. Release<IDirect3DTexture9*>(_tex);
  20. Release<IDirect3DVertexBuffer9*>(_vb);
  21. }
  22. bool CParticleSystem::init(IDirect3DDevice9* device, LPCTSTR texFileName)
  23. {
  24. _device = device;
  25. HRESULT hr;
  26. hr = D3DXCreateTextureFromFile( _device, texFileName, &_tex );
  27. if(FAILED(hr))
  28. {
  29. ::MessageBoxA(NULL, "Create Texture Failed!", "ParticleSystem", 0);
  30. return false;
  31. }
  32. hr = _device->CreateVertexBuffer( _vbSize * sizeof( ParticleVertex ), D3DUSAGE_DYNAMIC|D3DUSAGE_POINTS|D3DUSAGE_WRITEONLY,
  33. ParticleVertex::FVF, D3DPOOL_DEFAULT, &_vb, NULL );
  34. if(FAILED(hr))
  35. {
  36. ::MessageBoxA(NULL, "Create VertexBuffer Failed!", "ParticleSystem", 0);
  37. return false;
  38. }
  39. return true;
  40. }
  41. void CParticleSystem::reset()
  42. {
  43. std::list<Particle>::iterator particleIter;
  44. for(particleIter = _particleList.begin(); particleIter != _particleList.end(); particleIter++)
  45. {
  46. resetParticle( &(*particleIter));
  47. }
  48. }
  49. void CParticleSystem::addParticle()
  50. {
  51. Particle newParticle;
  52. resetParticle(&newParticle);
  53. _particleList.push_back(newParticle);
  54. }
  55. void CParticleSystem::preRender()
  56. {
  57. _device->SetRenderState(D3DRS_LIGHTING, false);
  58. _device->SetRenderState(D3DRS_POINTSPRITEENABLE, true);
  59. _device->SetRenderState(D3DRS_POINTSCALEENABLE, true); 
  60. _device->SetRenderState(D3DRS_POINTSIZE, FtoDw(_size));
  61. _device->SetRenderState(D3DRS_POINTSIZE_MIN, FtoDw(0.0f));
  62. // control the size of the particle relative to distance
  63. _device->SetRenderState(D3DRS_POINTSCALE_A, FtoDw(0.0f));
  64. _device->SetRenderState(D3DRS_POINTSCALE_B, FtoDw(0.0f));
  65. _device->SetRenderState(D3DRS_POINTSCALE_C, FtoDw(1.0f));
  66. // use alpha from texture
  67. _device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
  68. _device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
  69. _device->SetRenderState(D3DRS_ALPHABLENDENABLE, true);
  70. _device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
  71.     _device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_DESTALPHA);
  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. }
  172. int CParticleSystem::getParticleNum()
  173. {
  174. return (int)_particleList.size();
  175. }
  176. bool CParticleSystem::isDead()
  177. {
  178. if( isEmpty() )
  179. return true;
  180. std::list<Particle>::iterator i;
  181. for( i = _particleList.begin(); i != _particleList.end(); i++ )
  182. {
  183. if( i->_isAlive )
  184. return false;
  185. }
  186. return true;
  187. }
  188. bool CParticleSystem::isEmpty()
  189. {
  190. return _particleList.empty();
  191. }
  192. void CParticleSystem::removeDeadParticles()
  193. {
  194. if( isEmpty() )
  195. return;
  196. std::list<Particle>::iterator i;
  197. for( i = _particleList.begin(); i != _particleList.end(); i++ )
  198. {
  199. if( i->_isAlive == false )
  200. _particleList.erase(i);
  201. }
  202. }
  203. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  204. //Imenpletation of CSnowSystem
  205. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  206. CSnowSystem::CSnowSystem(int numParticles):CParticleSystem()
  207. {
  208. _size = 0.15f;
  209. m_yVelocity = -0.25f;
  210. m_xzVel_max = 0.5f;
  211. m_yAcceleration = -0.98f;
  212. m_xzAcc_max = 5.0f;
  213. _boundingBox._maxPoint = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
  214. _boundingBox._minPoint = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
  215. for(int i=0; i<numParticles; i++)
  216. addParticle();
  217. }
  218. CSnowSystem::CSnowSystem(BoundingBox* pBoundingBox, int numParticles):CParticleSystem()
  219. {
  220. _size = 0.15f;
  221. m_yVelocity = -0.25f;
  222. m_xzVel_max = 0.5f;
  223. m_yAcceleration = -0.98f;
  224. m_xzAcc_max = 5.0f;
  225. _boundingBox._maxPoint = pBoundingBox->_maxPoint;
  226. _boundingBox._minPoint = pBoundingBox->_minPoint;
  227. for(int i=0; i<numParticles; i++)
  228. addParticle();
  229. }
  230. CSnowSystem::~CSnowSystem()
  231. {
  232. }
  233. void CSnowSystem::resetBoundingBox(BoundingBox& boundingBox)
  234. {
  235. _boundingBox = boundingBox;
  236. }
  237. void CSnowSystem::resetParticle(Particle* pParticle)
  238. {
  239. pParticle->_isAlive = true;
  240. //init snow's position
  241. GetRandomVector( &pParticle->_position, &_boundingBox._minPoint, &_boundingBox._maxPoint );
  242. pParticle->_position.y = _boundingBox._maxPoint.y;
  243. //init snow's size and color
  244. pParticle->_size = _size;
  245. pParticle->_color = WHITE;
  246. //init snow's velocity
  247. pParticle->_velocity.x = GetRandomFloat( -m_xzVel_max, m_xzVel_max );
  248. pParticle->_velocity.z = GetRandomFloat( -m_xzVel_max, m_xzVel_max );
  249. pParticle->_velocity.y = m_yVelocity;
  250. //init snow's acceleration
  251. pParticle->_acceleration.x = GetRandomFloat( -m_xzAcc_max, m_xzAcc_max );
  252. pParticle->_acceleration.z = GetRandomFloat( -m_xzAcc_max, m_xzAcc_max );
  253. pParticle->_acceleration.y = m_yAcceleration;
  254. }
  255. void CSnowSystem::update(float timeDelta)
  256. {
  257. std::list<Particle>::iterator i;
  258. //update every snow particle in the particleList
  259. for(i = _particleList.begin(); i != _particleList.end(); i++)
  260. {
  261. i->_position += i->_velocity * timeDelta;
  262. i->_velocity += i->_acceleration * timeDelta;
  263. //update the snow particle's acceleration
  264. i->_acceleration.x = GetRandomFloat( -m_xzAcc_max, m_xzAcc_max );
  265. i->_acceleration.z = GetRandomFloat( -m_xzAcc_max, m_xzAcc_max );
  266. i->_acceleration.y = m_yAcceleration;
  267. //update the snow particle's _isAlive attribute
  268. // i->_isAlive = _boundingBox.isPointInside( i->_position );
  269. //reset particle that's dead
  270. if( !_boundingBox.isPointInside( i->_position ) )
  271. resetParticle( &(*i) );
  272. }
  273. }
  274. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  275. //Imenpletation of CRainSystem
  276. //////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  277. CRainSystem::CRainSystem(int numParticles):CParticleSystem()
  278. {
  279. _size = GetRandomFloat(0.01f, 0.1f);
  280. m_yVelocity = -5.0f;
  281. m_xzVel_max = 0.25f;
  282. m_yAcceleration = -0.98f;
  283. m_xzAcc_max = 1.0f;
  284. _boundingBox._maxPoint = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
  285. _boundingBox._minPoint = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
  286. for(int i=0; i<numParticles; i++)
  287. addParticle();
  288. }
  289. CRainSystem::CRainSystem(BoundingBox* pBoundingBox, int numParticles):CParticleSystem()
  290. {
  291. _size = GetRandomFloat(0.2f, 0.4f);
  292. m_yVelocity = -5.0f;
  293. m_xzVel_max = 0.25f;
  294. m_yAcceleration = -0.98f;
  295. m_xzAcc_max = 1.0f;
  296. _boundingBox._maxPoint = pBoundingBox->_maxPoint;
  297. _boundingBox._minPoint = pBoundingBox->_minPoint;
  298. for(int i=0; i<numParticles; i++)
  299. addParticle();
  300. }
  301. CRainSystem::~CRainSystem()
  302. {
  303. }
  304. void CRainSystem::resetBoundingBox(BoundingBox& boundingBox)
  305. {
  306. _boundingBox = boundingBox;
  307. }
  308. void CRainSystem::resetParticle(Particle* pParticle)
  309. {
  310. pParticle->_isAlive = true;
  311. //init rain's position
  312. GetRandomVector( &pParticle->_position, &_boundingBox._minPoint, &_boundingBox._maxPoint );
  313. pParticle->_position.y = GetRandomFloat(0.0f, _boundingBox._maxPoint.y);
  314. //init rain's size and color
  315. pParticle->_size = _size;
  316. pParticle->_color = D3DXCOLOR(0.5f, 0.5f, 0.5f, 0.5f);
  317. //init rain's velocity
  318. pParticle->_velocity.x = GetRandomFloat( -m_xzVel_max, m_xzVel_max );
  319. pParticle->_velocity.z = GetRandomFloat( -m_xzVel_max, m_xzVel_max );
  320. pParticle->_velocity.y = m_yVelocity;
  321. //init rain's acceleration
  322. pParticle->_acceleration.x = GetRandomFloat( -m_xzAcc_max, m_xzAcc_max );
  323. pParticle->_acceleration.z = GetRandomFloat( -m_xzAcc_max, m_xzAcc_max );
  324. pParticle->_acceleration.y = m_yAcceleration;
  325. }
  326. void CRainSystem::update(float timeDelta)
  327. {
  328. std::list<Particle>::iterator i;
  329. //update every rain particle in the particleList
  330. for(i = _particleList.begin(); i != _particleList.end(); i++)
  331. {
  332. i->_position += i->_velocity * timeDelta;
  333. i->_velocity += i->_acceleration * timeDelta;
  334. //update the rain particle's acceleration
  335. i->_acceleration.x = GetRandomFloat( -m_xzAcc_max, m_xzAcc_max );
  336. i->_acceleration.z = GetRandomFloat( -m_xzAcc_max, m_xzAcc_max );
  337. i->_acceleration.y = m_yAcceleration;
  338. //update the rain particle's _isAlive attribute
  339. // i->_isAlive = _boundingBox.isPointInside( i->_position );
  340. //reset particle that's dead
  341. if( !_boundingBox.isPointInside( i->_position ) )
  342. resetParticle( &(*i) );
  343. }
  344. }