ParticleSys.h 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818
  1. /*
  2. ** Command & Conquer Generals Zero Hour(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. ////////////////////////////////////////////////////////////////////////////////
  19. // //
  20. // (c) 2001-2003 Electronic Arts Inc. //
  21. // //
  22. ////////////////////////////////////////////////////////////////////////////////
  23. // ParticleSys.h //////////////////////////////////////////////////////////////////////////////////
  24. // Particle System type definitions
  25. // Author: Michael S. Booth, November 2001
  26. ///////////////////////////////////////////////////////////////////////////////////////////////////
  27. #pragma once
  28. #ifndef _PARTICLE_SYS_H_
  29. #define _PARTICLE_SYS_H_
  30. #include <stdio.h>
  31. #include "Common/AsciiString.h"
  32. #include "Common/GameMemory.h"
  33. #include "Common/GameType.h"
  34. #include "Common/Snapshot.h"
  35. #include "Common/SubsystemInterface.h"
  36. #include "GameClient/ClientRandomValue.h"
  37. #include "WWMath/Matrix3D.h" ///< @todo Replace with our own matrix library
  38. #include "Common/STLTypedefs.h"
  39. /// @todo Once the client framerate is decoupled, the frame counters within will have to become time-based
  40. class Particle;
  41. class ParticleSystem;
  42. class ParticleSystemManager;
  43. class Drawable;
  44. class Object;
  45. struct FieldParse;
  46. class INI;
  47. class DebugWindowDialog; // really ParticleEditorDialog
  48. class RenderInfoClass; // ick
  49. enum ParticleSystemID
  50. {
  51. INVALID_PARTICLE_SYSTEM_ID = 0
  52. };
  53. #define MAX_VOLUME_PARTICLE_DEPTH ( 16 )
  54. #define DEFAULT_VOLUME_PARTICLE_DEPTH ( 0 )//The Default is not to do the volume thing!
  55. #define OPTIMUM_VOLUME_PARTICLE_DEPTH ( 6 )
  56. //--------------------------------------------------------------------------------------------------------------
  57. enum { MAX_KEYFRAMES=8 };
  58. struct Keyframe
  59. {
  60. Real value;
  61. UnsignedInt frame;
  62. };
  63. struct RGBColorKeyframe
  64. {
  65. RGBColor color;
  66. UnsignedInt frame;
  67. };
  68. enum ParticlePriorityType
  69. {
  70. INVALID_PRIORITY = 0,
  71. PARTICLE_PRIORITY_LOWEST = 1,
  72. // FLUFF = PARTICLE_PRIORITY_LOWEST, ///< total and absolute fluff
  73. // DEBRIS, ///< debris related particles
  74. // NATURE, ///< neato effects we just might see in the world
  75. // WEAPON, ///< Weapons firing and flying in the air
  76. // DAMAGE, ///< taking damage/dying explosions
  77. // SPECIAL, ///< super special top priority like a superweapon
  78. WEAPON_EXPLOSION = PARTICLE_PRIORITY_LOWEST,
  79. SCORCHMARK,
  80. DUST_TRAIL,
  81. BUILDUP,
  82. DEBRIS_TRAIL,
  83. UNIT_DAMAGE_FX,
  84. DEATH_EXPLOSION,
  85. SEMI_CONSTANT,
  86. CONSTANT,
  87. WEAPON_TRAIL,
  88. AREA_EFFECT,
  89. CRITICAL, ///< super special top priority like a superweapon
  90. ALWAYS_RENDER, ///< used for logically important display (not just fluff), so must never be culled, regardless of particle cap, lod, etc
  91. // !!! *Noting* goes here ... special is the top priority !!!
  92. PARTICLE_PRIORITY_HIGHEST = ALWAYS_RENDER,
  93. NUM_PARTICLE_PRIORITIES ///< Keep this last
  94. };
  95. /**
  96. * This structure is filled out and passed to the constructor of a Particle to initialize it
  97. */
  98. class ParticleInfo : public Snapshot
  99. {
  100. public:
  101. ParticleInfo( void );
  102. Coord3D m_vel; ///< initial velocity
  103. Coord3D m_pos; ///< initial position
  104. Coord3D m_emitterPos; ///< position of the emitter
  105. Real m_velDamping; ///< velocity damping coefficient
  106. Real m_angleZ; ///< initial angle around Z axis
  107. Real m_angularRateZ; ///< initial angle around Z axis
  108. Real m_angularDamping; ///< angular velocity damping coefficient
  109. UnsignedInt m_lifetime; ///< lifetime of this particle
  110. Real m_size; ///< size of the particle
  111. Real m_sizeRate; ///< rate of change of size
  112. Real m_sizeRateDamping; ///< damping of size change rate
  113. Keyframe m_alphaKey[ MAX_KEYFRAMES ];
  114. RGBColorKeyframe m_colorKey[ MAX_KEYFRAMES ];
  115. Real m_colorScale; ///< color "scaling" coefficient
  116. Real m_windRandomness; ///< multiplier for wind randomness per particle
  117. Bool m_particleUpTowardsEmitter; ///< if this is true, then the 0.0 Z rotation should actually
  118. ///< correspond to the direction of the emitter.
  119. protected:
  120. // snapshot methods
  121. virtual void crc( Xfer *xfer );
  122. virtual void xfer( Xfer *xfer );
  123. virtual void loadPostProcess( void );
  124. };
  125. /**
  126. * An individual particle created by a ParticleSystem.
  127. * NOTE: Particles cannot exist without a parent particle system.
  128. */
  129. class Particle : public MemoryPoolObject,
  130. public ParticleInfo
  131. {
  132. MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( Particle, "ParticlePool" )
  133. public:
  134. Particle( ParticleSystem *system, const ParticleInfo *data );
  135. inline Bool update( void ); ///< update this particle's behavior - return false if dead
  136. void doWindMotion( void ); ///< do wind motion (if present) from particle system
  137. void applyForce( const Coord3D *force ); ///< add the given acceleration
  138. inline const Coord3D *getPosition( void ) { return &m_pos; }
  139. inline Real getSize( void ) { return m_size; }
  140. inline Real getAngle( void ) { return m_angleZ; }
  141. inline Real getAlpha( void ) { return m_alpha; }
  142. inline const RGBColor *getColor( void ) { return &m_color; }
  143. inline void setColor( RGBColor *color ) { m_color = *color; }
  144. inline Bool isInvisible( void ); ///< return true if this particle is invisible
  145. inline Bool isCulled (void) {return m_isCulled;} ///< return true if the particle falls off the edge of the screen
  146. inline void setIsCulled (Bool enable) { m_isCulled = enable;} ///< set particle to not visible because it's outside view frustum
  147. void controlParticleSystem( ParticleSystem *sys ) { m_systemUnderControl = sys; }
  148. void detachControlledParticleSystem( void ) { m_systemUnderControl = NULL; }
  149. // get priority of this particle ... which is the priority of the system it belongs to
  150. ParticlePriorityType getPriority( void );
  151. UnsignedInt getPersonality(void) { return m_personality; };
  152. void setPersonality(UnsignedInt p) { m_personality = p; };
  153. protected:
  154. // snapshot methods
  155. virtual void crc( Xfer *xfer );
  156. virtual void xfer( Xfer *xfer );
  157. virtual void loadPostProcess( void );
  158. void computeAlphaRate( void ); ///< compute alpha rate to get to next key
  159. void computeColorRate( void ); ///< compute color change to get to next key
  160. public:
  161. Particle * m_systemNext;
  162. Particle * m_systemPrev;
  163. Particle * m_overallNext;
  164. Particle * m_overallPrev;
  165. protected:
  166. ParticleSystem * m_system; ///< the particle system this particle belongs to
  167. UnsignedInt m_personality; ///< each new particle assigned a number one higher than the previous
  168. // most of the particle data is derived from ParticleInfo
  169. Coord3D m_accel; ///< current acceleration
  170. Coord3D m_lastPos; ///< previous position
  171. UnsignedInt m_lifetimeLeft; ///< lifetime remaining, if zero -> destroy
  172. UnsignedInt m_createTimestamp; ///< frame this particle was created
  173. Real m_alpha; ///< current alpha of this particle
  174. Real m_alphaRate; ///< current rate of alpha change
  175. Int m_alphaTargetKey; ///< next index into key array
  176. RGBColor m_color; ///< current color of this particle
  177. RGBColor m_colorRate; ///< current rate of color change
  178. Int m_colorTargetKey; ///< next index into key array
  179. Bool m_isCulled; ///< status of particle relative to screen bounds
  180. public:
  181. Bool m_inSystemList;
  182. Bool m_inOverallList;
  183. union
  184. {
  185. ParticleSystem * m_systemUnderControl; ///< the particle system attached to this particle (not the system that created us)
  186. ParticleSystemID m_systemUnderControlID; ///< id of system attached to this particle (not the system that created us);
  187. };
  188. };
  189. //--------------------------------------------------------------------------------------------------------------
  190. #ifdef DEFINE_PARTICLE_SYSTEM_NAMES
  191. /**** NOTE: These MUST be kept in sync with the enumerations below *****/
  192. static char *ParticleShaderTypeNames[] =
  193. {
  194. "NONE", "ADDITIVE", "ALPHA", "ALPHA_TEST", "MULTIPLY", NULL
  195. };
  196. static char *ParticleTypeNames[] =
  197. {
  198. "NONE", "PARTICLE", "DRAWABLE", "STREAK", "VOLUME_PARTICLE","SMUDGE", NULL
  199. };
  200. static char *EmissionVelocityTypeNames[] =
  201. {
  202. "NONE", "ORTHO", "SPHERICAL", "HEMISPHERICAL", "CYLINDRICAL", "OUTWARD", NULL
  203. };
  204. static char *EmissionVolumeTypeNames[] =
  205. {
  206. "NONE", "POINT", "LINE", "BOX", "SPHERE", "CYLINDER", NULL
  207. };
  208. //"NONE", "FLUFF", "DEBRIS", "NATURE", "WEAPON", "DAMAGE", "SPECIAL"
  209. static char *ParticlePriorityNames[] =
  210. {
  211. "NONE", "WEAPON_EXPLOSION","SCORCHMARK","DUST_TRAIL","BUILDUP","DEBRIS_TRAIL","UNIT_DAMAGE_FX","DEATH_EXPLOSION","SEMI_CONSTANT","CONSTANT","WEAPON_TRAIL","AREA_EFFECT","CRITICAL", "ALWAYS_RENDER", NULL
  212. };
  213. static char *WindMotionNames[] =
  214. {
  215. "NONE", "Unused", "PingPong", "Circular", NULL
  216. };
  217. #endif
  218. /**
  219. * All of the properties of a particle system, used by both ParticleSystemTemplates
  220. * and ParticleSystem classes.
  221. */
  222. class ParticleSystemInfo : public Snapshot
  223. {
  224. public:
  225. ParticleSystemInfo(); ///< to set defaults.
  226. // snapshot methods
  227. virtual void crc( Xfer *xfer );
  228. virtual void xfer( Xfer *xfer );
  229. virtual void loadPostProcess( void );
  230. Bool m_isOneShot; ///< if true, destroy system after one burst has occurred
  231. enum ParticleShaderType
  232. {
  233. INVALID_SHADER=0, ADDITIVE, ALPHA, ALPHA_TEST, MULTIPLY
  234. }
  235. m_shaderType; ///< how this particle is rendered
  236. enum ParticleType
  237. {
  238. INVALID_TYPE=0, PARTICLE, DRAWABLE, STREAK, VOLUME_PARTICLE, SMUDGE ///< is a particle a 2D-screen-facing particle, or a Drawable, or a Segment in a streak?
  239. }
  240. m_particleType;
  241. AsciiString m_particleTypeName; ///< if PARTICLE, texture filename, if DRAWABLE, Drawable name
  242. GameClientRandomVariable m_angleZ; ///< initial angle around Z axis
  243. GameClientRandomVariable m_angularRateZ; ///< initial angle around Z axis
  244. GameClientRandomVariable m_angularDamping; ///< angular velocity damping coefficient
  245. GameClientRandomVariable m_velDamping; ///< velocity damping factor
  246. GameClientRandomVariable m_lifetime; ///< lifetime of emitted particles
  247. UnsignedInt m_systemLifetime; ///< lifetime of the particle system
  248. GameClientRandomVariable m_startSize; ///< initial size of emitted particles
  249. GameClientRandomVariable m_startSizeRate; ///< change in start size of emitted particles
  250. GameClientRandomVariable m_sizeRate; ///< rate of change of size
  251. GameClientRandomVariable m_sizeRateDamping; ///< damping of size change
  252. UnsignedInt m_volumeParticleDepth; ///< how many layers deep to draw the particle, if >1
  253. struct RandomKeyframe
  254. {
  255. GameClientRandomVariable var; ///< the range of values at this keyframe
  256. UnsignedInt frame; ///< the frame number
  257. };
  258. RandomKeyframe m_alphaKey[ MAX_KEYFRAMES ];
  259. RGBColorKeyframe m_colorKey[ MAX_KEYFRAMES ]; ///< color of particle
  260. typedef Int Color;
  261. void tintAllColors( Color tintColor );
  262. GameClientRandomVariable m_colorScale; ///< color coefficient
  263. GameClientRandomVariable m_burstDelay; ///< time between particle emissions
  264. GameClientRandomVariable m_burstCount; ///< number of particles emitted per burst
  265. GameClientRandomVariable m_initialDelay; ///< delay before particles begin emitting
  266. Coord3D m_driftVelocity; ///< additional velocity added to all particles
  267. Real m_gravity; ///< gravity acceleration (global Z) for particles in this system
  268. AsciiString m_slaveSystemName; ///< if non-empty, create a system whose particles track this system's
  269. Coord3D m_slavePosOffset; ///< positional offset of slave particles relative to master's
  270. AsciiString m_attachedSystemName; ///< if non-empty, create a system attached to each particle of this system
  271. //-------------------------------------------------------
  272. // The direction and speed at which particles are emitted
  273. enum EmissionVelocityType
  274. {
  275. INVALID_VELOCITY=0, ORTHO, SPHERICAL, HEMISPHERICAL, CYLINDRICAL, OUTWARD
  276. }
  277. m_emissionVelocityType;
  278. ParticlePriorityType m_priority;
  279. union
  280. {
  281. struct
  282. {
  283. GameClientRandomVariable x; ///< initial speed of particle along X axis
  284. GameClientRandomVariable y; ///< initial speed of particle along Y axis
  285. GameClientRandomVariable z; ///< initial speed of particle along Z axis
  286. }
  287. ortho;
  288. struct
  289. {
  290. GameClientRandomVariable speed; ///< initial speed of particle along random radial direction
  291. }
  292. spherical, hemispherical;
  293. struct
  294. {
  295. GameClientRandomVariable radial; ///< initial speed of particle in the disk
  296. GameClientRandomVariable normal; ///< initial speed of particle perpendicular to disk
  297. }
  298. cylindrical;
  299. struct
  300. {
  301. GameClientRandomVariable speed; ///< speed outward from emission volume
  302. GameClientRandomVariable otherSpeed; ///< speed along "other" axis, such as cylinder length
  303. }
  304. outward;
  305. }
  306. m_emissionVelocity;
  307. //----------------------------------------------------------
  308. // The volume of space where particles are initially created
  309. // Note that the volume is relative to the system's position and orientation
  310. enum EmissionVolumeType
  311. {
  312. INVALID_VOLUME=0, POINT, LINE, BOX, SPHERE, CYLINDER
  313. }
  314. m_emissionVolumeType; ///< the type of volume where particles are created
  315. union emissionVolumeUnion
  316. {
  317. // point just uses system's position
  318. // line
  319. struct
  320. {
  321. Coord3D start, end;
  322. }
  323. line;
  324. // box
  325. struct
  326. {
  327. Coord3D halfSize;
  328. }
  329. box;
  330. // sphere
  331. struct
  332. {
  333. Real radius;
  334. }
  335. sphere;
  336. // cylinder
  337. struct
  338. {
  339. Real radius;
  340. Real length;
  341. }
  342. cylinder;
  343. }
  344. m_emissionVolume; ///< the dimensions of the emission volume
  345. Bool m_isEmissionVolumeHollow; ///< if true, only create particles at boundary of volume
  346. Bool m_isGroundAligned; ///< if true, align with the ground. if false, then do the normal billboarding.
  347. Bool m_isEmitAboveGroundOnly; ///< if true, only emit particles when the system is above ground.
  348. Bool m_isParticleUpTowardsEmitter; ///< if true, align the up direction to be towards the emitter.
  349. enum WindMotion
  350. {
  351. WIND_MOTION_INVALID = 0,
  352. WIND_MOTION_NOT_USED,
  353. WIND_MOTION_PING_PONG,
  354. WIND_MOTION_CIRCULAR
  355. };
  356. WindMotion m_windMotion; ///< motion of the wind angle updating
  357. Real m_windAngle; ///< angle of the "wind" associated with this system
  358. Real m_windAngleChange; ///< current how fast the angle changes (higher=faster change)
  359. Real m_windAngleChangeMin; ///< min for angle change
  360. Real m_windAngleChangeMax; ///< max for angle change
  361. Real m_windMotionStartAngle; ///< (for ping pong) angle 1 of the ping pong
  362. Real m_windMotionStartAngleMin; ///< (for ping pong) min angle for angle 1
  363. Real m_windMotionStartAngleMax; ///< (for ping pong) max angle for angle 1
  364. Real m_windMotionEndAngle; ///< (for ping pong) angle 2 of the ping pong
  365. Real m_windMotionEndAngleMin; ///< (for ping pong) min angle for angle 2
  366. Real m_windMotionEndAngleMax; ///< (for ping pong) max angel for angle 2
  367. Byte m_windMotionMovingToEndAngle; ///< (for ping pong) TRUE if we're moving "towards" the end angle
  368. };
  369. /**
  370. * A ParticleSystemTemplate, used by the ParticleSystemManager to instantiate ParticleSystems.
  371. */
  372. class ParticleSystemTemplate : public MemoryPoolObject, protected ParticleSystemInfo
  373. {
  374. MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( ParticleSystemTemplate, "ParticleSystemTemplatePool" )
  375. public:
  376. ParticleSystemTemplate( const AsciiString &name );
  377. AsciiString getName( void ) const { return m_name; }
  378. // This function was made const because of update modules' module data being all const.
  379. ParticleSystem *createSlaveSystem( Bool createSlaves = TRUE ) const ; ///< if returns non-NULL, it is a slave system for use
  380. const FieldParse *getFieldParse( void ) const { return m_fieldParseTable; } ///< Parsing from INI access
  381. static void parseRGBColorKeyframe( INI* ini, void *instance, void *store, const void* /*userData*/ );
  382. static void parseRandomKeyframe( INI* ini, void *instance, void *store, const void* /*userData*/ );
  383. static void parseRandomRGBColor( INI* ini, void *instance, void *store, const void* /*userData*/ );
  384. static void parseRandomRGBColorRate( INI* ini, void *instance, void *store, const void* /*userData*/ );
  385. protected:
  386. friend class ParticleSystemManager; ///< @todo remove this friendship
  387. friend class ParticleSystem; ///< @todo remove this friendship
  388. // These friendships are naughty but necessary for particle editing.
  389. friend class DebugWindowDialog; ///< @todo remove this friendship when no longer editing particles
  390. friend void _updateAsciiStringParmsToSystem(ParticleSystemTemplate *particleTemplate);
  391. friend void _updateAsciiStringParmsFromSystem(ParticleSystemTemplate *particleTemplate);
  392. friend void _writeSingleParticleSystem( File *out, ParticleSystemTemplate *templ );
  393. static const FieldParse m_fieldParseTable[]; ///< the parse table for INI definition
  394. protected:
  395. AsciiString m_name; ///< the name of this template
  396. // This has to be mutable because of the delayed initialization thing in createSlaveSystem
  397. mutable const ParticleSystemTemplate *m_slaveTemplate; ///< if non-NULL, use this to create a slave system
  398. // template attribute data inherited from ParticleSystemInfo class
  399. };
  400. /**
  401. * A particle system, responsible for creating Particles.
  402. * If a particle system has finished, but still has particles "in the air", it must wait
  403. * before destroying itself in order to ensure everything can be cleaned up if the system
  404. * is reset.
  405. */
  406. class ParticleSystem : public MemoryPoolObject,
  407. public ParticleSystemInfo
  408. {
  409. MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( ParticleSystem, "ParticleSystemPool" )
  410. public:
  411. ParticleSystem( const ParticleSystemTemplate *sysTemplate,
  412. ParticleSystemID id,
  413. Bool createSlaves ); ///< create a particle system from a template and assign it this ID
  414. inline ParticleSystemID getSystemID( void ) const { return m_systemID; } ///< get unique system ID
  415. void setPosition( const Coord3D *pos ); ///< set the position of the particle system
  416. void getPosition( Coord3D *pos ); ///< get the position of the particle system
  417. void setLocalTransform( const Matrix3D *matrix ); ///< set the system's local transform
  418. void rotateLocalTransformX( Real x ); ///< rotate local transform matrix
  419. void rotateLocalTransformY( Real y ); ///< rotate local transform matrix
  420. void rotateLocalTransformZ( Real z ); ///< rotate local transform matrix
  421. void setSkipParentXfrm(Bool enable) { m_skipParentXfrm = enable; } ///<disable transforming particle system with parent matrix.
  422. const Coord3D *getDriftVelocity( void ) { return &m_driftVelocity; } ///< get the drift velocity of the system
  423. void attachToDrawable( const Drawable *draw ); ///< attach this particle system to a Drawable
  424. void attachToObject( const Object *obj ); ///< attach this particle system to an Object
  425. virtual Bool update( Int localPlayerIndex ); ///< update this particle system, return false if dead
  426. void updateWindMotion( void ); ///< update wind motion
  427. void setControlParticle( Particle *p ); ///< set control particle
  428. void start( void ); ///< (re)start a stopped particle system
  429. void stop( void ); ///< stop a particle system from emitting
  430. void destroy( void ); ///< stop emitting, and wait for particles to die, then destroy self
  431. void setVelocityMultiplier( const Coord3D *value ) { m_velCoeff = *value; } ///< set the velocity multiplier coefficient
  432. const Coord3D *getVelocityMultiplier( void ) { return &m_velCoeff; } ///< get the velocity multiplier coefficient
  433. void setBurstCountMultiplier( Real value ) { m_countCoeff = value; }
  434. Real getBurstCountMultiplier( void ) { return m_countCoeff; }
  435. void setBurstDelayMultiplier( Real value ) { m_delayCoeff = value; }
  436. Real getBurstDelayMultiplier( void ) { return m_delayCoeff; }
  437. void setSizeMultiplier( Real value ) { m_sizeCoeff = value; }
  438. Real getSizeMultiplier( void ) { return m_sizeCoeff; }
  439. /// Force a burst of particles to be emitted immediately.
  440. void trigger (void) { m_burstDelayLeft = 0; m_delayLeft = 0;}
  441. void setInitialDelay( UnsignedInt delay ) { m_delayLeft = delay; }
  442. AsciiString getParticleTypeName( void ) { return m_particleTypeName; } ///< return the name of the particles
  443. Bool isUsingDrawables( void ) { return (m_particleType == DRAWABLE) ? true : false; }
  444. Bool isUsingStreak( void ) { return (m_particleType == STREAK) ? true : false; }
  445. Bool isUsingSmudge( void ) { return (m_particleType == SMUDGE) ? true : false; }
  446. UnsignedInt getVolumeParticleDepth( void ) { return ( m_particleType == VOLUME_PARTICLE ) ? OPTIMUM_VOLUME_PARTICLE_DEPTH : 0; }
  447. Bool shouldBillboard( void ) { return !m_isGroundAligned; }
  448. ParticleShaderType getShaderType( void ) { return m_shaderType; }
  449. void setSlave( ParticleSystem *slave ); ///< set a slave system for us
  450. ParticleSystem *getSlave( void ) { return m_slaveSystem; }
  451. void setMaster( ParticleSystem *master ); ///< make this a slave with a master
  452. ParticleSystem *getMaster( void ) { return m_masterSystem; }
  453. const Coord3D *getSlavePositionOffset( void ) { return &m_slavePosOffset; }
  454. void setSystemLifetime( UnsignedInt frames ) { m_systemLifetimeLeft = frames; }; ///< not the particle life, the system!... Lorenzen
  455. void setLifetimeRange( Real min, Real max );
  456. Bool isSystemForever() const {return m_isForever;}
  457. UnsignedInt getStartFrame( void ) { return m_startTimestamp; } ///< return frame when this system was created
  458. Bool isDestroyed( void ) const { return m_isDestroyed; }
  459. void setSaveable( Bool b );
  460. Bool isSaveable( void ) const { return m_isSaveable; }
  461. /// called when the particle this system is controlled by dies
  462. void detachControlParticle( Particle *p ) { m_controlParticle = NULL; }
  463. /// called to merge two systems info. If slaveNeedsFullPromotion is true, then the slave needs to be aware of how many particles
  464. /// to generate as well.
  465. static ParticleInfo mergeRelatedParticleSystems( ParticleSystem *masterParticleSystem, ParticleSystem *slaveParticleSystem, Bool slaveNeedsFullPromotion);
  466. /// @todo Const this (MSB)
  467. const ParticleSystemTemplate *getTemplate( void ) { return m_template; } ///< get the template used to create this system
  468. // @todo Const this jkmcd
  469. Particle *getFirstParticle( void ) { return m_systemParticlesHead; }
  470. void addParticle( Particle *particleToAdd );
  471. /// when a particle dies, it calls this method - ONLY FOR USE BY PARTICLE
  472. void removeParticle( Particle *p );
  473. UnsignedInt getParticleCount( void ) const { return m_particleCount; }
  474. inline ObjectID getAttachedObject( void ) { return m_attachedToObjectID; }
  475. inline DrawableID getAttachedDrawable( void ) { return m_attachedToDrawableID; }
  476. // Access to dynamically changing part of a particle system.
  477. void setEmissionVolumeSphereRadius( Real newRadius ) { if (m_emissionVolumeType == SPHERE) m_emissionVolume.sphere.radius = newRadius; }
  478. void setEmissionVolumeCylinderRadius( Real newRadius ) { if (m_emissionVolumeType == CYLINDER) m_emissionVolume.cylinder.radius = newRadius; }
  479. EmissionVolumeType getEmisionVolumeType() const { return m_emissionVolumeType; }
  480. ParticlePriorityType getPriority() const { return m_priority; }
  481. // Access to wind motoin
  482. Real getWindAngle( void ) { return m_windAngle; }
  483. WindMotion getWindMotion( void ) { return m_windMotion; }
  484. protected:
  485. // snapshot methods
  486. virtual void crc( Xfer *xfer );
  487. virtual void xfer( Xfer *xfer );
  488. virtual void loadPostProcess( void );
  489. virtual Particle *createParticle( const ParticleInfo *data,
  490. ParticlePriorityType priority,
  491. Bool forceCreate = FALSE ); ///< factory method for particles
  492. const ParticleInfo *generateParticleInfo( Int particleNum, Int particleCount ); ///< generate a new, random set of ParticleInfo
  493. const Coord3D *computeParticlePosition( void ); ///< compute a position based on emission properties
  494. const Coord3D *computeParticleVelocity( const Coord3D *pos ); ///< compute a velocity vector based on emission properties
  495. const Coord3D *computePointOnUnitSphere( void ); ///< compute a random point on a unit sphere
  496. protected:
  497. Particle * m_systemParticlesHead;
  498. Particle * m_systemParticlesTail;
  499. UnsignedInt m_particleCount; ///< current count of particles for this system
  500. ParticleSystemID m_systemID; ///< unique id given to this system from the particle system manager
  501. DrawableID m_attachedToDrawableID; ///< if non-zero, system is parented to this Drawable
  502. ObjectID m_attachedToObjectID; ///< if non-zero, system is parented to this Object
  503. Matrix3D m_localTransform; ///< local orientation & position of system
  504. Matrix3D m_transform; ///< composite transform of parent Drawable and local
  505. UnsignedInt m_burstDelayLeft; ///< when zero, emit a particle burst
  506. UnsignedInt m_delayLeft; ///< decremented until zero
  507. UnsignedInt m_startTimestamp; ///< timestamp when this particle system was (re)started
  508. UnsignedInt m_systemLifetimeLeft; ///< lifetime remaining for entire particle system
  509. UnsignedInt m_personalityStore; ///< increments each time it is aggigned to each new particle
  510. ///< so that each particle gets an ever greater number
  511. Real m_accumulatedSizeBonus; ///< For a system that wants to make particles start bigger and bigger. StartSizeRate
  512. Coord3D m_velCoeff; ///< scalar value multiplied by all velocity parameters
  513. Real m_countCoeff; ///< scalar value multiplied by burst count
  514. Real m_delayCoeff; ///< scalar value multiplied by burst delay
  515. Real m_sizeCoeff; ///< scalar value multiplied by initial size
  516. Coord3D m_pos; ///< this is the position to emit at.
  517. Coord3D m_lastPos; ///< this is the previous position we emitted at.
  518. ParticleSystem * m_slaveSystem; ///< if non-NULL, another system this one has control of
  519. ParticleSystemID m_slaveSystemID; ///< id of slave system (if present)
  520. ParticleSystem * m_masterSystem; ///< if non-NULL, the system that controls this one
  521. ParticleSystemID m_masterSystemID; ///< master system id (if present);
  522. const ParticleSystemTemplate * m_template; ///< the template this system was constructed from
  523. Particle * m_controlParticle; ///< if non-NULL, this system is controlled by this particle
  524. Bool m_isLocalIdentity; ///< if true, the matrix can be ignored
  525. Bool m_isIdentity; ///< if true, the matrix can be ignored
  526. Bool m_isForever; ///< System has infinite lifetime
  527. Bool m_isStopped; ///< if stopped, do not emit particles
  528. Bool m_isDestroyed; ///< are we destroyed and waiting for particles to die
  529. Bool m_isFirstPos; ///< true if this system hasn't been drawn before.
  530. Bool m_isSaveable; ///< true if this system should be saved/loaded
  531. Bool m_skipParentXfrm; ///< true if this system is already in world space.
  532. // the actual particle system data is inherited from ParticleSystemInfo
  533. };
  534. //--------------------------------------------------------------------------------------------------------------
  535. /**
  536. * The particle system manager, responsible for maintaining all ParticleSystems
  537. */
  538. class ParticleSystemManager : public SubsystemInterface,
  539. public Snapshot
  540. {
  541. public:
  542. typedef std::list<ParticleSystem*> ParticleSystemList;
  543. typedef std::list<ParticleSystem*>::iterator ParticleSystemListIt;
  544. typedef std::hash_map<AsciiString, ParticleSystemTemplate *, rts::hash<AsciiString>, rts::equal_to<AsciiString> > TemplateMap;
  545. ParticleSystemManager( void );
  546. virtual ~ParticleSystemManager();
  547. virtual void init( void ); ///< initialize the manager
  548. virtual void reset( void ); ///< reset the manager and all particle systems
  549. virtual void update( void ); ///< update all particle systems
  550. virtual Int getOnScreenParticleCount( void ) = 0; ///< returns the number of particles on screen
  551. virtual void setOnScreenParticleCount(int count);
  552. ParticleSystemTemplate *findTemplate( const AsciiString &name ) const;
  553. ParticleSystemTemplate *findParentTemplate( const AsciiString &name, int parentNum ) const;
  554. ParticleSystemTemplate *newTemplate( const AsciiString &name );
  555. /// given a template, instantiate a particle system
  556. ParticleSystem *createParticleSystem( const ParticleSystemTemplate *sysTemplate,
  557. Bool createSlaves = TRUE );
  558. /** given a template, instantiate a particle system.
  559. if attachTo is not null, attach the particle system to the given object.
  560. return the particle system's ID, NOT its pointer.
  561. */
  562. ParticleSystemID createAttachedParticleSystemID( const ParticleSystemTemplate *sysTemplate,
  563. Object* attachTo,
  564. Bool createSlaves = TRUE );
  565. /// find a particle system given a unique system identifier
  566. ParticleSystem *findParticleSystem( ParticleSystemID id );
  567. /// destroy the particle system with the given id (if it still exists)
  568. void destroyParticleSystemByID(ParticleSystemID id);
  569. /// return iterators to the particle system template
  570. TemplateMap::iterator beginParticleSystemTemplate() { return m_templateMap.begin(); }
  571. TemplateMap::iterator endParticleSystemTemplate() { return m_templateMap.end(); }
  572. TemplateMap::const_iterator beginParticleSystemTemplate() const { return m_templateMap.begin(); }
  573. TemplateMap::const_iterator endParticleSystemTemplate() const { return m_templateMap.end(); }
  574. /// destroy attached systems to object
  575. void destroyAttachedSystems( Object *obj );
  576. void setLocalPlayerIndex(Int index) {m_localPlayerIndex=index;}
  577. void addParticle( Particle *particleToAdd, ParticlePriorityType priority );
  578. void removeParticle( Particle *particleToRemove );
  579. Int removeOldestParticles( UnsignedInt count, ParticlePriorityType priorityCap );
  580. UnsignedInt getParticleCount( void ) const { return m_particleCount; }
  581. UnsignedInt getFieldParticleCount( void ) const { return m_fieldParticleCount; }
  582. UnsignedInt getParticleSystemCount( void ) const { return m_particleSystemCount; }
  583. // @todo const this jkmcd
  584. ParticleSystemList &getAllParticleSystems( void ) { return m_allParticleSystemList; }
  585. virtual void doParticles(RenderInfoClass &rinfo) = 0;
  586. virtual void queueParticleRender() = 0;
  587. virtual void preloadAssets( TimeOfDay timeOfDay );
  588. // these are only for use by partcle systems to link and unlink themselves
  589. void friend_addParticleSystem( ParticleSystem *particleSystemToAdd );
  590. void friend_removeParticleSystem( ParticleSystem *particleSystemToRemove );
  591. protected:
  592. // snapshot methods
  593. virtual void crc( Xfer *xfer );
  594. virtual void xfer( Xfer *xfer );
  595. virtual void loadPostProcess( void );
  596. Particle *m_allParticlesHead[ NUM_PARTICLE_PRIORITIES ];
  597. Particle *m_allParticlesTail[ NUM_PARTICLE_PRIORITIES ];
  598. ParticleSystemID m_uniqueSystemID; ///< unique system ID to assign to each system created
  599. ParticleSystemList m_allParticleSystemList;
  600. UnsignedInt m_particleCount;
  601. UnsignedInt m_fieldParticleCount; ///< this does not need to be xfered, since it is evaluated every frame
  602. UnsignedInt m_particleSystemCount;
  603. Int m_onScreenParticleCount; ///< number of particles displayed on screen per frame
  604. UnsignedInt m_lastLogicFrameUpdate;
  605. Int m_localPlayerIndex; ///<used to tell particle systems which particles can be skipped due to player shroud status
  606. private:
  607. TemplateMap m_templateMap; ///< a hash map of all particle system templates
  608. };
  609. /// The particle system manager singleton
  610. extern ParticleSystemManager *TheParticleSystemManager;
  611. class DebugDisplayInterface;
  612. extern void ParticleSystemDebugDisplay( DebugDisplayInterface *dd, void *, FILE *fp = NULL );
  613. #endif // _PARTICLE_SYS_H_