Particle.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. /******************************************************************************
  2. Use 'Particles' for simplified particles management (updating and drawing).
  3. Use 'RawParticles' for batched drawing of thousands of particles that are updated manually.
  4. Use 'DrawParticle' functions for drawing each particle manually.
  5. /******************************************************************************/
  6. enum PARTICLE_SRC : Byte // Particles Source Type
  7. {
  8. PARTICLE_NONE , // none
  9. PARTICLE_STATIC_SHAPE , // static shape , 'Particles.shape' transformed by 'Particles.matrix'
  10. PARTICLE_DYNAMIC_SHAPE , // dynamic shape , 'Shape'
  11. PARTICLE_DYNAMIC_SHAPES , // dynamic shapes , 'Shape' array
  12. PARTICLE_DYNAMIC_ORIENTP , // dynamic point , 'OrientP'
  13. PARTICLE_DYNAMIC_SKELETON , // dynamic skeleton , 'AnimatedSkeleton'
  14. PARTICLE_DYNAMIC_MESH , // dynamic mesh , 'Mesh' transformed by 'Particles.matrix'
  15. PARTICLE_DYNAMIC_MESH_SKELETON, // dynamic mesh animated by skeleton, 'Mesh' transformed by 'AnimatedSkeleton'
  16. };
  17. /******************************************************************************/
  18. struct Particle // Single Particle
  19. {
  20. Byte palette_y , // palette y coordinate for 'Particles.palette_image'
  21. image_index; // image index for animated particle images, used when "image_speed<=0 && (image_x_frames>1 || image_y_frames>1)"
  22. Flt life , // current life
  23. life_max , // maximum life
  24. radius , // radius
  25. ang_vel ; // angular velocity
  26. Vec pos , // position
  27. vel ; // velocity
  28. Particle() {Zero(T);}
  29. };
  30. /******************************************************************************/
  31. struct Particles // Set of Particles
  32. {
  33. Mems<Particle> p; // particles
  34. Bool reborn , // if reborn particles after their death , false/true, default=true
  35. smooth_fade , // false for (quick fade-in and slow fade-out) or true for (smooth fade-in and fade-out), false/true, default=false (this is ignored if 'opacity_func' is specified)
  36. motion_affects_alpha; // if motion stretching affects opacity , false/true, default=true
  37. Byte glow ; // glow amount , 0..255 , default=0 (this is valid only for particles rendered in RM_BLEND mode when 'palette'=false)
  38. Color color ; // color , , (this is used when the color table isn't set)
  39. Flt radius , // Particle radius at its creation time , 0..Inf, (this is the initial value of 'Particle.radius' at its creation time)
  40. radius_random, // Particle radius random factor , 0..Inf, default=0 (this affects initial value of 'Particle.radius', 0 value keeps it constant, 1 value can make it 2x smaller to 2x bigger, 2 value can make it 3x smaller to 3x bigger)
  41. radius_growth, // Particle radius growth factor , 0..Inf, default=1 (this affects 'Particle.radius' in each frame, where a value of 0..1 decreases the radius, 1 keeps it constant, and 1..Inf increases the radius)
  42. offset_range , // Particle position offset range applied during drawing, 0..Inf, default=0 (this simulates the range of random position offsets for each particle during drawing, value of 0 is the fastest and disables the offset usage)
  43. offset_speed , // Particle position offset speed applied during drawing, 0..Inf, default=1 (this simulates the speed of random potision offsets for each particle during drawing)
  44. life , // Particle life , 0..Inf, (this is the life of a single particle 'Particle.max_life')
  45. life_random ; // Particle life random factor , 0..Inf, (this affects 'Particle.max_life', 0 value keeps it constant, 1 value can make it 2x shorter to 2x longer, 2 value can make it 3x shorter to 3x longer)
  46. Flt glue , // moves particles along with the source movement, 0..1 , default=0 (this affects each single particle position according to source generation object movement, value of 0 disables position adjustment and doesn't require any additional calculations)
  47. damping , // Particle velocity damping , 0..1 , default=0 (this dampens particles velocity in each frame)
  48. ang_vel , // angular velocity range , 0..Inf , default=0
  49. vel_random ; // random velocity applied at particle creation, 0..Inf , default=0
  50. Vec vel_constant, // constant velocity applied at particle creation, (-Inf,-Inf,-Inf)..(Inf,Inf,Inf), default=(0,0,0)
  51. accel ; // acceleration applied each frame , (-Inf,-Inf,-Inf)..(Inf,Inf,Inf), default=(0,0,0)
  52. Flt emitter_life_max , // maximum life of the Particles Emitter , 0..Inf , default=0 (this specifies the maximum life of the Particles Set, value <=0 specifies infinite life, value >0 specifies finite life)
  53. emitter_life , // current life of the Particles Emitter , 0..emitter_life_max, default=0 (this specifies the current life of the Particles Set, this value is increased only if the Particles Set has finite life)
  54. fade_in , // fade in time , 0..Inf , default=1 (this affects the global opacity of all particles , this value is used only if the Particles Set has finite life)
  55. fade_out , // fade out time , 0..Inf , default=1 (this affects the global opacity of all particles , this value is used only if the Particles Set has finite life)
  56. radius_scale_base, // Particle radius global scale applied during drawing, -Inf..Inf , default=1 (this is the base global scale of all particles radius applied during drawing only) final particle radius value = "Particle.radius * radiusScale()"
  57. radius_scale_time; // Particle radius global scale applied during drawing, -Inf..Inf , default=0 (this is the time relative global scale of all particles radius applied during drawing only) final particle radius value = "Particle.radius * radiusScale()"
  58. Matrix matrix ; // particle generation matrix , , default=MatrixIdentity (this matrix is used for following source types: PARTICLE_STATIC_SHAPE, PARTICLE_DYNAMIC_MESH)
  59. Shape shape ; // particle generation shape , , default=Ball(1) (this shape is used for following source types: PARTICLE_STATIC_SHAPE)
  60. Bool inside_shape; // if generate particles inside shape or on its surface, false/true, default=true
  61. ImagePtr image ; // particle image
  62. UShort image_x_frames, // number of animation frames in image width , 1..65535, default=1
  63. image_y_frames; // number of animation frames in image height, 1..65535, default=1
  64. Flt image_speed ; // image animation speed , 0..Inf , default=1
  65. ImagePtr palette_image; // if specified, then particle colors will be multiplied by this image, x coordinate of the image is based on particle life, y coordinate of the image is taken from 'Particle.palette_y', the mode of this image must be equal to IMAGE_SOFT (to avoid unnecessary locking)
  66. Flt hard_depth_offset; // 0..1, default=0, this value is used when particles are not drawn with softing (D.particlesSoft is false or not supported), in that case each particle will be offsetted towards the camera by its radius multiplied by this factor, decreasing the chance of particles being occluded
  67. Flt (*opacity_func)(Flt life_frac); // pointer to a custom function (may be null) used to calculate opacity of a single particle, based on its life, if this is null then a default function is used based on 'smooth_fade', this member is not saved in 'save/load' methods, default=null
  68. // set / get
  69. Flt fade ( )C {return _fade ;} // get current fading value according to 'fade_in fade_out emitter_life_max', this should be used for accessing the fade value of particle sets with finite life (emitter_life_max>0)
  70. Flt opacity (Vec *pos=null)C; // get average particles opacity (0..1) and position (this can be useful for example in applying lights basing on particles average opacity and position)
  71. Flt radiusScale( )C {return emitter_life*radius_scale_time + radius_scale_base ;} // get current radius scale
  72. Bool alive ( )C {return emitter_life_max<=0 || emitter_life<emitter_life_max;} // if Particle Set is alive
  73. Bool is ( )C {return _src_type!=PARTICLE_NONE ;} // if Particle Set was created
  74. RENDER_MODE renderMode ( )C; // get RENDER_MODE in which Particle Set should be drawn (can be RM_BLEND, RM_PALETTE or RM_PALETTE1)
  75. Particles& palette (Bool palette); Bool palette ()C {return _palette ;} // if draw particles in palette mode (RM_PALETTE or RM_PALETTE1) instead of blend mode (RM_BLEND) , false/true, default=false (particles in palette mode use only Alpha component from the Texture, while blend mode uses all RGBA channels from the Texture)
  76. Particles& paletteIndex(Byte index ); Byte paletteIndex()C {return _palette_index;} // specifies which palette mode (RM_PALETTE or RM_PALETTE1) should be used when 'palette' is enabled, 0..1 , defailt=0 (if 'palette' is enabled then this will specify whether RM_PALETTE index=0 or RM_PALETTE1 index=1 should be used)
  77. // manage
  78. Particles& del ( ); // delete
  79. Particles& create(C ImagePtr &image, C Color &color, Int elms, Flt radius, Flt life); // create from image object
  80. Particles& create(C Particles &src ); // create from 'src'
  81. // particle generation source
  82. PARTICLE_SRC sourceType( )C {return _src_type;} // get particle generation source type
  83. Particles& source (C Shape & static_shape ); // set particle generation source to a static shape (this shape will be copied to the Particles object, and can be modified manually via 'Particles.shape')
  84. Particles& source (C Shape *dynamic_shape ); // set particle generation source to a dynamic shape (this shape will not be copied to the Particles object, which means that the Particles object will access each frame the memory address of 'dynamic_shape ' , you'll need to make sure that the memory address of 'dynamic_shape' will remain constant throughout the life of Particles)
  85. Particles& source (C Shape *dynamic_shapes , Int shapes ); // set particle generation source to dynamic shapes (these shapes will not be copied to the Particles object, which means that the Particles object will access each frame the memory address of 'dynamic_shapes ' , you'll need to make sure that the memory address of 'dynamic_shapes' will remain constant throughout the life of Particles)
  86. Particles& source (C OrientP *dynamic_point ); // set particle generation source to a dynamic point (this point will not be copied to the Particles object, which means that the Particles object will access each frame the memory address of 'dynamic_point ' , you'll need to make sure that the memory address of 'dynamic_point' will remain constant throughout the life of Particles)
  87. Particles& source (C AnimatedSkeleton *dynamic_skeleton, Bool ragdoll_bones_only ); // set particle generation source to a dynamic skeleton (this skeleton will not be copied to the Particles object, which means that the Particles object will access each frame the memory address of 'dynamic_skeleton' , you'll need to make sure that the memory address of 'dynamic_skeleton' will remain constant throughout the life of Particles)
  88. Particles& source (C MeshPtr &dynamic_mesh ); // set particle generation source to a dynamic mesh (this mesh will not be copied to the Particles object, which means that the Particles object will access each frame the memory address of 'dynamic_mesh ' , you'll need to make sure that the memory address of 'dynamic_mesh' will remain constant throughout the life of Particles)
  89. Particles& source (C MeshPtr &dynamic_mesh , C AnimatedSkeleton *dynamic_skeleton); // set particle generation source to a dynamic mesh animated by skeleton (these objects will not be copied to the Particles object, which means that the Particles object will access each frame the memory address of 'dynamic_mesh' and 'dynamic_skeleton', you'll need to make sure that the memory address of 'dynamic_mesh' and 'dynamic_skeleton' will remain constant throughout the life of Particles)
  90. // operations
  91. #if EE_PRIVATE
  92. Particles& setRenderMode(); // set _render_mode according to current particle settings
  93. void zero ();
  94. #endif
  95. void reset (Int i ); // reset i-th particle , if 'reborn' is false then the particle will be set as dead
  96. Particles& reset ( ); // reset all particles using 'reset(Int i)' method, if 'reborn' is false then the particle will be set as dead
  97. Particles& resetFull( ); // reset 'emitter_life' and all particles , this method ignores 'reborn' and always sets particles to alive
  98. Bool update (Flt dt=Time.d()); // update all particles, returns false if Particles Set has died "!alive()", true if it's still alive (or has infinite life), you can use this information to delete the particles if they're no longer needed, 'dt'=time delta used for updating the particles
  99. // draw
  100. void draw(Flt opacity=1)C; // draw, 'opacity'=custom opacity multiplier, this method should be called only in RM_PALETTE, RM_PALETTE1 and RM_BLEND rendering modes, doesn't use automatic Frustum culling
  101. // io
  102. Bool save( File &f , Bool include_particles, CChar *path=null)C; // save, does not include saving dynamic sources, false on fail, 'include_particles'=if include each single particle data in saving (if not, then they will be set randomly when loading), 'path'=path at which resource is located (this is needed so that the sub-resources can be accessed with relative path)
  103. Bool load( File &f , CChar *path=null) ; // load, does not include loading dynamic sources, false on fail , 'path'=path at which resource is located (this is needed so that the sub-resources can be accessed with relative path)
  104. Bool save(C Str &name, Bool include_particles )C; // save, does not include saving dynamic sources, false on fail, 'include_particles'=if include each single particle data in saving (if not, then they will be set randomly when loading)
  105. Bool load(C Str &name ) ; // load, does not include loading dynamic sources, false on fail
  106. ~Particles() {del();}
  107. Particles();
  108. #if !EE_PRIVATE
  109. private:
  110. #endif
  111. Bool _palette ;
  112. Byte _palette_index;
  113. PARTICLE_SRC _src_type ;
  114. Flt _fade ;
  115. RENDER_MODE _render_mode ;
  116. CPtr _src_ptr ; Int _src_elms;
  117. MeshPtr _src_mesh ;
  118. Byte *_src_help ;
  119. Matrix _matrix_prev ;
  120. NO_COPY_CONSTRUCTOR(Particles);
  121. };
  122. /******************************************************************************/
  123. struct RawParticles // buffered particles
  124. {
  125. struct Particle
  126. {
  127. Vec pos , // position
  128. vel ; // velocity
  129. Color color ; // color
  130. Flt radius, // radius
  131. angle ; // angle
  132. };
  133. Bool motion_affects_alpha; // if motion stretching affects opacity, default=true
  134. Byte glow ; // glow amount, 0..255, default=0 (this is valid only for particles rendered in RM_BLEND mode when 'palette'=false)
  135. ImagePtr image ; // particle image
  136. // manage
  137. RawParticles& del ( ); // delete manually
  138. RawParticles& create(C ImagePtr &image); // create with 'image'
  139. // get / set
  140. RENDER_MODE renderMode()C; // get RENDER_MODE in which particles should be drawn (can be RM_BLEND, RM_PALETTE or RM_PALETTE1)
  141. #if EE_PRIVATE
  142. RawParticles& setRenderMode();
  143. void zero ();
  144. #endif
  145. RawParticles& palette (Bool palette); Bool palette ()C {return _palette ;} // if draw particles in palette mode (RM_PALETTE or RM_PALETTE1) instead of blend mode (RM_BLEND) , false/true, default=false (particles in palette mode use only Alpha component from the Texture, while blend mode uses all RGBA channels from the Texture)
  146. RawParticles& paletteIndex(Byte index ); Byte paletteIndex()C {return _palette_index;} // specifies which palette mode (RM_PALETTE or RM_PALETTE1) should be used when 'palette' is enabled, 0..1 , defailt=0 (if 'palette' is enabled then this will specify whether RM_PALETTE index=0 or RM_PALETTE1 index=1 should be used)
  147. // operations
  148. RawParticles& set(C Particle *particle, Int particles); // set from 'particle' array of 'particles'
  149. // draw
  150. void draw()C; // draw, this method should be called only in RM_PALETTE, RM_PALETTE1 and RM_BLEND rendering modes, doesn't use automatic Frustum culling
  151. ~RawParticles() {del();}
  152. RawParticles();
  153. private:
  154. Bool _palette;
  155. Byte _palette_index;
  156. Int _particles, _max_particles;
  157. RENDER_MODE _render_mode;
  158. VtxBuf _vb;
  159. IndBuf _ib;
  160. };
  161. /******************************************************************************/
  162. // manually draw a set of particles
  163. Bool DrawParticleBegin(C Image &image, Byte glow, Bool motion_affects_alpha ); // call this at start of drawing particles, 'glow'=glow amount 0..255, 'motion_affects_alpha'=if motion stretching affects opacity, false on fail, this function should be called only in RM_PALETTE, RM_PALETTE1 and RM_BLEND rendering modes
  164. void DrawParticleAdd (C Color &color, Flt opacity, Flt radius, Flt angle, C Vec &pos, C Vec &vel); // call this repeatedly for each particle
  165. void DrawParticleEnd ( ); // call this after drawing all particles
  166. inline void DrawParticle(C Image &image, Byte glow, C Color &color, Flt opacity, Flt radius, Flt angle, C Vec &pos, C Vec &vel) // draw a single particle
  167. {
  168. if(DrawParticleBegin(image, glow, true))
  169. {
  170. DrawParticleAdd(color, opacity, radius, angle, pos, vel);
  171. DrawParticleEnd();
  172. }
  173. }
  174. // manually draw a set of animated particles
  175. Bool DrawAnimatedParticleBegin(C Image &image, Byte glow, Bool motion_affects_alpha, Int x_frames, Int y_frames ); // call this at start of drawing animated particles, 'glow'=glow amount 0..255, 'motion_affects_alpha'=if motion stretching affects opacity, 'x_frames'=number of frames in image width, 'y_frames'=number of frames in image height, false on fail, this function should be called only in RM_PALETTE, RM_PALETTE1 and RM_BLEND rendering modes
  176. void DrawAnimatedParticleAdd (C Color &color, Flt opacity, Flt radius, Flt angle, C Vec &pos, C Vec &vel, Flt frame); // call this repeatedly for each particle, 'frame'=current frame (0..1)
  177. void DrawAnimatedParticleEnd ( ); // call this after drawing all particles
  178. Flt ParticleOpacity(Flt particle_life, Flt particle_life_max, Bool particles_smooth_fade); // calculate opacity of a single particle by specifying its current life 'Particle.life', maximum life 'Particle.life_max' and if smooth fade 'Particles.smooth_fade' is enabled
  179. /******************************************************************************/
  180. extern Cache<Particles> ParticlesCache; // Particles Cache
  181. inline Int Elms(C Particles &particles) {return particles.p.elms();}
  182. /******************************************************************************/
  183. #if EE_PRIVATE
  184. void ShutParticles();
  185. #endif
  186. /******************************************************************************/