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