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