Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

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

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

orxonox/trunk: particles documented

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