/* 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_GRAPHICS #include "particle_emitter.h" #include "particle_system.h" #include "util/loading/load_param.h" #include "debug.h" ObjectListDefinition(ParticleEmitter); /** * standard constructor */ ParticleEmitter::ParticleEmitter(float emissionRate, float velocity, float angle) { this->registerObject(this, ParticleEmitter::_objectList); this->system = NULL; this->setInheritSpeed(PARTICLE_EMITTER_DEFAULT_INHERIT_SPEED); this->setEmissionMomentum(0); this->setSpread(angle); this->setEmissionRate(emissionRate); this->setEmissionVelocity(velocity); this->saveTime = 0.0; } /** * standard destructor removes the EmitterSystem from the ParticleEngine */ ParticleEmitter::~ParticleEmitter () { this->setSystem(NULL); } /** * loads a ParticleEmitter from a XML-element * @param root the XML-element to load from */ void ParticleEmitter::loadParams(const TiXmlElement* root) { PNode::loadParams(root); LoadParam(root, "rate", this, ParticleEmitter, setEmissionRate) .describe("How many particles should be emittet from this emitter"); LoadParam(root, "inherit-speed", this, ParticleEmitter, setInheritSpeed) .describe("the extent, the speed of the emitter has on the particles"); LoadParam(root, "emission-velocity", this, ParticleEmitter, setEmissionVelocity) .describe("How fast the particles are emittet (their initial speed)"); LoadParam(root, "emission-momentum", this, ParticleEmitter, setEmissionMomentum) .describe("How fast the particles rotation is at emissiontime (their initial momentum)"); LoadParam(root, "spread", this, ParticleEmitter, setSpread) .describe("The angle the particles are emitted from (angle, deviation)"); } void ParticleEmitter::setSystem(ParticleSystem* system) { if (system != NULL) system->addEmitter(this); else if (this->system != NULL) this->system->removeEmitter(this); } /** * this start the emitter */ void ParticleEmitter::start() {} /** * this stops the emitter */ void ParticleEmitter::stop() {} /** * set the emission rate * @param emissionRate: 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; } /** * how much of the speed from the ParticleEmitter should flow onto the ParticleSystem * @param value a Value between zero and one 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::setInheritSpeed(float value) { if (unlikely(value > 1.0)) this->inheritSpeed = 1; else if (unlikely(value < 0.0)) this->inheritSpeed = 0; else this->inheritSpeed = value; } /** * 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; } /** * sets the initial velocity of all particles emitted * @param velocity The starting velocity of the emitted particles * @param randomVelocity 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; } /** * sets the initial Momentum of all particles emitted * @param momentum the new Momentum (just a float for being not too complicated). * @param randomMomentum variation from the given value. */ void ParticleEmitter::setEmissionMomentum(float momentum, float randomMomentum) { this->momentum = momentum; this->momentumRandom = randomMomentum; } /** * this set the time to life of a particle, after which it will die * @param dt: the time to live in seconds * @param system: the system into which to emitt 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) { assert (this->system != NULL); if (likely(dt > 0.0 && this->emissionRate > 0.0)) { // saving the time (particles only partly emitted in this timestep) 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 timestep\n", count, this->saveTime); if (count + this->system->getCount() > this->system->getMaxCount()) count = this->system->getMaxCount() - this->system->getCount(); if (likely(count > 0.0f)) this->emitParticles((unsigned int)count); } } /** * outputs some nice debug information */ void ParticleEmitter::debug() const { PRINT(0)(" ParticleEmitter %s::%s\n", this->getClassCName(), this->getCName()); PRINT(0)(" EmissionRate: %f, Speed: %f, SpreadAngle: %f\n", this->getEmissionRate(), this->getEmissionVelocity(), this->getSpread()); }