1 | /* |
---|
2 | ----------------------------------------------------------------------------- |
---|
3 | This source file is part of OGRE |
---|
4 | (Object-oriented Graphics Rendering Engine) |
---|
5 | For the latest info, see http://www.ogre3d.org/ |
---|
6 | |
---|
7 | Copyright (c) 2000-2006 Torus Knot Software Ltd |
---|
8 | Also see acknowledgements in Readme.html |
---|
9 | |
---|
10 | This program is free software; you can redistribute it and/or modify it under |
---|
11 | the terms of the GNU Lesser General Public License as published by the Free Software |
---|
12 | Foundation; either version 2 of the License, or (at your option) any later |
---|
13 | version. |
---|
14 | |
---|
15 | This program is distributed in the hope that it will be useful, but WITHOUT |
---|
16 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
---|
17 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. |
---|
18 | |
---|
19 | You should have received a copy of the GNU Lesser General Public License along with |
---|
20 | this program; if not, write to the Free Software Foundation, Inc., 59 Temple |
---|
21 | Place - Suite 330, Boston, MA 02111-1307, USA, or go to |
---|
22 | http://www.gnu.org/copyleft/lesser.txt. |
---|
23 | |
---|
24 | You may alternatively use this source under the terms of a specific version of |
---|
25 | the OGRE Unrestricted License provided you have obtained such a license from |
---|
26 | Torus Knot Software Ltd. |
---|
27 | ----------------------------------------------------------------------------- |
---|
28 | */ |
---|
29 | #ifndef __ParticleSystem_H__ |
---|
30 | #define __ParticleSystem_H__ |
---|
31 | |
---|
32 | #include "OgrePrerequisites.h" |
---|
33 | |
---|
34 | #include "OgreVector3.h" |
---|
35 | #include "OgreString.h" |
---|
36 | #include "OgreParticleIterator.h" |
---|
37 | #include "OgreStringInterface.h" |
---|
38 | #include "OgreMovableObject.h" |
---|
39 | #include "OgreRadixSort.h" |
---|
40 | #include "OgreController.h" |
---|
41 | |
---|
42 | |
---|
43 | namespace Ogre { |
---|
44 | |
---|
45 | /** Class defining particle system based special effects. |
---|
46 | @remarks |
---|
47 | Particle systems are special effects generators which are based on a |
---|
48 | number of moving points to create the impression of things like like |
---|
49 | sparkles, smoke, blood spurts, dust etc. |
---|
50 | @par |
---|
51 | This class simply manages a single collection of particles in world space |
---|
52 | with a shared local origin for emission. The visual aspect of the |
---|
53 | particles is handled by a ParticleSystemRenderer instance. |
---|
54 | @par |
---|
55 | Particle systems are created using the SceneManager, never directly. |
---|
56 | In addition, like all subclasses of MovableObject, the ParticleSystem |
---|
57 | will only be considered for rendering once it has been attached to a |
---|
58 | SceneNode. |
---|
59 | */ |
---|
60 | class _OgreExport ParticleSystem : public StringInterface, public MovableObject |
---|
61 | { |
---|
62 | public: |
---|
63 | |
---|
64 | /** Command object for quota (see ParamCommand).*/ |
---|
65 | class _OgrePrivate CmdQuota : public ParamCommand |
---|
66 | { |
---|
67 | public: |
---|
68 | String doGet(const void* target) const; |
---|
69 | void doSet(void* target, const String& val); |
---|
70 | }; |
---|
71 | /** Command object for emittedEmitterQuota (see ParamCommand).*/ |
---|
72 | class _OgrePrivate CmdEmittedEmitterQuota : public ParamCommand |
---|
73 | { |
---|
74 | public: |
---|
75 | String doGet(const void* target) const; |
---|
76 | void doSet(void* target, const String& val); |
---|
77 | }; |
---|
78 | /** Command object for material (see ParamCommand).*/ |
---|
79 | class _OgrePrivate CmdMaterial : public ParamCommand |
---|
80 | { |
---|
81 | public: |
---|
82 | String doGet(const void* target) const; |
---|
83 | void doSet(void* target, const String& val); |
---|
84 | }; |
---|
85 | /** Command object for cull_each (see ParamCommand).*/ |
---|
86 | class _OgrePrivate CmdCull : public ParamCommand |
---|
87 | { |
---|
88 | public: |
---|
89 | String doGet(const void* target) const; |
---|
90 | void doSet(void* target, const String& val); |
---|
91 | }; |
---|
92 | /** Command object for particle_width (see ParamCommand).*/ |
---|
93 | class _OgrePrivate CmdWidth : public ParamCommand |
---|
94 | { |
---|
95 | public: |
---|
96 | String doGet(const void* target) const; |
---|
97 | void doSet(void* target, const String& val); |
---|
98 | }; |
---|
99 | /** Command object for particle_height (see ParamCommand).*/ |
---|
100 | class _OgrePrivate CmdHeight : public ParamCommand |
---|
101 | { |
---|
102 | public: |
---|
103 | String doGet(const void* target) const; |
---|
104 | void doSet(void* target, const String& val); |
---|
105 | }; |
---|
106 | /** Command object for renderer (see ParamCommand).*/ |
---|
107 | class _OgrePrivate CmdRenderer : public ParamCommand |
---|
108 | { |
---|
109 | public: |
---|
110 | String doGet(const void* target) const; |
---|
111 | void doSet(void* target, const String& val); |
---|
112 | }; |
---|
113 | /** Command object for sorting (see ParamCommand).*/ |
---|
114 | class CmdSorted : public ParamCommand |
---|
115 | { |
---|
116 | public: |
---|
117 | String doGet(const void* target) const; |
---|
118 | void doSet(void* target, const String& val); |
---|
119 | }; |
---|
120 | /** Command object for local space (see ParamCommand).*/ |
---|
121 | class CmdLocalSpace : public ParamCommand |
---|
122 | { |
---|
123 | public: |
---|
124 | String doGet(const void* target) const; |
---|
125 | void doSet(void* target, const String& val); |
---|
126 | }; |
---|
127 | /** Command object for iteration interval(see ParamCommand).*/ |
---|
128 | class CmdIterationInterval : public ParamCommand |
---|
129 | { |
---|
130 | public: |
---|
131 | String doGet(const void* target) const; |
---|
132 | void doSet(void* target, const String& val); |
---|
133 | }; |
---|
134 | /** Command object for nonvisible timeout (see ParamCommand).*/ |
---|
135 | class CmdNonvisibleTimeout : public ParamCommand |
---|
136 | { |
---|
137 | public: |
---|
138 | String doGet(const void* target) const; |
---|
139 | void doSet(void* target, const String& val); |
---|
140 | }; |
---|
141 | |
---|
142 | /// Default constructor required for STL creation in manager |
---|
143 | ParticleSystem(); |
---|
144 | /** Creates a particle system with no emitters or affectors. |
---|
145 | @remarks |
---|
146 | You should use the ParticleSystemManager to create particle systems rather than creating |
---|
147 | them directly. |
---|
148 | */ |
---|
149 | ParticleSystem(const String& name, const String& resourceGroupName); |
---|
150 | |
---|
151 | virtual ~ParticleSystem(); |
---|
152 | |
---|
153 | /** Sets the ParticleRenderer to be used to render this particle system. |
---|
154 | @remarks |
---|
155 | The main ParticleSystem just manages the creation and movement of |
---|
156 | particles; they are rendered using functions in ParticleRenderer |
---|
157 | and the ParticleVisual instances they create. |
---|
158 | @param typeName String identifying the type of renderer to use; a new |
---|
159 | instance of this type will be created; a factory must have been registered |
---|
160 | with ParticleSystemManager. |
---|
161 | */ |
---|
162 | void setRenderer(const String& typeName); |
---|
163 | |
---|
164 | /** Gets the ParticleRenderer to be used to render this particle system. */ |
---|
165 | ParticleSystemRenderer* getRenderer(void) const; |
---|
166 | /** Gets the name of the ParticleRenderer to be used to render this particle system. */ |
---|
167 | const String& getRendererName(void) const; |
---|
168 | |
---|
169 | /** Adds an emitter to this particle system. |
---|
170 | @remarks |
---|
171 | Particles are created in a particle system by emitters - see the ParticleEmitter |
---|
172 | class for more details. |
---|
173 | @param |
---|
174 | emitterType String identifying the emitter type to create. Emitter types are defined |
---|
175 | by registering new factories with the manager - see ParticleEmitterFactory for more details. |
---|
176 | Emitter types can be extended by OGRE, plugin authors or application developers. |
---|
177 | */ |
---|
178 | ParticleEmitter* addEmitter(const String& emitterType); |
---|
179 | |
---|
180 | /** Retrieves an emitter by it's index (zero-based). |
---|
181 | @remarks |
---|
182 | Used to retrieve a pointer to an emitter for a particle system to procedurally change |
---|
183 | emission parameters etc. |
---|
184 | You should check how many emitters are registered against this system before calling |
---|
185 | this method with an arbitrary index using getNumEmitters. |
---|
186 | @param |
---|
187 | index Zero-based index of the emitter to retrieve. |
---|
188 | */ |
---|
189 | ParticleEmitter* getEmitter(unsigned short index) const; |
---|
190 | |
---|
191 | /** Returns the number of emitters for this particle system. */ |
---|
192 | unsigned short getNumEmitters(void) const; |
---|
193 | |
---|
194 | /** Removes an emitter from the system. |
---|
195 | @remarks |
---|
196 | Drops the emitter with the index specified from this system. |
---|
197 | You should check how many emitters are registered against this system before calling |
---|
198 | this method with an arbitrary index using getNumEmitters. |
---|
199 | @param |
---|
200 | index Zero-based index of the emitter to retrieve. |
---|
201 | */ |
---|
202 | void removeEmitter(unsigned short index); |
---|
203 | |
---|
204 | /** Removes all the emitters from this system. */ |
---|
205 | void removeAllEmitters(void); |
---|
206 | |
---|
207 | |
---|
208 | /** Adds an affector to this particle system. |
---|
209 | @remarks |
---|
210 | Particles are modified over time in a particle system by affectors - see the ParticleAffector |
---|
211 | class for more details. |
---|
212 | @param |
---|
213 | affectorType String identifying the affector type to create. Affector types are defined |
---|
214 | by registering new factories with the manager - see ParticleAffectorFactory for more details. |
---|
215 | Affector types can be extended by OGRE, plugin authors or application developers. |
---|
216 | */ |
---|
217 | ParticleAffector* addAffector(const String& affectorType); |
---|
218 | |
---|
219 | /** Retrieves an affector by it's index (zero-based). |
---|
220 | @remarks |
---|
221 | Used to retrieve a pointer to an affector for a particle system to procedurally change |
---|
222 | affector parameters etc. |
---|
223 | You should check how many affectors are registered against this system before calling |
---|
224 | this method with an arbitrary index using getNumAffectors. |
---|
225 | @param |
---|
226 | index Zero-based index of the affector to retrieve. |
---|
227 | */ |
---|
228 | ParticleAffector* getAffector(unsigned short index) const; |
---|
229 | |
---|
230 | /** Returns the number of affectors for this particle system. */ |
---|
231 | unsigned short getNumAffectors(void) const; |
---|
232 | |
---|
233 | /** Removes an affector from the system. |
---|
234 | @remarks |
---|
235 | Drops the affector with the index specified from this system. |
---|
236 | You should check how many affectors are registered against this system before calling |
---|
237 | this method with an arbitrary index using getNumAffectors. |
---|
238 | @param |
---|
239 | index Zero-based index of the affector to retrieve. |
---|
240 | */ |
---|
241 | void removeAffector(unsigned short index); |
---|
242 | |
---|
243 | /** Removes all the affectors from this system. */ |
---|
244 | void removeAllAffectors(void); |
---|
245 | |
---|
246 | /** Empties this set of all particles. |
---|
247 | */ |
---|
248 | void clear(); |
---|
249 | |
---|
250 | /** Gets the number of individual particles in the system right now. |
---|
251 | @remarks |
---|
252 | The number of particles active in a system at a point in time depends on |
---|
253 | the number of emitters, their emission rates, the time-to-live (TTL) each particle is |
---|
254 | given on emission (and whether any affectors modify that TTL) and the maximum |
---|
255 | number of particles allowed in this system at once (particle quota). |
---|
256 | */ |
---|
257 | size_t getNumParticles(void) const; |
---|
258 | |
---|
259 | /** Manually add a particle to the system. |
---|
260 | @remarks |
---|
261 | Instead of using an emitter, you can manually add a particle to the system. |
---|
262 | You must initialise the returned particle instance immediately with the |
---|
263 | 'emission' state. |
---|
264 | @note |
---|
265 | There is no corresponding 'destroyParticle' method - if you want to dispose of a |
---|
266 | particle manually (say, if you've used setSpeedFactor(0) to make particles live forever) |
---|
267 | you should use getParticle() and modify it's timeToLive to zero, meaning that it will |
---|
268 | get cleaned up in the next update. |
---|
269 | */ |
---|
270 | Particle* createParticle(void); |
---|
271 | |
---|
272 | /** Manually add an emitter particle to the system. |
---|
273 | @remarks |
---|
274 | The purpose of a particle emitter is to emit particles. Besides visual particles, also other other |
---|
275 | particle types can be emitted, other emitters for example. The emitted emitters have a double role; |
---|
276 | they behave as particles and can be influenced by affectors, but they are still emitters and capable |
---|
277 | to emit other particles (or emitters). It is possible to create a chain of emitters - emitters |
---|
278 | emitting other emitters, which also emit emitters. |
---|
279 | @param emitterName The name of a particle emitter that must be emitted. |
---|
280 | */ |
---|
281 | Particle* createEmitterParticle(const String& emitterName); |
---|
282 | |
---|
283 | /** Retrieve a particle from the system for manual tweaking. |
---|
284 | @remarks |
---|
285 | Normally you use an affector to alter particles in flight, but |
---|
286 | for small manually controlled particle systems you might want to use |
---|
287 | this method. |
---|
288 | */ |
---|
289 | Particle* getParticle(size_t index); |
---|
290 | |
---|
291 | /** Returns the maximum number of particles this system is allowed to have active at once. |
---|
292 | @remarks |
---|
293 | See ParticleSystem::setParticleQuota for more info. |
---|
294 | */ |
---|
295 | size_t getParticleQuota(void) const; |
---|
296 | |
---|
297 | /** Sets the maximum number of particles this system is allowed to have active at once. |
---|
298 | @remarks |
---|
299 | Particle systems all have a particle quota, i.e. a maximum number of particles they are |
---|
300 | allowed to have active at a time. This allows the application to set a keep particle systems |
---|
301 | under control should they be affected by complex parameters which alter their emission rates |
---|
302 | etc. If a particle system reaches it's particle quota, none of the emitters will be able to |
---|
303 | emit any more particles. As existing particles die, the spare capacity will be allocated |
---|
304 | equally across all emitters to be as consistent to the origina particle system style as possible. |
---|
305 | @param quota The maximum number of particles this system is allowed to have. |
---|
306 | */ |
---|
307 | void setParticleQuota(size_t quota); |
---|
308 | |
---|
309 | /** Returns the maximum number of emitted emitters this system is allowed to have active at once. |
---|
310 | @remarks |
---|
311 | See ParticleSystem::setEmittedEmitterQuota for more info. |
---|
312 | */ |
---|
313 | size_t getEmittedEmitterQuota(void) const; |
---|
314 | |
---|
315 | /** Sets the maximum number of emitted emitters this system is allowed to have active at once. |
---|
316 | @remarks |
---|
317 | Particle systems can have - besides a particle quota - also an emitted emitter quota. |
---|
318 | @param quota The maximum number of emitted emitters this system is allowed to have. |
---|
319 | */ |
---|
320 | void setEmittedEmitterQuota(size_t quota); |
---|
321 | |
---|
322 | /** Assignment operator for copying. |
---|
323 | @remarks |
---|
324 | This operator deep copies all particle emitters and effectors, but not particles. The |
---|
325 | system's name is also not copied. |
---|
326 | */ |
---|
327 | ParticleSystem& operator=(const ParticleSystem& rhs); |
---|
328 | |
---|
329 | /** Updates the particles in the system based on time elapsed. |
---|
330 | @remarks |
---|
331 | This is called automatically every frame by OGRE. |
---|
332 | @param |
---|
333 | timeElapsed The amount of time, in seconds, since the last frame. |
---|
334 | */ |
---|
335 | void _update(Real timeElapsed); |
---|
336 | |
---|
337 | /** Returns an iterator for stepping through all particles in this system. |
---|
338 | @remarks |
---|
339 | This method is designed to be used by people providing new ParticleAffector subclasses, |
---|
340 | this is the easiest way to step through all the particles in a system and apply the |
---|
341 | changes the affector wants to make. |
---|
342 | */ |
---|
343 | ParticleIterator _getIterator(void); |
---|
344 | |
---|
345 | /** Sets the name of the material to be used for this billboard set. |
---|
346 | @param |
---|
347 | name The new name of the material to use for this set. |
---|
348 | */ |
---|
349 | virtual void setMaterialName(const String& name); |
---|
350 | |
---|
351 | /** Sets the name of the material to be used for this billboard set. |
---|
352 | @returns The name of the material that is used for this set. |
---|
353 | */ |
---|
354 | virtual const String& getMaterialName(void) const; |
---|
355 | |
---|
356 | /** Overridden from MovableObject |
---|
357 | @see |
---|
358 | MovableObject |
---|
359 | */ |
---|
360 | virtual void _notifyCurrentCamera(Camera* cam); |
---|
361 | |
---|
362 | /** Overridden from MovableObject |
---|
363 | @see |
---|
364 | MovableObject |
---|
365 | */ |
---|
366 | void _notifyAttached(Node* parent, bool isTagPoint = false); |
---|
367 | |
---|
368 | /** Overridden from MovableObject |
---|
369 | @see |
---|
370 | MovableObject |
---|
371 | */ |
---|
372 | virtual const AxisAlignedBox& getBoundingBox(void) const { return mAABB; } |
---|
373 | |
---|
374 | /** Overridden from MovableObject |
---|
375 | @see |
---|
376 | MovableObject |
---|
377 | */ |
---|
378 | virtual Real getBoundingRadius(void) const { return mBoundingRadius; } |
---|
379 | |
---|
380 | /** Overridden from MovableObject |
---|
381 | @see |
---|
382 | MovableObject |
---|
383 | */ |
---|
384 | virtual void _updateRenderQueue(RenderQueue* queue); |
---|
385 | |
---|
386 | /** Fast-forwards this system by the required number of seconds. |
---|
387 | @remarks |
---|
388 | This method allows you to fast-forward a system so that it effectively looks like |
---|
389 | it has already been running for the time you specify. This is useful to avoid the |
---|
390 | 'startup sequence' of a system, when you want the system to be fully populated right |
---|
391 | from the start. |
---|
392 | @param |
---|
393 | time The number of seconds to fast-forward by. |
---|
394 | @param |
---|
395 | interval The sampling interval used to generate particles, apply affectors etc. The lower this |
---|
396 | is the more realistic the fast-forward, but it takes more iterations to do it. |
---|
397 | */ |
---|
398 | void fastForward(Real time, Real interval = 0.1); |
---|
399 | |
---|
400 | /** Sets a 'speed factor' on this particle system, which means it scales the elapsed |
---|
401 | real time which has passed by this factor before passing it to the emitters, affectors, |
---|
402 | and the particle life calculation. |
---|
403 | @remarks |
---|
404 | An interesting side effect - if you want to create a completely manual particle system |
---|
405 | where you control the emission and life of particles yourself, you can set the speed |
---|
406 | factor to 0.0f, thus disabling normal particle emission, alteration, and death. |
---|
407 | */ |
---|
408 | void setSpeedFactor(Real speedFactor) { mSpeedFactor = speedFactor; } |
---|
409 | |
---|
410 | /** Gets the 'speed factor' on this particle system. |
---|
411 | */ |
---|
412 | Real getSpeedFactor(void) const { return mSpeedFactor; } |
---|
413 | |
---|
414 | /** Sets a 'iteration interval' on this particle system. |
---|
415 | @remarks |
---|
416 | The default Particle system update interval, based on elapsed frame time, |
---|
417 | will cause different behavior between low frame-rate and high frame-rate. |
---|
418 | By using this option, you can make the particle system update at |
---|
419 | a fixed interval, keeping the behavior the same no matter what frame-rate |
---|
420 | is. |
---|
421 | @par |
---|
422 | When iteration interval is set to zero, it means the update occurs based |
---|
423 | on an elapsed frame time, otherwise each iteration will take place |
---|
424 | at the given interval, repeating until it has used up all the elapsed |
---|
425 | frame time. |
---|
426 | @param |
---|
427 | iterationInterval The iteration interval, default to zero. |
---|
428 | */ |
---|
429 | void setIterationInterval(Real iterationInterval); |
---|
430 | |
---|
431 | /** Gets a 'iteration interval' on this particle system. |
---|
432 | */ |
---|
433 | Real getIterationInterval(void) const { return mIterationInterval; } |
---|
434 | |
---|
435 | /** Set the default iteration interval for all ParticleSystem instances. |
---|
436 | */ |
---|
437 | static void setDefaultIterationInterval(Real iterationInterval) { msDefaultIterationInterval = iterationInterval; } |
---|
438 | |
---|
439 | /** Get the default iteration interval for all ParticleSystem instances. |
---|
440 | */ |
---|
441 | static Real getDefaultIterationInterval(void) { return msDefaultIterationInterval; } |
---|
442 | |
---|
443 | /** Sets when the particle system should stop updating after it hasn't been |
---|
444 | visible for a while. |
---|
445 | @remarks |
---|
446 | By default, visible particle systems update all the time, even when |
---|
447 | not in view. This means that they are guaranteed to be consistent when |
---|
448 | they do enter view. However, this comes at a cost, updating particle |
---|
449 | systems can be expensive, especially if they are perpetual. |
---|
450 | @par |
---|
451 | This option lets you set a 'timeout' on the particle system, so that |
---|
452 | if it isn't visible for this amount of time, it will stop updating |
---|
453 | until it is next visible. |
---|
454 | @param timeout The time after which the particle system will be disabled |
---|
455 | if it is no longer visible. 0 to disable the timeout and always update. |
---|
456 | */ |
---|
457 | void setNonVisibleUpdateTimeout(Real timeout); |
---|
458 | /** Gets when the particle system should stop updating after it hasn't been |
---|
459 | visible for a while. |
---|
460 | */ |
---|
461 | Real getNonVisibleUpdateTimeout(void) const { return mNonvisibleTimeout; } |
---|
462 | |
---|
463 | /** Set the default nonvisible timeout for all ParticleSystem instances. |
---|
464 | */ |
---|
465 | static void setDefaultNonVisibleUpdateTimeout(Real timeout) |
---|
466 | { msDefaultNonvisibleTimeout = timeout; } |
---|
467 | |
---|
468 | /** Get the default nonvisible timeout for all ParticleSystem instances. |
---|
469 | */ |
---|
470 | static Real getDefaultNonVisibleUpdateTimeout(void) { return msDefaultNonvisibleTimeout; } |
---|
471 | |
---|
472 | /** Overridden from MovableObject */ |
---|
473 | const String& getMovableType(void) const; |
---|
474 | |
---|
475 | /** Internal callback used by Particles to notify their parent that they have been resized. |
---|
476 | */ |
---|
477 | virtual void _notifyParticleResized(void); |
---|
478 | |
---|
479 | /** Internal callback used by Particles to notify their parent that they have been rotated. |
---|
480 | */ |
---|
481 | virtual void _notifyParticleRotated(void); |
---|
482 | |
---|
483 | /** Sets the default dimensions of the particles in this set. |
---|
484 | @remarks |
---|
485 | All particles in a set are created with these default dimensions. The set will render most efficiently if |
---|
486 | all the particles in the set are the default size. It is possible to alter the size of individual |
---|
487 | particles at the expense of extra calculation. See the Particle class for more info. |
---|
488 | @param width |
---|
489 | The new default width for the particles in this set. |
---|
490 | @param height |
---|
491 | The new default height for the particles in this set. |
---|
492 | */ |
---|
493 | virtual void setDefaultDimensions(Real width, Real height); |
---|
494 | |
---|
495 | /** See setDefaultDimensions - this sets 1 component individually. */ |
---|
496 | virtual void setDefaultWidth(Real width); |
---|
497 | /** See setDefaultDimensions - this gets 1 component individually. */ |
---|
498 | virtual Real getDefaultWidth(void) const; |
---|
499 | /** See setDefaultDimensions - this sets 1 component individually. */ |
---|
500 | virtual void setDefaultHeight(Real height); |
---|
501 | /** See setDefaultDimensions - this gets 1 component individually. */ |
---|
502 | virtual Real getDefaultHeight(void) const; |
---|
503 | /** Returns whether or not particles in this are tested individually for culling. */ |
---|
504 | virtual bool getCullIndividually(void) const; |
---|
505 | /** Sets whether culling tests particles in this individually as well as in a group. |
---|
506 | @remarks |
---|
507 | Particle sets are always culled as a whole group, based on a bounding box which |
---|
508 | encloses all particles in the set. For fairly localised sets, this is enough. However, you |
---|
509 | can optionally tell the set to also cull individual particles in the set, i.e. to test |
---|
510 | each individual particle before rendering. The default is not to do this. |
---|
511 | @par |
---|
512 | This is useful when you have a large, fairly distributed set of particles, like maybe |
---|
513 | trees on a landscape. You probably still want to group them into more than one |
---|
514 | set (maybe one set per section of landscape), which will be culled coarsely, but you also |
---|
515 | want to cull the particles individually because they are spread out. Whilst you could have |
---|
516 | lots of single-tree sets which are culled separately, this would be inefficient to render |
---|
517 | because each tree would be issued as it's own rendering operation. |
---|
518 | @par |
---|
519 | By calling this method with a parameter of true, you can have large particle sets which |
---|
520 | are spaced out and so get the benefit of batch rendering and coarse culling, but also have |
---|
521 | fine-grained culling so unnecessary rendering is avoided. |
---|
522 | @param cullIndividual If true, each particle is tested before being sent to the pipeline as well |
---|
523 | as the whole set having to pass the coarse group bounding test. |
---|
524 | */ |
---|
525 | virtual void setCullIndividually(bool cullIndividual); |
---|
526 | /// Return the resource group to be used to load dependent resources |
---|
527 | virtual const String& getResourceGroupName(void) const { return mResourceGroupName; } |
---|
528 | /** Get the origin of this particle system, e.g. a script file name. |
---|
529 | @remarks |
---|
530 | This property will only contain something if the creator of |
---|
531 | this particle system chose to populate it. Script loaders are advised |
---|
532 | to populate it. |
---|
533 | */ |
---|
534 | const String& getOrigin(void) const { return mOrigin; } |
---|
535 | /// Notify this particle system of it's origin |
---|
536 | void _notifyOrigin(const String& origin) { mOrigin = origin; } |
---|
537 | |
---|
538 | /** @copydoc MovableObject::setRenderQueueGroup */ |
---|
539 | void setRenderQueueGroup(uint8 queueID); |
---|
540 | |
---|
541 | /** Set whether or not particles are sorted according to the camera. |
---|
542 | @remarks |
---|
543 | Enabling sorting alters the order particles are sent to the renderer. |
---|
544 | When enabled, particles are sent to the renderer in order of |
---|
545 | furthest distance from the camera. |
---|
546 | */ |
---|
547 | void setSortingEnabled(bool enabled) { mSorted = enabled; } |
---|
548 | /// Gets whether particles are sorted relative to the camera. |
---|
549 | bool getSortingEnabled(void) const { return mSorted; } |
---|
550 | |
---|
551 | /** Set the (initial) bounds of the particle system manually. |
---|
552 | @remarks |
---|
553 | If you can, set the bounds of a particle system up-front and |
---|
554 | call setBoundsAutoUpdated(false); this is the most efficient way to |
---|
555 | organise it. Otherwise, set an initial bounds and let the bounds increase |
---|
556 | for a little while (the default is 5 seconds), after which time the |
---|
557 | AABB is fixed to save time. |
---|
558 | @param aabb Bounds in local space. |
---|
559 | */ |
---|
560 | void setBounds(const AxisAlignedBox& aabb); |
---|
561 | |
---|
562 | /** Sets whether the bounds will be automatically updated |
---|
563 | for the life of the particle system |
---|
564 | @remarks |
---|
565 | If you have a stationary particle system, it would be a good idea to |
---|
566 | call this method and set the value to 'false', since the maximum |
---|
567 | bounds of the particle system will eventually be static. If you do |
---|
568 | this, you can either set the bounds manually using the setBounds() |
---|
569 | method, or set the second parameter of this method to a positive |
---|
570 | number of seconds, so that the bounds are calculated for a few |
---|
571 | seconds and then frozen. |
---|
572 | @param autoUpdate If true (the default), the particle system will |
---|
573 | update it's bounds every frame. If false, the bounds update will |
---|
574 | cease after the 'stopIn' number of seconds have passed. |
---|
575 | @param stopIn Only applicable if the first parameter is true, this is the |
---|
576 | number of seconds after which the automatic update will cease. |
---|
577 | */ |
---|
578 | void setBoundsAutoUpdated(bool autoUpdate, Real stopIn = 0.0f); |
---|
579 | |
---|
580 | /** Sets whether particles (and any affector effects) remain relative |
---|
581 | to the node the particle system is attached to. |
---|
582 | @remarks |
---|
583 | By defalt particles are in world space once emitted, so they are not |
---|
584 | affected by movement in the parent node of the particle system. This |
---|
585 | makes the most sense when dealing with completely independent particles, |
---|
586 | but if you want to constrain them to follow local motion too, you |
---|
587 | can set this to true. |
---|
588 | */ |
---|
589 | void setKeepParticlesInLocalSpace(bool keepLocal); |
---|
590 | |
---|
591 | /** Gets whether particles (and any affector effects) remain relative |
---|
592 | to the node the particle system is attached to. |
---|
593 | */ |
---|
594 | bool getKeepParticlesInLocalSpace(void) const { return mLocalSpace; } |
---|
595 | |
---|
596 | /** Internal method for updating the bounds of the particle system. |
---|
597 | @remarks |
---|
598 | This is called automatically for a period of time after the system's |
---|
599 | creation (10 seconds by default, settable by setBoundsAutoUpdated) |
---|
600 | to increase (and only increase) the bounds of the system according |
---|
601 | to the emitted and affected particles. After this period, the |
---|
602 | system is assumed to achieved its maximum size, and the bounds are |
---|
603 | no longer computed for efficiency. You can tweak the behaviour by |
---|
604 | either setting the bounds manually (setBounds, preferred), or |
---|
605 | changing the time over which the bounds are updated (performance cost). |
---|
606 | You can also call this method manually if you need to update the |
---|
607 | bounds on an ad-hoc basis. |
---|
608 | */ |
---|
609 | void _updateBounds(void); |
---|
610 | |
---|
611 | /// Override to return specific type flag |
---|
612 | uint32 getTypeFlags(void) const; |
---|
613 | protected: |
---|
614 | |
---|
615 | /// Command objects |
---|
616 | static CmdCull msCullCmd; |
---|
617 | static CmdHeight msHeightCmd; |
---|
618 | static CmdMaterial msMaterialCmd; |
---|
619 | static CmdQuota msQuotaCmd; |
---|
620 | static CmdEmittedEmitterQuota msEmittedEmitterQuotaCmd; |
---|
621 | static CmdWidth msWidthCmd; |
---|
622 | static CmdRenderer msRendererCmd; |
---|
623 | static CmdSorted msSortedCmd; |
---|
624 | static CmdLocalSpace msLocalSpaceCmd; |
---|
625 | static CmdIterationInterval msIterationIntervalCmd; |
---|
626 | static CmdNonvisibleTimeout msNonvisibleTimeoutCmd; |
---|
627 | |
---|
628 | |
---|
629 | AxisAlignedBox mAABB; |
---|
630 | Real mBoundingRadius; |
---|
631 | bool mBoundsAutoUpdate; |
---|
632 | Real mBoundsUpdateTime; |
---|
633 | Real mUpdateRemainTime; |
---|
634 | |
---|
635 | /// World AABB, only used to compare world-space positions to calc bounds |
---|
636 | AxisAlignedBox mWorldAABB; |
---|
637 | |
---|
638 | /// Name of the resource group to use to load materials |
---|
639 | String mResourceGroupName; |
---|
640 | /// Name of the material to use |
---|
641 | String mMaterialName; |
---|
642 | /// Have we set the material etc on the renderer? |
---|
643 | bool mIsRendererConfigured; |
---|
644 | /// Pointer to the material to use |
---|
645 | MaterialPtr mpMaterial; |
---|
646 | /// Default width of each particle |
---|
647 | Real mDefaultWidth; |
---|
648 | /// Default height of each particle |
---|
649 | Real mDefaultHeight; |
---|
650 | /// Speed factor |
---|
651 | Real mSpeedFactor; |
---|
652 | /// Iteration interval |
---|
653 | Real mIterationInterval; |
---|
654 | /// Iteration interval set? Otherwise track default |
---|
655 | bool mIterationIntervalSet; |
---|
656 | /// Particles sorted according to camera? |
---|
657 | bool mSorted; |
---|
658 | /// Particles in local space? |
---|
659 | bool mLocalSpace; |
---|
660 | /// Update timeout when nonvisible (0 for no timeout) |
---|
661 | Real mNonvisibleTimeout; |
---|
662 | /// Update timeout when nonvisible set? Otherwise track default |
---|
663 | bool mNonvisibleTimeoutSet; |
---|
664 | /// Amount of time non-visible so far |
---|
665 | Real mTimeSinceLastVisible; |
---|
666 | /// Last frame in which known to be visible |
---|
667 | unsigned long mLastVisibleFrame; |
---|
668 | /// Controller for time update |
---|
669 | Controller<Real>* mTimeController; |
---|
670 | /// Indication whether the emitted emitter pool (= pool with particle emitters that are emitted) is initialised |
---|
671 | bool mEmittedEmitterPoolInitialised; |
---|
672 | |
---|
673 | typedef std::list<Particle*> ActiveParticleList; |
---|
674 | typedef std::list<Particle*> FreeParticleList; |
---|
675 | typedef std::vector<Particle*> ParticlePool; |
---|
676 | |
---|
677 | /** Sort by direction functor */ |
---|
678 | struct SortByDirectionFunctor |
---|
679 | { |
---|
680 | /// Direction to sort in |
---|
681 | Vector3 sortDir; |
---|
682 | |
---|
683 | SortByDirectionFunctor(const Vector3& dir); |
---|
684 | float operator()(Particle* p) const; |
---|
685 | }; |
---|
686 | |
---|
687 | /** Sort by distance functor */ |
---|
688 | struct SortByDistanceFunctor |
---|
689 | { |
---|
690 | /// Position to sort in |
---|
691 | Vector3 sortPos; |
---|
692 | |
---|
693 | SortByDistanceFunctor(const Vector3& pos); |
---|
694 | float operator()(Particle* p) const; |
---|
695 | }; |
---|
696 | |
---|
697 | static RadixSort<ActiveParticleList, Particle*, float> mRadixSorter; |
---|
698 | |
---|
699 | /** Active particle list. |
---|
700 | @remarks |
---|
701 | This is a linked list of pointers to particles in the particle pool. |
---|
702 | @par |
---|
703 | This allows very fast instertions and deletions from anywhere in |
---|
704 | the list to activate / deactivate particles as well as resuse of |
---|
705 | Particle instances in the pool without construction & destruction |
---|
706 | which avoids memory thrashing. |
---|
707 | */ |
---|
708 | ActiveParticleList mActiveParticles; |
---|
709 | |
---|
710 | /** Free particle queue. |
---|
711 | @remarks |
---|
712 | This contains a list of the particles free for use as new instances |
---|
713 | as required by the set. Particle instances are preconstructed up |
---|
714 | to the estimated size in the mParticlePool vector and are |
---|
715 | referenced on this deque at startup. As they get used this list |
---|
716 | reduces, as they get released back to to the set they get added |
---|
717 | back to the list. |
---|
718 | */ |
---|
719 | FreeParticleList mFreeParticles; |
---|
720 | |
---|
721 | /** Pool of particle instances for use and reuse in the active particle list. |
---|
722 | @remarks |
---|
723 | This vector will be preallocated with the estimated size of the set,and will extend as required. |
---|
724 | */ |
---|
725 | ParticlePool mParticlePool; |
---|
726 | |
---|
727 | typedef std::list<ParticleEmitter*> FreeEmittedEmitterList; |
---|
728 | typedef std::list<ParticleEmitter*> ActiveEmittedEmitterList; |
---|
729 | typedef std::vector<ParticleEmitter*> EmittedEmitterList; |
---|
730 | typedef std::map<String, FreeEmittedEmitterList> FreeEmittedEmitterMap; |
---|
731 | typedef std::map<String, EmittedEmitterList> EmittedEmitterPool; |
---|
732 | |
---|
733 | /** Pool of emitted emitters for use and reuse in the active emitted emitter list. |
---|
734 | @remarks |
---|
735 | The emitters in this pool act as particles and as emitters. The pool is a map containing lists |
---|
736 | of emitters, identified by their name. |
---|
737 | @par |
---|
738 | The emitters in this pool are cloned using emitters that are kept in the main emitter list |
---|
739 | of the ParticleSystem. |
---|
740 | */ |
---|
741 | EmittedEmitterPool mEmittedEmitterPool; |
---|
742 | |
---|
743 | /** Free emitted emitter list. |
---|
744 | @remarks |
---|
745 | This contains a list of the emitters free for use as new instances as required by the set. |
---|
746 | */ |
---|
747 | FreeEmittedEmitterMap mFreeEmittedEmitters; |
---|
748 | |
---|
749 | /** Active emitted emitter list. |
---|
750 | @remarks |
---|
751 | This is a linked list of pointers to emitters in the emitted emitter pool. |
---|
752 | Emitters that are used are stored (their pointers) in both the list with active particles and in |
---|
753 | the list with active emitted emitters. */ |
---|
754 | ActiveEmittedEmitterList mActiveEmittedEmitters; |
---|
755 | |
---|
756 | typedef std::vector<ParticleEmitter*> ParticleEmitterList; |
---|
757 | typedef std::vector<ParticleAffector*> ParticleAffectorList; |
---|
758 | |
---|
759 | /// List of particle emitters, ie sources of particles |
---|
760 | ParticleEmitterList mEmitters; |
---|
761 | /// List of particle affectors, ie modifiers of particles |
---|
762 | ParticleAffectorList mAffectors; |
---|
763 | |
---|
764 | /// The renderer used to render this particle system |
---|
765 | ParticleSystemRenderer* mRenderer; |
---|
766 | |
---|
767 | /// Do we cull each particle individually? |
---|
768 | bool mCullIndividual; |
---|
769 | |
---|
770 | /// The name of the type of renderer used to render this system |
---|
771 | String mRendererType; |
---|
772 | |
---|
773 | /// The number of particles in the pool. |
---|
774 | size_t mPoolSize; |
---|
775 | |
---|
776 | /// The number of emitted emitters in the pool. |
---|
777 | size_t mEmittedEmitterPoolSize; |
---|
778 | |
---|
779 | /// Optional origin of this particle system (eg script name) |
---|
780 | String mOrigin; |
---|
781 | |
---|
782 | /// Default iteration interval |
---|
783 | static Real msDefaultIterationInterval; |
---|
784 | /// Default nonvisible update timeout |
---|
785 | static Real msDefaultNonvisibleTimeout; |
---|
786 | |
---|
787 | /** Internal method used to expire dead particles. */ |
---|
788 | void _expire(Real timeElapsed); |
---|
789 | |
---|
790 | /** Spawn new particles based on free quota and emitter requirements. */ |
---|
791 | void _triggerEmitters(Real timeElapsed); |
---|
792 | |
---|
793 | /** Helper function that actually performs the emission of particles |
---|
794 | */ |
---|
795 | void _executeTriggerEmitters(ParticleEmitter* emitter, unsigned requested, Real timeElapsed); |
---|
796 | |
---|
797 | /** Updates existing particle based on their momentum. */ |
---|
798 | void _applyMotion(Real timeElapsed); |
---|
799 | |
---|
800 | /** Applies the effects of affectors. */ |
---|
801 | void _triggerAffectors(Real timeElapsed); |
---|
802 | |
---|
803 | /** Sort the particles in the system **/ |
---|
804 | void _sortParticles(Camera* cam); |
---|
805 | |
---|
806 | /** Resize the internal pool of particles. */ |
---|
807 | void increasePool(size_t size); |
---|
808 | |
---|
809 | /** Resize the internal pool of emitted emitters. |
---|
810 | @remarks |
---|
811 | The pool consists of multiple vectors containing pointers to particle emitters. Increasing the |
---|
812 | pool with ´size´ implies that the vectors are equally increased. The quota of emitted emitters is |
---|
813 | defined on a particle system level and not on a particle emitter level. This is to prevent that |
---|
814 | the number of created emitters becomes too high; the quota is shared amongst the emitted emitters. |
---|
815 | */ |
---|
816 | void increaseEmittedEmitterPool(size_t size); |
---|
817 | |
---|
818 | /** Internal method for initialising string interface. */ |
---|
819 | void initParameters(void); |
---|
820 | |
---|
821 | /** Internal method to configure the renderer. */ |
---|
822 | void configureRenderer(void); |
---|
823 | |
---|
824 | /// Internal method for creating ParticleVisualData instances for the pool |
---|
825 | void createVisualParticles(size_t poolstart, size_t poolend); |
---|
826 | /// Internal method for destroying ParticleVisualData instances for the pool |
---|
827 | void destroyVisualParticles(size_t poolstart, size_t poolend); |
---|
828 | |
---|
829 | /** Create a pool of emitted emitters and assign them to the free emitter list. |
---|
830 | @remarks |
---|
831 | The emitters in the pool are grouped by name. This name is the name of the base emitter in the |
---|
832 | main list with particle emitters, which forms the template of the created emitted emitters. |
---|
833 | */ |
---|
834 | void initialiseEmittedEmitters(void); |
---|
835 | |
---|
836 | /** Determine which emitters in the Particle Systems main emitter become a template for creating an |
---|
837 | pool of emitters that can be emitted. |
---|
838 | */ |
---|
839 | void initialiseEmittedEmitterPool(void); |
---|
840 | |
---|
841 | /** Add emitters from the pool to the free emitted emitter queue. */ |
---|
842 | void addFreeEmittedEmitters(void); |
---|
843 | |
---|
844 | /** Removes all emitted emitters from this system. */ |
---|
845 | void removeAllEmittedEmitters(void); |
---|
846 | |
---|
847 | /** Find the list with free emitted emitters. |
---|
848 | @param name The name that identifies the list with free emitted emitters. |
---|
849 | */ |
---|
850 | FreeEmittedEmitterList* findFreeEmittedEmitter (const String& name); |
---|
851 | |
---|
852 | /** Removes an emitter from the active emitted emitter list. |
---|
853 | @remarks |
---|
854 | The emitter will not be destroyed! |
---|
855 | @param emitter Pointer to a particle emitter. |
---|
856 | */ |
---|
857 | void removeFromActiveEmittedEmitters (ParticleEmitter* emitter); |
---|
858 | |
---|
859 | /** Moves all emitted emitters from the active list to the free list |
---|
860 | @remarks |
---|
861 | The active emitted emitter list will not be cleared and still keeps references to the emitters! |
---|
862 | */ |
---|
863 | void addActiveEmittedEmittersToFreeList (void); |
---|
864 | |
---|
865 | /** This function clears all data structures that are used in combination with emitted emitters and |
---|
866 | sets the flag to indicate that the emitted emitter pool must be initialised again. |
---|
867 | @remarks |
---|
868 | This function should be called if new emitters are added to a ParticleSystem or deleted from a |
---|
869 | ParticleSystem. The emitted emitter data structures become out of sync and need to be build up |
---|
870 | again. The data structures are not reorganised in this function, but by setting a ´flag´, |
---|
871 | they are rebuild in the regular process flow. |
---|
872 | */ |
---|
873 | void _notifyReorganiseEmittedEmitterData (void); |
---|
874 | }; |
---|
875 | |
---|
876 | } |
---|
877 | |
---|
878 | #endif |
---|