Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: orxonox.OLD/branches/world_entities/src/lib/particles/particle_emitter.cc @ 5715

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

orxonox/branches/world_entities: Factory is now also able to fabricate by ClassID
for this the construction-MACRO changed from
CREATE_FACTORY(CLASS_NAME)
to
CREATE_FACTORY(CLASS_NAME, CLASS_ID)

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