/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. ### File Specific: main-programmer: Benjamin Grauer co-programmer: Patrick Boenzli */ #define DEBUG_SPECIAL_MODULE DEBUG_MODULE_PARTICLE #include "particle_emitter.h" #include "particle_system.h" #include "particle_engine.h" #include "debug.h" #include "stdlibincl.h" using namespace std; /** \brief standard constructor */ ParticleEmitter::ParticleEmitter(const Vector& direction, float angle, float emissionRate, float velocity) { this->setClassID(CL_PARTICLE_EMITTER, "ParticleEmitter"); this->type = EMITTER_DOT; this->emitterSize = 1.0; this->direction = direction; this->setSpread(angle); this->setEmissionRate(emissionRate); this->setEmissionVelocity(velocity); this->saveTime = 0.0; ParticleEngine::getInstance()->addEmitter(this); } /** \brief standard destructor */ ParticleEmitter::~ParticleEmitter () { ParticleEngine::getInstance()->removeEmitter(this); } /** \brief this start the emitter */ void ParticleEmitter::start() {} /** \brief this stops the emitter */ void ParticleEmitter::stop() {} /* these are Animation interfaces: so you can change spec values as you want */ /** \param type the new Type of this emitter */ void ParticleEmitter::setType(EMITTER_TYPE type) { this->type = type; } void ParticleEmitter::setSize(float emitterSize) { if (emitterSize > 0.0) this->emitterSize = emitterSize; else emitterSize = 0.0; } /** \brief set the emission rate \param sets the number of particles emitted per second if you want to change the value of this variable during emission time (to make it more dynamic) you may want to use the animation class */ void ParticleEmitter::setEmissionRate(float emissionRate) { if (emissionRate > 0.0) this->emissionRate = emissionRate; else this->emissionRate = 0.0; } /** \brief set the angle of the emitter \param angle around the direction in which there are particles to be emitted \param randomAngle A random spread-angle, the +- randomness of this option if you want to change the value of this variable during emission time (to make it more dynamic) you may want to use the animation class */ void ParticleEmitter::setSpread(float angle, float randomAngle) { this->angle = angle; this->randomAngle = randomAngle; } /** \brief sets the velocity of all particles emitted \param velocity The starting velocity of the emitted particles \param random A random starting velocity, the +- randomness of this option if you want to change the value of this variable during emission time (to make it more dynamic) you may want to use the animation class */ void ParticleEmitter::setEmissionVelocity(float velocity, float randomVelocity) { this->velocity = velocity; this->randomVelocity = randomVelocity; } /** \brief this set the time to life of a particle, after which it will die \param the time to live in seconds if you want to change the value of this variable during emission time (to make it more dynamic) you may want to use the animation class */ void ParticleEmitter::tick(float dt, ParticleSystem* system) { if (likely(dt > 0.0 && this->emissionRate > 0.0)) { // saving the time float count = (dt+this->saveTime) * this->emissionRate; this->saveTime = modff(count, &count) / this->emissionRate; PRINTF(5)("emitting %f particles, saving %f seconds for the next round\n", count, this->saveTime); if (likely(count > 0)) { Vector inheritVelocity = this->getVelocity() * system->inheritSpeed; for (int i = 0; i < count; i++) // emmits from EMITTER_DOT, { Vector randDir = Vector(rand()-RAND_MAX/2, rand()-RAND_MAX/2, rand()-RAND_MAX/2); randDir.normalize(); randDir = (this->getAbsDir()*Quaternion(angle + randomAngle *((float)rand()/RAND_MAX -.5), randDir)).apply(this->direction); Vector velocityV = randDir.getNormalized()*this->velocity + inheritVelocity; // this should spread the Particles evenly. if the Emitter is moved around quickly Vector equalSpread = this->getVelocity() * rand()/RAND_MAX * dt; Vector extension; // the Vector for different fields. if (this->type & 2) { extension = Vector(this->emitterSize * ((float)rand()/RAND_MAX -.5), 0, this->emitterSize * ((float)rand()/RAND_MAX - .5)); extension = this->getAbsDir().apply(extension); } else if (this->type & 8) { extension = Vector((float)rand()/RAND_MAX -.5, (float)rand()/RAND_MAX -.5, (float)rand()/RAND_MAX -.5) * this->emitterSize; } system->addParticle(this->getAbsCoor() + extension - equalSpread, velocityV); } } } } /** \brief outputs some nice debug information */ void ParticleEmitter::debug(void) { }