Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: small patch to prevent interlock

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