ParticleEmitter.cpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077
  1. #include "Base.h"
  2. #include "ParticleEmitter.h"
  3. #include "Game.h"
  4. #include "Node.h"
  5. #include "Scene.h"
  6. #include "Quaternion.h"
  7. #include "Properties.h"
  8. #define PARTICLE_COUNT_MAX 100
  9. #define PARTICLE_EMISSION_RATE 10
  10. #define PARTICLE_EMISSION_RATE_TIME_INTERVAL 1000.0f / (float)PARTICLE_EMISSION_RATE
  11. #define PARTICLE_UPDATE_RATE_MAX 8
  12. namespace gameplay
  13. {
  14. ParticleEmitter::ParticleEmitter(unsigned int particleCountMax) :
  15. _particleCountMax(particleCountMax), _particleCount(0), _particles(NULL),
  16. _emissionRate(PARTICLE_EMISSION_RATE), _started(false), _ellipsoid(false),
  17. _sizeStartMin(1.0f), _sizeStartMax(1.0f), _sizeEndMin(1.0f), _sizeEndMax(1.0f),
  18. _energyMin(1000L), _energyMax(1000L),
  19. _colorStart(Vector4::zero()), _colorStartVar(Vector4::zero()), _colorEnd(Vector4::one()), _colorEndVar(Vector4::zero()),
  20. _position(Vector3::zero()), _positionVar(Vector3::zero()),
  21. _velocity(Vector3::zero()), _velocityVar(Vector3::one()),
  22. _acceleration(Vector3::zero()), _accelerationVar(Vector3::zero()),
  23. _rotationPerParticleSpeedMin(0.0f), _rotationPerParticleSpeedMax(0.0f),
  24. _rotationSpeedMin(0.0f), _rotationSpeedMax(0.0f),
  25. _rotationAxis(Vector3::zero()), _rotation(Matrix::identity()),
  26. _spriteBatch(NULL), _spriteBlendMode(BLEND_ALPHA), _spriteTextureWidth(0), _spriteTextureHeight(0), _spriteTextureWidthRatio(0), _spriteTextureHeightRatio(0), _spriteTextureCoords(NULL),
  27. _spriteAnimated(false), _spriteLooped(false), _spriteFrameCount(1), _spriteFrameRandomOffset(0),_spriteFrameDuration(0L), _spriteFrameDurationSecs(0.0f), _spritePercentPerFrame(0.0f),
  28. _node(NULL), _orbitPosition(false), _orbitVelocity(false), _orbitAcceleration(false),
  29. _timePerEmission(PARTICLE_EMISSION_RATE_TIME_INTERVAL), _emitTime(0), _lastUpdated(0)
  30. {
  31. GP_ASSERT(particleCountMax);
  32. _particles = new Particle[particleCountMax];
  33. }
  34. ParticleEmitter::~ParticleEmitter()
  35. {
  36. SAFE_DELETE(_spriteBatch);
  37. SAFE_DELETE_ARRAY(_particles);
  38. SAFE_DELETE_ARRAY(_spriteTextureCoords);
  39. }
  40. ParticleEmitter* ParticleEmitter::create(const char* textureFile, BlendMode blendMode, unsigned int particleCountMax)
  41. {
  42. Texture* texture = Texture::create(textureFile, true);
  43. if (!texture)
  44. {
  45. GP_ERROR("Failed to create texture for particle emitter.");
  46. return NULL;
  47. }
  48. GP_ASSERT(texture->getWidth());
  49. GP_ASSERT(texture->getHeight());
  50. ParticleEmitter* emitter = ParticleEmitter::create(texture, blendMode, particleCountMax);
  51. SAFE_RELEASE(texture);
  52. return emitter;
  53. }
  54. ParticleEmitter* ParticleEmitter::create(Texture* texture, BlendMode blendMode, unsigned int particleCountMax)
  55. {
  56. ParticleEmitter* emitter = new ParticleEmitter(particleCountMax);
  57. GP_ASSERT(emitter);
  58. emitter->setTexture(texture, blendMode);
  59. return emitter;
  60. }
  61. ParticleEmitter* ParticleEmitter::create(const char* url)
  62. {
  63. Properties* properties = Properties::create(url);
  64. if (!properties)
  65. {
  66. GP_ERROR("Failed to create particle emitter from file.");
  67. return NULL;
  68. }
  69. ParticleEmitter* particle = create((strlen(properties->getNamespace()) > 0) ? properties : properties->getNextNamespace());
  70. SAFE_DELETE(properties);
  71. return particle;
  72. }
  73. ParticleEmitter* ParticleEmitter::create(Properties* properties)
  74. {
  75. if (!properties || strcmp(properties->getNamespace(), "particle") != 0)
  76. {
  77. GP_ERROR("Properties object must be non-null and have namespace equal to 'particle'.");
  78. return NULL;
  79. }
  80. Properties* sprite = properties->getNextNamespace();
  81. if (!sprite || strcmp(sprite->getNamespace(), "sprite") != 0)
  82. {
  83. GP_ERROR("Failed to load particle emitter: required namespace 'sprite' is missing.");
  84. return NULL;
  85. }
  86. // Load sprite properties.
  87. // Path to image file is required.
  88. std::string texturePath;
  89. if (!sprite->getPath("path", &texturePath))
  90. {
  91. GP_ERROR("Failed to load particle emitter: required image file path ('path') is missing.");
  92. return NULL;
  93. }
  94. const char* blendModeString = sprite->getString("blendMode");
  95. // Check for the old naming
  96. if (blendModeString == NULL)
  97. blendModeString = sprite->getString("blending");
  98. BlendMode blendMode = getBlendModeFromString(blendModeString);
  99. int spriteWidth = sprite->getInt("width");
  100. int spriteHeight = sprite->getInt("height");
  101. bool spriteAnimated = sprite->getBool("animated");
  102. bool spriteLooped = sprite->getBool("looped");
  103. int spriteFrameCount = sprite->getInt("frameCount");
  104. int spriteFrameRandomOffset = sprite->getInt("frameRandomOffset");
  105. float spriteFrameDuration = sprite->getFloat("frameDuration");
  106. // Emitter properties.
  107. unsigned int particleCountMax = (unsigned int)properties->getInt("particleCountMax");
  108. if (particleCountMax == 0)
  109. {
  110. // Set sensible default.
  111. particleCountMax = PARTICLE_COUNT_MAX;
  112. }
  113. unsigned int emissionRate = (unsigned int)properties->getInt("emissionRate");
  114. if (emissionRate == 0)
  115. {
  116. emissionRate = PARTICLE_EMISSION_RATE;
  117. }
  118. bool ellipsoid = properties->getBool("ellipsoid");
  119. float sizeStartMin = properties->getFloat("sizeStartMin");
  120. float sizeStartMax = properties->getFloat("sizeStartMax");
  121. float sizeEndMin = properties->getFloat("sizeEndMin");
  122. float sizeEndMax = properties->getFloat("sizeEndMax");
  123. long energyMin = properties->getLong("energyMin");
  124. long energyMax = properties->getLong("energyMax");
  125. Vector4 colorStart;
  126. Vector4 colorStartVar;
  127. Vector4 colorEnd;
  128. Vector4 colorEndVar;
  129. properties->getVector4("colorStart", &colorStart);
  130. properties->getVector4("colorStartVar", &colorStartVar);
  131. properties->getVector4("colorEnd", &colorEnd);
  132. properties->getVector4("colorEndVar", &colorEndVar);
  133. Vector3 position;
  134. Vector3 positionVar;
  135. Vector3 velocity;
  136. Vector3 velocityVar;
  137. Vector3 acceleration;
  138. Vector3 accelerationVar;
  139. Vector3 rotationAxis;
  140. Vector3 rotationAxisVar;
  141. properties->getVector3("position", &position);
  142. properties->getVector3("positionVar", &positionVar);
  143. properties->getVector3("velocity", &velocity);
  144. properties->getVector3("velocityVar", &velocityVar);
  145. properties->getVector3("acceleration", &acceleration);
  146. properties->getVector3("accelerationVar", &accelerationVar);
  147. float rotationPerParticleSpeedMin = properties->getFloat("rotationPerParticleSpeedMin");
  148. float rotationPerParticleSpeedMax = properties->getFloat("rotationPerParticleSpeedMax");
  149. float rotationSpeedMin = properties->getFloat("rotationSpeedMin");
  150. float rotationSpeedMax = properties->getFloat("rotationSpeedMax");
  151. properties->getVector3("rotationAxis", &rotationAxis);
  152. properties->getVector3("rotationAxisVar", &rotationAxisVar);
  153. bool orbitPosition = properties->getBool("orbitPosition");
  154. bool orbitVelocity = properties->getBool("orbitVelocity");
  155. bool orbitAcceleration = properties->getBool("orbitAcceleration");
  156. // Apply all properties to a newly created ParticleEmitter.
  157. ParticleEmitter* emitter = ParticleEmitter::create(texturePath.c_str(), blendMode, particleCountMax);
  158. if (!emitter)
  159. {
  160. GP_ERROR("Failed to create particle emitter.");
  161. return NULL;
  162. }
  163. emitter->setEmissionRate(emissionRate);
  164. emitter->setEllipsoid(ellipsoid);
  165. emitter->setSize(sizeStartMin, sizeStartMax, sizeEndMin, sizeEndMax);
  166. emitter->setEnergy(energyMin, energyMax);
  167. emitter->setColor(colorStart, colorStartVar, colorEnd, colorEndVar);
  168. emitter->setPosition(position, positionVar);
  169. emitter->setVelocity(velocity, velocityVar);
  170. emitter->setAcceleration(acceleration, accelerationVar);
  171. emitter->setRotationPerParticle(rotationPerParticleSpeedMin, rotationPerParticleSpeedMax);
  172. emitter->setRotation(rotationSpeedMin, rotationSpeedMax, rotationAxis, rotationAxisVar);
  173. emitter->setSpriteAnimated(spriteAnimated);
  174. emitter->setSpriteLooped(spriteLooped);
  175. emitter->setSpriteFrameRandomOffset(spriteFrameRandomOffset);
  176. emitter->setSpriteFrameDuration(spriteFrameDuration);
  177. emitter->setSpriteFrameCoords(spriteFrameCount, spriteWidth, spriteHeight);
  178. emitter->setOrbit(orbitPosition, orbitVelocity, orbitAcceleration);
  179. return emitter;
  180. }
  181. void ParticleEmitter::setTexture(const char* texturePath, BlendMode blendMode)
  182. {
  183. Texture* texture = Texture::create(texturePath, true);
  184. if (texture)
  185. {
  186. setTexture(texture, blendMode);
  187. texture->release();
  188. }
  189. else
  190. {
  191. GP_WARN("Failed set new texture on particle emitter: %s", texturePath);
  192. }
  193. }
  194. void ParticleEmitter::setTexture(Texture* texture, BlendMode blendMode)
  195. {
  196. // Create new batch before releasing old one, in case the same texture
  197. // is used for both (so it's not released before passing to the new batch).
  198. SpriteBatch* batch = SpriteBatch::create(texture, NULL, _particleCountMax);
  199. batch->getSampler()->setFilterMode(Texture::LINEAR_MIPMAP_LINEAR, Texture::LINEAR);
  200. // Free existing batch
  201. SAFE_DELETE(_spriteBatch);
  202. _spriteBatch = batch;
  203. _spriteBatch->getStateBlock()->setDepthWrite(false);
  204. _spriteBatch->getStateBlock()->setDepthTest(true);
  205. setBlendMode(blendMode);
  206. _spriteTextureWidth = texture->getWidth();
  207. _spriteTextureHeight = texture->getHeight();
  208. _spriteTextureWidthRatio = 1.0f / (float)texture->getWidth();
  209. _spriteTextureHeightRatio = 1.0f / (float)texture->getHeight();
  210. // By default assume only one frame which uses the entire texture.
  211. Rectangle texCoord((float)texture->getWidth(), (float)texture->getHeight());
  212. setSpriteFrameCoords(1, &texCoord);
  213. }
  214. Texture* ParticleEmitter::getTexture() const
  215. {
  216. Texture::Sampler* sampler = _spriteBatch ? _spriteBatch->getSampler() : NULL;
  217. return sampler? sampler->getTexture() : NULL;
  218. }
  219. void ParticleEmitter::setParticleCountMax(unsigned int max)
  220. {
  221. _particleCountMax = max;
  222. }
  223. unsigned int ParticleEmitter::getParticleCountMax() const
  224. {
  225. return _particleCountMax;
  226. }
  227. unsigned int ParticleEmitter::getEmissionRate() const
  228. {
  229. return _emissionRate;
  230. }
  231. void ParticleEmitter::setEmissionRate(unsigned int rate)
  232. {
  233. GP_ASSERT(rate);
  234. _emissionRate = rate;
  235. _timePerEmission = 1000.0f / (float)_emissionRate;
  236. }
  237. void ParticleEmitter::start()
  238. {
  239. _started = true;
  240. _lastUpdated = 0;
  241. }
  242. void ParticleEmitter::stop()
  243. {
  244. _started = false;
  245. }
  246. bool ParticleEmitter::isStarted() const
  247. {
  248. return _started;
  249. }
  250. bool ParticleEmitter::isActive() const
  251. {
  252. if (_started)
  253. return true;
  254. if (!_node)
  255. return false;
  256. return (_particleCount > 0);
  257. }
  258. void ParticleEmitter::emitOnce(unsigned int particleCount)
  259. {
  260. GP_ASSERT(_node);
  261. GP_ASSERT(_particles);
  262. // Limit particleCount so as not to go over _particleCountMax.
  263. if (particleCount + _particleCount > _particleCountMax)
  264. {
  265. particleCount = _particleCountMax - _particleCount;
  266. }
  267. Vector3 translation;
  268. Matrix world = _node->getWorldMatrix();
  269. world.getTranslation(&translation);
  270. // Take translation out of world matrix so it can be used to rotate orbiting properties.
  271. world.m[12] = 0.0f;
  272. world.m[13] = 0.0f;
  273. world.m[14] = 0.0f;
  274. // Emit the new particles.
  275. for (unsigned int i = 0; i < particleCount; i++)
  276. {
  277. Particle* p = &_particles[_particleCount];
  278. generateColor(_colorStart, _colorStartVar, &p->_colorStart);
  279. generateColor(_colorEnd, _colorEndVar, &p->_colorEnd);
  280. p->_color.set(p->_colorStart);
  281. p->_energy = p->_energyStart = generateScalar(_energyMin, _energyMax);
  282. p->_size = p->_sizeStart = generateScalar(_sizeStartMin, _sizeStartMax);
  283. p->_sizeEnd = generateScalar(_sizeEndMin, _sizeEndMax);
  284. p->_rotationPerParticleSpeed = generateScalar(_rotationPerParticleSpeedMin, _rotationPerParticleSpeedMax);
  285. p->_angle = generateScalar(0.0f, p->_rotationPerParticleSpeed);
  286. p->_rotationSpeed = generateScalar(_rotationSpeedMin, _rotationSpeedMax);
  287. // Only initial position can be generated within an ellipsoidal domain.
  288. generateVector(_position, _positionVar, &p->_position, _ellipsoid);
  289. generateVector(_velocity, _velocityVar, &p->_velocity, false);
  290. generateVector(_acceleration, _accelerationVar, &p->_acceleration, false);
  291. generateVector(_rotationAxis, _rotationAxisVar, &p->_rotationAxis, false);
  292. // Initial position, velocity and acceleration can all be relative to the emitter's transform.
  293. // Rotate specified properties by the node's rotation.
  294. if (_orbitPosition)
  295. {
  296. world.transformPoint(p->_position, &p->_position);
  297. }
  298. if (_orbitVelocity)
  299. {
  300. world.transformPoint(p->_velocity, &p->_velocity);
  301. }
  302. if (_orbitAcceleration)
  303. {
  304. world.transformPoint(p->_acceleration, &p->_acceleration);
  305. }
  306. // The rotation axis always orbits the node.
  307. if (p->_rotationSpeed != 0.0f && !p->_rotationAxis.isZero())
  308. {
  309. world.transformPoint(p->_rotationAxis, &p->_rotationAxis);
  310. }
  311. // Translate position relative to the node's world space.
  312. p->_position.add(translation);
  313. // Initial sprite frame.
  314. if (_spriteFrameRandomOffset > 0)
  315. {
  316. p->_frame = rand() % _spriteFrameRandomOffset;
  317. }
  318. else
  319. {
  320. p->_frame = 0;
  321. }
  322. p->_timeOnCurrentFrame = 0.0f;
  323. ++_particleCount;
  324. }
  325. }
  326. unsigned int ParticleEmitter::getParticlesCount() const
  327. {
  328. return _particleCount;
  329. }
  330. void ParticleEmitter::setEllipsoid(bool ellipsoid)
  331. {
  332. _ellipsoid = ellipsoid;
  333. }
  334. bool ParticleEmitter::isEllipsoid() const
  335. {
  336. return _ellipsoid;
  337. }
  338. void ParticleEmitter::setSize(float startMin, float startMax, float endMin, float endMax)
  339. {
  340. _sizeStartMin = startMin;
  341. _sizeStartMax = startMax;
  342. _sizeEndMin = endMin;
  343. _sizeEndMax = endMax;
  344. }
  345. float ParticleEmitter::getSizeStartMin() const
  346. {
  347. return _sizeStartMin;
  348. }
  349. float ParticleEmitter::getSizeStartMax() const
  350. {
  351. return _sizeStartMax;
  352. }
  353. float ParticleEmitter::getSizeEndMin() const
  354. {
  355. return _sizeEndMin;
  356. }
  357. float ParticleEmitter::getSizeEndMax() const
  358. {
  359. return _sizeEndMax;
  360. }
  361. void ParticleEmitter::setEnergy(long energyMin, long energyMax)
  362. {
  363. _energyMin = energyMin;
  364. _energyMax = energyMax;
  365. }
  366. long ParticleEmitter::getEnergyMin() const
  367. {
  368. return _energyMin;
  369. }
  370. long ParticleEmitter::getEnergyMax() const
  371. {
  372. return _energyMax;
  373. }
  374. void ParticleEmitter::setColor(const Vector4& startColor, const Vector4& startColorVar, const Vector4& endColor, const Vector4& endColorVar)
  375. {
  376. _colorStart.set(startColor);
  377. _colorStartVar.set(startColorVar);
  378. _colorEnd.set(endColor);
  379. _colorEndVar.set(endColorVar);
  380. }
  381. const Vector4& ParticleEmitter::getColorStart() const
  382. {
  383. return _colorStart;
  384. }
  385. const Vector4& ParticleEmitter::getColorStartVariance() const
  386. {
  387. return _colorStartVar;
  388. }
  389. const Vector4& ParticleEmitter::getColorEnd() const
  390. {
  391. return _colorEnd;
  392. }
  393. const Vector4& ParticleEmitter::getColorEndVariance() const
  394. {
  395. return _colorEndVar;
  396. }
  397. void ParticleEmitter::setPosition(const Vector3& position, const Vector3& positionVar)
  398. {
  399. _position.set(position);
  400. _positionVar.set(positionVar);
  401. }
  402. const Vector3& ParticleEmitter::getPosition() const
  403. {
  404. return _position;
  405. }
  406. const Vector3& ParticleEmitter::getPositionVariance() const
  407. {
  408. return _positionVar;
  409. }
  410. const Vector3& ParticleEmitter::getVelocity() const
  411. {
  412. return _velocity;
  413. }
  414. const Vector3& ParticleEmitter::getVelocityVariance() const
  415. {
  416. return _velocityVar;
  417. }
  418. void ParticleEmitter::setVelocity(const Vector3& velocity, const Vector3& velocityVar)
  419. {
  420. _velocity.set(velocity);
  421. _velocityVar.set(velocityVar);
  422. }
  423. const Vector3& ParticleEmitter::getAcceleration() const
  424. {
  425. return _acceleration;
  426. }
  427. const Vector3& ParticleEmitter::getAccelerationVariance() const
  428. {
  429. return _accelerationVar;
  430. }
  431. void ParticleEmitter::setAcceleration(const Vector3& acceleration, const Vector3& accelerationVar)
  432. {
  433. _acceleration.set(acceleration);
  434. _accelerationVar.set(accelerationVar);
  435. }
  436. void ParticleEmitter::setRotationPerParticle(float speedMin, float speedMax)
  437. {
  438. _rotationPerParticleSpeedMin = speedMin;
  439. _rotationPerParticleSpeedMax = speedMax;
  440. }
  441. float ParticleEmitter::getRotationPerParticleSpeedMin() const
  442. {
  443. return _rotationPerParticleSpeedMin;
  444. }
  445. float ParticleEmitter::getRotationPerParticleSpeedMax() const
  446. {
  447. return _rotationPerParticleSpeedMax;
  448. }
  449. void ParticleEmitter::setRotation(float speedMin, float speedMax, const Vector3& axis, const Vector3& axisVariance)
  450. {
  451. _rotationSpeedMin = speedMin;
  452. _rotationSpeedMax = speedMax;
  453. _rotationAxis.set(axis);
  454. _rotationAxisVar.set(axisVariance);
  455. }
  456. float ParticleEmitter::getRotationSpeedMin() const
  457. {
  458. return _rotationSpeedMin;
  459. }
  460. float ParticleEmitter::getRotationSpeedMax() const
  461. {
  462. return _rotationSpeedMax;
  463. }
  464. const Vector3& ParticleEmitter::getRotationAxis() const
  465. {
  466. return _rotationAxis;
  467. }
  468. const Vector3& ParticleEmitter::getRotationAxisVariance() const
  469. {
  470. return _rotationAxisVar;
  471. }
  472. void ParticleEmitter::setBlendMode(BlendMode blendMode)
  473. {
  474. GP_ASSERT(_spriteBatch);
  475. GP_ASSERT(_spriteBatch->getStateBlock());
  476. switch (blendMode)
  477. {
  478. case BLEND_NONE:
  479. _spriteBatch->getStateBlock()->setBlend(false);
  480. break;
  481. case BLEND_ALPHA:
  482. _spriteBatch->getStateBlock()->setBlend(true);
  483. _spriteBatch->getStateBlock()->setBlendSrc(RenderState::BLEND_SRC_ALPHA);
  484. _spriteBatch->getStateBlock()->setBlendDst(RenderState::BLEND_ONE_MINUS_SRC_ALPHA);
  485. break;
  486. case BLEND_ADDITIVE:
  487. _spriteBatch->getStateBlock()->setBlend(true);
  488. _spriteBatch->getStateBlock()->setBlendSrc(RenderState::BLEND_SRC_ALPHA);
  489. _spriteBatch->getStateBlock()->setBlendDst(RenderState::BLEND_ONE);
  490. break;
  491. case BLEND_MULTIPLIED:
  492. _spriteBatch->getStateBlock()->setBlend(true);
  493. _spriteBatch->getStateBlock()->setBlendSrc(RenderState::BLEND_ZERO);
  494. _spriteBatch->getStateBlock()->setBlendDst(RenderState::BLEND_SRC_COLOR);
  495. break;
  496. default:
  497. GP_ERROR("Unsupported blend mode (%d).", blendMode);
  498. break;
  499. }
  500. _spriteBlendMode = blendMode;
  501. }
  502. ParticleEmitter::BlendMode ParticleEmitter::getBlendMode() const
  503. {
  504. return _spriteBlendMode;
  505. }
  506. void ParticleEmitter::setSpriteAnimated(bool animated)
  507. {
  508. _spriteAnimated = animated;
  509. }
  510. bool ParticleEmitter::isSpriteAnimated() const
  511. {
  512. return _spriteAnimated;
  513. }
  514. void ParticleEmitter::setSpriteLooped(bool looped)
  515. {
  516. _spriteLooped = looped;
  517. }
  518. bool ParticleEmitter::isSpriteLooped() const
  519. {
  520. return _spriteLooped;
  521. }
  522. void ParticleEmitter::setSpriteFrameRandomOffset(int maxOffset)
  523. {
  524. _spriteFrameRandomOffset = maxOffset;
  525. }
  526. int ParticleEmitter::getSpriteFrameRandomOffset() const
  527. {
  528. return _spriteFrameRandomOffset;
  529. }
  530. void ParticleEmitter::setSpriteFrameDuration(long duration)
  531. {
  532. _spriteFrameDuration = duration;
  533. _spriteFrameDurationSecs = (float)duration / 1000.0f;
  534. }
  535. long ParticleEmitter::getSpriteFrameDuration() const
  536. {
  537. return _spriteFrameDuration;
  538. }
  539. unsigned int ParticleEmitter::getSpriteWidth() const
  540. {
  541. return (unsigned int)fabs(_spriteTextureWidth * (_spriteTextureCoords[2] - _spriteTextureCoords[0]));
  542. }
  543. unsigned int ParticleEmitter::getSpriteHeight() const
  544. {
  545. return (unsigned int)fabs(_spriteTextureHeight * (_spriteTextureCoords[3] - _spriteTextureCoords[1]));
  546. }
  547. void ParticleEmitter::setSpriteTexCoords(unsigned int frameCount, float* texCoords)
  548. {
  549. GP_ASSERT(frameCount);
  550. GP_ASSERT(texCoords);
  551. _spriteFrameCount = frameCount;
  552. _spritePercentPerFrame = 1.0f / (float)frameCount;
  553. SAFE_DELETE_ARRAY(_spriteTextureCoords);
  554. _spriteTextureCoords = new float[frameCount * 4];
  555. memcpy(_spriteTextureCoords, texCoords, frameCount * 4 * sizeof(float));
  556. }
  557. void ParticleEmitter::setSpriteFrameCoords(unsigned int frameCount, Rectangle* frameCoords)
  558. {
  559. GP_ASSERT(frameCount);
  560. GP_ASSERT(frameCoords);
  561. _spriteFrameCount = frameCount;
  562. _spritePercentPerFrame = 1.0f / (float)frameCount;
  563. SAFE_DELETE_ARRAY(_spriteTextureCoords);
  564. _spriteTextureCoords = new float[frameCount * 4];
  565. // Pre-compute texture coordinates from rects.
  566. for (unsigned int i = 0; i < frameCount; i++)
  567. {
  568. _spriteTextureCoords[i*4] = _spriteTextureWidthRatio * frameCoords[i].x;
  569. _spriteTextureCoords[i*4 + 1] = 1.0f - _spriteTextureHeightRatio * frameCoords[i].y;
  570. _spriteTextureCoords[i*4 + 2] = _spriteTextureCoords[i*4] + _spriteTextureWidthRatio * frameCoords[i].width;
  571. _spriteTextureCoords[i*4 + 3] = _spriteTextureCoords[i*4 + 1] - _spriteTextureHeightRatio * frameCoords[i].height;
  572. }
  573. }
  574. void ParticleEmitter::setSpriteFrameCoords(unsigned int frameCount, int width, int height)
  575. {
  576. GP_ASSERT(width);
  577. GP_ASSERT(height);
  578. Rectangle* frameCoords = new Rectangle[frameCount];
  579. unsigned int cols = _spriteTextureWidth / width;
  580. unsigned int rows = _spriteTextureHeight / height;
  581. unsigned int n = 0;
  582. for (unsigned int i = 0; i < rows; ++i)
  583. {
  584. int y = i * height;
  585. for (unsigned int j = 0; j < cols; ++j)
  586. {
  587. int x = j * width;
  588. frameCoords[i*cols + j] = Rectangle(x, y, width, height);
  589. if (++n == frameCount)
  590. {
  591. break;
  592. }
  593. }
  594. if (n == frameCount)
  595. {
  596. break;
  597. }
  598. }
  599. setSpriteFrameCoords(frameCount, frameCoords);
  600. SAFE_DELETE_ARRAY(frameCoords);
  601. }
  602. unsigned int ParticleEmitter::getSpriteFrameCount() const
  603. {
  604. return _spriteFrameCount;
  605. }
  606. Node* ParticleEmitter::getNode() const
  607. {
  608. return _node;
  609. }
  610. void ParticleEmitter::setNode(Node* node)
  611. {
  612. // Connect the new node.
  613. _node = node;
  614. }
  615. void ParticleEmitter::setOrbit(bool orbitPosition, bool orbitVelocity, bool orbitAcceleration)
  616. {
  617. _orbitPosition = orbitPosition;
  618. _orbitVelocity = orbitVelocity;
  619. _orbitAcceleration = orbitAcceleration;
  620. }
  621. bool ParticleEmitter::getOrbitPosition() const
  622. {
  623. return _orbitPosition;
  624. }
  625. bool ParticleEmitter::getOrbitVelocity() const
  626. {
  627. return _orbitVelocity;
  628. }
  629. bool ParticleEmitter::getOrbitAcceleration() const
  630. {
  631. return _orbitAcceleration;
  632. }
  633. long ParticleEmitter::generateScalar(long min, long max)
  634. {
  635. // Note: this is not a very good RNG, but it should be suitable for our purposes.
  636. long r = 0;
  637. for (unsigned int i = 0; i < sizeof(long)/sizeof(int); i++)
  638. {
  639. r = r << 8; // sizeof(int) * CHAR_BITS
  640. r |= rand();
  641. }
  642. // Now we have a random long between 0 and MAX_LONG. We need to clamp it between min and max.
  643. r %= max - min;
  644. r += min;
  645. return r;
  646. }
  647. float ParticleEmitter::generateScalar(float min, float max)
  648. {
  649. return min + (max - min) * MATH_RANDOM_0_1();
  650. }
  651. void ParticleEmitter::generateVectorInRect(const Vector3& base, const Vector3& variance, Vector3* dst)
  652. {
  653. GP_ASSERT(dst);
  654. // Scale each component of the variance vector by a random float
  655. // between -1 and 1, then add this to the corresponding base component.
  656. dst->x = base.x + variance.x * MATH_RANDOM_MINUS1_1();
  657. dst->y = base.y + variance.y * MATH_RANDOM_MINUS1_1();
  658. dst->z = base.z + variance.z * MATH_RANDOM_MINUS1_1();
  659. }
  660. void ParticleEmitter::generateVectorInEllipsoid(const Vector3& center, const Vector3& scale, Vector3* dst)
  661. {
  662. GP_ASSERT(dst);
  663. // Generate a point within a unit cube, then reject if the point is not in a unit sphere.
  664. do
  665. {
  666. dst->x = MATH_RANDOM_MINUS1_1();
  667. dst->y = MATH_RANDOM_MINUS1_1();
  668. dst->z = MATH_RANDOM_MINUS1_1();
  669. } while (dst->length() > 1.0f);
  670. // Scale this point by the scaling vector.
  671. dst->x *= scale.x;
  672. dst->y *= scale.y;
  673. dst->z *= scale.z;
  674. // Translate by the center point.
  675. dst->add(center);
  676. }
  677. void ParticleEmitter::generateVector(const Vector3& base, const Vector3& variance, Vector3* dst, bool ellipsoid)
  678. {
  679. if (ellipsoid)
  680. {
  681. generateVectorInEllipsoid(base, variance, dst);
  682. }
  683. else
  684. {
  685. generateVectorInRect(base, variance, dst);
  686. }
  687. }
  688. void ParticleEmitter::generateColor(const Vector4& base, const Vector4& variance, Vector4* dst)
  689. {
  690. GP_ASSERT(dst);
  691. // Scale each component of the variance color by a random float
  692. // between -1 and 1, then add this to the corresponding base component.
  693. dst->x = base.x + variance.x * MATH_RANDOM_MINUS1_1();
  694. dst->y = base.y + variance.y * MATH_RANDOM_MINUS1_1();
  695. dst->z = base.z + variance.z * MATH_RANDOM_MINUS1_1();
  696. dst->w = base.w + variance.w * MATH_RANDOM_MINUS1_1();
  697. }
  698. ParticleEmitter::BlendMode ParticleEmitter::getBlendModeFromString(const char* str)
  699. {
  700. GP_ASSERT(str);
  701. if (strcmp(str, "BLEND_NONE") == 0 || strcmp(str, "NONE") == 0 )
  702. {
  703. return BLEND_NONE;
  704. }
  705. else if (strcmp(str, "BLEND_ALPHA") == 0 || strcmp(str, "ALPHA") == 0 )
  706. {
  707. return BLEND_ALPHA;
  708. }
  709. else if (strcmp(str, "BLEND_ADDITIVE") == 0 || strcmp(str, "ADDITIVE") == 0)
  710. {
  711. return BLEND_ADDITIVE;
  712. }
  713. else if (strcmp(str, "BLEND_MULTIPLIED") == 0 || strcmp(str, "MULTIPLIED") == 0)
  714. {
  715. return BLEND_MULTIPLIED;
  716. }
  717. else
  718. {
  719. return BLEND_ALPHA;
  720. }
  721. }
  722. void ParticleEmitter::update(float elapsedTime)
  723. {
  724. if (!isActive())
  725. return;
  726. // Cap particle updates at a maximum rate. This saves processing
  727. // and also improves precision since updating with very small
  728. // time increments is more lossy.
  729. static double runningTime = 0;
  730. runningTime += elapsedTime;
  731. if (runningTime < PARTICLE_UPDATE_RATE_MAX)
  732. return;
  733. float elapsedMs = runningTime;
  734. runningTime = 0;
  735. float elapsedSecs = elapsedMs * 0.001f;
  736. if (_started && _emissionRate)
  737. {
  738. // Calculate how much time has passed since we last emitted particles.
  739. _emitTime += elapsedMs; //+= elapsedTime;
  740. // How many particles should we emit this frame?
  741. GP_ASSERT(_timePerEmission);
  742. unsigned int emitCount = (unsigned int)(_emitTime / _timePerEmission);
  743. if (emitCount)
  744. {
  745. if ((int)_timePerEmission > 0)
  746. {
  747. _emitTime = fmod((double)_emitTime, (double)_timePerEmission);
  748. }
  749. emitOnce(emitCount);
  750. }
  751. }
  752. // Now update all currently living particles.
  753. GP_ASSERT(_particles);
  754. for (unsigned int particlesIndex = 0; particlesIndex < _particleCount; ++particlesIndex)
  755. {
  756. Particle* p = &_particles[particlesIndex];
  757. p->_energy -= elapsedMs;
  758. if (p->_energy > 0L)
  759. {
  760. if (p->_rotationSpeed != 0.0f && !p->_rotationAxis.isZero())
  761. {
  762. Matrix::createRotation(p->_rotationAxis, p->_rotationSpeed * elapsedSecs, &_rotation);
  763. _rotation.transformPoint(p->_velocity, &p->_velocity);
  764. _rotation.transformPoint(p->_acceleration, &p->_acceleration);
  765. }
  766. // Particle is still alive.
  767. p->_velocity.x += p->_acceleration.x * elapsedSecs;
  768. p->_velocity.y += p->_acceleration.y * elapsedSecs;
  769. p->_velocity.z += p->_acceleration.z * elapsedSecs;
  770. p->_position.x += p->_velocity.x * elapsedSecs;
  771. p->_position.y += p->_velocity.y * elapsedSecs;
  772. p->_position.z += p->_velocity.z * elapsedSecs;
  773. p->_angle += p->_rotationPerParticleSpeed * elapsedSecs;
  774. // Simple linear interpolation of color and size.
  775. float percent = 1.0f - ((float)p->_energy / (float)p->_energyStart);
  776. p->_color.x = p->_colorStart.x + (p->_colorEnd.x - p->_colorStart.x) * percent;
  777. p->_color.y = p->_colorStart.y + (p->_colorEnd.y - p->_colorStart.y) * percent;
  778. p->_color.z = p->_colorStart.z + (p->_colorEnd.z - p->_colorStart.z) * percent;
  779. p->_color.w = p->_colorStart.w + (p->_colorEnd.w - p->_colorStart.w) * percent;
  780. p->_size = p->_sizeStart + (p->_sizeEnd - p->_sizeStart) * percent;
  781. // Handle sprite animations.
  782. if (_spriteAnimated)
  783. {
  784. if (!_spriteLooped)
  785. {
  786. // The last frame should finish exactly when the particle dies.
  787. float percentSpent = 0.0f;
  788. for (unsigned int i = 0; i < p->_frame; i++)
  789. {
  790. percentSpent += _spritePercentPerFrame;
  791. }
  792. p->_timeOnCurrentFrame = percent - percentSpent;
  793. if (p->_frame < _spriteFrameCount - 1 &&
  794. p->_timeOnCurrentFrame >= _spritePercentPerFrame)
  795. {
  796. ++p->_frame;
  797. }
  798. }
  799. else
  800. {
  801. // _spriteFrameDurationSecs is an absolute time measured in seconds,
  802. // and the animation repeats indefinitely.
  803. p->_timeOnCurrentFrame += elapsedSecs;
  804. if (p->_timeOnCurrentFrame >= _spriteFrameDurationSecs)
  805. {
  806. p->_timeOnCurrentFrame -= _spriteFrameDurationSecs;
  807. ++p->_frame;
  808. if (p->_frame == _spriteFrameCount)
  809. {
  810. p->_frame = 0;
  811. }
  812. }
  813. }
  814. }
  815. }
  816. else
  817. {
  818. // Particle is dead. Move the particle furthest from the start of the array
  819. // down to take its place, and re-use the slot at the end of the list of living particles.
  820. if (particlesIndex != _particleCount - 1)
  821. {
  822. _particles[particlesIndex] = _particles[_particleCount - 1];
  823. }
  824. --_particleCount;
  825. }
  826. }
  827. }
  828. unsigned int ParticleEmitter::draw()
  829. {
  830. if (!isActive())
  831. return 0;
  832. if (_particleCount > 0)
  833. {
  834. GP_ASSERT(_spriteBatch);
  835. GP_ASSERT(_particles);
  836. GP_ASSERT(_spriteTextureCoords);
  837. // Set our node's view projection matrix to this emitter's effect.
  838. if (_node)
  839. {
  840. _spriteBatch->setProjectionMatrix(_node->getViewProjectionMatrix());
  841. }
  842. // Begin sprite batch drawing
  843. _spriteBatch->start();
  844. // 2D Rotation.
  845. static const Vector2 pivot(0.5f, 0.5f);
  846. // 3D Rotation so that particles always face the camera.
  847. GP_ASSERT(_node && _node->getScene() && _node->getScene()->getActiveCamera() && _node->getScene()->getActiveCamera()->getNode());
  848. const Matrix& cameraWorldMatrix = _node->getScene()->getActiveCamera()->getNode()->getWorldMatrix();
  849. Vector3 right;
  850. cameraWorldMatrix.getRightVector(&right);
  851. Vector3 up;
  852. cameraWorldMatrix.getUpVector(&up);
  853. for (unsigned int i = 0; i < _particleCount; i++)
  854. {
  855. Particle* p = &_particles[i];
  856. _spriteBatch->draw(p->_position, right, up, p->_size, p->_size,
  857. _spriteTextureCoords[p->_frame * 4], _spriteTextureCoords[p->_frame * 4 + 1], _spriteTextureCoords[p->_frame * 4 + 2], _spriteTextureCoords[p->_frame * 4 + 3],
  858. p->_color, pivot, p->_angle);
  859. }
  860. // Render.
  861. _spriteBatch->finish();
  862. }
  863. return 1;
  864. }
  865. ParticleEmitter* ParticleEmitter::clone()
  866. {
  867. // Create a clone of this emitter
  868. ParticleEmitter* emitter = ParticleEmitter::create(_spriteBatch->getSampler()->getTexture(),
  869. _spriteBlendMode, _particleCountMax);
  870. // Copy all properties to the clone
  871. emitter->setEmissionRate(_emissionRate);
  872. emitter->_ellipsoid = _ellipsoid;
  873. emitter->_sizeStartMin = _sizeStartMin;
  874. emitter->_sizeStartMax = _sizeStartMax;
  875. emitter->_sizeEndMin = _sizeEndMin;
  876. emitter->_sizeEndMax = _sizeEndMax;
  877. emitter->_energyMin = _energyMin;
  878. emitter->_energyMax = _energyMax;
  879. emitter->_colorStart = _colorStart;
  880. emitter->_colorStartVar = _colorStartVar;
  881. emitter->_colorEnd = _colorEnd;
  882. emitter->_colorEndVar = _colorEndVar;
  883. emitter->_position = _position;
  884. emitter->_positionVar = _positionVar;
  885. emitter->_velocity = _velocity;
  886. emitter->_velocityVar = _velocityVar;
  887. emitter->_acceleration = _acceleration;
  888. emitter->_accelerationVar = _accelerationVar;
  889. emitter->_rotationPerParticleSpeedMin = _rotationPerParticleSpeedMin;
  890. emitter->_rotationPerParticleSpeedMax = _rotationPerParticleSpeedMax;
  891. emitter->_rotationSpeedMin = _rotationSpeedMin;
  892. emitter->_rotationSpeedMax = _rotationSpeedMax;
  893. emitter->_rotationAxis = _rotationAxis;
  894. emitter->_rotationAxisVar = _rotationAxisVar;
  895. emitter->setSpriteTexCoords(_spriteFrameCount, _spriteTextureCoords);
  896. emitter->_spriteAnimated = _spriteAnimated;
  897. emitter->_spriteLooped = _spriteLooped;
  898. emitter->_spriteFrameRandomOffset = _spriteFrameRandomOffset;
  899. emitter->setSpriteFrameDuration(_spriteFrameDuration);
  900. emitter->_orbitPosition = _orbitPosition;
  901. emitter->_orbitVelocity = _orbitVelocity;
  902. emitter->_orbitAcceleration = _orbitAcceleration;
  903. return emitter;
  904. }
  905. }