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 1200
// 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
// Feature flags
# define FX_DEPTH_HACK 0x00100000
# define FX_RELATIVE 0x00200000
# define FX_SET_SHADER_TIME 0x00400000 // by having the effects system set the shader time, we can make animating textures start at the correct time
# 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
//------------------------------
class CEffect
{
protected :
vec3_t mOrigin1 ;
int mTimeStart ;
int mTimeEnd ;
unsigned int mFlags ;
// 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
refEntity_t mRefEnt ;
public :
CEffect ( ) { memset ( & mRefEnt , 0 , sizeof ( refEntity_t ) ) ; }
virtual ~ CEffect ( ) { }
virtual void Die ( ) { }
virtual bool Update ( )
{ // Game pausing can cause dumb time things to happen, so kill the effect in this instance
if ( mTimeStart > theFxHelper . mTime ) {
return false ;
}
return true ;
}
inline void SetSTScale ( float s , float t ) { mRefEnt . shaderTexCoord [ 0 ] = s ; mRefEnt . shaderTexCoord [ 1 ] = t ; }
inline void SetMin ( const vec3_t min ) { if ( min ) { VectorCopy ( min , mMin ) ; } else { VectorClear ( mMin ) ; } }
inline void SetMax ( const 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 ( const 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 = cg . time * 0.001f ; } }
inline void SetTimeEnd ( int time ) { mTimeEnd = time ; }
inline void SetImpactFxID ( int id ) { mImpactFxID = id ; }
inline void SetDeathFxID ( int id ) { mDeathFxID = id ; }
} ;
//---------------------------------------------------
// 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 mRGBStart ;
vec3_t mRGBEnd ;
float mRGBParm ;
void UpdateSize ( ) ;
void UpdateRGB ( ) ;
void Draw ( )
{
theFxHelper . AddLightToScene ( mOrigin1 , mRefEnt . radius ,
mRefEnt . lightingOrigin [ 0 ] , mRefEnt . lightingOrigin [ 1 ] , mRefEnt . lightingOrigin [ 2 ] ) ;
}
public :
CLight ( ) { }
virtual ~ CLight ( ) { }
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 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 CFlash : public CLight
{
protected :
void Draw ( ) ;
public :
CFlash ( ) { }
virtual ~ CFlash ( ) { }
virtual bool Update ( ) ;
inline void SetShader ( qhandle_t sh )
{ assert ( sh ) ;
mRefEnt . customShader = sh ;
}
void Init ( void ) ;
} ;
//------------------------------
class CParticle : public CEffect
{
protected :
vec3_t mOrgOffset ;
vec3_t mVel ;
vec3_t mAccel ;
float mGravity ;
float mSizeStart ;
float mSizeEnd ;
float mSizeParm ;
vec3_t mRGBStart ;
vec3_t mRGBEnd ;
float mRGBParm ;
float mAlphaStart ;
float mAlphaEnd ;
float mAlphaParm ;
float mRotationDelta ;
float mElasticity ;
short mClientID ;
char mModelNum ;
char mBoltNum ;
bool UpdateOrigin ( ) ;
void UpdateVelocity ( ) { VectorMA ( mVel , theFxHelper . mFloatFrameTime , mAccel , mVel ) ; }
void UpdateSize ( ) ;
void UpdateRGB ( ) ;
void UpdateAlpha ( ) ;
void UpdateRotation ( ) { mRefEnt . rotation + = theFxHelper . mFrameTime * 0.01f * mRotationDelta ; }
bool Cull ( ) ;
void Draw ( ) ;
public :
inline CParticle ( ) { mRefEnt . reType = RT_SPRITE ; mClientID = - 1 ; mModelNum = - 1 ; mBoltNum = - 1 ; }
virtual ~ CParticle ( ) { }
virtual void Die ( ) ;
virtual bool Update ( ) ;
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 ( const vec3_t vel ) { if ( vel ) { VectorCopy ( vel , mVel ) ; } else { VectorClear ( mVel ) ; } }
inline void SetAccel ( const vec3_t ac ) { if ( ac ) { VectorCopy ( ac , mAccel ) ; } else { VectorClear ( mAccel ) ; } }
inline void SetGravity ( float grav ) { mGravity = grav ; }
inline void SetSizeStart ( float sz ) { mSizeStart = sz ; }
inline void SetSizeEnd ( float sz ) { mSizeEnd = sz ; }
inline void SetSizeParm ( float parm ) { mSizeParm = parm ; }
inline void SetRGBStart ( const vec3_t rgb ) { if ( rgb ) { VectorCopy ( rgb , mRGBStart ) ; } else { VectorClear ( mRGBStart ) ; } }
inline void SetRGBEnd ( const 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 ; }
inline void SetClient ( int clientID , int modelNum = - 1 , int boltNum = - 1 ) { mClientID = clientID ; mModelNum = modelNum ; mBoltNum = boltNum ; }
} ;
//------------------------------
class CLine : public CParticle
{
protected :
vec3_t mOrigin2 ;
void Draw ( ) ;
public :
CLine ( ) { mRefEnt . reType = RT_LINE ; }
virtual ~ CLine ( ) { }
virtual void Die ( ) { }
virtual bool Update ( ) ;
inline void SetOrigin2 ( const 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 ;
void Draw ( ) ;
public :
CBezier ( ) { mInit = false ; }
virtual ~ CBezier ( ) { }
virtual void Die ( ) { }
virtual bool Update ( ) ;
void DrawSegment ( vec3_t start , vec3_t end , float texcoord1 , float texcoord2 ) ;
inline void SetControlPoints ( const vec3_t ctrl1 , const vec3_t ctrl2 ) { VectorCopy ( ctrl1 , mControl1 ) ; VectorCopy ( ctrl2 , mControl2 ) ; }
inline void SetControlVel ( const vec3_t ctrl1v , const vec3_t ctrl2v ) { VectorCopy ( ctrl1v , mControl1Vel ) ; VectorCopy ( ctrl2v , mControl2Vel ) ; }
} ;
//------------------------------
class CElectricity : public CLine
{
protected :
float mChaos ;
void Draw ( ) ;
public :
CElectricity ( ) { mRefEnt . reType = RT_ELECTRICITY ; }
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 ;
vec3_t mNormalOffset ;
bool Cull ( ) ;
void Draw ( ) ;
public :
COrientedParticle ( ) { mRefEnt . reType = RT_ORIENTED_QUAD ; }
virtual ~ COrientedParticle ( ) { }
virtual bool Update ( ) ;
inline void SetNormal ( const vec3_t norm ) { VectorCopy ( norm , mNormal ) ; }
inline void SetNormalOffset ( const vec3_t norm ) { VectorCopy ( norm , mNormalOffset ) ; }
} ;
//------------------------------
class CTail : public CParticle
{
protected :
vec3_t mOldOrigin ;
float mLengthStart ;
float mLengthEnd ;
float mLengthParm ;
float mLength ;
void UpdateLength ( ) ;
void CalcNewEndpoint ( ) ;
void Draw ( ) ;
bool Cull ( ) ;
public :
CTail ( ) { mRefEnt . reType = RT_LINE ; }
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 ;
void UpdateSize2 ( ) ;
void Draw ( ) ;
public :
CCylinder ( ) { mRefEnt . reType = RT_CYLINDER ; }
virtual ~ CCylinder ( ) { }
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 SetNormal ( const 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 ( ) ;
void Draw ( ) ;
public :
CEmitter ( ) {
// There may or may not be a model, but if there isn't one,
// we just won't bother adding the refEnt in our Draw func
mRefEnt . reType = RT_MODEL ;
}
virtual ~ CEmitter ( ) { }
virtual bool Update ( ) ;
inline void SetModel ( qhandle_t model ) { mRefEnt . hModel = model ; }
inline void SetAngles ( const vec3_t ang ) { if ( ang ) { VectorCopy ( ang , mAngles ) ; } else { VectorClear ( mAngles ) ; } }
inline void SetAngleDelta ( const 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 ( const vec3_t org ) { if ( org ) { VectorCopy ( org , mLastOrigin ) ; } else { VectorClear ( mLastOrigin ) ; } }
inline void SetLastVel ( const 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....
// The editor doesn't need to see or do anything with this
//------------------------------
# define MAX_CPOLY_VERTS 5
class CPoly : public CParticle
{
protected :
int mCount ;
vec3_t mRotDelta ;
int mTimeStamp ;
bool Cull ( ) ;
void Draw ( ) ;
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 ( ) ;
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 . mTime + t ; }
inline int GetMotionTimeStamp ( ) { return mTimeStamp ; }
} ;
2013-04-04 22:35:38 +00:00
# endif //FX_PRIMITIVES_H_INC