ParticleEngine.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. /*
  2. * Copyright (c) 2011 Nokia Corporation.
  3. */
  4. #include "PongApp.h"
  5. #include <memory.h>
  6. #include "ParticleEngine.h"
  7. #include <math.h>
  8. #include <stdlib.h>
  9. /**
  10. * Particle
  11. */
  12. Particle::Particle() {
  13. memset( m_pos, 0, sizeof(int)*3);
  14. memset( m_dir, 0, sizeof(int)*3);
  15. };
  16. Particle::~Particle() {
  17. };
  18. void Particle::run( ParticleEngine *engine, int *fixedGravity, int fixedFrameTime ) {
  19. // Move
  20. m_pos[0] += (((m_dir[0]>>2) * fixedFrameTime)>>10);
  21. m_pos[1] += (((m_dir[1]>>2) * fixedFrameTime)>>10);
  22. m_pos[2] += (((m_dir[2]>>2) * fixedFrameTime)>>10);
  23. // Fraction
  24. int te = ((m_type->m_fraction * fixedFrameTime)>>12);
  25. if (te>4096) te = 4096;
  26. m_dir[0] -= (((m_dir[0]>>2) * te ) >> 10);
  27. m_dir[1] -= (((m_dir[1]>>2) * te ) >> 10);
  28. m_dir[2] -= (((m_dir[2]>>2) * te ) >> 10);
  29. // Gravity
  30. /*
  31. m_dir[1] -= (((m_type->m_gravity>>2)*fixedFrameTime)>>10);
  32. */
  33. m_dir[0] += (((fixedGravity[0]>>2) * (fixedFrameTime>>2))>>12);
  34. m_dir[1] += (((fixedGravity[1]>>2) * (fixedFrameTime>>2))>>12);
  35. m_dir[2] += (((fixedGravity[2]>>2) * (fixedFrameTime>>2))>>12);
  36. // Size increment
  37. m_size += (((m_sizeInc>>4)*fixedFrameTime)>>8);
  38. // Angle increment
  39. m_angle += (((m_angleInc>>4)*fixedFrameTime)>>8);
  40. // Second phase increments for size and angle increments.
  41. m_sizeInc += ((m_type->m_sizeIncInc*fixedFrameTime));
  42. m_angleInc += ((m_type->m_angleIncInc*fixedFrameTime));
  43. m_lifeTime-=fixedFrameTime;
  44. m_aliveCounter+=fixedFrameTime;
  45. // Particle is dead if size has been dropped below one.
  46. if (m_size<1<<12) m_lifeTime = 0;
  47. };
  48. /*
  49. * ParticleType
  50. */
  51. ParticleType::ParticleType(unsigned int tid ) {
  52. textureID = tid;
  53. m_angle = 0;
  54. m_angleRandom = 0;
  55. m_angleInc = 0;
  56. m_angleIncRandom = 0;
  57. m_size = 4096;
  58. m_sizeRandom = 0;
  59. m_sizeInc = 0;
  60. m_sizeIncRandom = 0;
  61. m_lifeTime = 4096;
  62. m_lifeTimeRandom = 0;
  63. m_fraction = 0;
  64. m_gravity = 0;
  65. m_angleIncInc = 0;
  66. m_sizeIncInc = 0;
  67. m_fadeOutTimeSecs = 1.0f/2000.0f;
  68. m_additiveParticle = true;
  69. setVisibility( 0.0f, 0.5f, 1.0f );
  70. col[0] = 1.0f;
  71. col[1] = 1.0f;
  72. col[2] = 1.0f;
  73. col_random[0] = 0.0f;
  74. col_random[1] = 0.0f;
  75. col_random[2] = 0.0f;
  76. };
  77. void ParticleType::setVisibility( float fadeInTime,
  78. float fadeOutTime,
  79. float generalVisibility ) {
  80. m_fadeOutTimeSecs = 1.0f / (fadeOutTime);
  81. m_fadeInTimeSecs = 1.0f / (fadeInTime);
  82. m_generalVisibility = generalVisibility;
  83. };
  84. void ParticleType::setColors( float r, float g, float b,
  85. float rr, float gr, float br ) {
  86. col[0] = r;
  87. col[1] = g;
  88. col[2] = b;
  89. col_random[0] = rr;
  90. col_random[1] = gr;
  91. col_random[2] = br;
  92. };
  93. ParticleType::~ParticleType() {
  94. };
  95. /*
  96. * ParticleEngine
  97. */
  98. ParticleEngine::ParticleEngine( int maxParticles ) {
  99. m_particles = new Particle[ maxParticles ];
  100. memset( m_particles, 0, sizeof( Particle ) * maxParticles );
  101. m_maxParticles = maxParticles;
  102. m_currentParticle = 0;
  103. };
  104. ParticleEngine::~ParticleEngine() {
  105. delete [] m_particles;
  106. };
  107. void ParticleEngine::render( SpriteBatch *batch, ParticleType *renderType ) {
  108. if (renderType==0) return;
  109. SpriteDrawInfo sdi;
  110. float ftemp;
  111. Particle *p = m_particles;
  112. Particle *p_target = m_particles + m_maxParticles;
  113. #ifdef EPONG_DEBUG
  114. while (p!=p_target) {
  115. if (p->m_type==renderType) {
  116. sdi.setTargetPos( (float)m_gravity[0]/40000.0f, (float)m_gravity[1]/80000.0f);
  117. sdi.textureHandle = p->m_type->textureID;
  118. sdi.setScale( 0.25f );
  119. sdi.setColor( 255.0f, 255.0f, 255.0f, 0.5f);
  120. sdi.a = 0.5f;
  121. batch->draw( &sdi);
  122. break;
  123. }
  124. p++;
  125. }
  126. p = m_particles;
  127. #endif
  128. while (p!=p_target) {
  129. if (p->m_type==renderType && p->m_lifeTime>0) {
  130. sdi.setTargetPos( (float)p->m_pos[0]/4096.0f, (float)p->m_pos[1]/4096.0f );
  131. sdi.textureHandle = p->m_type->textureID;
  132. sdi.setScale( (float)p->m_size * 2.0f / 409600.0f, (float)p->m_size * 2.0f / 409600.0f );
  133. sdi.setColor( (float)((p->color>>0)&255)/255.0f, (float)((p->color>>8)&255)/255.0f, (float)((p->color>>16)&255)/255.0f, 1.0f);
  134. sdi.a = p->m_type->m_generalVisibility*(float)p->m_lifeTime/(65536.0f/4.0f)*p->m_type->m_fadeOutTimeSecs;
  135. ftemp = ((float)p->m_aliveCounter / (65536.0f/4.0f)) * p->m_type->m_fadeInTimeSecs;
  136. if (sdi.a == p->m_type->m_generalVisibility)
  137. sdi.a = p->m_type->m_generalVisibility;
  138. if (ftemp<sdi.a) sdi.a = ftemp;
  139. batch->draw( &sdi );
  140. };
  141. p++;
  142. };
  143. }
  144. void ParticleEngine::run( float frameTime ) {
  145. // -> 12bit fixedpoint
  146. int fixedFrameTime = (int)( frameTime * 4096.0f );
  147. Particle *p = m_particles;
  148. Particle *p_target = p+m_maxParticles;
  149. while (p!=p_target) {
  150. if (p->m_lifeTime>0) p->run( this, m_gravity, fixedFrameTime );
  151. p++;
  152. };
  153. }
  154. void ParticleEngine::emitParticles( int count,
  155. ParticleType *type,
  156. float *pos,
  157. float posRandom,
  158. float *dir,
  159. float dirRandom ) {
  160. int fixed_p[3];
  161. int fixed_d[3];
  162. int fixedPosRandom = (int)( posRandom*256.0f );
  163. int fixedDirRandom = (int)( dirRandom*256.0f );
  164. fixed_p[0] = (int)(pos[0]*4096.0f);
  165. fixed_p[1] = (int)(pos[1]*4096.0f);
  166. fixed_p[2] = (int)(pos[2]*4096.0f);
  167. if (dir) {
  168. fixed_d[0] = (int)(dir[0]*4096.0f);
  169. fixed_d[1] = (int)(dir[1]*4096.0f);
  170. fixed_d[2] = (int)(dir[2]*4096.0f);
  171. } else memset( fixed_d, 0, sizeof( int ) *3 );
  172. int fixed_r[3];
  173. int temp;
  174. float c[3];
  175. Particle *p;
  176. while (count>0) {
  177. p = m_particles + m_currentParticle;
  178. p->m_type = type;
  179. p->m_aliveCounter = 0;
  180. // create a random vector
  181. fixed_r[0] = (rand()&255)-128;
  182. fixed_r[1] = (rand()&255)-128;
  183. fixed_r[2] = (rand()&255)-128;
  184. temp = (int)sqrtf( fixed_r[0] * fixed_r[0]
  185. + fixed_r[1]*fixed_r[1]
  186. + fixed_r[2]*fixed_r[2] );
  187. if (temp>0) {
  188. fixed_r[0] = (fixed_r[0]<<16)/temp;
  189. fixed_r[1] = (fixed_r[1]<<16)/temp;
  190. fixed_r[2] = (fixed_r[2]<<16)/temp;
  191. }
  192. // random vector is
  193. // position
  194. p->m_pos[0] = ((fixed_r[0]*fixedPosRandom)>>12) + fixed_p[0];
  195. p->m_pos[1] = ((fixed_r[1]*fixedPosRandom)>>12) + fixed_p[1];
  196. p->m_pos[2] = ((fixed_r[2]*fixedPosRandom)>>12) + fixed_p[2];
  197. // direction
  198. p->m_dir[0] = ((fixed_r[0]*fixedDirRandom)>>12) + fixed_d[0];
  199. p->m_dir[1] = ((fixed_r[1]*fixedDirRandom)>>12) + fixed_d[1];
  200. p->m_dir[2] = ((fixed_r[2]*fixedDirRandom)>>12) + fixed_d[2];
  201. //p->m_dir[0] = 800000;
  202. //p->m_dir[1] = 0;
  203. //p->m_dir[2] = 0;
  204. p->m_angle = type->m_angle
  205. + (((rand()&255)*type->m_angleRandom) >> 8);
  206. p->m_angleInc = type->m_angleInc
  207. + (((rand()&255)*type->m_angleIncRandom) >> 8);
  208. p->m_size = type->m_size
  209. + (((rand()&255)*type->m_sizeRandom) >> 8);
  210. p->m_sizeInc = type->m_sizeInc
  211. + (((rand()&255)*type->m_sizeIncRandom) >> 8);
  212. p->m_lifeTime = type->m_lifeTime
  213. + (((rand()&255)*type->m_lifeTimeRandom) >> 8);
  214. // colro
  215. c[0] = type->col[0]+((float)(rand()&255)/255.0f)*type->col_random[0];
  216. c[1] = type->col[1]+((float)(rand()&255)/255.0f)*type->col_random[1];
  217. c[2] = type->col[2]+((float)(rand()&255)/255.0f)*type->col_random[2];
  218. if (c[0]>1.0f) c[0] = 1.0f; if (c[0]<0.0f) c[0] = 0.0f;
  219. if (c[1]>1.0f) c[1] = 1.0f; if (c[1]<0.0f) c[1] = 0.0f;
  220. if (c[2]>1.0f) c[2] = 1.0f; if (c[2]<0.0f) c[2] = 0.0f;
  221. p->color = (unsigned int)(c[0]*255.0f)
  222. | ((unsigned int)(c[1]*255.0f)<<8)
  223. | ((unsigned int)(c[2]*255.0f)<<16);
  224. count--;
  225. m_currentParticle++;
  226. if (m_currentParticle>=m_maxParticles) m_currentParticle = 0;
  227. };
  228. }