[1809] | 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 setBoundsAutoUpdated(false); 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 (10 seconds by default, settable by setBoundsAutoUpdated)
|
---|
| 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
|
---|