ParticleSys.h 33 KB

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