ParticleEmitter.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. #include "ParticleEmitter.h"
  2. #include "Renderer.h"
  3. #include "PhyCommon.h"
  4. #include "App.h"
  5. #include "Scene.h"
  6. //=====================================================================================================================================
  7. // render =
  8. //=====================================================================================================================================
  9. void ParticleEmitter::Particle::render()
  10. {
  11. if( lifeTillDeath < 0 ) return;
  12. glPushMatrix();
  13. R::multMatrix( getWorldTransform() );
  14. glBegin( GL_POINTS );
  15. glVertex3fv( &(Vec3(0.0))[0] );
  16. glEnd();
  17. glPopMatrix();
  18. }
  19. //=====================================================================================================================================
  20. // init =
  21. //=====================================================================================================================================
  22. void ParticleEmitter::init( const char* filename )
  23. {
  24. // dummy props init
  25. maxParticleLife = 400;
  26. minParticleLife = 100;
  27. minDirection = Vec3( -0.1, 1.0, 0.0 );
  28. maxDirection = Vec3( 0.1, 1.0, 0.0 );
  29. minForceMagnitude = 1.0;
  30. maxForceMagnitude = 2.0;
  31. minParticleMass = 1.0;
  32. maxParticleMass = 2.0;
  33. minGravity = Vec3( 0.0, 0.0, 0.0 );
  34. minGravity = Vec3( 0.0, -1.0, 0.0 );
  35. minStartingPos = Vec3( -1.0, -1.0, -1.0 );
  36. maxStartingPos = Vec3( 1.0, 1.0, 1.0 );
  37. maxNumOfParticles = 5;
  38. emittionPeriod = 1000;
  39. // init the particles
  40. btCollisionShape* colShape = new btSphereShape( 0.1 );
  41. particles.resize( maxNumOfParticles );
  42. for( uint i=0; i<maxNumOfParticles; i++ )
  43. {
  44. particles[i] = new Particle;
  45. float mass = Util::randRange( minParticleMass, maxParticleMass );
  46. btRigidBody* body = app->getScene()->getPhyWorld()->createNewRigidBody( mass, Transform::getIdentity(), colShape, particles[i],
  47. PhyWorld::CG_PARTICLE, PhyWorld::CG_MAP );
  48. body->forceActivationState( DISABLE_SIMULATION );
  49. }
  50. /*btDiscreteDynamicsWorld* btWorld = app->getScene()->getPhyWorld()->getDynamicsWorld();
  51. btWorld->getBroadphase()->resetPool( btWorld->getDispatcher() );
  52. btWorld->getConstraintSolver()->reset();*/
  53. }
  54. //=====================================================================================================================================
  55. // update =
  56. //=====================================================================================================================================
  57. void ParticleEmitter::update()
  58. {
  59. uint crntTime = app->getTicks();
  60. // decrease particle life and deactivate the dead particles
  61. for( Vec<Particle*>::iterator it=particles.begin(); it!=particles.end(); ++it )
  62. {
  63. Particle* part = *it;
  64. if( part->lifeTillDeath < 0 ) continue; // its already dead so dont deactivate it again
  65. part->lifeTillDeath -= crntTime-timeOfPrevUpdate;
  66. if( part->lifeTillDeath < 1 )
  67. {
  68. part->body->setActivationState( DISABLE_SIMULATION );
  69. }
  70. }
  71. // emit new particles
  72. DEBUG_ERR( particlesPerEmittion == 0 );
  73. if( (crntTime - timeOfPrevEmittion) > emittionPeriod )
  74. {
  75. uint partNum = 0;
  76. for( Vec<Particle*>::iterator it=particles.begin(); it!=particles.end(); ++it )
  77. {
  78. Particle* part = *it;
  79. if( part->lifeTillDeath > 0 ) continue; // its alive so skip it
  80. // reinit a dead particle
  81. //
  82. // activate it (Bullet stuff)
  83. part->body->forceActivationState( ACTIVE_TAG );
  84. part->body->clearForces();
  85. // life
  86. if( minParticleLife != maxParticleLife )
  87. part->lifeTillDeath = Util::randRange( minParticleLife, maxParticleLife );
  88. else
  89. part->lifeTillDeath = minParticleLife;
  90. // force
  91. Vec3 forceDir;
  92. if( minDirection != maxDirection )
  93. {
  94. forceDir = Vec3( Util::randRange( minDirection.x , maxDirection.x ), Util::randRange( minDirection.y , maxDirection.y ),
  95. Util::randRange( minDirection.z , maxDirection.z ) );
  96. }
  97. else
  98. {
  99. forceDir = minDirection;
  100. }
  101. forceDir.normalize();
  102. if( minForceMagnitude != maxForceMagnitude )
  103. part->body->applyCentralForce( toBt( forceDir * Util::randRange( minForceMagnitude, maxForceMagnitude ) ) );
  104. else
  105. part->body->applyCentralForce( toBt( forceDir * minForceMagnitude ) );
  106. // gravity
  107. Vec3 grav;
  108. if( minGravity != maxGravity )
  109. {
  110. grav = Vec3( Util::randRange(minGravity.x,maxGravity.x), Util::randRange(minGravity.y,maxGravity.y),
  111. Util::randRange(minGravity.z,maxGravity.z) );
  112. }
  113. else
  114. {
  115. grav = minGravity;
  116. }
  117. part->body->setGravity( toBt( grav ) );
  118. // starting pos
  119. Vec3 pos;
  120. if( minStartingPos != maxStartingPos )
  121. {
  122. pos = Vec3( Util::randRange(minStartingPos.x,maxStartingPos.x), Util::randRange(minStartingPos.y,maxStartingPos.y),
  123. Util::randRange(minStartingPos.z,maxStartingPos.z) );
  124. }
  125. else
  126. {
  127. pos = minStartingPos;
  128. }
  129. pos += getWorldTransform().getOrigin();
  130. part->body->setWorldTransform( toBt( Mat4( pos, Mat3::getIdentity(), 1.0 ) ) );
  131. // do the rest
  132. ++partNum;
  133. if( partNum >= particlesPerEmittion ) break;
  134. } // end for all particles
  135. timeOfPrevEmittion = crntTime;
  136. } // end if can emit
  137. timeOfPrevUpdate = crntTime;
  138. }
  139. //=====================================================================================================================================
  140. // render =
  141. //=====================================================================================================================================
  142. void ParticleEmitter::render()
  143. {
  144. float vertPositions[] = { maxStartingPos.x, maxStartingPos.y, maxStartingPos.z, // right top front
  145. minStartingPos.x, maxStartingPos.y, maxStartingPos.z, // left top front
  146. minStartingPos.x, minStartingPos.y, maxStartingPos.z, // left bottom front
  147. maxStartingPos.x, minStartingPos.y, maxStartingPos.z, // right bottom front
  148. maxStartingPos.x, maxStartingPos.y, minStartingPos.z, // right top back
  149. minStartingPos.x, maxStartingPos.y, minStartingPos.z, // left top back
  150. minStartingPos.x, minStartingPos.y, minStartingPos.z, // left bottom back
  151. maxStartingPos.x, minStartingPos.y, minStartingPos.z }; // right bottom back
  152. uint vertIndices [] = { 0, 1, 1, 2, 2, 3, 3, 0, 4, 5, 5, 6, 6, 7, 7, 4, 0, 4, 1, 5, 3, 7, 2, 6 };
  153. glPushMatrix();
  154. R::multMatrix( getWorldTransform() );
  155. R::color3( Vec3(1.0) );
  156. /*glEnableClientState( GL_VERTEX_ARRAY );
  157. glVertexPointer( 3, GL_FLOAT, 0, vertPositions );
  158. glDrawElements( GL_LINES, sizeof(vertIndices)/sizeof(uint), GL_UNSIGNED_INT, vertIndices );
  159. glDisableClientState( GL_VERTEX_ARRAY );*/
  160. R::Dbg::renderCube();
  161. glPopMatrix();
  162. }