| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222 |
- #include <boost/foreach.hpp>
- #include <btBulletCollisionCommon.h>
- #include <btBulletDynamicsCommon.h>
- #include "ParticleEmitterNode.h"
- #include "Particle.h"
- #include "Physics/RigidBody.h"
- #include "Core/App.h"
- #include "Scene.h"
- #include "Util/Util.h"
- btTransform ParticleEmitterNode::startingTrf(toBt(Mat3::getIdentity()),
- btVector3(10000000.0, 10000000.0, 10000000.0));
- //==============================================================================
- // Destructor =
- //==============================================================================
- ParticleEmitterNode::~ParticleEmitterNode()
- {}
- //==============================================================================
- // getRandom =
- //==============================================================================
- float ParticleEmitterNode::getRandom(float initial, float deviation)
- {
- return (deviation == 0.0) ? initial :
- initial + Util::randFloat(deviation) * 2.0 - deviation;
- }
- //==============================================================================
- // getRandom =
- //==============================================================================
- Vec3 ParticleEmitterNode::getRandom(const Vec3& initial, const Vec3& deviation)
- {
- if(deviation == Vec3(0.0))
- {
- return initial;
- }
- else
- {
- Vec3 out;
- for(int i = 0; i < 3; i++)
- {
- out[i] = getRandom(initial[i], deviation[i]);
- }
- return out;
- }
- }
- //==============================================================================
- // init =
- //==============================================================================
- void ParticleEmitterNode::init(const char* filename)
- {
- particleEmitterProps.loadRsrc(filename);
- // copy the resource to me
- ParticleEmitterRsrc& me = *this;
- ParticleEmitterRsrc& other = *particleEmitterProps.get();
- me = other;
- // create the particles
- collShape.reset(new btSphereShape(size));
- for(uint i = 0; i < maxNumOfParticles; i++)
- {
- Particle* particle = new Particle(-1.0, NULL);
- particle->init(modelName.c_str());
- particle->disableFlag(SceneNode::SNF_ACTIVE);
- particle->setWorldTransform(Transform(Vec3(1000000.0),
- Mat3::getIdentity(), 1.0));
- particles.push_back(particle);
- float mass = particleMass +
- Util::randFloat(particleMassDeviation) * 2.0 -
- particleMassDeviation;
- Phys::RigidBody::Initializer init;
- init.mass = mass;
- init.startTrf = toAnki(startingTrf);
- init.shape = collShape.get();
- init.sceneNode = particle;
- init.group = Phys::MasterContainer::CG_PARTICLE;
- init.mask = Phys::MasterContainer::CG_ALL ^
- Phys::MasterContainer::CG_PARTICLE;
- Phys::RigidBody* body = new Phys::RigidBody(
- SceneSingleton::getInstance().getPhysMasterContainer(), init);
- body->forceActivationState(DISABLE_SIMULATION);
- particle->setNewRigidBody(body);
- }
- timeLeftForNextEmission = 0.0;
- }
- //==============================================================================
- // frameUpdate =
- //==============================================================================
- void ParticleEmitterNode::frameUpdate(float prevUpdateTime, float crntTime)
- {
- // Opt: We dont have to make extra calculations if the ParticleEmitterNode's
- // rotation is the identity
- bool identRot = getWorldTransform().getRotation() == Mat3::getIdentity();
- // deactivate the dead particles
- BOOST_FOREACH(Particle* p, particles)
- {
- if(p->isDead()) // its already dead so dont deactivate it again
- {
- continue;
- }
- if(p->getTimeOfDeath() < crntTime)
- {
- //cout << "Killing " << i << " " << p.timeOfDeath << endl;
- p->getRigidBody().setActivationState(DISABLE_SIMULATION);
- p->getRigidBody().setWorldTransform(startingTrf);
- p->disableFlag(SceneNode::SNF_ACTIVE);
- p->setTimeOfDeath(-1.0);
- }
- }
- // pre calculate
- bool forceFlag = hasForce();
- bool worldGravFlag = usingWorldGrav();
- if(timeLeftForNextEmission <= 0.0)
- {
- uint partNum = 0;
- BOOST_FOREACH(Particle* pp, particles)
- {
- Particle& p = *pp;
- if(!p.isDead())
- {
- // its alive so skip it
- continue;
- }
- Phys::RigidBody& body = p.getRigidBody();
- p.enableFlag(SceneNode::SNF_ACTIVE);
- // life
- p.setTimeOfDeath(getRandom(crntTime + particleLife,
- particleLifeDeviation));
- //cout << "Time of death " << p.timeOfDeath << endl;
- //cout << "Particle life " << p.timeOfDeath - crntTime << endl;
- // activate it (Bullet stuff)
- body.forceActivationState(ACTIVE_TAG);
- body.activate();
- body.clearForces();
- body.setLinearVelocity(btVector3(0.0, 0.0, 0.0));
- body.setAngularVelocity(btVector3(0.0, 0.0, 0.0));
- //cout << p.body->internalGetDeltaAngularVelocity() << endl;
- // force
- if(forceFlag)
- {
- Vec3 forceDir = getRandom(forceDirection,
- forceDirectionDeviation);
- forceDir.normalize();
- if(!identRot)
- {
- // the forceDir depends on the particle emitter rotation
- forceDir = getWorldTransform().getRotation() * forceDir;
- }
- float forceMag = getRandom(forceMagnitude,
- forceMagnitudeDeviation);
- body.applyCentralForce(toBt(forceDir * forceMag));
- }
- // gravity
- if(!worldGravFlag)
- {
- body.setGravity(toBt(getRandom(gravity, gravityDeviation)));
- }
- // Starting pos. In local space
- Vec3 pos = getRandom(startingPos, startingPosDeviation);
- if(identRot)
- {
- pos += getWorldTransform().getOrigin();
- }
- else
- {
- pos.transform(getWorldTransform());
- }
- btTransform trf(toBt(Transform(pos,
- getWorldTransform().getRotation(), 1.0)));
- body.setWorldTransform(trf);
- // do the rest
- ++partNum;
- if(partNum >= particlesPerEmittion)
- {
- break;
- }
- } // end for all particles
- timeLeftForNextEmission = emissionPeriod;
- } // end if can emit
- else
- {
- timeLeftForNextEmission -= crntTime - prevUpdateTime;
- }
- }
|