ParticleEmitter.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  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( transformationWspace );
  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. btVector3 localInertia;
  47. colShape->calculateLocalInertia( mass, localInertia );
  48. MotionState* mState = new MotionState( btTransform::getIdentity(), particles[i] );
  49. btRigidBody::btRigidBodyConstructionInfo rbInfo( mass, mState, colShape, localInertia );
  50. btRigidBody* body = new btRigidBody( rbInfo );
  51. particles[i]->body = body;
  52. app->scene->getPhyWorld()->getDynamicsWorld()->addRigidBody( body, PhyWorld::CG_PARTICLE, PhyWorld::CG_MAP );
  53. body->forceActivationState( DISABLE_SIMULATION );
  54. }
  55. }
  56. //=====================================================================================================================================
  57. // update =
  58. //=====================================================================================================================================
  59. void ParticleEmitter::update()
  60. {
  61. uint crntTime = app->getTicks();
  62. // decrease particle life and deactivate the dead particles
  63. for( Vec<Particle*>::iterator it=particles.begin(); it!=particles.end(); ++it )
  64. {
  65. Particle* part = *it;
  66. if( part->lifeTillDeath < 0 ) continue; // its already dead so dont deactivate it again
  67. part->lifeTillDeath -= crntTime-timeOfPrevUpdate;
  68. if( part->lifeTillDeath < 1 )
  69. {
  70. part->body->setActivationState( DISABLE_SIMULATION );
  71. }
  72. }
  73. // emit new particles
  74. DEBUG_ERR( particlesPerEmittion == 0 );
  75. if( (crntTime - timeOfPrevEmittion) > emittionPeriod )
  76. {
  77. uint partNum = 0;
  78. for( Vec<Particle*>::iterator it=particles.begin(); it!=particles.end(); ++it )
  79. {
  80. Particle* part = *it;
  81. if( part->lifeTillDeath > 0 ) continue; // its alive so skip it
  82. // reinit a dead particle
  83. //
  84. // activate it (Bullet stuff)
  85. part->body->forceActivationState( ACTIVE_TAG );
  86. part->body->clearForces();
  87. // life
  88. if( minParticleLife != maxParticleLife )
  89. part->lifeTillDeath = Util::randRange( minParticleLife, maxParticleLife );
  90. else
  91. part->lifeTillDeath = minParticleLife;
  92. // force
  93. Vec3 forceDir;
  94. if( minDirection != maxDirection )
  95. {
  96. forceDir = Vec3( Util::randRange( minDirection.x , maxDirection.x ), Util::randRange( minDirection.y , maxDirection.y ),
  97. Util::randRange( minDirection.z , maxDirection.z ) );
  98. }
  99. else
  100. {
  101. forceDir = minDirection;
  102. }
  103. forceDir.normalize();
  104. if( minForceMagnitude != maxForceMagnitude )
  105. part->body->applyCentralForce( toBt( forceDir * Util::randRange( minForceMagnitude, maxForceMagnitude ) ) );
  106. else
  107. part->body->applyCentralForce( toBt( forceDir * minForceMagnitude ) );
  108. // gravity
  109. Vec3 grav;
  110. if( minGravity != maxGravity )
  111. {
  112. grav = Vec3( Util::randRange(minGravity.x,maxGravity.x), Util::randRange(minGravity.y,maxGravity.y),
  113. Util::randRange(minGravity.z,maxGravity.z) );
  114. }
  115. else
  116. {
  117. grav = minGravity;
  118. }
  119. part->body->setGravity( toBt( grav ) );
  120. // starting pos
  121. Vec3 pos;
  122. if( minStartingPos != maxStartingPos )
  123. {
  124. pos = Vec3( Util::randRange(minStartingPos.x,maxStartingPos.x), Util::randRange(minStartingPos.y,maxStartingPos.y),
  125. Util::randRange(minStartingPos.z,maxStartingPos.z) );
  126. }
  127. else
  128. {
  129. pos = minStartingPos;
  130. }
  131. pos += translationWspace;
  132. part->body->setWorldTransform( toBt( Mat4( pos, Mat3::getIdentity(), 1.0 ) ) );
  133. // do the rest
  134. ++partNum;
  135. if( partNum >= particlesPerEmittion ) break;
  136. } // end for all particles
  137. timeOfPrevEmittion = crntTime;
  138. } // end if can emit
  139. timeOfPrevUpdate = crntTime;
  140. }
  141. //=====================================================================================================================================
  142. // render =
  143. //=====================================================================================================================================
  144. void ParticleEmitter::render()
  145. {
  146. float vertPositions[] = { maxStartingPos.x, maxStartingPos.y, maxStartingPos.z, // right top front
  147. minStartingPos.x, maxStartingPos.y, maxStartingPos.z, // left top front
  148. minStartingPos.x, minStartingPos.y, maxStartingPos.z, // left bottom front
  149. maxStartingPos.x, minStartingPos.y, maxStartingPos.z, // right bottom front
  150. maxStartingPos.x, maxStartingPos.y, minStartingPos.z, // right top back
  151. minStartingPos.x, maxStartingPos.y, minStartingPos.z, // left top back
  152. minStartingPos.x, minStartingPos.y, minStartingPos.z, // left bottom back
  153. maxStartingPos.x, minStartingPos.y, minStartingPos.z }; // right bottom back
  154. 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 };
  155. glPushMatrix();
  156. R::multMatrix( transformationWspace );
  157. R::color3( Vec3(1.0) );
  158. glEnableClientState( GL_VERTEX_ARRAY );
  159. glVertexPointer( 3, GL_FLOAT, 0, vertPositions );
  160. glDrawElements( GL_LINES, sizeof(vertIndices)/sizeof(uint), GL_UNSIGNED_INT, vertIndices );
  161. glDisableClientState( GL_VERTEX_ARRAY );
  162. glPopMatrix();
  163. }