// RAVEN BEGIN // bdube: note that this file is no longer merged with Doom3 updates // // MERGE_DATE 09/30/2004 #ifndef __ANIM_H__ #define __ANIM_H__ // // animation channels // these can be changed by modmakers and licensees to be whatever they need. const int ANIM_NumAnimChannels = 5; const int ANIM_MaxAnimsPerChannel = 3; const int ANIM_MaxSyncedAnims = 3; // // animation channels. make sure to change script/doom_defs.script if you add any channels, or change their order // const int ANIMCHANNEL_ALL = 0; const int ANIMCHANNEL_TORSO = 1; const int ANIMCHANNEL_LEGS = 2; const int ANIMCHANNEL_HEAD = 3; const int ANIMCHANNEL_EYELIDS = 4; // for converting from 24 frames per second to milliseconds ID_INLINE int FRAME2MS( int framenum ) { return ( framenum * 1000 ) / 24; } class idRenderModel; class idAnimator; class idAnimBlend; class function_t; class idEntity; class idSaveGame; class idRestoreGame; typedef struct { int cycleCount; // how many times the anim has wrapped to the begining (0 for clamped anims) int frame1; int frame2; float frontlerp; float backlerp; } frameBlend_t; typedef struct { int nameIndex; int parentNum; int animBits; int firstComponent; } jointAnimInfo_t; typedef struct { jointHandle_t num; jointHandle_t parentNum; int channel; } jointInfo_t; // // joint modifier modes. make sure to change script/doom_defs.script if you add any, or change their order. // typedef enum { JOINTMOD_NONE, // no modification JOINTMOD_LOCAL, // modifies the joint's position or orientation in joint local space JOINTMOD_LOCAL_OVERRIDE, // sets the joint's position or orientation in joint local space JOINTMOD_WORLD, // modifies joint's position or orientation in model space JOINTMOD_WORLD_OVERRIDE, // sets the joint's position or orientation in model space JOINTMOD_COLLAPSE } jointModTransform_t; typedef struct { jointHandle_t jointnum; idMat3 mat; idVec3 pos; jointModTransform_t transform_pos; jointModTransform_t transform_axis; // RAVEN BEGIN // bdube: added more features to programmer controlled joints idInterpolateAccelDecelLinear angularVelocity; int lastTime; jointHandle_t collapseJoint; // RAVEN END } jointMod_t; #define ANIM_TX BIT( 0 ) #define ANIM_TY BIT( 1 ) #define ANIM_TZ BIT( 2 ) #define ANIM_QX BIT( 3 ) #define ANIM_QY BIT( 4 ) #define ANIM_QZ BIT( 5 ) typedef enum { FC_SCRIPTFUNCTION, FC_SCRIPTFUNCTIONOBJECT, FC_EVENTFUNCTION, // RAVEN BEGIN // abahr: event call with parms FC_EVENTFUNCTION_ARGS, // RAVEN END FC_SOUND, FC_SOUND_VOICE, FC_SOUND_VOICE2, FC_SOUND_BODY, FC_SOUND_BODY2, FC_SOUND_BODY3, FC_SOUND_WEAPON, FC_SOUND_ITEM, FC_SOUND_GLOBAL, FC_SOUND_CHATTER, FC_SKIN, FC_TRIGGER, FC_DIRECTDAMAGE, FC_MUZZLEFLASH, FC_FOOTSTEP, FC_LEFTFOOT, FC_RIGHTFOOT, FC_ENABLE_EYE_FOCUS, FC_DISABLE_EYE_FOCUS, FC_FX, FC_DISABLE_GRAVITY, FC_ENABLE_GRAVITY, FC_JUMP, FC_ENABLE_CLIP, FC_DISABLE_CLIP, FC_ENABLE_WALK_IK, FC_DISABLE_WALK_IK, FC_ENABLE_LEG_IK, FC_DISABLE_LEG_IK, FC_RECORDDEMO, FC_AVIGAME, FC_GUIEVENT, FC_AI_ENABLE_PAIN, FC_AI_DISABLE_PAIN, FC_AI_ENABLE_DAMAGE, FC_AI_DISABLE_DAMAGE, FC_AI_LOCKENEMYORIGIN, FC_AI_ATTACK, FC_AI_ATTACK_MELEE, FC_AI_SPEAK, FC_AI_SPEAK_RANDOM, // MCG: for attachment managing FC_ACT_ATTACH_HIDE, FC_ACT_ATTACH_SHOW, FC_ENABLE_BLINKING, FC_DISABLE_BLINKING, FC_ENABLE_AUTOBLINK, FC_DISABLE_AUTOBLINK, FC_COUNT } frameCommandType_t; // RAVEN BEGIN // rjohnson: new camera frame commands extern struct frameCommandInfo_t { const char* name; bool modview; } frameCommandInfo[FC_COUNT]; // RAVEN END typedef struct { int num; int firstCommand; } frameLookup_t; typedef struct { frameCommandType_t type; idStr* string; // RAVEN BEGIN // bdube: added joint idStr* joint; idStr* joint2; // abahr: idList* parmList; // RAVEN END union { const idSoundShader *soundShader; const function_t *function; const idDeclSkin *skin; int index; // RAVEN BEGIN // bdube: effects const idDecl *effect; idStr* projectile; idStr* melee; // abahr: const class idEventDef* event; // RAVEN END }; } frameCommand_t; typedef struct { bool prevent_idle_override : 1; bool random_cycle_start : 1; bool ai_no_turn : 1; bool ai_no_look : 1; bool ai_look_head_only : 1; bool anim_turn : 1; bool sync_cycle : 1; } animFlags_t; /* ============================================================================================== idModelExport ============================================================================================== */ class idModelExport { private: void Reset( void ); bool ParseOptions( idLexer &lex ); int ParseExportSection( idParser &parser ); static bool CheckMayaInstall( void ); static void LoadMayaDll( void ); bool ConvertMayaToMD5( void ); static bool initialized; public: idStr commandLine; idStr src; idStr dest; bool force; idModelExport(); static void Shutdown( void ); int ExportDefFile( const char *filename ); bool ExportModel( const char *model ); bool ExportAnim( const char *anim ); int ExportModels( const char *pathname, const char *extension ); }; /* ============================================================================================== idMD5Anim ============================================================================================== */ class idMD5Anim { private: int numFrames; int frameRate; int animLength; int numJoints; int numAnimatedComponents; idList bounds; idList jointInfo; idList baseFrame; idList componentFrames; idStr name; idVec3 totaldelta; mutable int ref_count; public: idMD5Anim(); ~idMD5Anim(); void Free( void ); bool Reload( void ); size_t Allocated( void ) const; size_t Size( void ) const { return sizeof( *this ) + Allocated(); }; bool LoadAnim( const char *filename ); void IncreaseRefs( void ) const; void DecreaseRefs( void ) const; int NumRefs( void ) const; void CheckModelHierarchy( const idRenderModel *model ) const; void GetInterpolatedFrame( const frameBlend_t &frame, idJointQuat *joints, const int *index, int numIndexes ) const; void GetSingleFrame( int framenum, idJointQuat *joints, const int *index, int numIndexes ) const; int Length( void ) const; int NumFrames( void ) const; int NumJoints( void ) const; const idVec3 &TotalMovementDelta( void ) const; const char *Name( void ) const; void ConvertTimeToFrame( int time, int cyclecount, frameBlend_t &frame ) const; // RAVEN BEGIN // jscott: for modview int ConvertFrameToTime( frameBlend_t &frame ) const; // RAVEN END void GetOrigin( idVec3 &offset, int currentTime, int cyclecount ) const; void GetOriginRotation( idQuat &rotation, int time, int cyclecount ) const; void GetBounds( idBounds &bounds, int currentTime, int cyclecount ) const; }; /* ============================================================================================== idAnim ============================================================================================== */ class idAnim { private: const class idDeclModelDef *modelDef; const idMD5Anim *anims[ ANIM_MaxSyncedAnims ]; int numAnims; idStr name; idStr realname; idList frameLookup; idList frameCommands; animFlags_t flags; // RAVEN BEGIN // bdube: added anim speed float rate; // RAVEN END public: idAnim(); idAnim( const idDeclModelDef *modelDef, const idAnim *anim ); ~idAnim(); void SetAnim( const idDeclModelDef *modelDef, const char *sourcename, const char *animname, int num, const idMD5Anim *md5anims[ ANIM_MaxSyncedAnims ] ); const char *Name( void ) const; const char *FullName( void ) const; const idMD5Anim *MD5Anim( int num ) const; const idDeclModelDef *ModelDef( void ) const; int Length( void ) const; int NumFrames( void ) const; int NumAnims( void ) const; const idVec3 &TotalMovementDelta( void ) const; bool GetOrigin( idVec3 &offset, int animNum, int time, int cyclecount ) const; bool GetOriginRotation( idQuat &rotation, int animNum, int currentTime, int cyclecount ) const; bool GetBounds( idBounds &bounds, int animNum, int time, int cyclecount ) const; // RAVEN BEGIN // bdube: frame command function that takes a list of frames const char *AddFrameCommand( const class idDeclModelDef *modelDef, const idList& frames, idLexer &src, const idDict *def ); // RAVEN END void CallFrameCommands( idEntity *ent, int from, int to ) const; bool HasFrameCommands( void ) const; // returns first frame (zero based) that command occurs. returns -1 if not found. int FindFrameForFrameCommand( frameCommandType_t framecommand, const frameCommand_t **command ) const; void SetAnimFlags( const animFlags_t &animflags ); const animFlags_t &GetAnimFlags( void ) const; // RAVEN BEGIN // bdube: added void CallFrameCommandSound ( const frameCommand_t& command, idEntity* ent, const s_channelType channel ) const; float GetPlaybackRate ( void ) const; void SetPlaybackRate ( float rate ); // jsinger: to support binary serialization/deserialization of idAnims #ifdef RV_BINARYDECLS idAnim( idDeclModelDef const *def, SerialInputStream &stream ); void Write( SerialOutputStream &stream ) const; #endif // RAVEN END }; // RAVEN BEGIN // bdube: added configurable playback rate ID_INLINE float idAnim::GetPlaybackRate ( void ) const { return rate; } ID_INLINE void idAnim::SetPlaybackRate ( float _rate ) { rate = _rate; } // RAVEN END /* ============================================================================================== idDeclModelDef ============================================================================================== */ // RAVEN BEGIN // jsinger; allow support for serialization/deserialization of binary decls #ifdef RV_BINARYDECLS class idDeclModelDef : public idDecl, public Serializable<'DMD '> { public: virtual void Write( SerialOutputStream &stream ) const; virtual void AddReferences() const; idDeclModelDef( SerialInputStream &stream ); private: int mNumChannels; #else class idDeclModelDef : public idDecl { #endif // RAVEN END public: idDeclModelDef(); ~idDeclModelDef(); virtual size_t Size( void ) const; virtual const char * DefaultDefinition( void ) const; virtual bool Parse( const char *text, const int textLength, bool noCaching ); virtual void FreeData( void ); // RAVEN BEGIN // jscott: to prevent a recursive crash virtual bool RebuildTextSource( void ) { return( false ); } // scork: for detailed error-reporting virtual bool Validate( const char *psText, int iTextLength, idStr &strReportTo ) const; // RAVEN END void Touch( void ) const; const idDeclSkin * GetDefaultSkin( void ) const; const idJointQuat * GetDefaultPose( void ) const; void SetupJoints( int *numJoints, idJointMat **jointList, idBounds &frameBounds, bool removeOriginOffset ) const; idRenderModel * ModelHandle( void ) const; void GetJointList( const char *jointnames, idList &jointList ) const; const jointInfo_t * FindJoint( const char *name ) const; int NumAnims( void ) const; const idAnim * GetAnim( int index ) const; int GetSpecificAnim( const char *name ) const; int GetAnim( const char *name ) const; bool HasAnim( const char *name ) const; const idDeclSkin * GetSkin( void ) const; const char * GetModelName( void ) const; const idList & Joints( void ) const; const int * JointParents( void ) const; int NumJoints( void ) const; const jointInfo_t * GetJoint( int jointHandle ) const; const char * GetJointName( int jointHandle ) const; int NumJointsOnChannel( int channel ) const; const int * GetChannelJoints( int channel ) const; const idVec3 & GetVisualOffset( void ) const; private: void CopyDecl( const idDeclModelDef *decl ); bool ParseAnim( idLexer &src, int numDefaultAnims ); private: idVec3 offset; idList joints; idList jointParents; idList channelJoints[ ANIM_NumAnimChannels ]; idRenderModel * modelHandle; idList anims; const idDeclSkin * skin; }; ID_INLINE const idAnim *idDeclModelDef::GetAnim( int index ) const { if ( ( index < 1 ) || ( index > anims.Num() ) ) { return NULL; } return anims[ index - 1 ]; } /* ============================================================================================== idAnimBlend ============================================================================================== */ class idAnimBlend { private: const class idDeclModelDef *modelDef; int starttime; int endtime; int timeOffset; float rate; int blendStartTime; int blendDuration; float blendStartValue; float blendEndValue; float animWeights[ ANIM_MaxSyncedAnims ]; short cycle; short animNum; bool allowMove; bool allowFrameCommands; bool useFrameBlend; frameBlend_t frameBlend; friend class idAnimator; void Reset( const idDeclModelDef *_modelDef ); void CallFrameCommands( idEntity *ent, int fromtime, int totime ) const; // RAVEN BEGIN // twhitaker & jscott: create new SetFrame that allows interpolation between arbitrary frames void SetFrame( const idDeclModelDef *modelDef, int animnum, const frameBlend_t & frameBlend ); // jshepard: added rate parameter so we can speed up/slow down animations. void CycleAnim( const idDeclModelDef *modelDef, int animnum, int currenttime, int blendtime, float rate ); void PlayAnim( const idDeclModelDef *modelDef, int animnum, int currenttime, int blendtime, float rate ); // RAVEN END bool BlendAnim( int currentTime, int channel, int numJoints, idJointQuat *blendFrame, float &blendWeight, bool removeOrigin, bool overrideBlend, bool printInfo ) const; void BlendOrigin( int currentTime, idVec3 &blendPos, float &blendWeight, bool removeOriginOffset ) const; void BlendDelta( int fromtime, int totime, idVec3 &blendDelta, float &blendWeight ) const; void BlendDeltaRotation( int fromtime, int totime, idQuat &blendDelta, float &blendWeight ) const; bool AddBounds( int currentTime, idBounds &bounds, bool removeOriginOffset ) const; public: idAnimBlend(); void Save( idSaveGame *savefile ) const; void Restore( idRestoreGame *savefile, const idDeclModelDef *modelDef ); const char *AnimName( void ) const; const char *AnimFullName( void ) const; float GetWeight( int currenttime ) const; float GetFinalWeight( void ) const; void SetWeight( float newweight, int currenttime, int blendtime ); int NumSyncedAnims( void ) const; bool SetSyncedAnimWeight( int num, float weight ); void Clear( int currentTime, int clearTime ); bool IsDone( int currentTime ) const; bool FrameHasChanged( int currentTime ) const; int GetCycleCount( void ) const; void SetCycleCount( int count ); void SetPlaybackRate( int currentTime, float newRate ); float GetPlaybackRate( void ) const; void SetStartTime( int startTime ); int GetStartTime( void ) const; int GetEndTime( void ) const; int GetFrameNumber( int currenttime ) const; int AnimTime( int currenttime ) const; int NumFrames( void ) const; int Length( void ) const; int PlayLength( void ) const; void AllowMovement( bool allow ); void AllowFrameCommands( bool allow ); const idAnim *Anim( void ) const; int AnimNum( void ) const; }; ID_INLINE const idAnim *idAnimBlend::Anim( void ) const { if ( !modelDef ) { return NULL; } return modelDef->GetAnim( animNum ); } /* ============================================================================================== idAFPoseJointMod ============================================================================================== */ typedef enum { AF_JOINTMOD_AXIS, AF_JOINTMOD_ORIGIN, AF_JOINTMOD_BOTH } AFJointModType_t; class idAFPoseJointMod { public: idAFPoseJointMod( void ); AFJointModType_t mod; idMat3 axis; idVec3 origin; }; ID_INLINE idAFPoseJointMod::idAFPoseJointMod( void ) { mod = AF_JOINTMOD_AXIS; axis.Identity(); origin.Zero(); } /* ============================================================================================== idAnimator ============================================================================================== */ class idAnimator{ public: idAnimator(); ~idAnimator(); size_t Allocated( void ) const; size_t Size( void ) const; void Save( idSaveGame *savefile ) const; // archives object for save game file void Restore( idRestoreGame *savefile ); // unarchives object from save game file void SetEntity( idEntity *ent ); idEntity *GetEntity( void ) const ; void RemoveOriginOffset( bool remove ); bool RemoveOrigin( void ) const; void GetJointList( const char *jointnames, idList &jointList ) const; int NumAnims( void ) const; const idAnim *GetAnim( int index ) const; int GetAnim( const char *name ) const; bool HasAnim( const char *name ) const; void ServiceAnims( int fromtime, int totime ); // RAVEN BEGIN // rjohnson: added flag to ignore AF when checking for animation bool IsAnimating ( int currentTime, bool IgnoreAF = false ) const; bool IsBlending ( int channelNum, int currentTime ) const; // RAVEN END void GetJoints( int *numJoints, idJointMat **jointsPtr ); int NumJoints( void ) const; jointHandle_t GetFirstChild( jointHandle_t jointnum ) const; jointHandle_t GetFirstChild( const char *name ) const; idRenderModel *SetModel( const char *modelname ); idRenderModel *ModelHandle( void ) const; const idDeclModelDef *ModelDef( void ) const; void ForceUpdate( void ); void ClearForceUpdate( void ); bool CreateFrame( int animtime, bool force ); bool FrameHasChanged( int animtime ) const; void GetDelta( int fromtime, int totime, idVec3 &delta ) const; bool GetDeltaRotation( int fromtime, int totime, idMat3 &delta ) const; void GetOrigin( int currentTime, idVec3 &pos ) const; bool GetBounds( int currentTime, idBounds &bounds ); idAnimBlend *CurrentAnim( int channelNum ); void Clear( int channelNum, int currentTime, int cleartime ); // twhitaker & jscott: create new SetFrame that allows interpolation between arbitrary frames void SetFrame( int channelNum, int animnum, const frameBlend_t & frameBlend ); void CycleAnim( int channelNum, int animnum, int currenttime, int blendtime ); void PlayAnim( int channelNum, int animnum, int currenttime, int blendTime ); // copies the current anim from fromChannelNum to channelNum. // the copied anim will have frame commands disabled to avoid executing them twice. void SyncAnimChannels( int channelNum, int fromChannelNum, int currenttime, int blendTime ); void SetJointPos( jointHandle_t jointnum, jointModTransform_t transform_type, const idVec3 &pos ); void SetJointAxis( jointHandle_t jointnum, jointModTransform_t transform_type, const idMat3 &mat ); void GetJointAxis( jointHandle_t jointnum, idMat3 &mat ); void CollapseJoint ( jointHandle_t jointnum, jointHandle_t collapseTo ); void CollapseJoints ( const char* jointnames, jointHandle_t collapseJoint ); void ClearJoint( jointHandle_t jointnum ); void ClearAllJoints( void ); // RAVEN BEGIN // bdube: more joint control functions void AimJointAt ( jointHandle_t jointnum, const idVec3& pos, const int blendtime ); void SetJointAngularVelocity ( jointHandle_t jointnum, const idAngles& vel, const int currentTime, const int blendTime ); idAngles GetJointAngularVelocity ( jointHandle_t jointnum, const int currentTime ); void ClearJointAngularVelocity ( jointHandle_t jointnum ); // jshepard: rate of playback change void SetPlaybackRate(float multiplier); // abahr: void SetPlaybackRate( const char* animName, float rate ); void SetPlaybackRate( int animHandle, float rate ); // RAVEN END void InitAFPose( void ); void SetAFPoseJointMod( const jointHandle_t jointNum, const AFJointModType_t mod, const idMat3 &axis, const idVec3 &origin ); void FinishAFPose( int animnum, const idBounds &bounds, const int time ); void SetAFPoseBlendWeight( float blendWeight ); bool BlendAFPose( idJointQuat *blendFrame ) const; void ClearAFPose( void ); void ClearAllAnims( int currentTime, int cleartime ); jointHandle_t GetJointHandle( const char *name ) const; const char * GetJointName( jointHandle_t handle ) const; int GetChannelForJoint( jointHandle_t joint ) const; bool GetJointTransform( jointHandle_t jointHandle, int currenttime, idVec3 &offset, idMat3 &axis ); bool GetJointLocalTransform( jointHandle_t jointHandle, int currentTime, idVec3 &offset, idMat3 &axis ); const animFlags_t GetAnimFlags( int animnum ) const; int NumFrames( int animnum ) const; int NumSyncedAnims( int animnum ) const; const char *AnimName( int animnum ) const; const char *AnimFullName( int animnum ) const; // RAVEN BEGIN // rjohnson: more output for animators const char *AnimMD5Name( int animnum, int index ) const; // RAVEN END int AnimLength( int animnum ) const; const idVec3 &TotalMovementDelta( int animnum ) const; // RAVEN BEGIN // nrausch: get the nearest joint to a segment - ignores joints behind the origin // you can pass it a null jointList in order to test against all joints ( use NumJoints() for the count ) jointHandle_t GetNearestJoint( const idVec3 &start, const idVec3 &end, int time, jointHandle_t *jointList, int cnt ); //MCG jointMod_t * FindExistingJointMod( jointHandle_t jointnum, int *index ); // RAVEN END private: // RAVEN BEGIN // bdube: added methods jointMod_t * FindJointMod ( jointHandle_t jointnum ); // RAVEN END void FreeData( void ); void PushAnims( int channel, int currentTime, int blendTime ); private: const idDeclModelDef * modelDef; idEntity * entity; idAnimBlend channels[ ANIM_NumAnimChannels ][ ANIM_MaxAnimsPerChannel ]; idList jointMods; int numJoints; idJointMat * joints; mutable int lastTransformTime; // mutable because the value is updated in CreateFrame mutable bool stoppedAnimatingUpdate; bool removeOriginOffset; bool forceUpdate; idBounds frameBounds; float AFPoseBlendWeight; idList AFPoseJoints; idList AFPoseJointMods; idJointQuat * AFPoseJointFrame; int AFPoseJointFrameSize; idBounds AFPoseBounds; int AFPoseTime; // RAVEN BEGIN // jshepard: multiplier for the animation rate for all anims under this animator float rateMultiplier; // RAVEN END }; ID_INLINE void idAnimator::SetPlaybackRate ( float _rate ) { rateMultiplier = _rate; } /* ============================================================================================== idAnimManager ============================================================================================== */ class idAnimManager { public: idAnimManager(); ~idAnimManager(); static bool forceExport; // RAVEN BEGIN // mwhitlock: Dynamic memory consolidation #if defined(_RV_MEM_SYS_SUPPORT) void BeginLevelLoad( void ); void EndLevelLoad( void ); #endif // RAVEN END void Shutdown( void ); idMD5Anim * GetAnim( const char *name ); void ReloadAnims( void ); void ListAnims( void ) const; void PrintMemInfo( MemInfo *mi ); int JointIndex( const char *name ); const char * JointName( int index ) const; void ClearAnimsInUse( void ); void FlushUnusedAnims( void ); private: idHashTable animations; idStrList jointnames; idHashIndex jointnamesHash; // RAVEN BEGIN // mwhitlock: Dynamic memory consolidation #if defined(_RV_MEM_SYS_SUPPORT) bool insideLevelLoad; #endif // RAVEN END }; #endif /* !__ANIM_H__ */ // RAVEN END