Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

Last change on this file since 6623 was 6623, checked in by bensch, 18 years ago

orxonox/trunk: particle Systems and Emitters are loaded and cleaned up nicely

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