Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: cycling read-in of parameters should work now… this is quite tricky, and the TrackManager has to be rewritten in some parts…. :(

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