part_emt.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. /*
  2. ** Command & Conquer Renegade(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. *** C O N F I D E N T I A L --- W E S T W O O D S T U D I O S ***
  20. ***************************************************************************
  21. * *
  22. * Project Name : G *
  23. * *
  24. * $Archive:: /VSS_Sync/ww3d2/part_emt.h $*
  25. * *
  26. * $Author:: Vss_sync $*
  27. * *
  28. * $Modtime:: 10/26/01 2:56p $*
  29. * *
  30. * $Revision:: 11 $*
  31. * *
  32. *-------------------------------------------------------------------------*
  33. * Functions: *
  34. * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
  35. #if defined(_MSC_VER)
  36. #pragma once
  37. #endif
  38. #ifndef PART_EMT_H
  39. #define PART_EMT_H
  40. #include "rendobj.h"
  41. #include "random.h"
  42. #include "part_buf.h"
  43. #include "quat.h"
  44. #include "w3d_file.h"
  45. #include "w3derr.h"
  46. #include "v3_rnd.h"
  47. // Forward declarations
  48. class ParticleEmitterDefClass;
  49. class ChunkSaveClass;
  50. struct NewParticleStruct;
  51. /*
  52. ** Properties / Keyframes: These are for properties of the particles which
  53. ** are a straight function of their age, such as color and size. These are
  54. ** typically defined by a series of "keyframes", which are property / age
  55. ** pairs. Linear interpolation is performed between the keyframes.
  56. */
  57. template<class T> struct ParticlePropertyStruct {
  58. T Start;
  59. T Rand;
  60. unsigned int NumKeyFrames;
  61. float * KeyTimes;
  62. T * Values;
  63. };
  64. /*
  65. ** Utility function for copying the contents of one keyframe struct into another.
  66. */
  67. template<class T> __inline
  68. void Copy_Emitter_Property_Struct
  69. (
  70. ParticlePropertyStruct<T> &dest,
  71. const ParticlePropertyStruct<T> &src
  72. )
  73. {
  74. dest.Start = src.Start;
  75. dest.Rand = src.Rand;
  76. dest.NumKeyFrames = src.NumKeyFrames;
  77. dest.KeyTimes = NULL;
  78. dest.Values = NULL;
  79. if (dest.NumKeyFrames > 0) {
  80. dest.KeyTimes = new float[dest.NumKeyFrames];
  81. dest.Values = new T[dest.NumKeyFrames];
  82. ::memcpy (dest.KeyTimes, src.KeyTimes, sizeof (float) * dest.NumKeyFrames);
  83. ::memcpy (dest.Values, src.Values, sizeof (T) * dest.NumKeyFrames);
  84. }
  85. return ;
  86. }
  87. /**
  88. ** ParticleEmitterClass: This is a renderobject which emits particles
  89. ** regularly. The particles emitted go into a different renderobject, a
  90. ** ParticleBufferClass (there is one particle buffer per particle emitter).
  91. ** This separation is so that the bounding volumes of the particle group and
  92. ** the object containing the emitter (emitters will typically be inserted
  93. ** into a hierarchy object or some such) will remain separate.
  94. */
  95. class ParticleEmitterClass : public RenderObjClass
  96. {
  97. public:
  98. // Note: all time/velocity/acceleration quantities use seconds (converted to ms internally)
  99. ParticleEmitterClass(float emit_rate, unsigned int burst_size, Vector3Randomizer *pos_rnd,
  100. Vector3 base_vel, Vector3Randomizer *vel_rnd, float out_vel, float vel_inherit_factor,
  101. ParticlePropertyStruct<Vector3> &color,
  102. ParticlePropertyStruct<float> &opacity,
  103. ParticlePropertyStruct<float> &size,
  104. ParticlePropertyStruct<float> &rotation, float orient_rnd,
  105. ParticlePropertyStruct<float> &frames,
  106. ParticlePropertyStruct<float> &blur_times,
  107. Vector3 accel, float max_age, TextureClass *tex,
  108. ShaderClass shader = ShaderClass::_PresetAdditiveSpriteShader,
  109. int max_particles = 0, int max_buffer_size = -1, bool pingpong = false,
  110. int render_mode = W3D_EMITTER_RENDER_MODE_TRI_PARTICLES,
  111. int frame_mode = W3D_EMITTER_FRAME_MODE_1x1,
  112. const W3dEmitterLinePropertiesStruct * line_props = NULL);
  113. ParticleEmitterClass(const ParticleEmitterClass & src);
  114. ParticleEmitterClass & operator = (const ParticleEmitterClass &);
  115. virtual ~ParticleEmitterClass(void);
  116. // Creation/serialization methods
  117. virtual RenderObjClass * Clone(void) const;
  118. static ParticleEmitterClass * Create_From_Definition (const ParticleEmitterDefClass &definition);
  119. ParticleEmitterDefClass * Build_Definition (void) const;
  120. WW3DErrorType Save (ChunkSaveClass &chunk_save) const;
  121. // Identification methods
  122. virtual int Class_ID (void) const { return CLASSID_PARTICLEEMITTER; }
  123. virtual const char * Get_Name (void) const { return NameString; }
  124. virtual void Set_Name (const char *pname);
  125. virtual void Notify_Added(SceneClass * scene);
  126. virtual void Notify_Removed(SceneClass * scene);
  127. // Update particle state and draw the particles.
  128. virtual void Render(RenderInfoClass & rinfo) { }
  129. virtual void Restart(void);
  130. // Scales the size of all particles and effects positions/velocities of
  131. // particles emitted after the Scale() call (but not before)
  132. virtual void Scale(float scale);
  133. // Put particle buffer in scene if this is the first time (clunky code
  134. // - hopefully can be rewritten more cleanly in future)...
  135. virtual void On_Frame_Update(void);
  136. virtual void Get_Obj_Space_Bounding_Sphere(SphereClass & sphere) const { sphere.Center.Set(0,0,0); sphere.Radius = 0; }
  137. virtual void Get_Obj_Space_Bounding_Box(AABoxClass & box) const { box.Center.Set(0,0,0); box.Extent.Set(0,0,0); }
  138. virtual void Set_Hidden(int onoff) { RenderObjClass::Set_Hidden (onoff); Update_On_Visibilty (); }
  139. virtual void Set_Visible(int onoff) { RenderObjClass::Set_Visible (onoff); Update_On_Visibilty (); }
  140. virtual void Set_Animation_Hidden(int onoff) { RenderObjClass::Set_Animation_Hidden (onoff); Update_On_Visibilty (); }
  141. virtual void Set_Force_Visible(int onoff) { RenderObjClass::Set_Force_Visible (onoff); Update_On_Visibilty (); }
  142. virtual void Set_LOD_Bias(float bias) { if (Buffer) Buffer->Set_LOD_Bias(bias); }
  143. // These are not part of the renderobject interface:
  144. // You can use Reset() to re-cycle a particle emitter. Make sure its transform is
  145. // set up before you call Reset().
  146. void Reset(void);
  147. void Start(void);
  148. void Stop(void);
  149. bool Is_Stopped(void);
  150. // Change starting position/velocity/acceleration parameters:
  151. void Set_Position_Randomizer(Vector3Randomizer *rand);
  152. void Set_Velocity_Randomizer(Vector3Randomizer *rand);
  153. void Set_Base_Velocity(const Vector3& base_vel);
  154. void Set_Outwards_Velocity(float out_vel);
  155. void Set_Velocity_Inheritance_Factor(float inh_factor);
  156. void Set_Acceleration (const Vector3 &acceleration) { if (Buffer != NULL) Buffer->Set_Acceleration (acceleration/1000000.0f); }
  157. // Change visual properties of emitter / buffer:
  158. void Reset_Colors(ParticlePropertyStruct<Vector3> &new_props) { if (Buffer) Buffer->Reset_Colors(new_props); }
  159. void Reset_Opacity(ParticlePropertyStruct<float> &new_props) { if (Buffer) Buffer->Reset_Opacity(new_props); }
  160. void Reset_Size(ParticlePropertyStruct<float> &new_props) { if (Buffer) Buffer->Reset_Size(new_props); }
  161. void Reset_Rotations(ParticlePropertyStruct<float> &new_props, float orient_rnd) { if (Buffer) Buffer->Reset_Rotations(new_props, orient_rnd); }
  162. void Reset_Frames(ParticlePropertyStruct<float> &new_props) { if (Buffer) Buffer->Reset_Frames(new_props); }
  163. void Reset_Blur_Times(ParticlePropertyStruct<float> &new_props) { if (Buffer) Buffer->Reset_Blur_Times(new_props); }
  164. // Change emission/burst rate, or tell the emitter to emit a one-time burst.
  165. // NOTE: default buffer size fits the emission/burst rate that the emitter was created with.
  166. // Setting the rates too high will cause particles to be prematurely killed (to make space
  167. // for new ones) - setting it too low will cause wasted space in the particle buffer.
  168. // These problems can be avoided by specifying the desired buffer size in the emitter CTor.
  169. void Set_Emission_Rate (float rate) { EmitRate = rate > 0.0f ? (unsigned int)(1000.0f / rate) : 1000U; }
  170. void Set_Burst_Size (int size) { BurstSize = size != 0 ? size : 1; }
  171. void Set_One_Time_Burst(int size) { OneTimeBurstSize = size != 0 ? size : 1; OneTimeBurst = true; }
  172. // Emit particles (put in particle buffer). This is called by the
  173. // particle buffer On_Frame_Update() function to avoid order dependence.
  174. virtual void Emit(void);
  175. // Buffer control
  176. ParticleBufferClass *Peek_Buffer( void ) { return Buffer; }
  177. void Buffer_Scene_Not_Needed( void ) { BufferSceneNeeded = false; }
  178. void Remove_Buffer_From_Scene (void) { Buffer->Remove (); FirstTime = true; BufferSceneNeeded = true; }
  179. // from RenderObj...
  180. virtual bool Is_Complete(void) { return IsComplete; }
  181. // Auto deletion behavior controls
  182. bool Is_Remove_On_Complete_Enabled(void) { return RemoveOnComplete; }
  183. void Enable_Remove_On_Complete(bool onoff) { RemoveOnComplete = onoff; }
  184. static bool Default_Remove_On_Complete (void) { return DefaultRemoveOnComplete; }
  185. static void Set_Default_Remove_On_Complete (bool onoff) { DefaultRemoveOnComplete = onoff; }
  186. //
  187. // Virtual accessors (used for type specific information)
  188. //
  189. virtual int Get_User_Type (void) const { return EMITTER_TYPEID_DEFAULT; }
  190. virtual const char * Get_User_String (void) const { return NULL; }
  191. //
  192. // Inline accessors.
  193. // These methods are provided as a means to get the emitter's settings.
  194. //
  195. int Get_Render_Mode (void) const { return Buffer->Get_Render_Mode(); }
  196. int Get_Frame_Mode (void) const { return Buffer->Get_Frame_Mode(); }
  197. float Get_Particle_Size (void) const { return Buffer->Get_Particle_Size(); }
  198. Vector3 Get_Acceleration (void) const { return Buffer->Get_Acceleration (); }
  199. float Get_Lifetime (void) const { return Buffer->Get_Lifetime (); }
  200. Vector3 Get_End_Color (void) const { return Buffer->Get_End_Color (); }
  201. float Get_End_Opacity (void) const { return Buffer->Get_End_Opacity (); }
  202. TextureClass * Get_Texture (void) const { return Buffer->Get_Texture (); }
  203. void Set_Texture (TextureClass *tex) { Buffer->Set_Texture(tex); }
  204. float Get_Fade_Time (void) const { return Buffer->Get_Fade_Time (); }
  205. Vector3 Get_Start_Color (void) const { return Buffer->Get_Start_Color(); }
  206. float Get_Start_Opacity (void) const { return Buffer->Get_Start_Opacity(); }
  207. float Get_Position_Random (void) const { return PosRand ? PosRand->Get_Maximum_Extent() : 0.0f; }
  208. //float Get_Velocity_Random (void) const { return VelRand ? (VelRand->Get_Maximum_Extent() * 1000.0f) : 0.0f; }
  209. float Get_Emission_Rate (void) const { return 1000.0f / float(EmitRate); }
  210. int Get_Burst_Size (void) const { return BurstSize; }
  211. int Get_Max_Particles (void) const { return MaxParticles; }
  212. Vector3 Get_Start_Velocity (void) const { return BaseVel * 1000.0F; }
  213. Vector3Randomizer * Get_Creation_Volume (void) const;
  214. Vector3Randomizer * Get_Velocity_Random (void) const;
  215. float Get_Outwards_Vel (void) const { return OutwardVel * 1000.0F; }
  216. float Get_Velocity_Inherit (void) const{ return VelInheritFactor; }
  217. ShaderClass Get_Shader (void) const { return Buffer->Get_Shader (); }
  218. // Note: Caller IS RESPONSIBLE for freeing any memory allocated by these calls
  219. void Get_Color_Key_Frames (ParticlePropertyStruct<Vector3> &colors) const { Buffer->Get_Color_Key_Frames (colors); }
  220. void Get_Opacity_Key_Frames (ParticlePropertyStruct<float> &opacities) const { Buffer->Get_Opacity_Key_Frames (opacities); }
  221. void Get_Size_Key_Frames (ParticlePropertyStruct<float> &sizes) const { Buffer->Get_Size_Key_Frames (sizes); }
  222. void Get_Rotation_Key_Frames (ParticlePropertyStruct<float> &rotations) const { Buffer->Get_Rotation_Key_Frames (rotations); }
  223. void Get_Frame_Key_Frames (ParticlePropertyStruct<float> &frames) const { Buffer->Get_Frame_Key_Frames (frames); }
  224. void Get_Blur_Time_Key_Frames (ParticlePropertyStruct<float> &blurtimes) const { Buffer->Get_Blur_Time_Key_Frames (blurtimes); }
  225. float Get_Initial_Orientation_Random (void) const { return Buffer->Get_Initial_Orientation_Random(); }
  226. // Line rendering accessors
  227. int Get_Line_Texture_Mapping_Mode(void) const { return Buffer->Get_Line_Texture_Mapping_Mode(); }
  228. int Is_Merge_Intersections(void) const { return Buffer->Is_Merge_Intersections(); }
  229. int Is_Freeze_Random(void) const { return Buffer->Is_Freeze_Random(); }
  230. int Is_Sorting_Disabled(void) const { return Buffer->Is_Sorting_Disabled(); }
  231. int Are_End_Caps_Enabled(void) const { return Buffer->Are_End_Caps_Enabled(); }
  232. int Get_Subdivision_Level(void) const { return Buffer->Get_Subdivision_Level(); }
  233. float Get_Noise_Amplitude(void) const { return Buffer->Get_Noise_Amplitude(); }
  234. float Get_Merge_Abort_Factor(void) const { return Buffer->Get_Merge_Abort_Factor(); }
  235. float Get_Texture_Tile_Factor(void) const { return Buffer->Get_Texture_Tile_Factor(); }
  236. Vector2 Get_UV_Offset_Rate(void) const { return Buffer->Get_UV_Offset_Rate(); }
  237. // Global debugging option for disabling all particle emission
  238. #ifdef WWDEBUG
  239. static void Disable_All_Emitters(bool onoff) { DebugDisable = onoff; }
  240. static bool Are_Emitters_Disabled(void) { return DebugDisable; }
  241. #endif
  242. protected:
  243. // Used to build a list of filenames this emitter is dependent on
  244. virtual void Add_Dependencies_To_List (DynamicVectorClass<StringClass> &file_list, bool textures_only = false);
  245. // This method is called each time the visiblity state of the emitter changes.
  246. virtual void Update_On_Visibilty (void);
  247. private:
  248. // Collision sphere is a point - emitter emits also when not visible,
  249. // so this is only important to avoid affecting the collision spheres
  250. // of heirarchy objects into which the emitter is inserted.
  251. virtual void Update_Cached_Bounding_Volumes(void) const;
  252. // Create new particles and pass them to the particle buffer. Receives
  253. // the end-of-interval quaternion and origin and interpolates between
  254. // them and PrevQ/PrevOrig to get the transform to apply to each
  255. // particle's position and velocity as it is created. New particles are
  256. // placed into a circular queue for processing by the particle buffer.
  257. void Create_New_Particles(const Quaternion & curr_quat, const Vector3 & curr_orig);
  258. // Initialize one new particle at the given NewParticleStruct
  259. // address, with the given age and emitter transform (expressed as a
  260. // quaternion and origin vector). (must check if address is NULL).
  261. void Initialize_Particle(NewParticleStruct * newpart, unsigned int age,
  262. const Quaternion & quat, const Vector3 & orig);
  263. unsigned int EmitRate; // Emission rate (1/milliseconds).
  264. unsigned int BurstSize; // Burst size (how many particles in each emission).
  265. unsigned int OneTimeBurstSize; // Burst size for a one-time burst.
  266. bool OneTimeBurst; // Do we need to do a one-time burst?
  267. Vector3Randomizer * PosRand; // Position randomizer pointer (may be NULL).
  268. Vector3 BaseVel; // Base initial emission velocity.
  269. Vector3Randomizer * VelRand; // Velocity randomizer pointer (may be NULL).
  270. float OutwardVel; // Size of outwards velocity.
  271. float VelInheritFactor; // Affects emitter vel. inherited by particles.
  272. unsigned int EmitRemain; // Millisecond emitter remainder.
  273. Quaternion PrevQ; // Previous quaternion (for interpolation).
  274. Vector3 PrevOrig; // Previous origin (for interpolation).
  275. bool Active; // Is the emitter currently Active?
  276. bool FirstTime; // Has it been rendered before?
  277. bool BufferSceneNeeded;// Does the buffer need a scene?
  278. int ParticlesLeft; // Particles left to emit
  279. int MaxParticles; // Total particles to emit
  280. bool IsComplete; // Completed Emissions
  281. char * NameString;
  282. char * UserString;
  283. bool RemoveOnComplete; // Should this emitter destroy itself when it completes?
  284. bool IsInScene;
  285. // This pointer is used only for sending new particles to the particle
  286. // buffer and for informing the buffer when the emitter is destroyed.
  287. ParticleBufferClass * Buffer;
  288. // This is used to set the global behavior of emitters...
  289. // Should they be removed from the scene when they complete their
  290. // emissions, or should they stay in the scene. (For editing purposes)
  291. static bool DefaultRemoveOnComplete;
  292. // This setting is used in debug and profile builds to disable
  293. // all particle emitters.
  294. static bool DebugDisable;
  295. };
  296. #endif // PART_EMT_H