mirror of
https://github.com/electronicarts/CnC_Renegade.git
synced 2025-12-16 07:31:40 -05:00
Initial commit of Command & Conquer Renegade source code.
This commit is contained in:
345
Code/ww3d2/part_emt.h
Normal file
345
Code/ww3d2/part_emt.h
Normal file
@@ -0,0 +1,345 @@
|
||||
/*
|
||||
** Command & Conquer Renegade(tm)
|
||||
** Copyright 2025 Electronic Arts Inc.
|
||||
**
|
||||
** This program is free software: you can redistribute it and/or modify
|
||||
** it under the terms of the GNU General Public License as published by
|
||||
** the Free Software Foundation, either version 3 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This program is distributed in the hope that it will be useful,
|
||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
** GNU General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU General Public License
|
||||
** along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/***************************************************************************
|
||||
*** 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 ***
|
||||
***************************************************************************
|
||||
* *
|
||||
* Project Name : G *
|
||||
* *
|
||||
* $Archive:: /VSS_Sync/ww3d2/part_emt.h $*
|
||||
* *
|
||||
* $Author:: Vss_sync $*
|
||||
* *
|
||||
* $Modtime:: 10/26/01 2:56p $*
|
||||
* *
|
||||
* $Revision:: 11 $*
|
||||
* *
|
||||
*-------------------------------------------------------------------------*
|
||||
* Functions: *
|
||||
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||
#if defined(_MSC_VER)
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#ifndef PART_EMT_H
|
||||
#define PART_EMT_H
|
||||
|
||||
#include "rendobj.h"
|
||||
#include "random.h"
|
||||
#include "part_buf.h"
|
||||
#include "quat.h"
|
||||
#include "w3d_file.h"
|
||||
#include "w3derr.h"
|
||||
#include "v3_rnd.h"
|
||||
|
||||
// Forward declarations
|
||||
class ParticleEmitterDefClass;
|
||||
class ChunkSaveClass;
|
||||
struct NewParticleStruct;
|
||||
|
||||
/*
|
||||
** Properties / Keyframes: These are for properties of the particles which
|
||||
** are a straight function of their age, such as color and size. These are
|
||||
** typically defined by a series of "keyframes", which are property / age
|
||||
** pairs. Linear interpolation is performed between the keyframes.
|
||||
*/
|
||||
template<class T> struct ParticlePropertyStruct {
|
||||
T Start;
|
||||
T Rand;
|
||||
unsigned int NumKeyFrames;
|
||||
float * KeyTimes;
|
||||
T * Values;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
** Utility function for copying the contents of one keyframe struct into another.
|
||||
*/
|
||||
template<class T> __inline
|
||||
void Copy_Emitter_Property_Struct
|
||||
(
|
||||
ParticlePropertyStruct<T> &dest,
|
||||
const ParticlePropertyStruct<T> &src
|
||||
)
|
||||
{
|
||||
dest.Start = src.Start;
|
||||
dest.Rand = src.Rand;
|
||||
dest.NumKeyFrames = src.NumKeyFrames;
|
||||
dest.KeyTimes = NULL;
|
||||
dest.Values = NULL;
|
||||
|
||||
if (dest.NumKeyFrames > 0) {
|
||||
dest.KeyTimes = new float[dest.NumKeyFrames];
|
||||
dest.Values = new T[dest.NumKeyFrames];
|
||||
::memcpy (dest.KeyTimes, src.KeyTimes, sizeof (float) * dest.NumKeyFrames);
|
||||
::memcpy (dest.Values, src.Values, sizeof (T) * dest.NumKeyFrames);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
** ParticleEmitterClass: This is a renderobject which emits particles
|
||||
** regularly. The particles emitted go into a different renderobject, a
|
||||
** ParticleBufferClass (there is one particle buffer per particle emitter).
|
||||
** This separation is so that the bounding volumes of the particle group and
|
||||
** the object containing the emitter (emitters will typically be inserted
|
||||
** into a hierarchy object or some such) will remain separate.
|
||||
*/
|
||||
class ParticleEmitterClass : public RenderObjClass
|
||||
{
|
||||
public:
|
||||
|
||||
// Note: all time/velocity/acceleration quantities use seconds (converted to ms internally)
|
||||
ParticleEmitterClass(float emit_rate, unsigned int burst_size, Vector3Randomizer *pos_rnd,
|
||||
Vector3 base_vel, Vector3Randomizer *vel_rnd, float out_vel, float vel_inherit_factor,
|
||||
ParticlePropertyStruct<Vector3> &color,
|
||||
ParticlePropertyStruct<float> &opacity,
|
||||
ParticlePropertyStruct<float> &size,
|
||||
ParticlePropertyStruct<float> &rotation, float orient_rnd,
|
||||
ParticlePropertyStruct<float> &frames,
|
||||
ParticlePropertyStruct<float> &blur_times,
|
||||
Vector3 accel, float max_age, TextureClass *tex,
|
||||
ShaderClass shader = ShaderClass::_PresetAdditiveSpriteShader,
|
||||
int max_particles = 0, int max_buffer_size = -1, bool pingpong = false,
|
||||
int render_mode = W3D_EMITTER_RENDER_MODE_TRI_PARTICLES,
|
||||
int frame_mode = W3D_EMITTER_FRAME_MODE_1x1,
|
||||
const W3dEmitterLinePropertiesStruct * line_props = NULL);
|
||||
|
||||
ParticleEmitterClass(const ParticleEmitterClass & src);
|
||||
ParticleEmitterClass & operator = (const ParticleEmitterClass &);
|
||||
virtual ~ParticleEmitterClass(void);
|
||||
|
||||
// Creation/serialization methods
|
||||
virtual RenderObjClass * Clone(void) const;
|
||||
static ParticleEmitterClass * Create_From_Definition (const ParticleEmitterDefClass &definition);
|
||||
ParticleEmitterDefClass * Build_Definition (void) const;
|
||||
WW3DErrorType Save (ChunkSaveClass &chunk_save) const;
|
||||
|
||||
// Identification methods
|
||||
virtual int Class_ID (void) const { return CLASSID_PARTICLEEMITTER; }
|
||||
virtual const char * Get_Name (void) const { return NameString; }
|
||||
virtual void Set_Name (const char *pname);
|
||||
|
||||
virtual void Notify_Added(SceneClass * scene);
|
||||
virtual void Notify_Removed(SceneClass * scene);
|
||||
|
||||
// Update particle state and draw the particles.
|
||||
virtual void Render(RenderInfoClass & rinfo) { }
|
||||
virtual void Restart(void);
|
||||
|
||||
// Scales the size of all particles and effects positions/velocities of
|
||||
// particles emitted after the Scale() call (but not before)
|
||||
virtual void Scale(float scale);
|
||||
|
||||
// Put particle buffer in scene if this is the first time (clunky code
|
||||
// - hopefully can be rewritten more cleanly in future)...
|
||||
virtual void On_Frame_Update(void);
|
||||
|
||||
virtual void Get_Obj_Space_Bounding_Sphere(SphereClass & sphere) const { sphere.Center.Set(0,0,0); sphere.Radius = 0; }
|
||||
virtual void Get_Obj_Space_Bounding_Box(AABoxClass & box) const { box.Center.Set(0,0,0); box.Extent.Set(0,0,0); }
|
||||
virtual void Set_Hidden(int onoff) { RenderObjClass::Set_Hidden (onoff); Update_On_Visibilty (); }
|
||||
virtual void Set_Visible(int onoff) { RenderObjClass::Set_Visible (onoff); Update_On_Visibilty (); }
|
||||
virtual void Set_Animation_Hidden(int onoff) { RenderObjClass::Set_Animation_Hidden (onoff); Update_On_Visibilty (); }
|
||||
virtual void Set_Force_Visible(int onoff) { RenderObjClass::Set_Force_Visible (onoff); Update_On_Visibilty (); }
|
||||
|
||||
virtual void Set_LOD_Bias(float bias) { if (Buffer) Buffer->Set_LOD_Bias(bias); }
|
||||
|
||||
|
||||
// These are not part of the renderobject interface:
|
||||
// You can use Reset() to re-cycle a particle emitter. Make sure its transform is
|
||||
// set up before you call Reset().
|
||||
void Reset(void);
|
||||
void Start(void);
|
||||
void Stop(void);
|
||||
bool Is_Stopped(void);
|
||||
|
||||
// Change starting position/velocity/acceleration parameters:
|
||||
void Set_Position_Randomizer(Vector3Randomizer *rand);
|
||||
void Set_Velocity_Randomizer(Vector3Randomizer *rand);
|
||||
void Set_Base_Velocity(const Vector3& base_vel);
|
||||
void Set_Outwards_Velocity(float out_vel);
|
||||
void Set_Velocity_Inheritance_Factor(float inh_factor);
|
||||
void Set_Acceleration (const Vector3 &acceleration) { if (Buffer != NULL) Buffer->Set_Acceleration (acceleration/1000000.0f); }
|
||||
|
||||
// Change visual properties of emitter / buffer:
|
||||
void Reset_Colors(ParticlePropertyStruct<Vector3> &new_props) { if (Buffer) Buffer->Reset_Colors(new_props); }
|
||||
void Reset_Opacity(ParticlePropertyStruct<float> &new_props) { if (Buffer) Buffer->Reset_Opacity(new_props); }
|
||||
void Reset_Size(ParticlePropertyStruct<float> &new_props) { if (Buffer) Buffer->Reset_Size(new_props); }
|
||||
void Reset_Rotations(ParticlePropertyStruct<float> &new_props, float orient_rnd) { if (Buffer) Buffer->Reset_Rotations(new_props, orient_rnd); }
|
||||
void Reset_Frames(ParticlePropertyStruct<float> &new_props) { if (Buffer) Buffer->Reset_Frames(new_props); }
|
||||
void Reset_Blur_Times(ParticlePropertyStruct<float> &new_props) { if (Buffer) Buffer->Reset_Blur_Times(new_props); }
|
||||
|
||||
// Change emission/burst rate, or tell the emitter to emit a one-time burst.
|
||||
// NOTE: default buffer size fits the emission/burst rate that the emitter was created with.
|
||||
// Setting the rates too high will cause particles to be prematurely killed (to make space
|
||||
// for new ones) - setting it too low will cause wasted space in the particle buffer.
|
||||
// These problems can be avoided by specifying the desired buffer size in the emitter CTor.
|
||||
void Set_Emission_Rate (float rate) { EmitRate = rate > 0.0f ? (unsigned int)(1000.0f / rate) : 1000U; }
|
||||
void Set_Burst_Size (int size) { BurstSize = size != 0 ? size : 1; }
|
||||
void Set_One_Time_Burst(int size) { OneTimeBurstSize = size != 0 ? size : 1; OneTimeBurst = true; }
|
||||
|
||||
// Emit particles (put in particle buffer). This is called by the
|
||||
// particle buffer On_Frame_Update() function to avoid order dependence.
|
||||
virtual void Emit(void);
|
||||
|
||||
// Buffer control
|
||||
ParticleBufferClass *Peek_Buffer( void ) { return Buffer; }
|
||||
void Buffer_Scene_Not_Needed( void ) { BufferSceneNeeded = false; }
|
||||
void Remove_Buffer_From_Scene (void) { Buffer->Remove (); FirstTime = true; BufferSceneNeeded = true; }
|
||||
|
||||
// from RenderObj...
|
||||
virtual bool Is_Complete(void) { return IsComplete; }
|
||||
|
||||
// Auto deletion behavior controls
|
||||
bool Is_Remove_On_Complete_Enabled(void) { return RemoveOnComplete; }
|
||||
void Enable_Remove_On_Complete(bool onoff) { RemoveOnComplete = onoff; }
|
||||
static bool Default_Remove_On_Complete (void) { return DefaultRemoveOnComplete; }
|
||||
static void Set_Default_Remove_On_Complete (bool onoff) { DefaultRemoveOnComplete = onoff; }
|
||||
|
||||
//
|
||||
// Virtual accessors (used for type specific information)
|
||||
//
|
||||
virtual int Get_User_Type (void) const { return EMITTER_TYPEID_DEFAULT; }
|
||||
virtual const char * Get_User_String (void) const { return NULL; }
|
||||
|
||||
//
|
||||
// Inline accessors.
|
||||
// These methods are provided as a means to get the emitter's settings.
|
||||
//
|
||||
int Get_Render_Mode (void) const { return Buffer->Get_Render_Mode(); }
|
||||
int Get_Frame_Mode (void) const { return Buffer->Get_Frame_Mode(); }
|
||||
float Get_Particle_Size (void) const { return Buffer->Get_Particle_Size(); }
|
||||
Vector3 Get_Acceleration (void) const { return Buffer->Get_Acceleration (); }
|
||||
float Get_Lifetime (void) const { return Buffer->Get_Lifetime (); }
|
||||
Vector3 Get_End_Color (void) const { return Buffer->Get_End_Color (); }
|
||||
float Get_End_Opacity (void) const { return Buffer->Get_End_Opacity (); }
|
||||
TextureClass * Get_Texture (void) const { return Buffer->Get_Texture (); }
|
||||
void Set_Texture (TextureClass *tex) { Buffer->Set_Texture(tex); }
|
||||
float Get_Fade_Time (void) const { return Buffer->Get_Fade_Time (); }
|
||||
Vector3 Get_Start_Color (void) const { return Buffer->Get_Start_Color(); }
|
||||
float Get_Start_Opacity (void) const { return Buffer->Get_Start_Opacity(); }
|
||||
float Get_Position_Random (void) const { return PosRand ? PosRand->Get_Maximum_Extent() : 0.0f; }
|
||||
//float Get_Velocity_Random (void) const { return VelRand ? (VelRand->Get_Maximum_Extent() * 1000.0f) : 0.0f; }
|
||||
float Get_Emission_Rate (void) const { return 1000.0f / float(EmitRate); }
|
||||
int Get_Burst_Size (void) const { return BurstSize; }
|
||||
int Get_Max_Particles (void) const { return MaxParticles; }
|
||||
Vector3 Get_Start_Velocity (void) const { return BaseVel * 1000.0F; }
|
||||
Vector3Randomizer * Get_Creation_Volume (void) const;
|
||||
Vector3Randomizer * Get_Velocity_Random (void) const;
|
||||
float Get_Outwards_Vel (void) const { return OutwardVel * 1000.0F; }
|
||||
float Get_Velocity_Inherit (void) const{ return VelInheritFactor; }
|
||||
ShaderClass Get_Shader (void) const { return Buffer->Get_Shader (); }
|
||||
|
||||
// Note: Caller IS RESPONSIBLE for freeing any memory allocated by these calls
|
||||
void Get_Color_Key_Frames (ParticlePropertyStruct<Vector3> &colors) const { Buffer->Get_Color_Key_Frames (colors); }
|
||||
void Get_Opacity_Key_Frames (ParticlePropertyStruct<float> &opacities) const { Buffer->Get_Opacity_Key_Frames (opacities); }
|
||||
void Get_Size_Key_Frames (ParticlePropertyStruct<float> &sizes) const { Buffer->Get_Size_Key_Frames (sizes); }
|
||||
void Get_Rotation_Key_Frames (ParticlePropertyStruct<float> &rotations) const { Buffer->Get_Rotation_Key_Frames (rotations); }
|
||||
void Get_Frame_Key_Frames (ParticlePropertyStruct<float> &frames) const { Buffer->Get_Frame_Key_Frames (frames); }
|
||||
void Get_Blur_Time_Key_Frames (ParticlePropertyStruct<float> &blurtimes) const { Buffer->Get_Blur_Time_Key_Frames (blurtimes); }
|
||||
float Get_Initial_Orientation_Random (void) const { return Buffer->Get_Initial_Orientation_Random(); }
|
||||
|
||||
// Line rendering accessors
|
||||
int Get_Line_Texture_Mapping_Mode(void) const { return Buffer->Get_Line_Texture_Mapping_Mode(); }
|
||||
int Is_Merge_Intersections(void) const { return Buffer->Is_Merge_Intersections(); }
|
||||
int Is_Freeze_Random(void) const { return Buffer->Is_Freeze_Random(); }
|
||||
int Is_Sorting_Disabled(void) const { return Buffer->Is_Sorting_Disabled(); }
|
||||
int Are_End_Caps_Enabled(void) const { return Buffer->Are_End_Caps_Enabled(); }
|
||||
int Get_Subdivision_Level(void) const { return Buffer->Get_Subdivision_Level(); }
|
||||
float Get_Noise_Amplitude(void) const { return Buffer->Get_Noise_Amplitude(); }
|
||||
float Get_Merge_Abort_Factor(void) const { return Buffer->Get_Merge_Abort_Factor(); }
|
||||
float Get_Texture_Tile_Factor(void) const { return Buffer->Get_Texture_Tile_Factor(); }
|
||||
Vector2 Get_UV_Offset_Rate(void) const { return Buffer->Get_UV_Offset_Rate(); }
|
||||
|
||||
// Global debugging option for disabling all particle emission
|
||||
#ifdef WWDEBUG
|
||||
static void Disable_All_Emitters(bool onoff) { DebugDisable = onoff; }
|
||||
static bool Are_Emitters_Disabled(void) { return DebugDisable; }
|
||||
#endif
|
||||
|
||||
protected:
|
||||
|
||||
// Used to build a list of filenames this emitter is dependent on
|
||||
virtual void Add_Dependencies_To_List (DynamicVectorClass<StringClass> &file_list, bool textures_only = false);
|
||||
|
||||
// This method is called each time the visiblity state of the emitter changes.
|
||||
virtual void Update_On_Visibilty (void);
|
||||
|
||||
private:
|
||||
|
||||
// Collision sphere is a point - emitter emits also when not visible,
|
||||
// so this is only important to avoid affecting the collision spheres
|
||||
// of heirarchy objects into which the emitter is inserted.
|
||||
virtual void Update_Cached_Bounding_Volumes(void) const;
|
||||
|
||||
// Create new particles and pass them to the particle buffer. Receives
|
||||
// the end-of-interval quaternion and origin and interpolates between
|
||||
// them and PrevQ/PrevOrig to get the transform to apply to each
|
||||
// particle's position and velocity as it is created. New particles are
|
||||
// placed into a circular queue for processing by the particle buffer.
|
||||
void Create_New_Particles(const Quaternion & curr_quat, const Vector3 & curr_orig);
|
||||
|
||||
// Initialize one new particle at the given NewParticleStruct
|
||||
// address, with the given age and emitter transform (expressed as a
|
||||
// quaternion and origin vector). (must check if address is NULL).
|
||||
void Initialize_Particle(NewParticleStruct * newpart, unsigned int age,
|
||||
const Quaternion & quat, const Vector3 & orig);
|
||||
|
||||
unsigned int EmitRate; // Emission rate (1/milliseconds).
|
||||
unsigned int BurstSize; // Burst size (how many particles in each emission).
|
||||
unsigned int OneTimeBurstSize; // Burst size for a one-time burst.
|
||||
bool OneTimeBurst; // Do we need to do a one-time burst?
|
||||
Vector3Randomizer * PosRand; // Position randomizer pointer (may be NULL).
|
||||
Vector3 BaseVel; // Base initial emission velocity.
|
||||
Vector3Randomizer * VelRand; // Velocity randomizer pointer (may be NULL).
|
||||
float OutwardVel; // Size of outwards velocity.
|
||||
float VelInheritFactor; // Affects emitter vel. inherited by particles.
|
||||
unsigned int EmitRemain; // Millisecond emitter remainder.
|
||||
Quaternion PrevQ; // Previous quaternion (for interpolation).
|
||||
Vector3 PrevOrig; // Previous origin (for interpolation).
|
||||
bool Active; // Is the emitter currently Active?
|
||||
bool FirstTime; // Has it been rendered before?
|
||||
bool BufferSceneNeeded;// Does the buffer need a scene?
|
||||
int ParticlesLeft; // Particles left to emit
|
||||
int MaxParticles; // Total particles to emit
|
||||
bool IsComplete; // Completed Emissions
|
||||
char * NameString;
|
||||
char * UserString;
|
||||
bool RemoveOnComplete; // Should this emitter destroy itself when it completes?
|
||||
bool IsInScene;
|
||||
|
||||
// This pointer is used only for sending new particles to the particle
|
||||
// buffer and for informing the buffer when the emitter is destroyed.
|
||||
ParticleBufferClass * Buffer;
|
||||
|
||||
// This is used to set the global behavior of emitters...
|
||||
// Should they be removed from the scene when they complete their
|
||||
// emissions, or should they stay in the scene. (For editing purposes)
|
||||
static bool DefaultRemoveOnComplete;
|
||||
|
||||
// This setting is used in debug and profile builds to disable
|
||||
// all particle emitters.
|
||||
static bool DebugDisable;
|
||||
};
|
||||
|
||||
#endif // PART_EMT_H
|
||||
|
||||
|
||||
Reference in New Issue
Block a user