ParticleEmitterNode.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. #include <boost/foreach.hpp>
  2. #include <btBulletCollisionCommon.h>
  3. #include <btBulletDynamicsCommon.h>
  4. #include "ParticleEmitterNode.h"
  5. #include "Particle.h"
  6. #include "Physics/RigidBody.h"
  7. #include "Core/App.h"
  8. #include "Scene.h"
  9. #include "Util/Util.h"
  10. btTransform ParticleEmitterNode::startingTrf(toBt(Mat3::getIdentity()),
  11. btVector3(10000000.0, 10000000.0, 10000000.0));
  12. //==============================================================================
  13. // Destructor =
  14. //==============================================================================
  15. ParticleEmitterNode::~ParticleEmitterNode()
  16. {}
  17. //==============================================================================
  18. // getRandom =
  19. //==============================================================================
  20. float ParticleEmitterNode::getRandom(float initial, float deviation)
  21. {
  22. return (deviation == 0.0) ? initial :
  23. initial + Util::randFloat(deviation) * 2.0 - deviation;
  24. }
  25. //==============================================================================
  26. // getRandom =
  27. //==============================================================================
  28. Vec3 ParticleEmitterNode::getRandom(const Vec3& initial, const Vec3& deviation)
  29. {
  30. if(deviation == Vec3(0.0))
  31. {
  32. return initial;
  33. }
  34. else
  35. {
  36. Vec3 out;
  37. for(int i = 0; i < 3; i++)
  38. {
  39. out[i] = getRandom(initial[i], deviation[i]);
  40. }
  41. return out;
  42. }
  43. }
  44. //==============================================================================
  45. // init =
  46. //==============================================================================
  47. void ParticleEmitterNode::init(const char* filename)
  48. {
  49. particleEmitterProps.loadRsrc(filename);
  50. // copy the resource to me
  51. ParticleEmitterRsrc& me = *this;
  52. ParticleEmitterRsrc& other = *particleEmitterProps.get();
  53. me = other;
  54. // create the particles
  55. collShape.reset(new btSphereShape(size));
  56. for(uint i = 0; i < maxNumOfParticles; i++)
  57. {
  58. Particle* particle = new Particle(-1.0, NULL);
  59. particle->init(modelName.c_str());
  60. particle->disableFlag(SceneNode::SNF_ACTIVE);
  61. particle->setWorldTransform(Transform(Vec3(1000000.0),
  62. Mat3::getIdentity(), 1.0));
  63. particles.push_back(particle);
  64. float mass = particleMass +
  65. Util::randFloat(particleMassDeviation) * 2.0 -
  66. particleMassDeviation;
  67. Phys::RigidBody::Initializer init;
  68. init.mass = mass;
  69. init.startTrf = toAnki(startingTrf);
  70. init.shape = collShape.get();
  71. init.sceneNode = particle;
  72. init.group = Phys::MasterContainer::CG_PARTICLE;
  73. init.mask = Phys::MasterContainer::CG_ALL ^
  74. Phys::MasterContainer::CG_PARTICLE;
  75. Phys::RigidBody* body = new Phys::RigidBody(
  76. SceneSingleton::getInstance().getPhysMasterContainer(), init);
  77. body->forceActivationState(DISABLE_SIMULATION);
  78. particle->setNewRigidBody(body);
  79. }
  80. timeLeftForNextEmission = 0.0;
  81. }
  82. //==============================================================================
  83. // frameUpdate =
  84. //==============================================================================
  85. void ParticleEmitterNode::frameUpdate(float prevUpdateTime, float crntTime)
  86. {
  87. // Opt: We dont have to make extra calculations if the ParticleEmitterNode's
  88. // rotation is the identity
  89. bool identRot = getWorldTransform().getRotation() == Mat3::getIdentity();
  90. // deactivate the dead particles
  91. BOOST_FOREACH(Particle* p, particles)
  92. {
  93. if(p->isDead()) // its already dead so dont deactivate it again
  94. {
  95. continue;
  96. }
  97. if(p->getTimeOfDeath() < crntTime)
  98. {
  99. //cout << "Killing " << i << " " << p.timeOfDeath << endl;
  100. p->getRigidBody().setActivationState(DISABLE_SIMULATION);
  101. p->getRigidBody().setWorldTransform(startingTrf);
  102. p->disableFlag(SceneNode::SNF_ACTIVE);
  103. p->setTimeOfDeath(-1.0);
  104. }
  105. }
  106. // pre calculate
  107. bool forceFlag = hasForce();
  108. bool worldGravFlag = usingWorldGrav();
  109. if(timeLeftForNextEmission <= 0.0)
  110. {
  111. uint partNum = 0;
  112. BOOST_FOREACH(Particle* pp, particles)
  113. {
  114. Particle& p = *pp;
  115. if(!p.isDead())
  116. {
  117. // its alive so skip it
  118. continue;
  119. }
  120. Phys::RigidBody& body = p.getRigidBody();
  121. p.enableFlag(SceneNode::SNF_ACTIVE);
  122. // life
  123. p.setTimeOfDeath(getRandom(crntTime + particleLife,
  124. particleLifeDeviation));
  125. //cout << "Time of death " << p.timeOfDeath << endl;
  126. //cout << "Particle life " << p.timeOfDeath - crntTime << endl;
  127. // activate it (Bullet stuff)
  128. body.forceActivationState(ACTIVE_TAG);
  129. body.activate();
  130. body.clearForces();
  131. body.setLinearVelocity(btVector3(0.0, 0.0, 0.0));
  132. body.setAngularVelocity(btVector3(0.0, 0.0, 0.0));
  133. //cout << p.body->internalGetDeltaAngularVelocity() << endl;
  134. // force
  135. if(forceFlag)
  136. {
  137. Vec3 forceDir = getRandom(forceDirection,
  138. forceDirectionDeviation);
  139. forceDir.normalize();
  140. if(!identRot)
  141. {
  142. // the forceDir depends on the particle emitter rotation
  143. forceDir = getWorldTransform().getRotation() * forceDir;
  144. }
  145. float forceMag = getRandom(forceMagnitude,
  146. forceMagnitudeDeviation);
  147. body.applyCentralForce(toBt(forceDir * forceMag));
  148. }
  149. // gravity
  150. if(!worldGravFlag)
  151. {
  152. body.setGravity(toBt(getRandom(gravity, gravityDeviation)));
  153. }
  154. // Starting pos. In local space
  155. Vec3 pos = getRandom(startingPos, startingPosDeviation);
  156. if(identRot)
  157. {
  158. pos += getWorldTransform().getOrigin();
  159. }
  160. else
  161. {
  162. pos.transform(getWorldTransform());
  163. }
  164. btTransform trf(toBt(Transform(pos,
  165. getWorldTransform().getRotation(), 1.0)));
  166. body.setWorldTransform(trf);
  167. // do the rest
  168. ++partNum;
  169. if(partNum >= particlesPerEmittion)
  170. {
  171. break;
  172. }
  173. } // end for all particles
  174. timeLeftForNextEmission = emissionPeriod;
  175. } // end if can emit
  176. else
  177. {
  178. timeLeftForNextEmission -= crntTime - prevUpdateTime;
  179. }
  180. }