hello world

This commit is contained in:
Timothee 'TTimo' Besset
2011-11-22 15:28:15 -06:00
commit fb1609f554
2155 changed files with 1017022 additions and 0 deletions

1087
neo/game/anim/Anim.cpp Normal file

File diff suppressed because it is too large Load Diff

621
neo/game/anim/Anim.h Normal file
View File

@@ -0,0 +1,621 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code 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.
Doom 3 Source Code 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 Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#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
} jointModTransform_t;
typedef struct {
jointHandle_t jointnum;
idMat3 mat;
idVec3 pos;
jointModTransform_t transform_pos;
jointModTransform_t transform_axis;
} 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,
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_TRIGGER_SMOKE_PARTICLE,
FC_MELEE,
FC_DIRECTDAMAGE,
FC_BEGINATTACK,
FC_ENDATTACK,
FC_MUZZLEFLASH,
FC_CREATEMISSILE,
FC_LAUNCHMISSILE,
FC_FIREMISSILEATTARGET,
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
} frameCommandType_t;
typedef struct {
int num;
int firstCommand;
} frameLookup_t;
typedef struct {
frameCommandType_t type;
idStr *string;
union {
const idSoundShader *soundShader;
const function_t *function;
const idDeclSkin *skin;
int index;
};
} frameCommand_t;
typedef struct {
bool prevent_idle_override : 1;
bool random_cycle_start : 1;
bool ai_no_turn : 1;
bool anim_turn : 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<idBounds> bounds;
idList<jointAnimInfo_t> jointInfo;
idList<idJointQuat> baseFrame;
idList<float> 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( 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 GetFrameBlend( int framenum, frameBlend_t &frame ) const; // frame 1 is first frame
void ConvertTimeToFrame( int time, int cyclecount, frameBlend_t &frame ) const;
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_t> frameLookup;
idList<frameCommand_t> frameCommands;
animFlags_t flags;
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;
const char *AddFrameCommand( const class idDeclModelDef *modelDef, int framenum, idLexer &src, const idDict *def );
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;
};
/*
==============================================================================================
idDeclModelDef
==============================================================================================
*/
class idDeclModelDef : public idDecl {
public:
idDeclModelDef();
~idDeclModelDef();
virtual size_t Size( void ) const;
virtual const char * DefaultDefinition( void ) const;
virtual bool Parse( const char *text, const int textLength );
virtual void FreeData( void );
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<jointHandle_t> &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<jointInfo_t> & 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<jointInfo_t> joints;
idList<int> jointParents;
idList<int> channelJoints[ ANIM_NumAnimChannels ];
idRenderModel * modelHandle;
idList<idAnim *> anims;
const idDeclSkin * skin;
};
/*
==============================================================================================
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 frame;
short animNum;
bool allowMove;
bool allowFrameCommands;
friend class idAnimator;
void Reset( const idDeclModelDef *_modelDef );
void CallFrameCommands( idEntity *ent, int fromtime, int totime ) const;
void SetFrame( const idDeclModelDef *modelDef, int animnum, int frame, int currenttime, int blendtime );
void CycleAnim( const idDeclModelDef *modelDef, int animnum, int currenttime, int blendtime );
void PlayAnim( const idDeclModelDef *modelDef, int animnum, int currenttime, int blendtime );
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;
};
/*
==============================================================================================
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<jointHandle_t> &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 );
bool IsAnimating( int currentTime ) const;
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 );
void SetFrame( int channelNum, int animnum, int frame, int currenttime, int blendtime );
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 ClearJoint( jointHandle_t jointnum );
void ClearAllJoints( void );
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;
int AnimLength( int animnum ) const;
const idVec3 &TotalMovementDelta( int animnum ) const;
private:
void FreeData( void );
void PushAnims( int channel, int currentTime, int blendTime );
private:
const idDeclModelDef * modelDef;
idEntity * entity;
idAnimBlend channels[ ANIM_NumAnimChannels ][ ANIM_MaxAnimsPerChannel ];
idList<jointMod_t *> 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<int> AFPoseJoints;
idList<idAFPoseJointMod> AFPoseJointMods;
idList<idJointQuat> AFPoseJointFrame;
idBounds AFPoseBounds;
int AFPoseTime;
};
/*
==============================================================================================
idAnimManager
==============================================================================================
*/
class idAnimManager {
public:
idAnimManager();
~idAnimManager();
static bool forceExport;
void Shutdown( void );
idMD5Anim * GetAnim( const char *name );
void ReloadAnims( void );
void ListAnims( void ) const;
int JointIndex( const char *name );
const char * JointName( int index ) const;
void ClearAnimsInUse( void );
void FlushUnusedAnims( void );
private:
idHashTable<idMD5Anim *> animations;
idStrList jointnames;
idHashIndex jointnamesHash;
};
#endif /* !__ANIM_H__ */

5022
neo/game/anim/Anim_Blend.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,562 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code 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.
Doom 3 Source Code 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 Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "../../idlib/precompiled.h"
#pragma hdrstop
#include "../Game_local.h"
#include "../../MayaImport/maya_main.h"
/***********************************************************************
Maya conversion functions
***********************************************************************/
static idStr Maya_Error;
static exporterInterface_t Maya_ConvertModel = NULL;
static exporterShutdown_t Maya_Shutdown = NULL;
static int importDLL = 0;
bool idModelExport::initialized = false;
/*
====================
idModelExport::idModelExport
====================
*/
idModelExport::idModelExport() {
Reset();
}
/*
====================
idModelExport::Shutdown
====================
*/
void idModelExport::Shutdown( void ) {
if ( Maya_Shutdown ) {
Maya_Shutdown();
}
if ( importDLL ) {
sys->DLL_Unload( importDLL );
}
importDLL = 0;
Maya_Shutdown = NULL;
Maya_ConvertModel = NULL;
Maya_Error.Clear();
initialized = false;
}
/*
=====================
idModelExport::CheckMayaInstall
Determines if Maya is installed on the user's machine
=====================
*/
bool idModelExport::CheckMayaInstall( void ) {
#ifndef _WIN32
return false;
#elif 0
HKEY hKey;
long lres, lType;
lres = RegOpenKey( HKEY_LOCAL_MACHINE, "SOFTWARE\\Alias|Wavefront\\Maya\\4.5\\Setup\\InstallPath", &hKey );
if ( lres != ERROR_SUCCESS ) {
return false;
}
lres = RegQueryValueEx( hKey, "MAYA_INSTALL_LOCATION", NULL, (unsigned long*)&lType, (unsigned char*)NULL, (unsigned long*)NULL );
RegCloseKey( hKey );
if ( lres != ERROR_SUCCESS ) {
return false;
}
return true;
#else
HKEY hKey;
long lres;
// only check the non-version specific key so that we only have to update the maya dll when new versions are released
lres = RegOpenKey( HKEY_LOCAL_MACHINE, "SOFTWARE\\Alias|Wavefront\\Maya", &hKey );
RegCloseKey( hKey );
if ( lres != ERROR_SUCCESS ) {
return false;
}
return true;
#endif
}
/*
=====================
idModelExport::LoadMayaDll
Checks to see if we can load the Maya export dll
=====================
*/
void idModelExport::LoadMayaDll( void ) {
exporterDLLEntry_t dllEntry;
char dllPath[ MAX_OSPATH ];
fileSystem->FindDLL( "MayaImport", dllPath, false );
if ( !dllPath[ 0 ] ) {
return;
}
importDLL = sys->DLL_Load( dllPath );
if ( !importDLL ) {
return;
}
// look up the dll interface functions
dllEntry = ( exporterDLLEntry_t )sys->DLL_GetProcAddress( importDLL, "dllEntry" );
Maya_ConvertModel = ( exporterInterface_t )sys->DLL_GetProcAddress( importDLL, "Maya_ConvertModel" );
Maya_Shutdown = ( exporterShutdown_t )sys->DLL_GetProcAddress( importDLL, "Maya_Shutdown" );
if ( !Maya_ConvertModel || !dllEntry || !Maya_Shutdown ) {
Maya_ConvertModel = NULL;
Maya_Shutdown = NULL;
sys->DLL_Unload( importDLL );
importDLL = 0;
gameLocal.Error( "Invalid interface on export DLL." );
return;
}
// initialize the DLL
if ( !dllEntry( MD5_VERSION, common, sys ) ) {
// init failed
Maya_ConvertModel = NULL;
Maya_Shutdown = NULL;
sys->DLL_Unload( importDLL );
importDLL = 0;
gameLocal.Error( "Export DLL init failed." );
return;
}
}
/*
=====================
idModelExport::ConvertMayaToMD5
Checks if a Maya model should be converted to an MD5, and converts if if the time/date or
version number has changed.
=====================
*/
bool idModelExport::ConvertMayaToMD5( void ) {
ID_TIME_T
sourceTime;
ID_TIME_T destTime;
int version;
idToken cmdLine;
idStr path;
// check if our DLL got loaded
if ( initialized && !Maya_ConvertModel ) {
Maya_Error = "MayaImport dll not loaded.";
return false;
}
// if idAnimManager::forceExport is set then we always reexport Maya models
if ( idAnimManager::forceExport ) {
force = true;
}
// get the source file's time
if ( fileSystem->ReadFile( src, NULL, &sourceTime ) < 0 ) {
// source file doesn't exist
return true;
}
// get the destination file's time
if ( !force && ( fileSystem->ReadFile( dest, NULL, &destTime ) >= 0 ) ) {
idParser parser( LEXFL_ALLOWPATHNAMES | LEXFL_NOSTRINGESCAPECHARS );
parser.LoadFile( dest );
// read the file version
if ( parser.CheckTokenString( MD5_VERSION_STRING ) ) {
version = parser.ParseInt();
// check the command line
if ( parser.CheckTokenString( "commandline" ) ) {
parser.ReadToken( &cmdLine );
// check the file time, scale, and version
if ( ( destTime >= sourceTime ) && ( version == MD5_VERSION ) && ( cmdLine == commandLine ) ) {
// don't convert it
return true;
}
}
}
}
// if this is the first time we've been run, check if Maya is installed and load our DLL
if ( !initialized ) {
initialized = true;
if ( !CheckMayaInstall() ) {
Maya_Error = "Maya not installed in registry.";
return false;
}
LoadMayaDll();
// check if our DLL got loaded
if ( !Maya_ConvertModel ) {
Maya_Error = "Could not load MayaImport dll.";
return false;
}
}
// we need to make sure we have a full path, so convert the filename to an OS path
src = fileSystem->RelativePathToOSPath( src );
dest = fileSystem->RelativePathToOSPath( dest );
dest.ExtractFilePath( path );
if ( path.Length() ) {
fileSystem->CreateOSPath( path );
}
// get the os path in case it needs to create one
path = fileSystem->RelativePathToOSPath( "" );
common->SetRefreshOnPrint( true );
Maya_Error = Maya_ConvertModel( path, commandLine );
common->SetRefreshOnPrint( false );
if ( Maya_Error != "Ok" ) {
return false;
}
// conversion succeded
return true;
}
/*
====================
idModelExport::Reset
====================
*/
void idModelExport::Reset( void ) {
force = false;
commandLine = "";
src = "";
dest = "";
}
/*
====================
idModelExport::ExportModel
====================
*/
bool idModelExport::ExportModel( const char *model ) {
const char *game = cvarSystem->GetCVarString( "fs_game" );
if ( strlen(game) == 0 ) {
game = BASE_GAMEDIR;
}
Reset();
src = model;
dest = model;
dest.SetFileExtension( MD5_MESH_EXT );
sprintf( commandLine, "mesh %s -dest %s -game %s", src.c_str(), dest.c_str(), game );
if ( !ConvertMayaToMD5() ) {
gameLocal.Printf( "Failed to export '%s' : %s", src.c_str(), Maya_Error.c_str() );
return false;
}
return true;
}
/*
====================
idModelExport::ExportAnim
====================
*/
bool idModelExport::ExportAnim( const char *anim ) {
const char *game = cvarSystem->GetCVarString( "fs_game" );
if ( strlen(game) == 0 ) {
game = BASE_GAMEDIR;
}
Reset();
src = anim;
dest = anim;
dest.SetFileExtension( MD5_ANIM_EXT );
sprintf( commandLine, "anim %s -dest %s -game %s", src.c_str(), dest.c_str(), game );
if ( !ConvertMayaToMD5() ) {
gameLocal.Printf( "Failed to export '%s' : %s", src.c_str(), Maya_Error.c_str() );
return false;
}
return true;
}
/*
====================
idModelExport::ParseOptions
====================
*/
bool idModelExport::ParseOptions( idLexer &lex ) {
idToken token;
idStr destdir;
idStr sourcedir;
if ( !lex.ReadToken( &token ) ) {
lex.Error( "Expected filename" );
return false;
}
src = token;
dest = token;
while( lex.ReadToken( &token ) ) {
if ( token == "-" ) {
if ( !lex.ReadToken( &token ) ) {
lex.Error( "Expecting option" );
return false;
}
if ( token == "sourcedir" ) {
if ( !lex.ReadToken( &token ) ) {
lex.Error( "Missing pathname after -sourcedir" );
return false;
}
sourcedir = token;
} else if ( token == "destdir" ) {
if ( !lex.ReadToken( &token ) ) {
lex.Error( "Missing pathname after -destdir" );
return false;
}
destdir = token;
} else if ( token == "dest" ) {
if ( !lex.ReadToken( &token ) ) {
lex.Error( "Missing filename after -dest" );
return false;
}
dest = token;
} else {
commandLine += va( " -%s", token.c_str() );
}
} else {
commandLine += va( " %s", token.c_str() );
}
}
if ( sourcedir.Length() ) {
src.StripPath();
sourcedir.BackSlashesToSlashes();
sprintf( src, "%s/%s", sourcedir.c_str(), src.c_str() );
}
if ( destdir.Length() ) {
dest.StripPath();
destdir.BackSlashesToSlashes();
sprintf( dest, "%s/%s", destdir.c_str(), dest.c_str() );
}
return true;
}
/*
====================
idModelExport::ParseExportSection
====================
*/
int idModelExport::ParseExportSection( idParser &parser ) {
idToken command;
idToken token;
idStr defaultCommands;
idLexer lex;
idStr temp;
idStr parms;
int count;
// only export sections that match our export mask
if ( g_exportMask.GetString()[ 0 ] ) {
if ( parser.CheckTokenString( "{" ) ) {
parser.SkipBracedSection( false );
return 0;
}
parser.ReadToken( &token );
if ( token.Icmp( g_exportMask.GetString() ) ) {
parser.SkipBracedSection();
return 0;
}
parser.ExpectTokenString( "{" );
} else if ( !parser.CheckTokenString( "{" ) ) {
// skip the export mask
parser.ReadToken( &token );
parser.ExpectTokenString( "{" );
}
count = 0;
lex.SetFlags( LEXFL_NOSTRINGCONCAT | LEXFL_ALLOWPATHNAMES | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_ALLOWBACKSLASHSTRINGCONCAT );
while( 1 ) {
if ( !parser.ReadToken( &command ) ) {
parser.Error( "Unexpoected end-of-file" );
break;
}
if ( command == "}" ) {
break;
}
if ( command == "options" ) {
parser.ParseRestOfLine( defaultCommands );
} else if ( command == "addoptions" ) {
parser.ParseRestOfLine( temp );
defaultCommands += " ";
defaultCommands += temp;
} else if ( ( command == "mesh" ) || ( command == "anim" ) || ( command == "camera" ) ) {
if ( !parser.ReadToken( &token ) ) {
parser.Error( "Expected filename" );
}
temp = token;
parser.ParseRestOfLine( parms );
if ( defaultCommands.Length() ) {
sprintf( temp, "%s %s", temp.c_str(), defaultCommands.c_str() );
}
if ( parms.Length() ) {
sprintf( temp, "%s %s", temp.c_str(), parms.c_str() );
}
lex.LoadMemory( temp, temp.Length(), parser.GetFileName() );
Reset();
if ( ParseOptions( lex ) ) {
const char *game = cvarSystem->GetCVarString( "fs_game" );
if ( strlen(game) == 0 ) {
game = BASE_GAMEDIR;
}
if ( command == "mesh" ) {
dest.SetFileExtension( MD5_MESH_EXT );
} else if ( command == "anim" ) {
dest.SetFileExtension( MD5_ANIM_EXT );
} else if ( command == "camera" ) {
dest.SetFileExtension( MD5_CAMERA_EXT );
} else {
dest.SetFileExtension( command );
}
idStr back = commandLine;
sprintf( commandLine, "%s %s -dest %s -game %s%s", command.c_str(), src.c_str(), dest.c_str(), game, commandLine.c_str() );
if ( ConvertMayaToMD5() ) {
count++;
} else {
parser.Warning( "Failed to export '%s' : %s", src.c_str(), Maya_Error.c_str() );
}
}
lex.FreeSource();
} else {
parser.Error( "Unknown token: %s", command.c_str() );
parser.SkipBracedSection( false );
break;
}
}
return count;
}
/*
================
idModelExport::ExportDefFile
================
*/
int idModelExport::ExportDefFile( const char *filename ) {
idParser parser( LEXFL_NOSTRINGCONCAT | LEXFL_ALLOWPATHNAMES | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_ALLOWBACKSLASHSTRINGCONCAT );
idToken token;
int count;
count = 0;
if ( !parser.LoadFile( filename ) ) {
gameLocal.Printf( "Could not load '%s'\n", filename );
return 0;
}
while( parser.ReadToken( &token ) ) {
if ( token == "export" ) {
count += ParseExportSection( parser );
} else {
parser.ReadToken( &token );
parser.SkipBracedSection();
}
}
return count;
}
/*
================
idModelExport::ExportModels
================
*/
int idModelExport::ExportModels( const char *pathname, const char *extension ) {
int count;
count = 0;
idFileList *files;
int i;
if ( !CheckMayaInstall() ) {
// if Maya isn't installed, don't bother checking if we have anims to export
return 0;
}
gameLocal.Printf( "--------- Exporting models --------\n" );
if ( !g_exportMask.GetString()[ 0 ] ) {
gameLocal.Printf( " Export mask: '%s'\n", g_exportMask.GetString() );
}
count = 0;
files = fileSystem->ListFiles( pathname, extension );
for( i = 0; i < files->GetNumFiles(); i++ ) {
count += ExportDefFile( va( "%s/%s", pathname, files->GetFile( i ) ) );
}
fileSystem->FreeFileList( files );
gameLocal.Printf( "...%d models exported.\n", count );
gameLocal.Printf( "-----------------------------------\n" );
return count;
}

View File

@@ -0,0 +1,924 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code 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.
Doom 3 Source Code 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 Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
/*
=============================================================================
MODEL TESTING
Model viewing can begin with either "testmodel <modelname>"
The names must be the full pathname after the basedir, like
"models/weapons/v_launch/tris.md3" or "players/male/tris.md3"
Extension will default to ".ase" if not specified.
Testmodel will create a fake entity 100 units in front of the current view
position, directly facing the viewer. It will remain immobile, so you can
move around it to view it from different angles.
g_testModelRotate
g_testModelAnimate
g_testModelBlend
=============================================================================
*/
#include "../../idlib/precompiled.h"
#pragma hdrstop
#include "../Game_local.h"
CLASS_DECLARATION( idAnimatedEntity, idTestModel )
EVENT( EV_FootstepLeft, idTestModel::Event_Footstep )
EVENT( EV_FootstepRight, idTestModel::Event_Footstep )
END_CLASS
/*
================
idTestModel::idTestModel
================
*/
idTestModel::idTestModel() {
head = NULL;
headAnimator = NULL;
anim = 0;
headAnim = 0;
starttime = 0;
animtime = 0;
mode = 0;
frame = 0;
}
/*
================
idTestModel::Save
================
*/
void idTestModel::Save( idSaveGame *savefile ) {
}
/*
================
idTestModel::Restore
================
*/
void idTestModel::Restore( idRestoreGame *savefile ) {
// FIXME: one day we may actually want to save/restore test models, but for now we'll just delete them
delete this;
}
/*
================
idTestModel::Spawn
================
*/
void idTestModel::Spawn( void ) {
idVec3 size;
idBounds bounds;
const char *headModel;
jointHandle_t joint;
idStr jointName;
idVec3 origin, modelOffset;
idMat3 axis;
const idKeyValue *kv;
copyJoints_t copyJoint;
if ( renderEntity.hModel && renderEntity.hModel->IsDefaultModel() && !animator.ModelDef() ) {
gameLocal.Warning( "Unable to create testmodel for '%s' : model defaulted", spawnArgs.GetString( "model" ) );
PostEventMS( &EV_Remove, 0 );
return;
}
mode = g_testModelAnimate.GetInteger();
animator.RemoveOriginOffset( g_testModelAnimate.GetInteger() == 1 );
physicsObj.SetSelf( this );
physicsObj.SetOrigin( GetPhysics()->GetOrigin() );
physicsObj.SetAxis( GetPhysics()->GetAxis() );
if ( spawnArgs.GetVector( "mins", NULL, bounds[0] ) ) {
spawnArgs.GetVector( "maxs", NULL, bounds[1] );
physicsObj.SetClipBox( bounds, 1.0f );
physicsObj.SetContents( 0 );
} else if ( spawnArgs.GetVector( "size", NULL, size ) ) {
bounds[ 0 ].Set( size.x * -0.5f, size.y * -0.5f, 0.0f );
bounds[ 1 ].Set( size.x * 0.5f, size.y * 0.5f, size.z );
physicsObj.SetClipBox( bounds, 1.0f );
physicsObj.SetContents( 0 );
}
spawnArgs.GetVector( "offsetModel", "0 0 0", modelOffset );
// add the head model if it has one
headModel = spawnArgs.GetString( "def_head", "" );
if ( headModel[ 0 ] ) {
jointName = spawnArgs.GetString( "head_joint" );
joint = animator.GetJointHandle( jointName );
if ( joint == INVALID_JOINT ) {
gameLocal.Warning( "Joint '%s' not found for 'head_joint'", jointName.c_str() );
} else {
// copy any sounds in case we have frame commands on the head
idDict args;
const idKeyValue *sndKV = spawnArgs.MatchPrefix( "snd_", NULL );
while( sndKV ) {
args.Set( sndKV->GetKey(), sndKV->GetValue() );
sndKV = spawnArgs.MatchPrefix( "snd_", sndKV );
}
head = gameLocal.SpawnEntityType( idAnimatedEntity::Type, &args );
animator.GetJointTransform( joint, gameLocal.time, origin, axis );
origin = GetPhysics()->GetOrigin() + ( origin + modelOffset ) * GetPhysics()->GetAxis();
head.GetEntity()->SetModel( headModel );
head.GetEntity()->SetOrigin( origin );
head.GetEntity()->SetAxis( GetPhysics()->GetAxis() );
head.GetEntity()->BindToJoint( this, animator.GetJointName( joint ), true );
headAnimator = head.GetEntity()->GetAnimator();
// set up the list of joints to copy to the head
for( kv = spawnArgs.MatchPrefix( "copy_joint", NULL ); kv != NULL; kv = spawnArgs.MatchPrefix( "copy_joint", kv ) ) {
jointName = kv->GetKey();
if ( jointName.StripLeadingOnce( "copy_joint_world " ) ) {
copyJoint.mod = JOINTMOD_WORLD_OVERRIDE;
} else {
jointName.StripLeadingOnce( "copy_joint " );
copyJoint.mod = JOINTMOD_LOCAL_OVERRIDE;
}
copyJoint.from = animator.GetJointHandle( jointName );
if ( copyJoint.from == INVALID_JOINT ) {
gameLocal.Warning( "Unknown copy_joint '%s'", jointName.c_str() );
continue;
}
copyJoint.to = headAnimator->GetJointHandle( jointName );
if ( copyJoint.to == INVALID_JOINT ) {
gameLocal.Warning( "Unknown copy_joint '%s' on head", jointName.c_str() );
continue;
}
copyJoints.Append( copyJoint );
}
}
}
// start any shader effects based off of the spawn time
renderEntity.shaderParms[ SHADERPARM_TIMEOFFSET ] = -MS2SEC( gameLocal.time );
SetPhysics( &physicsObj );
gameLocal.Printf( "Added testmodel at origin = '%s', angles = '%s'\n", GetPhysics()->GetOrigin().ToString(), GetPhysics()->GetAxis().ToAngles().ToString() );
BecomeActive( TH_THINK );
}
/*
================
idTestModel::~idTestModel
================
*/
idTestModel::~idTestModel() {
StopSound( SND_CHANNEL_ANY, false );
if ( renderEntity.hModel ) {
gameLocal.Printf( "Removing testmodel %s\n", renderEntity.hModel->Name() );
} else {
gameLocal.Printf( "Removing testmodel\n" );
}
if ( gameLocal.testmodel == this ) {
gameLocal.testmodel = NULL;
}
if ( head.GetEntity() ) {
head.GetEntity()->StopSound( SND_CHANNEL_ANY, false );
head.GetEntity()->PostEventMS( &EV_Remove, 0 );
}
}
/*
===============
idTestModel::Event_Footstep
===============
*/
void idTestModel::Event_Footstep( void ) {
StartSound( "snd_footstep", SND_CHANNEL_BODY, 0, false, NULL );
}
/*
================
idTestModel::ShouldConstructScriptObjectAtSpawn
Called during idEntity::Spawn to see if it should construct the script object or not.
Overridden by subclasses that need to spawn the script object themselves.
================
*/
bool idTestModel::ShouldConstructScriptObjectAtSpawn( void ) const {
return false;
}
/*
================
idTestModel::Think
================
*/
void idTestModel::Think( void ) {
idVec3 pos;
idMat3 axis;
idAngles ang;
int i;
if ( thinkFlags & TH_THINK ) {
if ( anim && ( gameLocal.testmodel == this ) && ( mode != g_testModelAnimate.GetInteger() ) ) {
StopSound( SND_CHANNEL_ANY, false );
if ( head.GetEntity() ) {
head.GetEntity()->StopSound( SND_CHANNEL_ANY, false );
}
switch( g_testModelAnimate.GetInteger() ) {
default:
case 0:
// cycle anim with origin reset
if ( animator.NumFrames( anim ) <= 1 ) {
// single frame animations end immediately, so just cycle it since it's the same result
animator.CycleAnim( ANIMCHANNEL_ALL, anim, gameLocal.time, FRAME2MS( g_testModelBlend.GetInteger() ) );
if ( headAnim ) {
headAnimator->CycleAnim( ANIMCHANNEL_ALL, headAnim, gameLocal.time, FRAME2MS( g_testModelBlend.GetInteger() ) );
}
} else {
animator.PlayAnim( ANIMCHANNEL_ALL, anim, gameLocal.time, FRAME2MS( g_testModelBlend.GetInteger() ) );
if ( headAnim ) {
headAnimator->PlayAnim( ANIMCHANNEL_ALL, headAnim, gameLocal.time, FRAME2MS( g_testModelBlend.GetInteger() ) );
if ( headAnimator->AnimLength( headAnim ) > animator.AnimLength( anim ) ) {
// loop the body anim when the head anim is longer
animator.CurrentAnim( ANIMCHANNEL_ALL )->SetCycleCount( -1 );
}
}
}
animator.RemoveOriginOffset( false );
break;
case 1:
// cycle anim with fixed origin
animator.CycleAnim( ANIMCHANNEL_ALL, anim, gameLocal.time, FRAME2MS( g_testModelBlend.GetInteger() ) );
animator.RemoveOriginOffset( true );
if ( headAnim ) {
headAnimator->CycleAnim( ANIMCHANNEL_ALL, headAnim, gameLocal.time, FRAME2MS( g_testModelBlend.GetInteger() ) );
}
break;
case 2:
// cycle anim with continuous origin
animator.CycleAnim( ANIMCHANNEL_ALL, anim, gameLocal.time, FRAME2MS( g_testModelBlend.GetInteger() ) );
animator.RemoveOriginOffset( false );
if ( headAnim ) {
headAnimator->CycleAnim( ANIMCHANNEL_ALL, headAnim, gameLocal.time, FRAME2MS( g_testModelBlend.GetInteger() ) );
}
break;
case 3:
// frame by frame with continuous origin
animator.SetFrame( ANIMCHANNEL_ALL, anim, frame, gameLocal.time, FRAME2MS( g_testModelBlend.GetInteger() ) );
animator.RemoveOriginOffset( false );
if ( headAnim ) {
headAnimator->SetFrame( ANIMCHANNEL_ALL, headAnim, frame, gameLocal.time, FRAME2MS( g_testModelBlend.GetInteger() ) );
}
break;
case 4:
// play anim once
animator.PlayAnim( ANIMCHANNEL_ALL, anim, gameLocal.time, FRAME2MS( g_testModelBlend.GetInteger() ) );
animator.RemoveOriginOffset( false );
if ( headAnim ) {
headAnimator->PlayAnim( ANIMCHANNEL_ALL, headAnim, gameLocal.time, FRAME2MS( g_testModelBlend.GetInteger() ) );
}
break;
case 5:
// frame by frame with fixed origin
animator.SetFrame( ANIMCHANNEL_ALL, anim, frame, gameLocal.time, FRAME2MS( g_testModelBlend.GetInteger() ) );
animator.RemoveOriginOffset( true );
if ( headAnim ) {
headAnimator->SetFrame( ANIMCHANNEL_ALL, headAnim, frame, gameLocal.time, FRAME2MS( g_testModelBlend.GetInteger() ) );
}
break;
}
mode = g_testModelAnimate.GetInteger();
}
if ( ( mode == 0 ) && ( gameLocal.time >= starttime + animtime ) ) {
starttime = gameLocal.time;
StopSound( SND_CHANNEL_ANY, false );
animator.PlayAnim( ANIMCHANNEL_ALL, anim, gameLocal.time, FRAME2MS( g_testModelBlend.GetInteger() ) );
if ( headAnim ) {
headAnimator->PlayAnim( ANIMCHANNEL_ALL, headAnim, gameLocal.time, FRAME2MS( g_testModelBlend.GetInteger() ) );
if ( headAnimator->AnimLength( headAnim ) > animator.AnimLength( anim ) ) {
// loop the body anim when the head anim is longer
animator.CurrentAnim( ANIMCHANNEL_ALL )->SetCycleCount( -1 );
}
}
}
if ( headAnimator ) {
// copy the animation from the body to the head
for( i = 0; i < copyJoints.Num(); i++ ) {
if ( copyJoints[ i ].mod == JOINTMOD_WORLD_OVERRIDE ) {
idMat3 mat = head.GetEntity()->GetPhysics()->GetAxis().Transpose();
GetJointWorldTransform( copyJoints[ i ].from, gameLocal.time, pos, axis );
pos -= head.GetEntity()->GetPhysics()->GetOrigin();
headAnimator->SetJointPos( copyJoints[ i ].to, copyJoints[ i ].mod, pos * mat );
headAnimator->SetJointAxis( copyJoints[ i ].to, copyJoints[ i ].mod, axis * mat );
} else {
animator.GetJointLocalTransform( copyJoints[ i ].from, gameLocal.time, pos, axis );
headAnimator->SetJointPos( copyJoints[ i ].to, copyJoints[ i ].mod, pos );
headAnimator->SetJointAxis( copyJoints[ i ].to, copyJoints[ i ].mod, axis );
}
}
}
// update rotation
RunPhysics();
physicsObj.GetAngles( ang );
physicsObj.SetAngularExtrapolation( extrapolation_t(EXTRAPOLATION_LINEAR|EXTRAPOLATION_NOSTOP), gameLocal.time, 0, ang, idAngles( 0, g_testModelRotate.GetFloat() * 360.0f / 60.0f, 0 ), ang_zero );
idClipModel *clip = physicsObj.GetClipModel();
if ( clip && animator.ModelDef() ) {
idVec3 neworigin;
idMat3 axis;
jointHandle_t joint;
joint = animator.GetJointHandle( "origin" );
animator.GetJointTransform( joint, gameLocal.time, neworigin, axis );
neworigin = ( ( neworigin - animator.ModelDef()->GetVisualOffset() ) * physicsObj.GetAxis() ) + GetPhysics()->GetOrigin();
clip->Link( gameLocal.clip, this, 0, neworigin, clip->GetAxis() );
}
}
UpdateAnimation();
Present();
if ( ( gameLocal.testmodel == this ) && g_showTestModelFrame.GetInteger() && anim ) {
gameLocal.Printf( "^5 Anim: ^7%s ^5Frame: ^7%d/%d Time: %.3f\n", animator.AnimFullName( anim ), animator.CurrentAnim( ANIMCHANNEL_ALL )->GetFrameNumber( gameLocal.time ),
animator.CurrentAnim( ANIMCHANNEL_ALL )->NumFrames(), MS2SEC( gameLocal.time - animator.CurrentAnim( ANIMCHANNEL_ALL )->GetStartTime() ) );
if ( headAnim ) {
gameLocal.Printf( "^5 Head: ^7%s ^5Frame: ^7%d/%d Time: %.3f\n\n", headAnimator->AnimFullName( headAnim ), headAnimator->CurrentAnim( ANIMCHANNEL_ALL )->GetFrameNumber( gameLocal.time ),
headAnimator->CurrentAnim( ANIMCHANNEL_ALL )->NumFrames(), MS2SEC( gameLocal.time - headAnimator->CurrentAnim( ANIMCHANNEL_ALL )->GetStartTime() ) );
} else {
gameLocal.Printf( "\n\n" );
}
}
}
/*
================
idTestModel::NextAnim
================
*/
void idTestModel::NextAnim( const idCmdArgs &args ) {
if ( !animator.NumAnims() ) {
return;
}
anim++;
if ( anim >= animator.NumAnims() ) {
// anim 0 is no anim
anim = 1;
}
starttime = gameLocal.time;
animtime = animator.AnimLength( anim );
animname = animator.AnimFullName( anim );
headAnim = 0;
if ( headAnimator ) {
headAnimator->ClearAllAnims( gameLocal.time, 0 );
headAnim = headAnimator->GetAnim( animname );
if ( !headAnim ) {
headAnim = headAnimator->GetAnim( "idle" );
}
if ( headAnim && ( headAnimator->AnimLength( headAnim ) > animtime ) ) {
animtime = headAnimator->AnimLength( headAnim );
}
}
gameLocal.Printf( "anim '%s', %d.%03d seconds, %d frames\n", animname.c_str(), animator.AnimLength( anim ) / 1000, animator.AnimLength( anim ) % 1000, animator.NumFrames( anim ) );
if ( headAnim ) {
gameLocal.Printf( "head '%s', %d.%03d seconds, %d frames\n", headAnimator->AnimFullName( headAnim ), headAnimator->AnimLength( headAnim ) / 1000, headAnimator->AnimLength( headAnim ) % 1000, headAnimator->NumFrames( headAnim ) );
}
// reset the anim
mode = -1;
frame = 1;
}
/*
================
idTestModel::PrevAnim
================
*/
void idTestModel::PrevAnim( const idCmdArgs &args ) {
if ( !animator.NumAnims() ) {
return;
}
headAnim = 0;
anim--;
if ( anim < 0 ) {
anim = animator.NumAnims() - 1;
}
starttime = gameLocal.time;
animtime = animator.AnimLength( anim );
animname = animator.AnimFullName( anim );
headAnim = 0;
if ( headAnimator ) {
headAnimator->ClearAllAnims( gameLocal.time, 0 );
headAnim = headAnimator->GetAnim( animname );
if ( !headAnim ) {
headAnim = headAnimator->GetAnim( "idle" );
}
if ( headAnim && ( headAnimator->AnimLength( headAnim ) > animtime ) ) {
animtime = headAnimator->AnimLength( headAnim );
}
}
gameLocal.Printf( "anim '%s', %d.%03d seconds, %d frames\n", animname.c_str(), animator.AnimLength( anim ) / 1000, animator.AnimLength( anim ) % 1000, animator.NumFrames( anim ) );
if ( headAnim ) {
gameLocal.Printf( "head '%s', %d.%03d seconds, %d frames\n", headAnimator->AnimFullName( headAnim ), headAnimator->AnimLength( headAnim ) / 1000, headAnimator->AnimLength( headAnim ) % 1000, headAnimator->NumFrames( headAnim ) );
}
// reset the anim
mode = -1;
frame = 1;
}
/*
================
idTestModel::NextFrame
================
*/
void idTestModel::NextFrame( const idCmdArgs &args ) {
if ( !anim || ( ( g_testModelAnimate.GetInteger() != 3 ) && ( g_testModelAnimate.GetInteger() != 5 ) ) ) {
return;
}
frame++;
if ( frame > animator.NumFrames( anim ) ) {
frame = 1;
}
gameLocal.Printf( "^5 Anim: ^7%s\n^5Frame: ^7%d/%d\n\n", animator.AnimFullName( anim ), frame, animator.NumFrames( anim ) );
// reset the anim
mode = -1;
}
/*
================
idTestModel::PrevFrame
================
*/
void idTestModel::PrevFrame( const idCmdArgs &args ) {
if ( !anim || ( ( g_testModelAnimate.GetInteger() != 3 ) && ( g_testModelAnimate.GetInteger() != 5 ) ) ) {
return;
}
frame--;
if ( frame < 1 ) {
frame = animator.NumFrames( anim );
}
gameLocal.Printf( "^5 Anim: ^7%s\n^5Frame: ^7%d/%d\n\n", animator.AnimFullName( anim ), frame, animator.NumFrames( anim ) );
// reset the anim
mode = -1;
}
/*
================
idTestModel::TestAnim
================
*/
void idTestModel::TestAnim( const idCmdArgs &args ) {
idStr name;
int animNum;
const idAnim *newanim;
if ( args.Argc() < 2 ) {
gameLocal.Printf( "usage: testanim <animname>\n" );
return;
}
newanim = NULL;
name = args.Argv( 1 );
#if 0
if ( strstr( name, ".ma" ) || strstr( name, ".mb" ) ) {
const idMD5Anim *md5anims[ ANIM_MaxSyncedAnims ];
idModelExport exporter;
exporter.ExportAnim( name );
name.SetFileExtension( MD5_ANIM_EXT );
md5anims[ 0 ] = animationLib.GetAnim( name );
if ( md5anims[ 0 ] ) {
customAnim.SetAnim( animator.ModelDef(), name, name, 1, md5anims );
newanim = &customAnim;
}
} else {
animNum = animator.GetAnim( name );
}
#else
animNum = animator.GetAnim( name );
#endif
if ( !animNum ) {
gameLocal.Printf( "Animation '%s' not found.\n", name.c_str() );
return;
}
anim = animNum;
starttime = gameLocal.time;
animtime = animator.AnimLength( anim );
headAnim = 0;
if ( headAnimator ) {
headAnimator->ClearAllAnims( gameLocal.time, 0 );
headAnim = headAnimator->GetAnim( animname );
if ( !headAnim ) {
headAnim = headAnimator->GetAnim( "idle" );
if ( !headAnim ) {
gameLocal.Printf( "Missing 'idle' anim for head.\n" );
}
}
if ( headAnim && ( headAnimator->AnimLength( headAnim ) > animtime ) ) {
animtime = headAnimator->AnimLength( headAnim );
}
}
animname = name;
gameLocal.Printf( "anim '%s', %d.%03d seconds, %d frames\n", animname.c_str(), animator.AnimLength( anim ) / 1000, animator.AnimLength( anim ) % 1000, animator.NumFrames( anim ) );
// reset the anim
mode = -1;
}
/*
=====================
idTestModel::BlendAnim
=====================
*/
void idTestModel::BlendAnim( const idCmdArgs &args ) {
int anim1;
int anim2;
if ( args.Argc() < 4 ) {
gameLocal.Printf( "usage: testblend <anim1> <anim2> <frames>\n" );
return;
}
anim1 = gameLocal.testmodel->animator.GetAnim( args.Argv( 1 ) );
if ( !anim1 ) {
gameLocal.Printf( "Animation '%s' not found.\n", args.Argv( 1 ) );
return;
}
anim2 = gameLocal.testmodel->animator.GetAnim( args.Argv( 2 ) );
if ( !anim2 ) {
gameLocal.Printf( "Animation '%s' not found.\n", args.Argv( 2 ) );
return;
}
animname = args.Argv( 2 );
animator.CycleAnim( ANIMCHANNEL_ALL, anim1, gameLocal.time, 0 );
animator.CycleAnim( ANIMCHANNEL_ALL, anim2, gameLocal.time, FRAME2MS( atoi( args.Argv( 3 ) ) ) );
anim = anim2;
headAnim = 0;
}
/***********************************************************************
Testmodel console commands
***********************************************************************/
/*
=================
idTestModel::KeepTestModel_f
Makes the current test model permanent, allowing you to place
multiple test models
=================
*/
void idTestModel::KeepTestModel_f( const idCmdArgs &args ) {
if ( !gameLocal.testmodel ) {
gameLocal.Printf( "No active testModel.\n" );
return;
}
gameLocal.Printf( "modelDef %p kept\n", gameLocal.testmodel->renderEntity.hModel );
gameLocal.testmodel = NULL;
}
/*
=================
idTestModel::TestSkin_f
Sets a skin on an existing testModel
=================
*/
void idTestModel::TestSkin_f( const idCmdArgs &args ) {
idVec3 offset;
idStr name;
idPlayer * player;
idDict dict;
player = gameLocal.GetLocalPlayer();
if ( !player || !gameLocal.CheatsOk() ) {
return;
}
// delete the testModel if active
if ( !gameLocal.testmodel ) {
common->Printf( "No active testModel\n" );
return;
}
if ( args.Argc() < 2 ) {
common->Printf( "removing testSkin.\n" );
gameLocal.testmodel->SetSkin( NULL );
return;
}
name = args.Argv( 1 );
gameLocal.testmodel->SetSkin( declManager->FindSkin( name ) );
}
/*
=================
idTestModel::TestShaderParm_f
Sets a shaderParm on an existing testModel
=================
*/
void idTestModel::TestShaderParm_f( const idCmdArgs &args ) {
idVec3 offset;
idStr name;
idPlayer * player;
idDict dict;
player = gameLocal.GetLocalPlayer();
if ( !player || !gameLocal.CheatsOk() ) {
return;
}
// delete the testModel if active
if ( !gameLocal.testmodel ) {
common->Printf( "No active testModel\n" );
return;
}
if ( args.Argc() != 3 ) {
common->Printf( "USAGE: testShaderParm <parmNum> <float | \"time\">\n" );
return;
}
int parm = atoi( args.Argv( 1 ) );
if ( parm < 0 || parm >= MAX_ENTITY_SHADER_PARMS ) {
common->Printf( "parmNum %i out of range\n", parm );
return;
}
float value;
if ( !idStr::Icmp( args.Argv( 2 ), "time" ) ) {
value = gameLocal.time * -0.001;
} else {
value = atof( args.Argv( 2 ) );
}
gameLocal.testmodel->SetShaderParm( parm, value );
}
/*
=================
idTestModel::TestModel_f
Creates a static modelDef in front of the current position, which
can then be moved around
=================
*/
void idTestModel::TestModel_f( const idCmdArgs &args ) {
idVec3 offset;
idStr name;
idPlayer * player;
const idDict * entityDef;
idDict dict;
player = gameLocal.GetLocalPlayer();
if ( !player || !gameLocal.CheatsOk() ) {
return;
}
// delete the testModel if active
if ( gameLocal.testmodel ) {
delete gameLocal.testmodel;
gameLocal.testmodel = NULL;
}
if ( args.Argc() < 2 ) {
return;
}
name = args.Argv( 1 );
entityDef = gameLocal.FindEntityDefDict( name, false );
if ( entityDef ) {
dict = *entityDef;
} else {
if ( declManager->FindType( DECL_MODELDEF, name, false ) ) {
dict.Set( "model", name );
} else {
// allow map models with underscore prefixes to be tested during development
// without appending an ase
if ( name[ 0 ] != '_' ) {
name.DefaultFileExtension( ".ase" );
}
if ( strstr( name, ".ma" ) || strstr( name, ".mb" ) ) {
idModelExport exporter;
exporter.ExportModel( name );
name.SetFileExtension( MD5_MESH_EXT );
}
if ( !renderModelManager->CheckModel( name ) ) {
gameLocal.Printf( "Can't register model\n" );
return;
}
dict.Set( "model", name );
}
}
offset = player->GetPhysics()->GetOrigin() + player->viewAngles.ToForward() * 100.0f;
dict.Set( "origin", offset.ToString() );
dict.Set( "angle", va( "%f", player->viewAngles.yaw + 180.0f ) );
gameLocal.testmodel = ( idTestModel * )gameLocal.SpawnEntityType( idTestModel::Type, &dict );
gameLocal.testmodel->renderEntity.shaderParms[SHADERPARM_TIMEOFFSET] = -MS2SEC( gameLocal.time );
}
/*
=====================
idTestModel::ArgCompletion_TestModel
=====================
*/
void idTestModel::ArgCompletion_TestModel( const idCmdArgs &args, void(*callback)( const char *s ) ) {
int i, num;
num = declManager->GetNumDecls( DECL_ENTITYDEF );
for ( i = 0; i < num; i++ ) {
callback( idStr( args.Argv( 0 ) ) + " " + declManager->DeclByIndex( DECL_ENTITYDEF, i , false )->GetName() );
}
num = declManager->GetNumDecls( DECL_MODELDEF );
for ( i = 0; i < num; i++ ) {
callback( idStr( args.Argv( 0 ) ) + " " + declManager->DeclByIndex( DECL_MODELDEF, i , false )->GetName() );
}
cmdSystem->ArgCompletion_FolderExtension( args, callback, "models/", false, ".lwo", ".ase", ".md5mesh", ".ma", ".mb", NULL );
}
/*
=====================
idTestModel::TestParticleStopTime_f
=====================
*/
void idTestModel::TestParticleStopTime_f( const idCmdArgs &args ) {
if ( !gameLocal.testmodel ) {
gameLocal.Printf( "No testModel active.\n" );
return;
}
gameLocal.testmodel->renderEntity.shaderParms[SHADERPARM_PARTICLE_STOPTIME] = MS2SEC( gameLocal.time );
gameLocal.testmodel->UpdateVisuals();
}
/*
=====================
idTestModel::TestAnim_f
=====================
*/
void idTestModel::TestAnim_f( const idCmdArgs &args ) {
if ( !gameLocal.testmodel ) {
gameLocal.Printf( "No testModel active.\n" );
return;
}
gameLocal.testmodel->TestAnim( args );
}
/*
=====================
idTestModel::ArgCompletion_TestAnim
=====================
*/
void idTestModel::ArgCompletion_TestAnim( const idCmdArgs &args, void(*callback)( const char *s ) ) {
if ( gameLocal.testmodel ) {
idAnimator *animator = gameLocal.testmodel->GetAnimator();
for( int i = 0; i < animator->NumAnims(); i++ ) {
callback( va( "%s %s", args.Argv( 0 ), animator->AnimFullName( i ) ) );
}
}
}
/*
=====================
idTestModel::TestBlend_f
=====================
*/
void idTestModel::TestBlend_f( const idCmdArgs &args ) {
if ( !gameLocal.testmodel ) {
gameLocal.Printf( "No testModel active.\n" );
return;
}
gameLocal.testmodel->BlendAnim( args );
}
/*
=====================
idTestModel::TestModelNextAnim_f
=====================
*/
void idTestModel::TestModelNextAnim_f( const idCmdArgs &args ) {
if ( !gameLocal.testmodel ) {
gameLocal.Printf( "No testModel active.\n" );
return;
}
gameLocal.testmodel->NextAnim( args );
}
/*
=====================
idTestModel::TestModelPrevAnim_f
=====================
*/
void idTestModel::TestModelPrevAnim_f( const idCmdArgs &args ) {
if ( !gameLocal.testmodel ) {
gameLocal.Printf( "No testModel active.\n" );
return;
}
gameLocal.testmodel->PrevAnim( args );
}
/*
=====================
idTestModel::TestModelNextFrame_f
=====================
*/
void idTestModel::TestModelNextFrame_f( const idCmdArgs &args ) {
if ( !gameLocal.testmodel ) {
gameLocal.Printf( "No testModel active.\n" );
return;
}
gameLocal.testmodel->NextFrame( args );
}
/*
=====================
idTestModel::TestModelPrevFrame_f
=====================
*/
void idTestModel::TestModelPrevFrame_f( const idCmdArgs &args ) {
if ( !gameLocal.testmodel ) {
gameLocal.Printf( "No testModel active.\n" );
return;
}
gameLocal.testmodel->PrevFrame( args );
}

View File

@@ -0,0 +1,95 @@
/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
Doom 3 Source Code 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.
Doom 3 Source Code 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 Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#ifndef __ANIM_TESTMODEL_H__
#define __ANIM_TESTMODEL_H__
/*
==============================================================================================
idTestModel
==============================================================================================
*/
class idTestModel : public idAnimatedEntity {
public:
CLASS_PROTOTYPE( idTestModel );
idTestModel();
~idTestModel();
void Save( idSaveGame *savefile );
void Restore( idRestoreGame *savefile );
void Spawn( void );
virtual bool ShouldConstructScriptObjectAtSpawn( void ) const;
void NextAnim( const idCmdArgs &args );
void PrevAnim( const idCmdArgs &args );
void NextFrame( const idCmdArgs &args );
void PrevFrame( const idCmdArgs &args );
void TestAnim( const idCmdArgs &args );
void BlendAnim( const idCmdArgs &args );
static void KeepTestModel_f( const idCmdArgs &args );
static void TestModel_f( const idCmdArgs &args );
static void ArgCompletion_TestModel( const idCmdArgs &args, void(*callback)( const char *s ) );
static void TestSkin_f( const idCmdArgs &args );
static void TestShaderParm_f( const idCmdArgs &args );
static void TestParticleStopTime_f( const idCmdArgs &args );
static void TestAnim_f( const idCmdArgs &args );
static void ArgCompletion_TestAnim( const idCmdArgs &args, void(*callback)( const char *s ) );
static void TestBlend_f( const idCmdArgs &args );
static void TestModelNextAnim_f( const idCmdArgs &args );
static void TestModelPrevAnim_f( const idCmdArgs &args );
static void TestModelNextFrame_f( const idCmdArgs &args );
static void TestModelPrevFrame_f( const idCmdArgs &args );
private:
idEntityPtr<idEntity> head;
idAnimator *headAnimator;
idAnim customAnim;
idPhysics_Parametric physicsObj;
idStr animname;
int anim;
int headAnim;
int mode;
int frame;
int starttime;
int animtime;
idList<copyJoints_t> copyJoints;
virtual void Think( void );
void Event_Footstep( void );
};
#endif /* !__ANIM_TESTMODEL_H__*/