2013-04-19 02:52:48 +00:00
# if !defined(FX_SYSTEM_H_INC)
# include "FxSystem.h"
# endif
# ifndef FX_PRIMITIVES_H_INC
# define FX_PRIMITIVES_H_INC
# define MAX_EFFECTS 1800
// Generic group flags, used by parser, then get converted to the appropriate specific flags
# define FX_PARM_MASK 0xC // use this to mask off any transition types that use a parm
# define FX_GENERIC_MASK 0xF
# define FX_LINEAR 0x1
# define FX_RAND 0x2
# define FX_NONLINEAR 0x4
# define FX_WAVE 0x8
# define FX_CLAMP 0xC
// Group flags
# define FX_ALPHA_SHIFT 0
# define FX_ALPHA_PARM_MASK 0x0000000C
# define FX_ALPHA_LINEAR 0x00000001
# define FX_ALPHA_RAND 0x00000002
# define FX_ALPHA_NONLINEAR 0x00000004
# define FX_ALPHA_WAVE 0x00000008
# define FX_ALPHA_CLAMP 0x0000000C
# define FX_RGB_SHIFT 4
# define FX_RGB_PARM_MASK 0x000000C0
# define FX_RGB_LINEAR 0x00000010
# define FX_RGB_RAND 0x00000020
# define FX_RGB_NONLINEAR 0x00000040
# define FX_RGB_WAVE 0x00000080
# define FX_RGB_CLAMP 0x000000C0
# define FX_SIZE_SHIFT 8
# define FX_SIZE_PARM_MASK 0x00000C00
# define FX_SIZE_LINEAR 0x00000100
# define FX_SIZE_RAND 0x00000200
# define FX_SIZE_NONLINEAR 0x00000400
# define FX_SIZE_WAVE 0x00000800
# define FX_SIZE_CLAMP 0x00000C00
# define FX_LENGTH_SHIFT 12
# define FX_LENGTH_PARM_MASK 0x0000C000
# define FX_LENGTH_LINEAR 0x00001000
# define FX_LENGTH_RAND 0x00002000
# define FX_LENGTH_NONLINEAR 0x00004000
# define FX_LENGTH_WAVE 0x00008000
# define FX_LENGTH_CLAMP 0x0000C000
# define FX_SIZE2_SHIFT 16
# define FX_SIZE2_PARM_MASK 0x000C0000
# define FX_SIZE2_LINEAR 0x00010000
# define FX_SIZE2_RAND 0x00020000
# define FX_SIZE2_NONLINEAR 0x00040000
# define FX_SIZE2_WAVE 0x00080000
# define FX_SIZE2_CLAMP 0x000C0000
// Shared flag--these flags, at first glance would appear to be shared, but are safe. I'd rather not do this, but as you can see, features flags are currently all accounted for
# define FX_PAPER_PHYSICS 0x00010000 // emitters ONLY. shared with FX_SIZE_2_LINEAR
# define FX_LOCALIZED_FLASH 0x00010000 // full screen flashes ONLY. shared with FX_SIZE_2_LINEAR
# define FX_PLAYER_VIEW 0x00010000 // player view effects ONLY. shared with FX_SIZE_2_LINEAR
// Feature flags
# define FX_DEPTH_HACK 0x00100000
# define FX_RELATIVE 0x00200000
# define FX_SET_SHADER_TIME 0x00400000
# define FX_EXPENSIVE_PHYSICS 0x00800000
//rww - g2-related flags (these can slow things down significantly, use sparingly)
//These should be used only with particles/decals as they steal flags used by cylinders.
# define FX_GHOUL2_TRACE 0x00020000 //use in conjunction with particles - actually do full ghoul2 traces for physics collision against entities with a ghoul2 instance
//shared FX_SIZE2_RAND (used only with cylinders)
# define FX_GHOUL2_DECALS 0x00040000 //use in conjunction with decals - can project decal as a ghoul2 gore skin object onto ghoul2 models
//shared FX_SIZE2_NONLINEAR (used only with cylinders)
# define FX_ATTACHED_MODEL 0x01000000
# define FX_APPLY_PHYSICS 0x02000000
# define FX_USE_BBOX 0x04000000 // can make physics more accurate at the expense of speed
# define FX_USE_ALPHA 0x08000000 // the FX system actually uses RGB to do fades, but this will override that
// and cause it to fill in the alpha.
# define FX_EMIT_FX 0x10000000 // emitters technically don't have to emit stuff, but when they do
// this flag needs to be set
# define FX_DEATH_RUNS_FX 0x20000000 // Normal death triggers effect, but not kill_on_impact
# define FX_KILL_ON_IMPACT 0x40000000 // works just like it says, but only when physics are on.
# define FX_IMPACT_RUNS_FX 0x80000000 // an effect can call another effect when it hits something.
// Lightning flags, duplicates of existing flags, but lightning doesn't use those flags in that context...and nothing will ever use these in this context..so we are safe.
# define FX_TAPER 0x01000000 // tapers as it moves towards its endpoint
# define FX_BRANCH 0x02000000 // enables lightning branching
# define FX_GROW 0x04000000 // lightning grows from start point to end point over the course of its life
// stuff that can occur when an effect is flagged with "materialImpact" and it hits something
enum EMatImpactEffect
{
MATIMPACTFX_NONE = 0 ,
MATIMPACTFX_SHELLSOUND
} ;
//------------------------------
class CEffect
{
protected :
CEffect * mNext ;
vec3_t mOrigin1 ;
int mTimeStart ;
int mTimeEnd ;
unsigned int mFlags ;
EMatImpactEffect mMatImpactFX ;
int mMatImpactParm ;
// Size of our object, useful for things that have physics
vec3_t mMin ;
vec3_t mMax ;
int mImpactFxID ; // if we have an impact event, we may have to call an effect
int mDeathFxID ; // if we have a death event, we may have to call an effect
miniRefEntity_t mRefEnt ;
int mSoundRadius ;
int mSoundVolume ;
public :
CEffect ( ) ;
virtual ~ CEffect ( ) { }
virtual void Die ( ) { }
virtual bool Update ( ) { return true ; }
virtual void Draw ( void ) { }
inline miniRefEntity_t & GetRefEnt ( void ) { return mRefEnt ; }
inline void SetNext ( CEffect * Next ) { mNext = Next ; }
inline CEffect * GetNext ( void ) { return mNext ; }
inline void GetOrigin ( vec3_t dest ) { VectorCopy ( mOrigin1 , dest ) ; }
inline void SetSTScale ( float s , float t ) { mRefEnt . shaderTexCoord [ 0 ] = s ; mRefEnt . shaderTexCoord [ 1 ] = t ; }
inline void SetSound ( int vol , int rad ) { mSoundRadius = rad ; mSoundVolume = vol ; }
inline void SetMin ( vec3_t min ) { if ( min ) { VectorCopy ( min , mMin ) ; } else { VectorClear ( mMin ) ; } }
inline void SetMax ( vec3_t max ) { if ( max ) { VectorCopy ( max , mMax ) ; } else { VectorClear ( mMax ) ; } }
inline void SetFlags ( int flags ) { mFlags = flags ; }
inline void AddFlags ( int flags ) { mFlags | = flags ; }
inline void ClearFlags ( int flags ) { mFlags & = ~ flags ; }
inline void SetOrigin1 ( vec3_t org ) { if ( org ) { VectorCopy ( org , mOrigin1 ) ; } else { VectorClear ( mOrigin1 ) ; } }
inline void SetTimeStart ( int time ) { mTimeStart = time ; if ( mFlags & FX_SET_SHADER_TIME ) { mRefEnt . shaderTime = time * 0.001f ; } }
inline void SetTimeEnd ( int time ) { mTimeEnd = time ; }
inline void SetImpactFxID ( int id ) { mImpactFxID = id ; }
inline void SetDeathFxID ( int id ) { mDeathFxID = id ; }
inline EMatImpactEffect GetMatImpactFX ( ) { return mMatImpactFX ; }
inline int GetMatImpactParm ( ) { return mMatImpactParm ; }
inline void SetMatImpactFX ( EMatImpactEffect matFX ) { mMatImpactFX = matFX ; }
inline void SetMatImpactParm ( int matParm ) { mMatImpactParm = matParm ; }
} ;
//---------------------------------------------------
// This class is kind of an exception to the "rule".
// For now it exists only for allowing an easy way
// to get the saber slash trails rendered.
//---------------------------------------------------
class CTrail : public CEffect
{
// This is such a specific case thing, just grant public access to the goods.
protected :
void Draw ( ) ;
public :
typedef struct
{
vec3_t origin ;
// very specifc case, we can modulate the color and the alpha
vec3_t rgb ;
vec3_t destrgb ;
vec3_t curRGB ;
float alpha ;
float destAlpha ;
float curAlpha ;
// this is a very specific case thing...allow interpolating the st coords so we can map the texture
// properly as this segement progresses through it's life
float ST [ 2 ] ;
float destST [ 2 ] ;
float curST [ 2 ] ;
} TVert ;
TVert mVerts [ 4 ] ;
qhandle_t mShader ;
CTrail ( ) { } ;
virtual ~ CTrail ( ) { } ;
virtual bool Update ( ) ;
} ;
//------------------------------
class CLight : public CEffect
{
protected :
float mSizeStart ;
float mSizeEnd ;
float mSizeParm ;
vec3_t mOrgOffset ;
vec3_t mRGBStart ;
vec3_t mRGBEnd ;
float mRGBParm ;
CGhoul2Info_v mGhoul2 ;
short mEntNum ;
char mModelNum ;
char mBoltNum ;
void UpdateSize ( ) ;
void UpdateRGB ( ) ;
virtual void Draw ( void ) ;
public :
inline CLight ( void )
{
mEntNum = - 1 ; mModelNum = - 1 ; mBoltNum = - 1 ;
}
virtual ~ CLight ( void )
{
mGhoul2 . kill ( ) ; //remove my model ref without actually deleting
}
inline void SetBoltinfo ( int iGhoul2 , int entNum , int modelNum = - 1 , int boltNum = - 1 )
{
mGhoul2 = iGhoul2 ; mEntNum = entNum ; mModelNum = modelNum ; mBoltNum = boltNum ;
}
virtual bool Update ( ) ;
inline void SetSizeStart ( float sz ) { mSizeStart = sz ; }
inline void SetSizeEnd ( float sz ) { mSizeEnd = sz ; }
inline void SetSizeParm ( float parm ) { mSizeParm = parm ; }
inline void SetOrgOffset ( const vec3_t o ) { if ( o ) { VectorCopy ( o , mOrgOffset ) ; } else { VectorClear ( mOrgOffset ) ; } }
inline void SetRGBStart ( vec3_t rgb ) { if ( rgb ) { VectorCopy ( rgb , mRGBStart ) ; } else { VectorClear ( mRGBStart ) ; } }
inline void SetRGBEnd ( vec3_t rgb ) { if ( rgb ) { VectorCopy ( rgb , mRGBEnd ) ; } else { VectorClear ( mRGBEnd ) ; } }
inline void SetRGBParm ( float parm ) { mRGBParm = parm ; }
} ;
//------------------------------
class CParticle : public CEffect
{
protected :
vec3_t mOrgOffset ;
vec3_t mVel ;
vec3_t mAccel ;
float mSizeStart ;
float mSizeEnd ;
float mSizeParm ;
vec3_t mRGBStart ;
vec3_t mRGBEnd ;
float mRGBParm ;
float mAlphaStart ;
float mAlphaEnd ;
float mAlphaParm ;
float mRotationDelta ;
float mElasticity ;
CGhoul2Info_v mGhoul2 ;
short mEntNum ;
char mModelNum ;
char mBoltNum ;
bool UpdateOrigin ( ) ;
void UpdateSize ( ) ;
void UpdateRGB ( ) ;
void UpdateAlpha ( ) ;
void UpdateRotation ( ) ;
public :
inline void SetBoltinfo ( int iGhoul2 , int entNum , int modelNum = - 1 , int boltNum = - 1 )
{
mGhoul2 = iGhoul2 ; mEntNum = entNum ; mModelNum = modelNum ; mBoltNum = boltNum ;
}
2013-04-26 07:33:31 +00:00
inline CParticle ( void )
2013-04-19 02:52:48 +00:00
{
mRefEnt . reType = RT_SPRITE ; mEntNum = - 1 ; mModelNum = - 1 ; mBoltNum = - 1 ;
}
2013-04-26 07:33:31 +00:00
virtual ~ CParticle ( void )
2013-04-19 02:52:48 +00:00
{
mGhoul2 . kill ( ) ; //remove my model ref without actually deleting
}
virtual void Init ( ) ;
virtual void Die ( ) ;
virtual bool Update ( ) ;
virtual bool Cull ( void ) ;
virtual void Draw ( void ) ;
inline void SetShader ( qhandle_t sh ) { mRefEnt . customShader = sh ; }
inline void SetOrgOffset ( const vec3_t o ) { if ( o ) { VectorCopy ( o , mOrgOffset ) ; } else { VectorClear ( mOrgOffset ) ; } }
inline void SetVel ( vec3_t vel ) { if ( vel ) { VectorCopy ( vel , mVel ) ; } else { VectorClear ( mVel ) ; } }
inline void SetAccel ( vec3_t ac ) { if ( ac ) { VectorCopy ( ac , mAccel ) ; } else { VectorClear ( mAccel ) ; } }
inline void SetSizeStart ( float sz ) { mSizeStart = sz ; mRefEnt . radius = sz ; }
inline void SetSizeEnd ( float sz ) { mSizeEnd = sz ; }
inline void SetSizeParm ( float parm ) { mSizeParm = parm ; }
inline void SetRGBStart ( vec3_t rgb ) { if ( rgb ) { VectorCopy ( rgb , mRGBStart ) ; } else { VectorClear ( mRGBStart ) ; } }
inline void SetRGBEnd ( vec3_t rgb ) { if ( rgb ) { VectorCopy ( rgb , mRGBEnd ) ; } else { VectorClear ( mRGBEnd ) ; } }
inline void SetRGBParm ( float parm ) { mRGBParm = parm ; }
inline void SetAlphaStart ( float al ) { mAlphaStart = al ; }
inline void SetAlphaEnd ( float al ) { mAlphaEnd = al ; }
inline void SetAlphaParm ( float parm ) { mAlphaParm = parm ; }
inline void SetRotation ( float rot ) { mRefEnt . rotation = rot ; }
inline void SetRotationDelta ( float rot ) { mRotationDelta = rot ; }
inline void SetElasticity ( float el ) { mElasticity = el ; }
} ;
//------------------------------
class CFlash : public CParticle
{
public :
CFlash ( ) :
mScreenX ( 0 ) ,
mScreenY ( 0 ) ,
mRadiusModifier ( 1 )
{ }
virtual ~ CFlash ( ) { }
virtual bool Update ( ) ;
virtual void Draw ( void ) ;
virtual bool Cull ( void ) { return false ; }
void Init ( void ) ;
protected :
// kef -- mScreenX and mScreenY are used for flashes that are FX_LOCALIZED_FLASH
float mScreenX ;
float mScreenY ;
float mRadiusModifier ;
} ;
//------------------------------
class CLine : public CParticle
{
protected :
vec3_t mOrigin2 ;
virtual void Draw ( void ) ;
public :
CLine ( ) ;
virtual ~ CLine ( ) { }
virtual void Die ( ) { }
virtual bool Update ( ) ;
inline void SetOrigin2 ( vec3_t org2 ) { VectorCopy ( org2 , mOrigin2 ) ; }
} ;
//------------------------------
class CBezier : public CLine
{
protected :
vec3_t mControl1 ;
vec3_t mControl1Vel ;
vec3_t mControl2 ;
vec3_t mControl2Vel ;
bool mInit ;
public :
CBezier ( ) { mInit = false ; }
virtual ~ CBezier ( ) { }
virtual void Die ( ) { }
virtual bool Update ( ) ;
virtual bool Cull ( void ) ;
virtual void Draw ( void ) ;
void DrawSegment ( vec3_t start , vec3_t end , float texcoord1 , float texcoord2 , float segPercent , float lastSegPercent ) ;
inline void SetControlPoints ( vec3_t ctrl1 , vec3_t ctrl2 ) { VectorCopy ( ctrl1 , mControl1 ) ; VectorCopy ( ctrl2 , mControl2 ) ; }
inline void SetControlVel ( vec3_t ctrl1v , vec3_t ctrl2v ) { VectorCopy ( ctrl1v , mControl1Vel ) ; VectorCopy ( ctrl2v , mControl2Vel ) ; }
} ;
//------------------------------
class CElectricity : public CLine
{
protected :
float mChaos ;
virtual void Draw ( void ) ;
public :
CElectricity ( ) ;
virtual ~ CElectricity ( ) { }
virtual void Die ( ) { }
virtual bool Update ( ) ;
void Initialize ( ) ;
inline void SetChaos ( float chaos ) { mChaos = chaos ; }
} ;
// Oriented quad
//------------------------------
class COrientedParticle : public CParticle
{
protected :
vec3_t mNormal ;
public :
COrientedParticle ( ) ;
virtual ~ COrientedParticle ( ) { }
virtual bool Update ( ) ;
virtual bool Cull ( void ) ;
virtual void Draw ( void ) ;
inline void SetNormal ( vec3_t norm ) { VectorCopy ( norm , mNormal ) ; }
} ;
//------------------------------
class CTail : public CParticle
{
protected :
vec3_t mOldOrigin ;
float mLengthStart ;
float mLengthEnd ;
float mLengthParm ;
float mLength ;
void UpdateLength ( ) ;
void CalcNewEndpoint ( ) ;
virtual void Draw ( void ) ;
public :
CTail ( ) ;
virtual ~ CTail ( ) { }
virtual bool Update ( ) ;
inline void SetLengthStart ( float len ) { mLengthStart = len ; }
inline void SetLengthEnd ( float len ) { mLengthEnd = len ; }
inline void SetLengthParm ( float len ) { mLengthParm = len ; }
} ;
//------------------------------
class CCylinder : public CTail
{
protected :
float mSize2Start ;
float mSize2End ;
float mSize2Parm ;
qboolean mTraceEnd ;
void UpdateSize2 ( ) ;
virtual void Draw ( void ) ;
public :
CCylinder ( ) ;
virtual ~ CCylinder ( ) { }
virtual bool Cull ( void ) ;
virtual void UpdateLength ( void ) ;
virtual bool Update ( ) ;
inline void SetSize2Start ( float sz ) { mSize2Start = sz ; }
inline void SetSize2End ( float sz ) { mSize2End = sz ; }
inline void SetSize2Parm ( float parm ) { mSize2Parm = parm ; }
inline void SetTraceEnd ( qboolean traceEnd ) { mTraceEnd = traceEnd ; }
inline void SetNormal ( vec3_t norm ) { VectorCopy ( norm , mRefEnt . axis [ 0 ] ) ; }
} ;
//------------------------------
// Emitters are derived from particles because, although they don't draw, any effect called
// from them can borrow an initial or ending value from the emitters current alpha, rgb, etc..
class CEmitter : public CParticle
{
protected :
vec3_t mOldOrigin ; // we use these to do some nice
vec3_t mLastOrigin ; // tricks...
vec3_t mOldVelocity ; //
int mOldTime ;
vec3_t mAngles ; // for a rotating thing, using a delta
vec3_t mAngleDelta ; // as opposed to an end angle is probably much easier
int mEmitterFxID ; // if we have emitter fx, this is our id
float mDensity ; // controls how often emitter chucks an effect
float mVariance ; // density sloppiness
void UpdateAngles ( ) ;
virtual void Draw ( void ) ;
public :
CEmitter ( ) ;
virtual ~ CEmitter ( ) ;
virtual bool Cull ( void ) { return false ; }
virtual bool Update ( ) ;
inline void SetModel ( qhandle_t model ) { mRefEnt . hModel = model ; }
inline void SetAngles ( vec3_t ang ) { if ( ang ) { VectorCopy ( ang , mAngles ) ; } else { VectorClear ( mAngles ) ; } }
inline void SetAngleDelta ( vec3_t ang ) { if ( ang ) { VectorCopy ( ang , mAngleDelta ) ; } else { VectorClear ( mAngleDelta ) ; } }
inline void SetEmitterFxID ( int id ) { mEmitterFxID = id ; }
inline void SetDensity ( float density ) { mDensity = density ; }
inline void SetVariance ( float var ) { mVariance = var ; }
inline void SetOldTime ( int time ) { mOldTime = time ; }
inline void SetLastOrg ( vec3_t org ) { if ( org ) { VectorCopy ( org , mLastOrigin ) ; } else { VectorClear ( mLastOrigin ) ; } }
inline void SetLastVel ( vec3_t vel ) { if ( vel ) { VectorCopy ( vel , mOldVelocity ) ; } else { VectorClear ( mOldVelocity ) ; } }
} ;
// We're getting pretty low level here, not the kind of thing to abuse considering how much overhead this
// adds to a SINGLE triangle or quad....
//------------------------------
# define MAX_CPOLY_VERTS 5
class CPoly : public CParticle
{
protected :
int mCount ;
vec3_t mRotDelta ;
int mTimeStamp ;
public :
vec3_t mOrg [ MAX_CPOLY_VERTS ] ;
vec2_t mST [ MAX_CPOLY_VERTS ] ;
float mRot [ 3 ] [ 3 ] ;
int mLastFrameTime ;
CPoly ( ) { }
virtual ~ CPoly ( ) { }
virtual bool Update ( ) ;
virtual bool Cull ( void ) ;
virtual void Draw ( void ) ;
void PolyInit ( ) ;
void CalcRotateMatrix ( ) ;
void Rotate ( ) ;
inline void SetNumVerts ( int c ) { mCount = c ; }
inline void SetRot ( vec3_t r ) { if ( r ) { VectorCopy ( r , mRotDelta ) ; } else { VectorClear ( mRotDelta ) ; } }
inline void SetMotionTimeStamp ( int t ) { mTimeStamp = theFxHelper . GetTime ( ) + t ; }
inline int GetMotionTimeStamp ( ) { return mTimeStamp ; }
} ;
2013-04-26 07:33:31 +00:00
# endif //FX_PRIMITIVES_H_INC