source: GTP/trunk/App/Demos/Geom/include/OgreParticleSystem.h @ 1030

Revision 1030, 26.2 KB checked in by gumbau, 18 years ago (diff)

Ogre Stuff initial import

Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4        (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2005 The OGRE Team
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://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
36namespace Ogre {
37
38    /** Class defining particle system based special effects.
39    @remarks
40        Particle systems are special effects generators which are based on a
41        number of moving points to create the impression of things like like
42        sparkles, smoke, blood spurts, dust etc.
43    @par
44        This class simply manages a single collection of particles in world space
45        with a shared local origin for emission. The visual aspect of the
46        particles is handled by a ParticleSystemRenderer instance.
47    @par
48        Particle systems are created using the ParticleSystemManager methods, never directly.
49        In addition, like all subclasses of MovableObject, the ParticleSystem will only be considered for
50        rendering once it has been attached to a SceneNode.
51    */
52    class _OgreExport ParticleSystem : public StringInterface, public MovableObject
53    {
54    public:
55
56        /** Command object for quota (see ParamCommand).*/
57        class _OgrePrivate CmdQuota : public ParamCommand
58        {
59        public:
60            String doGet(const void* target) const;
61            void doSet(void* target, const String& val);
62        };
63        /** Command object for material (see ParamCommand).*/
64        class _OgrePrivate CmdMaterial : public ParamCommand
65        {
66        public:
67            String doGet(const void* target) const;
68            void doSet(void* target, const String& val);
69        };
70        /** Command object for cull_each (see ParamCommand).*/
71        class _OgrePrivate CmdCull : public ParamCommand
72        {
73        public:
74            String doGet(const void* target) const;
75            void doSet(void* target, const String& val);
76        };
77        /** Command object for particle_width (see ParamCommand).*/
78        class _OgrePrivate CmdWidth : public ParamCommand
79        {
80        public:
81            String doGet(const void* target) const;
82            void doSet(void* target, const String& val);
83        };
84        /** Command object for particle_height (see ParamCommand).*/
85        class _OgrePrivate CmdHeight : public ParamCommand
86        {
87        public:
88            String doGet(const void* target) const;
89            void doSet(void* target, const String& val);
90        };
91        /** Command object for renderer (see ParamCommand).*/
92        class _OgrePrivate CmdRenderer : public ParamCommand
93        {
94        public:
95            String doGet(const void* target) const;
96            void doSet(void* target, const String& val);
97        };
98
99        /// Default constructor required for STL creation in manager
100        ParticleSystem();
101        /** Creates a particle system with no emitters or affectors.
102        @remarks
103            You should use the ParticleSystemManager to create particle systems rather than creating
104            them directly.
105        */
106        ParticleSystem(const String& name, const String& resourceGroupName);
107
108        virtual ~ParticleSystem();
109
110        /** Sets the ParticleRenderer to be used to render this particle system.
111        @remarks
112            The main ParticleSystem just manages the creation and movement of
113            particles; they are rendered using functions in ParticleRenderer
114            and the ParticleVisual instances they create.
115                @param typeName String identifying the type of renderer to use; a new
116                        instance of this type will be created; a factory must have been registered
117                        with ParticleSystemManager.
118        */
119        void setRenderer(const String& typeName);
120
121        /** Gets the ParticleRenderer to be used to render this particle system. */
122        ParticleSystemRenderer* getRenderer(void) const;
123        /** Gets the name of the ParticleRenderer to be used to render this particle system. */
124        const String& getRendererName(void) const;
125
126        /** Adds an emitter to this particle system.
127        @remarks
128            Particles are created in a particle system by emitters - see the ParticleEmitter
129            class for more details.
130        @param
131            emitterType String identifying the emitter type to create. Emitter types are defined
132            by registering new factories with the manager - see ParticleEmitterFactory for more details.
133            Emitter types can be extended by OGRE, plugin authors or application developers.
134        */
135        ParticleEmitter* addEmitter(const String& emitterType);
136
137        /** Retrieves an emitter by it's index (zero-based).
138        @remarks
139            Used to retrieve a pointer to an emitter for a particle system to procedurally change
140            emission parameters etc.
141            You should check how many emitters are registered against this system before calling
142            this method with an arbitrary index using getNumEmitters.
143        @param
144            index Zero-based index of the emitter to retrieve.
145        */
146        ParticleEmitter* getEmitter(unsigned short index) const;
147
148        /** Returns the number of emitters for this particle system. */
149        unsigned short getNumEmitters(void) const;
150
151        /** Removes an emitter from the system.
152        @remarks
153            Drops the emitter with the index specified from this system.
154            You should check how many emitters are registered against this system before calling
155            this method with an arbitrary index using getNumEmitters.
156        @param
157            index Zero-based index of the emitter to retrieve.
158        */
159        void removeEmitter(unsigned short index);
160
161        /** Removes all the emitters from this system. */
162        void removeAllEmitters(void);
163
164
165        /** Adds an affector to this particle system.
166        @remarks
167            Particles are modified over time in a particle system by affectors - see the ParticleAffector
168            class for more details.
169        @param
170            affectorType String identifying the affector type to create. Affector types are defined
171            by registering new factories with the manager - see ParticleAffectorFactory for more details.
172            Affector types can be extended by OGRE, plugin authors or application developers.
173        */
174        ParticleAffector* addAffector(const String& affectorType);
175
176        /** Retrieves an affector by it's index (zero-based).
177        @remarks
178            Used to retrieve a pointer to an affector for a particle system to procedurally change
179            affector parameters etc.
180            You should check how many affectors are registered against this system before calling
181            this method with an arbitrary index using getNumAffectors.
182        @param
183            index Zero-based index of the affector to retrieve.
184        */
185        ParticleAffector* getAffector(unsigned short index) const;
186
187        /** Returns the number of affectors for this particle system. */
188        unsigned short getNumAffectors(void) const;
189
190        /** Removes an affector from the system.
191        @remarks
192            Drops the affector with the index specified from this system.
193            You should check how many affectors are registered against this system before calling
194            this method with an arbitrary index using getNumAffectors.
195        @param
196            index Zero-based index of the affector to retrieve.
197        */
198        void removeAffector(unsigned short index);
199
200        /** Removes all the affectors from this system. */
201        void removeAllAffectors(void);
202
203        /** Empties this set of all particles.
204        */
205        void clear();
206
207        /** Gets the number of individual particles in the system right now.
208        @remarks
209            The number of particles active in a system at a point in time depends on
210            the number of emitters, their emission rates, the time-to-live (TTL) each particle is
211            given on emission (and whether any affectors modify that TTL) and the maximum
212            number of particles allowed in this system at once (particle quota).
213        */
214        size_t getNumParticles(void) const;
215
216                /** Manually add a particle to the system.
217                @remarks
218                        Instead of using an emitter, you can manually add a particle to the system.
219                        You must initialise the returned particle instance immediately with the
220                        'emission' state.
221                @note
222                        There is no corresponding 'destroyParticle' method - if you want to dispose of a
223                        particle manually (say, if you've used setSpeedFactor(0) to make particles live forever)
224                        you should use getParticle() and modify it's timeToLive to zero, meaning that it will
225                        get cleaned up in the next update.
226                */
227                Particle* createParticle(void);
228
229                /** Retrieve a particle from the system for manual tweaking.
230                @remarks
231                        Normally you use an affector to alter particles in flight, but
232                        for small manually controlled particle systems you might want to use
233                        this method.
234                */
235                Particle* getParticle(size_t index);
236
237        /** Returns the maximum number of particles this system is allowed to have active at once.
238        @remarks
239            See ParticleSystem::setParticleQuota for more info.
240        */
241        size_t getParticleQuota(void) const;
242
243        /** Sets the maximum number of particles this system is allowed to have active at once.
244        @remarks
245            Particle systems all have a particle quota, i.e. a maximum number of particles they are
246            allowed to have active at a time. This allows the application to set a keep particle systems
247            under control should they be affected by complex parameters which alter their emission rates
248            etc. If a particle system reaches it's particle quota, none of the emitters will be able to
249            emit any more particles. As existing particles die, the spare capacity will be allocated
250            equally across all emitters to be as consistent to the origina particle system style as possible.
251        @param quota The maximum number of particles this system is allowed to have.
252        */
253        void setParticleQuota(size_t quota);
254
255
256        /** Assignment operator for copying.
257        @remarks
258            This operator deep copies all particle emitters and effectors, but not particles. The
259            system's name is also not copied.
260        */
261        ParticleSystem& operator=(const ParticleSystem& rhs);
262
263        /** Updates the particles in the system based on time elapsed.
264        @remarks
265            This is called automatically every frame by OGRE.
266        @param
267            timeElapsed The amount of time, in seconds, since the last frame.
268        */
269        void _update(Real timeElapsed);
270
271        /** Returns an iterator for stepping through all particles in this system.
272        @remarks
273            This method is designed to be used by people providing new ParticleAffector subclasses,
274            this is the easiest way to step through all the particles in a system and apply the
275            changes the affector wants to make.
276        */
277        ParticleIterator _getIterator(void);
278
279        /** Sets the name of the material to be used for this billboard set.
280            @param
281                name The new name of the material to use for this set.
282        */
283        virtual void setMaterialName(const String& name);
284
285        /** Sets the name of the material to be used for this billboard set.
286            @returns The name of the material that is used for this set.
287        */
288        virtual const String& getMaterialName(void) const;
289
290        /** Overridden from MovableObject
291            @see
292                MovableObject
293        */
294        virtual void _notifyCurrentCamera(Camera* cam);
295
296        /** Overridden from MovableObject
297        @see
298        MovableObject
299        */
300        void _notifyAttached(Node* parent, bool isTagPoint = false);
301
302        /** Overridden from MovableObject
303            @see
304                MovableObject
305        */
306        virtual const AxisAlignedBox& getBoundingBox(void) const { return mAABB; }
307
308        /** Overridden from MovableObject
309            @see
310                MovableObject
311        */
312        virtual Real getBoundingRadius(void) const { return mBoundingRadius; }
313
314        /** Overridden from MovableObject
315            @see
316                MovableObject
317        */
318        virtual void _updateRenderQueue(RenderQueue* queue);
319
320        /** Overridden from MovableObject */
321        const String& getName(void) const { return mName; }
322
323        /** Fast-forwards this system by the required number of seconds.
324        @remarks
325            This method allows you to fast-forward a system so that it effectively looks like
326            it has already been running for the time you specify. This is useful to avoid the
327            'startup sequence' of a system, when you want the system to be fully populated right
328            from the start.
329        @param
330            time The number of seconds to fast-forward by.
331        @param
332            interval The sampling interval used to generate particles, apply affectors etc. The lower this
333            is the more realistic the fast-forward, but it takes more iterations to do it.
334        */
335        void fastForward(Real time, Real interval = 0.1);
336
337                /** Sets a 'speed factor' on this particle system, which means it scales the elapsed
338                        real time which has passed by this factor before passing it to the emitters, affectors,
339                        and the particle life calculation.
340                @remarks
341                        An interesting side effect - if you want to create a completely manual particle system
342                        where you control the emission and life of particles yourself, you can set the speed
343                        factor to 0.0f, thus disabling normal particle emission, alteration, and death.
344                */
345                void setSpeedFactor(Real speedFactor) { mSpeedFactor = speedFactor; }
346
347                /** Gets the 'speed factor' on this particle system.
348                */
349                Real getSpeedFactor(void) const { return mSpeedFactor; }
350
351
352        /** Overridden from MovableObject */
353        const String& getMovableType(void) const;
354
355        /** Internal callback used by Particles to notify their parent that they have been resized.
356        */
357        virtual void _notifyParticleResized(void);
358
359        /** Internal callback used by Particles to notify their parent that they have been rotated.
360        */
361        virtual void _notifyParticleRotated(void);
362
363        /** Sets the default dimensions of the particles in this set.
364            @remarks
365                All particles in a set are created with these default dimensions. The set will render most efficiently if
366                all the particles in the set are the default size. It is possible to alter the size of individual
367                particles at the expense of extra calculation. See the Particle class for more info.
368            @param width
369                The new default width for the particles in this set.
370            @param height
371                The new default height for the particles in this set.
372        */
373        virtual void setDefaultDimensions(Real width, Real height);
374
375        /** See setDefaultDimensions - this sets 1 component individually. */
376        virtual void setDefaultWidth(Real width);
377        /** See setDefaultDimensions - this gets 1 component individually. */
378        virtual Real getDefaultWidth(void) const;
379        /** See setDefaultDimensions - this sets 1 component individually. */
380        virtual void setDefaultHeight(Real height);
381        /** See setDefaultDimensions - this gets 1 component individually. */
382        virtual Real getDefaultHeight(void) const;
383        /** Returns whether or not particles in this are tested individually for culling. */
384        virtual bool getCullIndividually(void) const;
385        /** Sets whether culling tests particles in this individually as well as in a group.
386        @remarks
387            Particle sets are always culled as a whole group, based on a bounding box which
388            encloses all particles in the set. For fairly localised sets, this is enough. However, you
389            can optionally tell the set to also cull individual particles in the set, i.e. to test
390            each individual particle before rendering. The default is not to do this.
391        @par
392            This is useful when you have a large, fairly distributed set of particles, like maybe
393            trees on a landscape. You probably still want to group them into more than one
394            set (maybe one set per section of landscape), which will be culled coarsely, but you also
395            want to cull the particles individually because they are spread out. Whilst you could have
396            lots of single-tree sets which are culled separately, this would be inefficient to render
397            because each tree would be issued as it's own rendering operation.
398        @par
399            By calling this method with a parameter of true, you can have large particle sets which
400            are spaced out and so get the benefit of batch rendering and coarse culling, but also have
401            fine-grained culling so unnecessary rendering is avoided.
402        @param cullIndividual If true, each particle is tested before being sent to the pipeline as well
403            as the whole set having to pass the coarse group bounding test.
404        */
405        virtual void setCullIndividually(bool cullIndividual);
406        /// Return the resource group to be used to load dependent resources
407        virtual const String& getResourceGroupName(void) const { return mResourceGroupName; }
408                /** Get the origin of this particle system, e.g. a script file name.
409                @remarks
410                        This property will only contain something if the creator of
411                        this particle system chose to populate it. Script loaders are advised
412                        to populate it.
413                */
414                const String& getOrigin(void) const { return mOrigin; }
415                /// Notify this particle system of it's origin
416                void _notifyOrigin(const String& origin) { mOrigin = origin; }
417
418                /** @copydoc MovableObject::setRenderQueueGroup */
419                void setRenderQueueGroup(RenderQueueGroupID queueID);
420
421        /** Set the (initial) bounds of the particle system manually.
422        @remarks
423            If you can, set the bounds of a particle system up-front and
424            call setBoundsUpdatePeriod(0); this is the most efficient way to
425            organise it. Otherwise, set an initial bounds and let the bounds increase
426            for a little while (the default is 5 seconds), after which time the
427            AABB is fixed to save time.
428        @param aabb Bounds in local space.
429        */
430        void setBounds(const AxisAlignedBox& aabb);
431
432        /** Sets whether the bounds will be automatically updated
433            for the life of the particle system
434        @remarks
435            If you have a stationary particle system, it would be a good idea to
436            call this method and set the value to 'false', since the maximum
437            bounds of the particle system will eventually be static. If you do
438            this, you can either set the bounds manually using the setBounds()
439            method, or set the second parameter of this method to a positive
440            number of seconds, so that the bounds are calculated for a few
441            seconds and then frozen.
442        @param autoUpdate If true (the default), the particle system will
443            update it's bounds every frame. If false, the bounds update will
444            cease after the 'stopIn' number of seconds have passed.
445        @param stopIn Only applicable if the first parameter is true, this is the
446            number of seconds after which the automatic update will cease.
447        */
448        void setBoundsAutoUpdated(bool autoUpdate, Real stopIn = 0.0f);
449
450        /** Internal method for updating the bounds of the particle system.
451        @remarks
452            This is called automatically for a period of time after the system's
453            creation (5 seconds by default, settable by setBoundsUpdatePeriod)
454            to increase (and only increase) the bounds of the system according
455            to the emitted and affected particles. After this period, the
456            system is assumed to achieved its maximum size, and the bounds are
457            no longer computed for efficiency. You can tweak the behaviour by
458            either setting the bounds manually (setBounds, preferred), or
459            changing the time over which the bounds are updated (performance cost).
460            You can also call this method manually if you need to update the
461            bounds on an ad-hoc basis.
462        */
463        void _updateBounds(void);
464
465    protected:
466
467        /// Command objects
468        static CmdCull msCullCmd;
469        static CmdHeight msHeightCmd;
470        static CmdMaterial msMaterialCmd;
471        static CmdQuota msQuotaCmd;
472        static CmdWidth msWidthCmd;
473        static CmdRenderer msRendererCmd;
474
475
476        AxisAlignedBox mAABB;
477        Real mBoundingRadius;
478        bool mBoundsAutoUpdate;
479        Real mBoundsUpdateTime;
480
481        /// World AABB, only used to compare world-space positions to calc bounds
482        AxisAlignedBox mWorldAABB;
483
484        /// Name of the system; used for location in the scene.
485        String mName;
486        /// Name of the resource group to use to load materials
487        String mResourceGroupName;
488        /// Name of the material to use
489        String mMaterialName;
490        /// Have we set the material etc on the renderer?
491        bool mIsRendererConfigured;
492        /// Pointer to the material to use
493        MaterialPtr mpMaterial;
494        /// Default width of each particle
495        Real mDefaultWidth;
496        /// Default height of each particle
497        Real mDefaultHeight;
498                /// Speed factor
499                Real mSpeedFactor;
500
501        typedef std::list<Particle*> ActiveParticleList;
502        typedef std::deque<Particle*> FreeParticleQueue;
503        typedef std::vector<Particle*> ParticlePool;
504
505        /** Active particle list.
506            @remarks
507                This is a linked list of pointers to particles in the particle pool.
508            @par
509                This allows very fast instertions and deletions from anywhere in
510                the list to activate / deactivate particles as well as resuse of
511                Particle instances in the pool without construction & destruction
512                which avoids memory thrashing.
513        */
514        ActiveParticleList mActiveParticles;
515
516        /** Free particle queue.
517            @remarks
518                This contains a list of the particles free for use as new instances
519                as required by the set. Particle instances are preconstructed up
520                to the estimated size in the mParticlePool vector and are
521                referenced on this deque at startup. As they get used this deque
522                reduces, as they get released back to to the set they get added back to the deque.
523        */
524        FreeParticleQueue mFreeParticles;
525
526        /** Pool of particle instances for use and reuse in the active particle list.
527            @remarks
528                This vector will be preallocated with the estimated size of the set,and will extend as required.
529        */
530        ParticlePool mParticlePool;
531
532        typedef std::vector<ParticleEmitter*> ParticleEmitterList;
533        typedef std::vector<ParticleAffector*> ParticleAffectorList;
534       
535        /// List of particle emitters, ie sources of particles
536        ParticleEmitterList mEmitters;
537        /// List of particle affectors, ie modifiers of particles
538        ParticleAffectorList mAffectors;
539
540        /// The renderer used to render this particle system
541        ParticleSystemRenderer* mRenderer;
542
543        /// Do we cull each particle individually?
544        bool mCullIndividual;
545
546        /// The name of the type of renderer used to render this system
547        String mRendererType;
548       
549        /// The number of particles in the pool.
550        size_t mPoolSize;
551
552                /// Optional origin of this particle system (eg script name)
553                String mOrigin;
554
555
556        /** Internal method used to expire dead particles. */
557        void _expire(Real timeElapsed);
558
559        /** Spawn new particles based on free quota and emitter requirements. */
560        void _triggerEmitters(Real timeElapsed);
561
562        /** Updates existing particle based on their momentum. */
563        void _applyMotion(Real timeElapsed);
564
565        /** Applies the effects of affectors. */
566        void _triggerAffectors(Real timeElapsed);
567
568        /** Resize the internal pool of particles. */
569        void increasePool(size_t size);
570
571        /** Internal method for initialising string interface. */
572        void initParameters(void);
573
574        /** Internal method to configure the renderer. */
575        void configureRenderer(void);
576
577                /// Internal method for creating ParticleVisualData instances for the pool
578                void createVisualParticles(size_t poolstart, size_t poolend);
579                /// Internal method for destroying ParticleVisualData instances for the pool
580                void destroyVisualParticles(size_t poolstart, size_t poolend);
581
582
583    };
584
585}
586
587#endif
Note: See TracBrowser for help on using the repository browser.