Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: ParticleEmitter completely loadable

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