Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/trunk/src/lib/particles/particle_emitter.cc @ 6806

Last change on this file since 6806 was 6627, checked in by bensch, 19 years ago

trunk: valgrind sweep

File size: 9.4 KB
RevLine 
[4597]1/*
[3926]2   orxonox - the future of 3D-vertical-scrollers
3
4   Copyright (C) 2004 orx
5
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10
11   ### File Specific:
[3938]12   main-programmer: Benjamin Grauer
[3926]13   co-programmer: Patrick Boenzli
14*/
15
[5357]16#define DEBUG_SPECIAL_MODULE DEBUG_MODULE_GRAPHICS
[3926]17
18#include "particle_emitter.h"
19
[3932]20#include "particle_system.h"
21
[4437]22#include "load_param.h"
[5652]23#include "factory.h"
[4381]24#include "debug.h"
25#include "stdlibincl.h"
26
[3926]27using namespace std;
28
29
[5750]30CREATE_FACTORY(ParticleEmitter, CL_PARTICLE_EMITTER);
[4725]31
[3926]32/**
[4836]33 *  standard constructor
[3926]34*/
[4597]35ParticleEmitter::ParticleEmitter(const Vector& direction, float angle, float emissionRate,
36                  float velocity)
[3926]37{
[4726]38  this->init();
39
[4439]40  this->direction = direction;
41  this->setSpread(angle);
42  this->setEmissionRate(emissionRate);
43  this->setEmissionVelocity(velocity);
[4437]44}
45
[4478]46/**
[4836]47 *  constructs and loads a ParticleEmitter from a XML-element
48 * @param root the XML-element to load from
[4478]49*/
[4437]50ParticleEmitter::ParticleEmitter(const TiXmlElement* root)
51{
[4726]52  this->init();
[4338]53
[5445]54   if (root != NULL)
[4437]55     this->loadParams(root);
[3926]56}
57
58/**
[4836]59 *  standard destructor
[3926]60
[4496]61   removes the EmitterSystem from the ParticleEngine
[3926]62*/
[4597]63ParticleEmitter::~ParticleEmitter ()
[3935]64{
[6623]65  this->setSystem(NULL);
[3935]66}
[3929]67
[4478]68/**
[6623]69  @brief initializes default values of a ParitcleEmitter
[4726]70*/
71void ParticleEmitter::init()
72{
73  this->setClassID(CL_PARTICLE_EMITTER, "ParticleEmitter");
74
75  this->type = PARTICLE_EMITTER_DEFAULT_TYPE;
76  this->emitterSize = PARTICLE_EMITTER_DEFAULT_SIZE;
77  this->setInheritSpeed(PARTICLE_EMITTER_DEFAULT_INHERIT_SPEED);
78  this->setEmissionRate(PARTICLE_EMITTER_DEFAULT_EMISSION_RATE);
79  this->setSize(PARTICLE_EMITTER_DEFAULT_SIZE);
[6627]80  this->setEmissionMomentum(0);
81  this->setEmissionVelocity(1.0);
82  this->setSpread(M_PI);
[4726]83
[6619]84  this->system = NULL;
85
[4726]86  this->saveTime = 0.0;
87}
88
89/**
[4836]90 *  loads a ParticleEmitter from a XML-element
91 * @param root the XML-element to load from
[4478]92*/
[4437]93void ParticleEmitter::loadParams(const TiXmlElement* root)
94{
[6512]95  PNode::loadParams(root);
[3929]96
[5671]97  LoadParam(root, "type", this, ParticleEmitter, setType)
[4437]98    .describe("What type of emitter is this [dot, plane, cube, sphere].");
99
[5671]100  LoadParam(root, "size", this, ParticleEmitter, setSize)
[4437]101    .describe("How big the emitter is (no effect on dot-emitters)");
102
[5671]103  LoadParam(root, "rate", this, ParticleEmitter, setEmissionRate)
[4437]104    .describe("How many particles should be emittet from this emitter");
105
[5671]106  LoadParam(root, "inherit-speed", this, ParticleEmitter, setInheritSpeed)
[4494]107    .describe("the extent, the speed of the emitter has on the particles");
108
[5671]109  LoadParam(root, "emission-velocity", this, ParticleEmitter, setEmissionVelocity)
[4437]110    .describe("How fast the particles are emittet (their initial speed)");
[4597]111
[5671]112  LoadParam(root, "emission-momentum", this, ParticleEmitter, setEmissionMomentum)
[4725]113      .describe("How fast the particles rotation is at emissiontime (their initial momentum)");
114
[5671]115  LoadParam(root, "spread", this, ParticleEmitter, setSpread)
[4437]116    .describe("The angle the particles are emitted from (angle, deviation)");
[4726]117
118
[5671]119  LoadParam(root, "emission-direction", this, ParticleEmitter, setDirection);
[4437]120}
121
[6619]122void ParticleEmitter::setSystem(ParticleSystem* system)
123{
124  if (system != NULL)
125    system->addEmitter(this);
126  else if (this->system != NULL)
127    this->system->removeEmitter(this);
128}
129
[3929]130/**
[4836]131 *  this start the emitter
[3929]132*/
133void ParticleEmitter::start() {}
134
135
136/**
[4836]137 *  this stops the emitter
[3929]138*/
139void ParticleEmitter::stop() {}
140
141
142
143
144
145/**
[4836]146 * @param type the new Type of this emitter
[4338]147*/
148void ParticleEmitter::setType(EMITTER_TYPE type)
149{
150  this->type = type;
151}
152
[4437]153/**
[4836]154 *  sets the type of emitter
155 * @param type the type as a const char*
[4478]156   dot: EMITTER_DOT, plane: EMITTER_PLANE, cube: EMITTER_CUBE, sphere, EMITTER_SPHERE;
[4437]157*/
158void ParticleEmitter::setType(const char* type)
159{
160  if (!strcmp(type, "plane"))
[4639]161    this->setType(EMITTER_PLANE);
[4437]162  else if (!strcmp(type, "cube"))
[4639]163    this->setType(EMITTER_CUBE);
[4437]164  else if (!strcmp(type, "sphere"))
[4639]165    this->setType(EMITTER_SPHERE);
[4437]166  else
[4639]167    this->setType(EMITTER_DOT);
[4437]168}
169
[4746]170const char* ParticleEmitter::getTypeC() const
[4639]171{
172  if (this->type == EMITTER_PLANE)
173    return "EMITTER_PLANE";
174  else if (this->type == EMITTER_CUBE)
175    return "EMITTER_CUBE";
176  else if (this->type == EMITTER_SPHERE)
177    return "EMITTER_SPHERE";
178  else
179    return "EMITTER_DOT";
180}
181
[4478]182/**
[4836]183 *  sets a new size to the emitter
[4478]184*/
[4338]185void ParticleEmitter::setSize(float emitterSize)
186{
187  if (emitterSize > 0.0)
188    this->emitterSize = emitterSize;
189  else
190    emitterSize = 0.0;
191}
192
193/**
[4836]194 *  set the emission rate
195 * @param emissionRate: sets the number of particles emitted per second
[3929]196
197   if you want to change the value of this variable during emission time (to make it more dynamic)
[3930]198   you may want to use the animation class
[3929]199*/
[3931]200void ParticleEmitter::setEmissionRate(float emissionRate)
[3933]201{
[4338]202  if (emissionRate > 0.0)
203    this->emissionRate = emissionRate;
204  else
205    this->emissionRate = 0.0;
[3933]206}
[3929]207
208/**
[4836]209 *  how much of the speed from the ParticleEmitter should flow onto the ParticleSystem
210 * @param value a Value between zero and one
[4493]211
212   if you want to change the value of this variable during emission time (to make it more dynamic)
213   you may want to use the animation class
214*/
215void ParticleEmitter::setInheritSpeed(float value)
216{
217  if (unlikely(value > 1.0))
218    this->inheritSpeed = 1;
219  else if (unlikely(value < 0.0))
220    this->inheritSpeed = 0;
221  else
222    this->inheritSpeed = value;
223}
224
225/**
[4836]226 *  set the angle of the emitter
227 * @param angle around the direction in which there are particles to be emitted
228 * @param randomAngle A random spread-angle, the +- randomness of this option
[3929]229
230   if you want to change the value of this variable during emission time (to make it more dynamic)
[3930]231   you may want to use the animation class
[3929]232*/
[3931]233void ParticleEmitter::setSpread(float angle, float randomAngle)
[3935]234{
235  this->angle = angle;
236  this->randomAngle = randomAngle;
237}
[3929]238
239/**
[4836]240 *  sets the initial velocity of all particles emitted
241 * @param velocity The starting velocity of the emitted particles
242 * @param randomVelocity A random starting velocity, the +- randomness of this option
[3929]243
244   if you want to change the value of this variable during emission time (to make it more dynamic)
[3930]245   you may want to use the animation class
[3929]246*/
[4338]247void ParticleEmitter::setEmissionVelocity(float velocity, float randomVelocity)
[3935]248{
249  this->velocity = velocity;
250  this->randomVelocity = randomVelocity;
251}
[3929]252
253/**
[4836]254 *  sets the initial Momentum of all particles emitted
255 * @param momentum the new Momentum (just a float for being not too complicated).
256 * @param randomMomentum variation from the given value.
[4690]257 */
258void ParticleEmitter::setEmissionMomentum(float momentum, float randomMomentum)
259{
260  this->momentum = momentum;
261  this->momentumRandom = randomMomentum;
262}
263
264/**
[4836]265 *  this set the time to life of a particle, after which it will die
266 * @param dt: the time to live in seconds
267 * @param system: the system into which to emitt
[3929]268
269   if you want to change the value of this variable during emission time (to make it more dynamic)
[3930]270   you may want to use the animation class
[3929]271*/
[6620]272void ParticleEmitter::tick(float dt)
[3932]273{
[6620]274  assert (this->system != NULL);
[3950]275  if (likely(dt > 0.0 && this->emissionRate > 0.0))
276  {
[4692]277    // saving the time (particles only partly emitted in this timestep)
[3950]278    float count = (dt+this->saveTime) * this->emissionRate;
[4017]279    this->saveTime = modff(count, &count) / this->emissionRate;
[4692]280    PRINTF(5)("emitting %f particles, saving %f seconds for the next timestep\n", count, this->saveTime);
[4597]281
[4017]282    if (likely(count > 0))
[4690]283    {
284      Vector inheritVelocity = this->getVelocity() * this->inheritSpeed;
[4693]285      for (int i = 0; i < (int)count; i++)
[3950]286      {
[4690]287        Vector randDir = Vector(rand()-RAND_MAX/2, rand()-RAND_MAX/2, rand()-RAND_MAX/2);
288        randDir.normalize();
289        randDir = (this->getAbsDir()*Quaternion(angle + randomAngle *((float)rand()/RAND_MAX -.5), randDir)).apply(this->direction);
290        Vector velocityV = randDir.getNormalized()*this->velocity + inheritVelocity;
[4176]291
[4692]292        // this should spread the Particles evenly. if the Emitter is moved around quickly
[4690]293        Vector equalSpread = this->getVelocity() * rand()/RAND_MAX * dt;
294        Vector extension; // the Vector for different fields.
[4176]295
[4692]296        if (this->type & EMITTER_PLANE)
[4690]297        {
298          extension = Vector(this->emitterSize * ((float)rand()/RAND_MAX -.5), 0, this->emitterSize * ((float)rand()/RAND_MAX - .5));
299          extension = this->getAbsDir().apply(extension);
300        }
[4692]301        else if (this->type & EMITTER_CUBE)
[4690]302        {
303          extension = Vector((float)rand()/RAND_MAX -.5, (float)rand()/RAND_MAX -.5, (float)rand()/RAND_MAX -.5) * this->emitterSize;
304        }
[4338]305
[4597]306
[4690]307        // ROTATIONAL CALCULATION (this must not be done for all types of particles.)
308        randDir = Vector(rand()-RAND_MAX/2, rand()-RAND_MAX/2, rand()-RAND_MAX/2);
309        randDir.normalize();
310        Quaternion orient = Quaternion(M_PI, randDir);
311        Quaternion moment = Quaternion(this->momentum + this->momentumRandom, randDir);
312
[6620]313        this->system->addParticle(this->getAbsCoor() + extension - equalSpread, velocityV, orient, moment);
[3950]314      }
[4690]315    }
[3950]316  }
[3932]317}
[3944]318
319/**
[4836]320 *  outputs some nice debug information
[3944]321*/
[4746]322void ParticleEmitter::debug() const
[3944]323{
[4493]324  PRINT(0)(" Emitter %s\n", this->getName());
[4639]325  PRINT(0)("  EmissionRate: %f, Speed: %f, SpreadAngle: %f\n", this->getEmissionRate(), this->getEmissionVelocity(), this->getSpread());
326  PRINT(0)("  Size %f, Type: %s\n", this->getSize(), this->getTypeC());
[3944]327}
Note: See TracBrowser for help on using the repository browser.