ParticleEmitter.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. #include <btBulletCollisionCommon.h>
  2. #include <btBulletDynamicsCommon.h>
  3. #include "ParticleEmitter.h"
  4. #include "RigidBody.h"
  5. #include "MainRenderer.h"
  6. #include "App.h"
  7. #include "Scene.h"
  8. #include "Util.h"
  9. btTransform ParticleEmitter::startingTrf(toBt(Mat3::getIdentity()), btVector3(10000000.0, 10000000.0, 10000000.0));
  10. //======================================================================================================================
  11. // render =
  12. //======================================================================================================================
  13. void ParticleEmitter::Particle::render()
  14. {
  15. /*if(lifeTillDeath < 0) return;
  16. glPushMatrix();
  17. app->getMainRenderer()->multMatrix(getWorldTransform());
  18. glBegin(GL_POINTS);
  19. glVertex3fv(&(Vec3(0.0))[0]);
  20. glEnd();
  21. glPopMatrix();*/
  22. }
  23. //======================================================================================================================
  24. // init =
  25. //======================================================================================================================
  26. void ParticleEmitter::init(const char* filename)
  27. {
  28. particleEmitterProps.loadRsrc(filename);
  29. // copy the resource to me
  30. ParticleEmitterPropsStruct& me = *this;
  31. ParticleEmitterPropsStruct& other = *particleEmitterProps.get();
  32. me = other;
  33. // create the particles
  34. collShape.reset(new btSphereShape(size));
  35. for(uint i = 0; i < maxNumOfParticles; i++)
  36. {
  37. Particle* particle = new Particle;
  38. particles.push_back(particle);
  39. float mass = particleMass + Util::randFloat(particleMassMargin) * 2.0 - particleMassMargin;
  40. RigidBody::Initializer init;
  41. init.mass = mass;
  42. init.startTrf = toAnki(startingTrf);
  43. init.shape = collShape.get();
  44. init.sceneNode = particle;
  45. init.group = Physics::CG_PARTICLE;
  46. init.mask = Physics::CG_ALL ^ Physics::CG_PARTICLE;
  47. RigidBody* body = new RigidBody(app->getScene().getPhysics(), init);
  48. body->forceActivationState(DISABLE_SIMULATION);
  49. particle->body.reset(body);
  50. }
  51. }
  52. //======================================================================================================================
  53. // update =
  54. //======================================================================================================================
  55. void ParticleEmitter::update()
  56. {
  57. float crntTime = app->getTicks() / 1000.0;
  58. // Opt: We dont have to make extra calculations if the ParticleEmitter's rotation is the identity
  59. bool identRot = worldTransform.getRotation() == Mat3::getIdentity();
  60. // deactivate the dead particles
  61. for(uint i=0; i<particles.size(); i++)
  62. {
  63. Particle& p = particles[i];
  64. if(p.timeOfDeath < 0.0) continue; // its already dead so dont deactivate it again
  65. if(p.timeOfDeath < crntTime)
  66. {
  67. //cout << "Killing " << i << " " << p.timeOfDeath << endl;
  68. p.body->setActivationState(DISABLE_SIMULATION);
  69. p.body->setWorldTransform(startingTrf);
  70. p.timeOfDeath = -1.0;
  71. }
  72. }
  73. if((crntTime - timeOfPrevEmittion) > emittionPeriod)
  74. {
  75. uint partNum = 0;
  76. for(uint i=0; i<particles.size(); i++)
  77. {
  78. Particle& p = particles[i];
  79. if(p.timeOfDeath > 0.0) continue; // its alive so skip it
  80. //INFO("Reiniting " << i);
  81. // life
  82. if(particleLifeMargin != 0.0)
  83. p.timeOfDeath = crntTime + particleLife + Util::randFloat(particleLifeMargin) * 2.0 - particleLifeMargin;
  84. else
  85. p.timeOfDeath = crntTime + particleLife;
  86. //cout << "Time of death " << p.timeOfDeath << endl;
  87. //cout << "Particle life " << p.timeOfDeath - crntTime << endl;
  88. // activate it (Bullet stuff)
  89. p.body->forceActivationState(ACTIVE_TAG);
  90. p.body->activate();
  91. p.body->clearForces();
  92. p.body->setLinearVelocity(btVector3(0.0, 0.0, 0.0));
  93. p.body->setAngularVelocity(btVector3(0.0, 0.0, 0.0));
  94. //cout << p.body->internalGetDeltaAngularVelocity() << endl;
  95. // force
  96. if(hasForce)
  97. {
  98. Vec3 forceDir;
  99. if(forceDirectionMargin != Vec3(0.0))
  100. {
  101. for(int i=0; i<3; i++)
  102. {
  103. forceDir[i] = forceDirection[i] + Util::randFloat(forceDirectionMargin[i]) * 2.0 - forceDirectionMargin[i];
  104. }
  105. }
  106. else
  107. {
  108. forceDir = forceDirection;
  109. }
  110. forceDir.normalize();
  111. if(!identRot)
  112. forceDir = worldTransform.getRotation() * forceDir; // the forceDir depends on the particle emitter rotation
  113. Vec3 force;
  114. if(forceMagnitudeMargin != 0.0)
  115. force = forceDir * (forceMagnitude + Util::randFloat(forceMagnitudeMargin) * 2.0 - forceMagnitudeMargin);
  116. else
  117. force = forceDir * forceMagnitude;
  118. p.body->applyCentralForce(toBt(force));
  119. }
  120. // gravity
  121. if(!usingWorldGrav)
  122. {
  123. Vec3 grav;
  124. if(gravityMargin != Vec3(0.0, 0.0, 0.0))
  125. {
  126. for(int i=0; i<3; i++)
  127. {
  128. grav[i] = gravity[i] + Util::randFloat(gravityMargin[i]) * 2.0 - gravityMargin[i];
  129. }
  130. }
  131. else
  132. {
  133. grav = gravity;
  134. }
  135. p.body->setGravity(toBt(grav));
  136. }
  137. // starting pos
  138. Vec3 pos; // in local space
  139. if(startingPosMargin != Vec3(0.0))
  140. {
  141. for(int i=0; i<3; i++)
  142. {
  143. pos[i] = startingPos[i] + Util::randFloat(startingPosMargin[i]) * 2.0 - startingPosMargin[i];
  144. }
  145. }
  146. else
  147. {
  148. pos = startingPos;
  149. }
  150. if(identRot)
  151. pos += worldTransform.getOrigin();
  152. else
  153. pos.transform(worldTransform);
  154. btTransform trf;
  155. trf.setIdentity();
  156. trf.setOrigin(toBt(pos));
  157. p.body->setWorldTransform(trf);
  158. // do the rest
  159. ++partNum;
  160. if(partNum >= particlesPerEmittion)
  161. break;
  162. } // end for all particles
  163. timeOfPrevEmittion = crntTime;
  164. } // end if can emit
  165. timeOfPrevUpdate = crntTime;
  166. }
  167. //======================================================================================================================
  168. // render =
  169. //======================================================================================================================
  170. void ParticleEmitter::render()
  171. {
  172. glPolygonMode(GL_FRONT, GL_LINE);
  173. Renderer::Dbg::setColor(Vec4(1.0));
  174. Renderer::Dbg::setModelMat(Mat4(getWorldTransform()));
  175. Renderer::Dbg::drawCube();
  176. glPolygonMode(GL_FRONT, GL_FILL);
  177. }