Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: more load-params for Particles

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