2011-11-22 21:28:15 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Doom 3 GPL Source Code
Copyright ( C ) 1999 - 2011 id Software LLC , a ZeniMax Media company .
2011-12-06 16:14:59 +00:00
This file is part of the Doom 3 GPL Source Code ( " Doom 3 Source Code " ) .
2011-11-22 21:28:15 +00:00
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"
static const char * channelNames [ ANIM_NumAnimChannels ] = {
" all " , " torso " , " legs " , " head " , " eyelids "
} ;
/***********************************************************************
idAnim
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
= = = = = = = = = = = = = = = = = = = = =
idAnim : : idAnim
= = = = = = = = = = = = = = = = = = = = =
*/
idAnim : : idAnim ( ) {
modelDef = NULL ;
numAnims = 0 ;
memset ( anims , 0 , sizeof ( anims ) ) ;
memset ( & flags , 0 , sizeof ( flags ) ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnim : : idAnim
= = = = = = = = = = = = = = = = = = = = =
*/
idAnim : : idAnim ( const idDeclModelDef * modelDef , const idAnim * anim ) {
int i ;
this - > modelDef = modelDef ;
numAnims = anim - > numAnims ;
name = anim - > name ;
realname = anim - > realname ;
flags = anim - > flags ;
memset ( anims , 0 , sizeof ( anims ) ) ;
for ( i = 0 ; i < numAnims ; i + + ) {
anims [ i ] = anim - > anims [ i ] ;
anims [ i ] - > IncreaseRefs ( ) ;
}
frameLookup . SetNum ( anim - > frameLookup . Num ( ) ) ;
memcpy ( frameLookup . Ptr ( ) , anim - > frameLookup . Ptr ( ) , frameLookup . MemoryUsed ( ) ) ;
frameCommands . SetNum ( anim - > frameCommands . Num ( ) ) ;
for ( i = 0 ; i < frameCommands . Num ( ) ; i + + ) {
frameCommands [ i ] = anim - > frameCommands [ i ] ;
if ( anim - > frameCommands [ i ] . string ) {
frameCommands [ i ] . string = new idStr ( * anim - > frameCommands [ i ] . string ) ;
}
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnim : : ~ idAnim
= = = = = = = = = = = = = = = = = = = = =
*/
idAnim : : ~ idAnim ( ) {
int i ;
for ( i = 0 ; i < numAnims ; i + + ) {
anims [ i ] - > DecreaseRefs ( ) ;
}
for ( i = 0 ; i < frameCommands . Num ( ) ; i + + ) {
delete frameCommands [ i ] . string ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnim : : SetAnim
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnim : : SetAnim ( const idDeclModelDef * modelDef , const char * sourcename , const char * animname , int num , const idMD5Anim * md5anims [ ANIM_MaxSyncedAnims ] ) {
int i ;
this - > modelDef = modelDef ;
for ( i = 0 ; i < numAnims ; i + + ) {
anims [ i ] - > DecreaseRefs ( ) ;
anims [ i ] = NULL ;
}
assert ( ( num > 0 ) & & ( num < = ANIM_MaxSyncedAnims ) ) ;
numAnims = num ;
realname = sourcename ;
name = animname ;
for ( i = 0 ; i < num ; i + + ) {
anims [ i ] = md5anims [ i ] ;
anims [ i ] - > IncreaseRefs ( ) ;
}
memset ( & flags , 0 , sizeof ( flags ) ) ;
for ( i = 0 ; i < frameCommands . Num ( ) ; i + + ) {
delete frameCommands [ i ] . string ;
}
frameLookup . Clear ( ) ;
frameCommands . Clear ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnim : : Name
= = = = = = = = = = = = = = = = = = = = =
*/
const char * idAnim : : Name ( void ) const {
return name ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnim : : FullName
= = = = = = = = = = = = = = = = = = = = =
*/
const char * idAnim : : FullName ( void ) const {
return realname ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnim : : MD5Anim
index 0 will never be NULL . Any anim > = NumAnims will return NULL .
= = = = = = = = = = = = = = = = = = = = =
*/
const idMD5Anim * idAnim : : MD5Anim ( int num ) const {
if ( anims = = NULL | | anims [ 0 ] = = NULL ) {
return NULL ;
}
return anims [ num ] ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnim : : ModelDef
= = = = = = = = = = = = = = = = = = = = =
*/
const idDeclModelDef * idAnim : : ModelDef ( void ) const {
return modelDef ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnim : : Length
= = = = = = = = = = = = = = = = = = = = =
*/
int idAnim : : Length ( void ) const {
if ( ! anims [ 0 ] ) {
return 0 ;
}
return anims [ 0 ] - > Length ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnim : : NumFrames
= = = = = = = = = = = = = = = = = = = = =
*/
int idAnim : : NumFrames ( void ) const {
if ( ! anims [ 0 ] ) {
return 0 ;
}
return anims [ 0 ] - > NumFrames ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnim : : NumAnims
= = = = = = = = = = = = = = = = = = = = =
*/
int idAnim : : NumAnims ( void ) const {
return numAnims ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnim : : TotalMovementDelta
= = = = = = = = = = = = = = = = = = = = =
*/
const idVec3 & idAnim : : TotalMovementDelta ( void ) const {
if ( ! anims [ 0 ] ) {
return vec3_zero ;
}
return anims [ 0 ] - > TotalMovementDelta ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnim : : GetOrigin
= = = = = = = = = = = = = = = = = = = = =
*/
bool idAnim : : GetOrigin ( idVec3 & offset , int animNum , int currentTime , int cyclecount ) const {
if ( ! anims [ animNum ] ) {
offset . Zero ( ) ;
return false ;
}
anims [ animNum ] - > GetOrigin ( offset , currentTime , cyclecount ) ;
return true ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnim : : GetOriginRotation
= = = = = = = = = = = = = = = = = = = = =
*/
bool idAnim : : GetOriginRotation ( idQuat & rotation , int animNum , int currentTime , int cyclecount ) const {
if ( ! anims [ animNum ] ) {
rotation . Set ( 0.0f , 0.0f , 0.0f , 1.0f ) ;
return false ;
}
anims [ animNum ] - > GetOriginRotation ( rotation , currentTime , cyclecount ) ;
return true ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnim : : GetBounds
= = = = = = = = = = = = = = = = = = = = =
*/
ID_INLINE bool idAnim : : GetBounds ( idBounds & bounds , int animNum , int currentTime , int cyclecount ) const {
if ( ! anims [ animNum ] ) {
return false ;
}
anims [ animNum ] - > GetBounds ( bounds , currentTime , cyclecount ) ;
return true ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnim : : AddFrameCommand
Returns NULL if no error .
= = = = = = = = = = = = = = = = = = = = =
*/
const char * idAnim : : AddFrameCommand ( const idDeclModelDef * modelDef , int framenum , idLexer & src , const idDict * def ) {
int i ;
int index ;
idStr text ;
idStr funcname ;
frameCommand_t fc ;
idToken token ;
const jointInfo_t * jointInfo ;
// make sure we're within bounds
if ( ( framenum < 1 ) | | ( framenum > anims [ 0 ] - > NumFrames ( ) ) ) {
return va ( " Frame %d out of range " , framenum ) ;
}
// frame numbers are 1 based in .def files, but 0 based internally
framenum - - ;
memset ( & fc , 0 , sizeof ( fc ) ) ;
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
if ( token = = " call " ) {
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
fc . type = FC_SCRIPTFUNCTION ;
fc . function = gameLocal . program . FindFunction ( token ) ;
if ( ! fc . function ) {
return va ( " Function '%s' not found " , token . c_str ( ) ) ;
}
} else if ( token = = " object_call " ) {
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
fc . type = FC_SCRIPTFUNCTIONOBJECT ;
fc . string = new idStr ( token ) ;
} else if ( token = = " event " ) {
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
fc . type = FC_EVENTFUNCTION ;
const idEventDef * ev = idEventDef : : FindEvent ( token ) ;
if ( ! ev ) {
return va ( " Event '%s' not found " , token . c_str ( ) ) ;
}
if ( ev - > GetNumArgs ( ) ! = 0 ) {
return va ( " Event '%s' has arguments " , token . c_str ( ) ) ;
}
fc . string = new idStr ( token ) ;
} else if ( token = = " sound " ) {
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
fc . type = FC_SOUND ;
if ( ! token . Cmpn ( " snd_ " , 4 ) ) {
fc . string = new idStr ( token ) ;
} else {
fc . soundShader = declManager - > FindSound ( token ) ;
if ( fc . soundShader - > GetState ( ) = = DS_DEFAULTED ) {
gameLocal . Warning ( " Sound '%s' not found " , token . c_str ( ) ) ;
}
}
} else if ( token = = " sound_voice " ) {
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
fc . type = FC_SOUND_VOICE ;
if ( ! token . Cmpn ( " snd_ " , 4 ) ) {
fc . string = new idStr ( token ) ;
} else {
fc . soundShader = declManager - > FindSound ( token ) ;
if ( fc . soundShader - > GetState ( ) = = DS_DEFAULTED ) {
gameLocal . Warning ( " Sound '%s' not found " , token . c_str ( ) ) ;
}
}
} else if ( token = = " sound_voice2 " ) {
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
fc . type = FC_SOUND_VOICE2 ;
if ( ! token . Cmpn ( " snd_ " , 4 ) ) {
fc . string = new idStr ( token ) ;
} else {
fc . soundShader = declManager - > FindSound ( token ) ;
if ( fc . soundShader - > GetState ( ) = = DS_DEFAULTED ) {
gameLocal . Warning ( " Sound '%s' not found " , token . c_str ( ) ) ;
}
}
} else if ( token = = " sound_body " ) {
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
fc . type = FC_SOUND_BODY ;
if ( ! token . Cmpn ( " snd_ " , 4 ) ) {
fc . string = new idStr ( token ) ;
} else {
fc . soundShader = declManager - > FindSound ( token ) ;
if ( fc . soundShader - > GetState ( ) = = DS_DEFAULTED ) {
gameLocal . Warning ( " Sound '%s' not found " , token . c_str ( ) ) ;
}
}
} else if ( token = = " sound_body2 " ) {
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
fc . type = FC_SOUND_BODY2 ;
if ( ! token . Cmpn ( " snd_ " , 4 ) ) {
fc . string = new idStr ( token ) ;
} else {
fc . soundShader = declManager - > FindSound ( token ) ;
if ( fc . soundShader - > GetState ( ) = = DS_DEFAULTED ) {
gameLocal . Warning ( " Sound '%s' not found " , token . c_str ( ) ) ;
}
}
} else if ( token = = " sound_body3 " ) {
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
fc . type = FC_SOUND_BODY3 ;
if ( ! token . Cmpn ( " snd_ " , 4 ) ) {
fc . string = new idStr ( token ) ;
} else {
fc . soundShader = declManager - > FindSound ( token ) ;
if ( fc . soundShader - > GetState ( ) = = DS_DEFAULTED ) {
gameLocal . Warning ( " Sound '%s' not found " , token . c_str ( ) ) ;
}
}
} else if ( token = = " sound_weapon " ) {
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
fc . type = FC_SOUND_WEAPON ;
if ( ! token . Cmpn ( " snd_ " , 4 ) ) {
fc . string = new idStr ( token ) ;
} else {
fc . soundShader = declManager - > FindSound ( token ) ;
if ( fc . soundShader - > GetState ( ) = = DS_DEFAULTED ) {
gameLocal . Warning ( " Sound '%s' not found " , token . c_str ( ) ) ;
}
}
} else if ( token = = " sound_global " ) {
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
fc . type = FC_SOUND_GLOBAL ;
if ( ! token . Cmpn ( " snd_ " , 4 ) ) {
fc . string = new idStr ( token ) ;
} else {
fc . soundShader = declManager - > FindSound ( token ) ;
if ( fc . soundShader - > GetState ( ) = = DS_DEFAULTED ) {
gameLocal . Warning ( " Sound '%s' not found " , token . c_str ( ) ) ;
}
}
} else if ( token = = " sound_item " ) {
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
fc . type = FC_SOUND_ITEM ;
if ( ! token . Cmpn ( " snd_ " , 4 ) ) {
fc . string = new idStr ( token ) ;
} else {
fc . soundShader = declManager - > FindSound ( token ) ;
if ( fc . soundShader - > GetState ( ) = = DS_DEFAULTED ) {
gameLocal . Warning ( " Sound '%s' not found " , token . c_str ( ) ) ;
}
}
} else if ( token = = " sound_chatter " ) {
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
fc . type = FC_SOUND_CHATTER ;
if ( ! token . Cmpn ( " snd_ " , 4 ) ) {
fc . string = new idStr ( token ) ;
} else {
fc . soundShader = declManager - > FindSound ( token ) ;
if ( fc . soundShader - > GetState ( ) = = DS_DEFAULTED ) {
gameLocal . Warning ( " Sound '%s' not found " , token . c_str ( ) ) ;
}
}
} else if ( token = = " skin " ) {
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
fc . type = FC_SKIN ;
if ( token = = " none " ) {
fc . skin = NULL ;
} else {
fc . skin = declManager - > FindSkin ( token ) ;
if ( ! fc . skin ) {
return va ( " Skin '%s' not found " , token . c_str ( ) ) ;
}
}
} else if ( token = = " fx " ) {
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
fc . type = FC_FX ;
if ( ! declManager - > FindType ( DECL_FX , token . c_str ( ) ) ) {
return va ( " fx '%s' not found " , token . c_str ( ) ) ;
}
fc . string = new idStr ( token ) ;
} else if ( token = = " trigger " ) {
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
fc . type = FC_TRIGGER ;
fc . string = new idStr ( token ) ;
} else if ( token = = " triggerSmokeParticle " ) {
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
fc . type = FC_TRIGGER_SMOKE_PARTICLE ;
fc . string = new idStr ( token ) ;
} else if ( token = = " melee " ) {
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
fc . type = FC_MELEE ;
if ( ! gameLocal . FindEntityDef ( token . c_str ( ) , false ) ) {
return va ( " Unknown entityDef '%s' " , token . c_str ( ) ) ;
}
fc . string = new idStr ( token ) ;
} else if ( token = = " direct_damage " ) {
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
fc . type = FC_DIRECTDAMAGE ;
if ( ! gameLocal . FindEntityDef ( token . c_str ( ) , false ) ) {
return va ( " Unknown entityDef '%s' " , token . c_str ( ) ) ;
}
fc . string = new idStr ( token ) ;
} else if ( token = = " attack_begin " ) {
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
fc . type = FC_BEGINATTACK ;
if ( ! gameLocal . FindEntityDef ( token . c_str ( ) , false ) ) {
return va ( " Unknown entityDef '%s' " , token . c_str ( ) ) ;
}
fc . string = new idStr ( token ) ;
} else if ( token = = " attack_end " ) {
fc . type = FC_ENDATTACK ;
} else if ( token = = " muzzle_flash " ) {
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
if ( ( token ! = " " ) & & ! modelDef - > FindJoint ( token ) ) {
return va ( " Joint '%s' not found " , token . c_str ( ) ) ;
}
fc . type = FC_MUZZLEFLASH ;
fc . string = new idStr ( token ) ;
} else if ( token = = " muzzle_flash " ) {
fc . type = FC_MUZZLEFLASH ;
fc . string = new idStr ( " " ) ;
} else if ( token = = " create_missile " ) {
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
if ( ! modelDef - > FindJoint ( token ) ) {
return va ( " Joint '%s' not found " , token . c_str ( ) ) ;
}
fc . type = FC_CREATEMISSILE ;
fc . string = new idStr ( token ) ;
} else if ( token = = " launch_missile " ) {
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
if ( ! modelDef - > FindJoint ( token ) ) {
return va ( " Joint '%s' not found " , token . c_str ( ) ) ;
}
fc . type = FC_LAUNCHMISSILE ;
fc . string = new idStr ( token ) ;
} else if ( token = = " fire_missile_at_target " ) {
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
jointInfo = modelDef - > FindJoint ( token ) ;
if ( ! jointInfo ) {
return va ( " Joint '%s' not found " , token . c_str ( ) ) ;
}
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
fc . type = FC_FIREMISSILEATTARGET ;
fc . string = new idStr ( token ) ;
fc . index = jointInfo - > num ;
# ifdef _D3XP
} else if ( token = = " launch_projectile " ) {
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
if ( ! declManager - > FindDeclWithoutParsing ( DECL_ENTITYDEF , token , false ) ) {
return " Unknown projectile def " ;
}
fc . type = FC_LAUNCH_PROJECTILE ;
fc . string = new idStr ( token ) ;
} else if ( token = = " trigger_fx " ) {
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
jointInfo = modelDef - > FindJoint ( token ) ;
if ( ! jointInfo ) {
return va ( " Joint '%s' not found " , token . c_str ( ) ) ;
}
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
if ( ! declManager - > FindType ( DECL_FX , token , false ) ) {
return " Unknown FX def " ;
}
fc . type = FC_TRIGGER_FX ;
fc . string = new idStr ( token ) ;
fc . index = jointInfo - > num ;
} else if ( token = = " start_emitter " ) {
idStr str ;
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
str = token + " " ;
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
jointInfo = modelDef - > FindJoint ( token ) ;
if ( ! jointInfo ) {
return va ( " Joint '%s' not found " , token . c_str ( ) ) ;
}
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
str + = token ;
fc . type = FC_START_EMITTER ;
fc . string = new idStr ( str ) ;
fc . index = jointInfo - > num ;
} else if ( token = = " stop_emitter " ) {
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
fc . type = FC_STOP_EMITTER ;
fc . string = new idStr ( token ) ;
# endif
} else if ( token = = " footstep " ) {
fc . type = FC_FOOTSTEP ;
} else if ( token = = " leftfoot " ) {
fc . type = FC_LEFTFOOT ;
} else if ( token = = " rightfoot " ) {
fc . type = FC_RIGHTFOOT ;
} else if ( token = = " enableEyeFocus " ) {
fc . type = FC_ENABLE_EYE_FOCUS ;
} else if ( token = = " disableEyeFocus " ) {
fc . type = FC_DISABLE_EYE_FOCUS ;
} else if ( token = = " disableGravity " ) {
fc . type = FC_DISABLE_GRAVITY ;
} else if ( token = = " enableGravity " ) {
fc . type = FC_ENABLE_GRAVITY ;
} else if ( token = = " jump " ) {
fc . type = FC_JUMP ;
} else if ( token = = " enableClip " ) {
fc . type = FC_ENABLE_CLIP ;
} else if ( token = = " disableClip " ) {
fc . type = FC_DISABLE_CLIP ;
} else if ( token = = " enableWalkIK " ) {
fc . type = FC_ENABLE_WALK_IK ;
} else if ( token = = " disableWalkIK " ) {
fc . type = FC_DISABLE_WALK_IK ;
} else if ( token = = " enableLegIK " ) {
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
fc . type = FC_ENABLE_LEG_IK ;
fc . index = atoi ( token ) ;
} else if ( token = = " disableLegIK " ) {
if ( ! src . ReadTokenOnLine ( & token ) ) {
return " Unexpected end of line " ;
}
fc . type = FC_DISABLE_LEG_IK ;
fc . index = atoi ( token ) ;
} else if ( token = = " recordDemo " ) {
fc . type = FC_RECORDDEMO ;
if ( src . ReadTokenOnLine ( & token ) ) {
fc . string = new idStr ( token ) ;
}
} else if ( token = = " aviGame " ) {
fc . type = FC_AVIGAME ;
if ( src . ReadTokenOnLine ( & token ) ) {
fc . string = new idStr ( token ) ;
}
} else {
return va ( " Unknown command '%s' " , token . c_str ( ) ) ;
}
// check if we've initialized the frame loopup table
if ( ! frameLookup . Num ( ) ) {
// we haven't, so allocate the table and initialize it
frameLookup . SetGranularity ( 1 ) ;
frameLookup . SetNum ( anims [ 0 ] - > NumFrames ( ) ) ;
for ( i = 0 ; i < frameLookup . Num ( ) ; i + + ) {
frameLookup [ i ] . num = 0 ;
frameLookup [ i ] . firstCommand = 0 ;
}
}
// allocate space for a new command
frameCommands . Alloc ( ) ;
// calculate the index of the new command
index = frameLookup [ framenum ] . firstCommand + frameLookup [ framenum ] . num ;
// move all commands from our index onward up one to give us space for our new command
for ( i = frameCommands . Num ( ) - 1 ; i > index ; i - - ) {
frameCommands [ i ] = frameCommands [ i - 1 ] ;
}
// fix the indices of any later frames to account for the inserted command
for ( i = framenum + 1 ; i < frameLookup . Num ( ) ; i + + ) {
frameLookup [ i ] . firstCommand + + ;
}
// store the new command
frameCommands [ index ] = fc ;
// increase the number of commands on this frame
frameLookup [ framenum ] . num + + ;
// return with no error
return NULL ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnim : : CallFrameCommands
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnim : : CallFrameCommands ( idEntity * ent , int from , int to ) const {
int index ;
int end ;
int frame ;
int numframes ;
numframes = anims [ 0 ] - > NumFrames ( ) ;
frame = from ;
while ( frame ! = to ) {
frame + + ;
if ( frame > = numframes ) {
frame = 0 ;
}
index = frameLookup [ frame ] . firstCommand ;
end = index + frameLookup [ frame ] . num ;
while ( index < end ) {
const frameCommand_t & command = frameCommands [ index + + ] ;
switch ( command . type ) {
case FC_SCRIPTFUNCTION : {
gameLocal . CallFrameCommand ( ent , command . function ) ;
break ;
}
case FC_SCRIPTFUNCTIONOBJECT : {
gameLocal . CallObjectFrameCommand ( ent , command . string - > c_str ( ) ) ;
break ;
}
case FC_EVENTFUNCTION : {
const idEventDef * ev = idEventDef : : FindEvent ( command . string - > c_str ( ) ) ;
ent - > ProcessEvent ( ev ) ;
break ;
}
case FC_SOUND : {
if ( ! command . soundShader ) {
if ( ! ent - > StartSound ( command . string - > c_str ( ) , SND_CHANNEL_ANY , 0 , false , NULL ) ) {
gameLocal . Warning ( " Framecommand 'sound' on entity '%s', anim '%s', frame %d: Could not find sound '%s' " ,
ent - > name . c_str ( ) , FullName ( ) , frame + 1 , command . string - > c_str ( ) ) ;
}
} else {
ent - > StartSoundShader ( command . soundShader , SND_CHANNEL_ANY , 0 , false , NULL ) ;
}
break ;
}
case FC_SOUND_VOICE : {
if ( ! command . soundShader ) {
if ( ! ent - > StartSound ( command . string - > c_str ( ) , SND_CHANNEL_VOICE , 0 , false , NULL ) ) {
gameLocal . Warning ( " Framecommand 'sound_voice' on entity '%s', anim '%s', frame %d: Could not find sound '%s' " ,
ent - > name . c_str ( ) , FullName ( ) , frame + 1 , command . string - > c_str ( ) ) ;
}
} else {
ent - > StartSoundShader ( command . soundShader , SND_CHANNEL_VOICE , 0 , false , NULL ) ;
}
break ;
}
case FC_SOUND_VOICE2 : {
if ( ! command . soundShader ) {
if ( ! ent - > StartSound ( command . string - > c_str ( ) , SND_CHANNEL_VOICE2 , 0 , false , NULL ) ) {
gameLocal . Warning ( " Framecommand 'sound_voice2' on entity '%s', anim '%s', frame %d: Could not find sound '%s' " ,
ent - > name . c_str ( ) , FullName ( ) , frame + 1 , command . string - > c_str ( ) ) ;
}
} else {
ent - > StartSoundShader ( command . soundShader , SND_CHANNEL_VOICE2 , 0 , false , NULL ) ;
}
break ;
}
case FC_SOUND_BODY : {
if ( ! command . soundShader ) {
if ( ! ent - > StartSound ( command . string - > c_str ( ) , SND_CHANNEL_BODY , 0 , false , NULL ) ) {
gameLocal . Warning ( " Framecommand 'sound_body' on entity '%s', anim '%s', frame %d: Could not find sound '%s' " ,
ent - > name . c_str ( ) , FullName ( ) , frame + 1 , command . string - > c_str ( ) ) ;
}
} else {
ent - > StartSoundShader ( command . soundShader , SND_CHANNEL_BODY , 0 , false , NULL ) ;
}
break ;
}
case FC_SOUND_BODY2 : {
if ( ! command . soundShader ) {
if ( ! ent - > StartSound ( command . string - > c_str ( ) , SND_CHANNEL_BODY2 , 0 , false , NULL ) ) {
gameLocal . Warning ( " Framecommand 'sound_body2' on entity '%s', anim '%s', frame %d: Could not find sound '%s' " ,
ent - > name . c_str ( ) , FullName ( ) , frame + 1 , command . string - > c_str ( ) ) ;
}
} else {
ent - > StartSoundShader ( command . soundShader , SND_CHANNEL_BODY2 , 0 , false , NULL ) ;
}
break ;
}
case FC_SOUND_BODY3 : {
if ( ! command . soundShader ) {
if ( ! ent - > StartSound ( command . string - > c_str ( ) , SND_CHANNEL_BODY3 , 0 , false , NULL ) ) {
gameLocal . Warning ( " Framecommand 'sound_body3' on entity '%s', anim '%s', frame %d: Could not find sound '%s' " ,
ent - > name . c_str ( ) , FullName ( ) , frame + 1 , command . string - > c_str ( ) ) ;
}
} else {
ent - > StartSoundShader ( command . soundShader , SND_CHANNEL_BODY3 , 0 , false , NULL ) ;
}
break ;
}
case FC_SOUND_WEAPON : {
if ( ! command . soundShader ) {
if ( ! ent - > StartSound ( command . string - > c_str ( ) , SND_CHANNEL_WEAPON , 0 , false , NULL ) ) {
gameLocal . Warning ( " Framecommand 'sound_weapon' on entity '%s', anim '%s', frame %d: Could not find sound '%s' " ,
ent - > name . c_str ( ) , FullName ( ) , frame + 1 , command . string - > c_str ( ) ) ;
}
} else {
ent - > StartSoundShader ( command . soundShader , SND_CHANNEL_WEAPON , 0 , false , NULL ) ;
}
break ;
}
case FC_SOUND_GLOBAL : {
if ( ! command . soundShader ) {
if ( ! ent - > StartSound ( command . string - > c_str ( ) , SND_CHANNEL_ANY , SSF_GLOBAL , false , NULL ) ) {
gameLocal . Warning ( " Framecommand 'sound_global' on entity '%s', anim '%s', frame %d: Could not find sound '%s' " ,
ent - > name . c_str ( ) , FullName ( ) , frame + 1 , command . string - > c_str ( ) ) ;
}
} else {
ent - > StartSoundShader ( command . soundShader , SND_CHANNEL_ANY , SSF_GLOBAL , false , NULL ) ;
}
break ;
}
case FC_SOUND_ITEM : {
if ( ! command . soundShader ) {
if ( ! ent - > StartSound ( command . string - > c_str ( ) , SND_CHANNEL_ITEM , 0 , false , NULL ) ) {
gameLocal . Warning ( " Framecommand 'sound_item' on entity '%s', anim '%s', frame %d: Could not find sound '%s' " ,
ent - > name . c_str ( ) , FullName ( ) , frame + 1 , command . string - > c_str ( ) ) ;
}
} else {
ent - > StartSoundShader ( command . soundShader , SND_CHANNEL_ITEM , 0 , false , NULL ) ;
}
break ;
}
case FC_SOUND_CHATTER : {
if ( ent - > CanPlayChatterSounds ( ) ) {
if ( ! command . soundShader ) {
if ( ! ent - > StartSound ( command . string - > c_str ( ) , SND_CHANNEL_VOICE , 0 , false , NULL ) ) {
gameLocal . Warning ( " Framecommand 'sound_chatter' on entity '%s', anim '%s', frame %d: Could not find sound '%s' " ,
ent - > name . c_str ( ) , FullName ( ) , frame + 1 , command . string - > c_str ( ) ) ;
}
} else {
ent - > StartSoundShader ( command . soundShader , SND_CHANNEL_VOICE , 0 , false , NULL ) ;
}
}
break ;
}
case FC_FX : {
idEntityFx : : StartFx ( command . string - > c_str ( ) , NULL , NULL , ent , true ) ;
break ;
}
case FC_SKIN : {
ent - > SetSkin ( command . skin ) ;
break ;
}
case FC_TRIGGER : {
idEntity * target ;
target = gameLocal . FindEntity ( command . string - > c_str ( ) ) ;
if ( target ) {
# ifdef _D3XP
SetTimeState ts ( target - > timeGroup ) ;
# endif
target - > Signal ( SIG_TRIGGER ) ;
target - > ProcessEvent ( & EV_Activate , ent ) ;
target - > TriggerGuis ( ) ;
} else {
gameLocal . Warning ( " Framecommand 'trigger' on entity '%s', anim '%s', frame %d: Could not find entity '%s' " ,
ent - > name . c_str ( ) , FullName ( ) , frame + 1 , command . string - > c_str ( ) ) ;
}
break ;
}
case FC_TRIGGER_SMOKE_PARTICLE : {
ent - > ProcessEvent ( & AI_TriggerParticles , command . string - > c_str ( ) ) ;
break ;
}
case FC_MELEE : {
ent - > ProcessEvent ( & AI_AttackMelee , command . string - > c_str ( ) ) ;
break ;
}
case FC_DIRECTDAMAGE : {
ent - > ProcessEvent ( & AI_DirectDamage , command . string - > c_str ( ) ) ;
break ;
}
case FC_BEGINATTACK : {
ent - > ProcessEvent ( & AI_BeginAttack , command . string - > c_str ( ) ) ;
break ;
}
case FC_ENDATTACK : {
ent - > ProcessEvent ( & AI_EndAttack ) ;
break ;
}
case FC_MUZZLEFLASH : {
ent - > ProcessEvent ( & AI_MuzzleFlash , command . string - > c_str ( ) ) ;
break ;
}
case FC_CREATEMISSILE : {
ent - > ProcessEvent ( & AI_CreateMissile , command . string - > c_str ( ) ) ;
break ;
}
case FC_LAUNCHMISSILE : {
ent - > ProcessEvent ( & AI_AttackMissile , command . string - > c_str ( ) ) ;
break ;
}
case FC_FIREMISSILEATTARGET : {
ent - > ProcessEvent ( & AI_FireMissileAtTarget , modelDef - > GetJointName ( command . index ) , command . string - > c_str ( ) ) ;
break ;
}
# ifdef _D3XP
case FC_LAUNCH_PROJECTILE : {
ent - > ProcessEvent ( & AI_LaunchProjectile , command . string - > c_str ( ) ) ;
break ;
}
case FC_TRIGGER_FX : {
ent - > ProcessEvent ( & AI_TriggerFX , modelDef - > GetJointName ( command . index ) , command . string - > c_str ( ) ) ;
break ;
}
case FC_START_EMITTER : {
int index = command . string - > Find ( " " ) ;
if ( index > = 0 ) {
idStr name = command . string - > Left ( index ) ;
idStr particle = command . string - > Right ( command . string - > Length ( ) - index - 1 ) ;
ent - > ProcessEvent ( & AI_StartEmitter , name . c_str ( ) , modelDef - > GetJointName ( command . index ) , particle . c_str ( ) ) ;
}
}
case FC_STOP_EMITTER : {
ent - > ProcessEvent ( & AI_StopEmitter , command . string - > c_str ( ) ) ;
}
# endif
case FC_FOOTSTEP : {
ent - > ProcessEvent ( & EV_Footstep ) ;
break ;
}
case FC_LEFTFOOT : {
ent - > ProcessEvent ( & EV_FootstepLeft ) ;
break ;
}
case FC_RIGHTFOOT : {
ent - > ProcessEvent ( & EV_FootstepRight ) ;
break ;
}
case FC_ENABLE_EYE_FOCUS : {
ent - > ProcessEvent ( & AI_EnableEyeFocus ) ;
break ;
}
case FC_DISABLE_EYE_FOCUS : {
ent - > ProcessEvent ( & AI_DisableEyeFocus ) ;
break ;
}
case FC_DISABLE_GRAVITY : {
ent - > ProcessEvent ( & AI_DisableGravity ) ;
break ;
}
case FC_ENABLE_GRAVITY : {
ent - > ProcessEvent ( & AI_EnableGravity ) ;
break ;
}
case FC_JUMP : {
ent - > ProcessEvent ( & AI_JumpFrame ) ;
break ;
}
case FC_ENABLE_CLIP : {
ent - > ProcessEvent ( & AI_EnableClip ) ;
break ;
}
case FC_DISABLE_CLIP : {
ent - > ProcessEvent ( & AI_DisableClip ) ;
break ;
}
case FC_ENABLE_WALK_IK : {
ent - > ProcessEvent ( & EV_EnableWalkIK ) ;
break ;
}
case FC_DISABLE_WALK_IK : {
ent - > ProcessEvent ( & EV_DisableWalkIK ) ;
break ;
}
case FC_ENABLE_LEG_IK : {
ent - > ProcessEvent ( & EV_EnableLegIK , command . index ) ;
break ;
}
case FC_DISABLE_LEG_IK : {
ent - > ProcessEvent ( & EV_DisableLegIK , command . index ) ;
break ;
}
case FC_RECORDDEMO : {
if ( command . string ) {
cmdSystem - > BufferCommandText ( CMD_EXEC_NOW , va ( " recordDemo %s " , command . string - > c_str ( ) ) ) ;
} else {
cmdSystem - > BufferCommandText ( CMD_EXEC_NOW , " stoprecording " ) ;
}
break ;
}
case FC_AVIGAME : {
if ( command . string ) {
cmdSystem - > BufferCommandText ( CMD_EXEC_NOW , va ( " aviGame %s " , command . string - > c_str ( ) ) ) ;
} else {
cmdSystem - > BufferCommandText ( CMD_EXEC_NOW , " aviGame " ) ;
}
break ;
}
}
}
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnim : : FindFrameForFrameCommand
= = = = = = = = = = = = = = = = = = = = =
*/
int idAnim : : FindFrameForFrameCommand ( frameCommandType_t framecommand , const frameCommand_t * * command ) const {
int frame ;
int index ;
int numframes ;
int end ;
if ( ! frameCommands . Num ( ) ) {
return - 1 ;
}
numframes = anims [ 0 ] - > NumFrames ( ) ;
for ( frame = 0 ; frame < numframes ; frame + + ) {
end = frameLookup [ frame ] . firstCommand + frameLookup [ frame ] . num ;
for ( index = frameLookup [ frame ] . firstCommand ; index < end ; index + + ) {
if ( frameCommands [ index ] . type = = framecommand ) {
if ( command ) {
* command = & frameCommands [ index ] ;
}
return frame ;
}
}
}
if ( command ) {
* command = NULL ;
}
return - 1 ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnim : : HasFrameCommands
= = = = = = = = = = = = = = = = = = = = =
*/
bool idAnim : : HasFrameCommands ( void ) const {
if ( ! frameCommands . Num ( ) ) {
return false ;
}
return true ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnim : : SetAnimFlags
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnim : : SetAnimFlags ( const animFlags_t & animflags ) {
flags = animflags ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnim : : GetAnimFlags
= = = = = = = = = = = = = = = = = = = = =
*/
const animFlags_t & idAnim : : GetAnimFlags ( void ) const {
return flags ;
}
/***********************************************************************
idAnimBlend
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : idAnimBlend
= = = = = = = = = = = = = = = = = = = = =
*/
idAnimBlend : : idAnimBlend ( void ) {
Reset ( NULL ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : Save
archives object for save game file
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimBlend : : Save ( idSaveGame * savefile ) const {
int i ;
savefile - > WriteInt ( starttime ) ;
savefile - > WriteInt ( endtime ) ;
savefile - > WriteInt ( timeOffset ) ;
savefile - > WriteFloat ( rate ) ;
savefile - > WriteInt ( blendStartTime ) ;
savefile - > WriteInt ( blendDuration ) ;
savefile - > WriteFloat ( blendStartValue ) ;
savefile - > WriteFloat ( blendEndValue ) ;
for ( i = 0 ; i < ANIM_MaxSyncedAnims ; i + + ) {
savefile - > WriteFloat ( animWeights [ i ] ) ;
}
savefile - > WriteShort ( cycle ) ;
savefile - > WriteShort ( frame ) ;
savefile - > WriteShort ( animNum ) ;
savefile - > WriteBool ( allowMove ) ;
savefile - > WriteBool ( allowFrameCommands ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : Restore
unarchives object from save game file
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimBlend : : Restore ( idRestoreGame * savefile , const idDeclModelDef * modelDef ) {
int i ;
this - > modelDef = modelDef ;
savefile - > ReadInt ( starttime ) ;
savefile - > ReadInt ( endtime ) ;
savefile - > ReadInt ( timeOffset ) ;
savefile - > ReadFloat ( rate ) ;
savefile - > ReadInt ( blendStartTime ) ;
savefile - > ReadInt ( blendDuration ) ;
savefile - > ReadFloat ( blendStartValue ) ;
savefile - > ReadFloat ( blendEndValue ) ;
for ( i = 0 ; i < ANIM_MaxSyncedAnims ; i + + ) {
savefile - > ReadFloat ( animWeights [ i ] ) ;
}
savefile - > ReadShort ( cycle ) ;
savefile - > ReadShort ( frame ) ;
savefile - > ReadShort ( animNum ) ;
if ( ! modelDef ) {
animNum = 0 ;
} else if ( ( animNum < 0 ) | | ( animNum > modelDef - > NumAnims ( ) ) ) {
gameLocal . Warning ( " Anim number %d out of range for model '%s' during save game " , animNum , modelDef - > GetModelName ( ) ) ;
animNum = 0 ;
}
savefile - > ReadBool ( allowMove ) ;
savefile - > ReadBool ( allowFrameCommands ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : Reset
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimBlend : : Reset ( const idDeclModelDef * _modelDef ) {
modelDef = _modelDef ;
cycle = 1 ;
starttime = 0 ;
endtime = 0 ;
timeOffset = 0 ;
rate = 1.0f ;
frame = 0 ;
allowMove = true ;
allowFrameCommands = true ;
animNum = 0 ;
memset ( animWeights , 0 , sizeof ( animWeights ) ) ;
blendStartValue = 0.0f ;
blendEndValue = 0.0f ;
blendStartTime = 0 ;
blendDuration = 0 ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : FullName
= = = = = = = = = = = = = = = = = = = = =
*/
const char * idAnimBlend : : AnimFullName ( void ) const {
const idAnim * anim = Anim ( ) ;
if ( ! anim ) {
return " " ;
}
return anim - > FullName ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : AnimName
= = = = = = = = = = = = = = = = = = = = =
*/
const char * idAnimBlend : : AnimName ( void ) const {
const idAnim * anim = Anim ( ) ;
if ( ! anim ) {
return " " ;
}
return anim - > Name ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : NumFrames
= = = = = = = = = = = = = = = = = = = = =
*/
int idAnimBlend : : NumFrames ( void ) const {
const idAnim * anim = Anim ( ) ;
if ( ! anim ) {
return 0 ;
}
return anim - > NumFrames ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : Length
= = = = = = = = = = = = = = = = = = = = =
*/
int idAnimBlend : : Length ( void ) const {
const idAnim * anim = Anim ( ) ;
if ( ! anim ) {
return 0 ;
}
return anim - > Length ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : GetWeight
= = = = = = = = = = = = = = = = = = = = =
*/
float idAnimBlend : : GetWeight ( int currentTime ) const {
int timeDelta ;
float frac ;
float w ;
timeDelta = currentTime - blendStartTime ;
if ( timeDelta < = 0 ) {
w = blendStartValue ;
} else if ( timeDelta > = blendDuration ) {
w = blendEndValue ;
} else {
frac = ( float ) timeDelta / ( float ) blendDuration ;
w = blendStartValue + ( blendEndValue - blendStartValue ) * frac ;
}
return w ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : GetFinalWeight
= = = = = = = = = = = = = = = = = = = = =
*/
float idAnimBlend : : GetFinalWeight ( void ) const {
return blendEndValue ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : SetWeight
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimBlend : : SetWeight ( float newweight , int currentTime , int blendTime ) {
blendStartValue = GetWeight ( currentTime ) ;
blendEndValue = newweight ;
blendStartTime = currentTime - 1 ;
blendDuration = blendTime ;
if ( ! newweight ) {
endtime = currentTime + blendTime ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : NumSyncedAnims
= = = = = = = = = = = = = = = = = = = = =
*/
int idAnimBlend : : NumSyncedAnims ( void ) const {
const idAnim * anim = Anim ( ) ;
if ( ! anim ) {
return 0 ;
}
return anim - > NumAnims ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : SetSyncedAnimWeight
= = = = = = = = = = = = = = = = = = = = =
*/
bool idAnimBlend : : SetSyncedAnimWeight ( int num , float weight ) {
const idAnim * anim = Anim ( ) ;
if ( ! anim ) {
return false ;
}
if ( ( num < 0 ) | | ( num > anim - > NumAnims ( ) ) ) {
return false ;
}
animWeights [ num ] = weight ;
return true ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : SetFrame
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimBlend : : SetFrame ( const idDeclModelDef * modelDef , int _animNum , int _frame , int currentTime , int blendTime ) {
Reset ( modelDef ) ;
if ( ! modelDef ) {
return ;
}
const idAnim * _anim = modelDef - > GetAnim ( _animNum ) ;
if ( ! _anim ) {
return ;
}
const idMD5Anim * md5anim = _anim - > MD5Anim ( 0 ) ;
if ( modelDef - > Joints ( ) . Num ( ) ! = md5anim - > NumJoints ( ) ) {
gameLocal . Warning ( " Model '%s' has different # of joints than anim '%s' " , modelDef - > GetModelName ( ) , md5anim - > Name ( ) ) ;
return ;
}
animNum = _animNum ;
starttime = currentTime ;
endtime = - 1 ;
cycle = - 1 ;
animWeights [ 0 ] = 1.0f ;
frame = _frame ;
// a frame of 0 means it's not a single frame blend, so we set it to frame + 1
if ( frame < = 0 ) {
frame = 1 ;
} else if ( frame > _anim - > NumFrames ( ) ) {
frame = _anim - > NumFrames ( ) ;
}
// set up blend
blendEndValue = 1.0f ;
blendStartTime = currentTime - 1 ;
blendDuration = blendTime ;
blendStartValue = 0.0f ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : CycleAnim
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimBlend : : CycleAnim ( const idDeclModelDef * modelDef , int _animNum , int currentTime , int blendTime ) {
Reset ( modelDef ) ;
if ( ! modelDef ) {
return ;
}
const idAnim * _anim = modelDef - > GetAnim ( _animNum ) ;
if ( ! _anim ) {
return ;
}
const idMD5Anim * md5anim = _anim - > MD5Anim ( 0 ) ;
if ( modelDef - > Joints ( ) . Num ( ) ! = md5anim - > NumJoints ( ) ) {
gameLocal . Warning ( " Model '%s' has different # of joints than anim '%s' " , modelDef - > GetModelName ( ) , md5anim - > Name ( ) ) ;
return ;
}
animNum = _animNum ;
animWeights [ 0 ] = 1.0f ;
endtime = - 1 ;
cycle = - 1 ;
if ( _anim - > GetAnimFlags ( ) . random_cycle_start ) {
// start the animation at a random time so that characters don't walk in sync
starttime = currentTime - gameLocal . random . RandomFloat ( ) * _anim - > Length ( ) ;
} else {
starttime = currentTime ;
}
// set up blend
blendEndValue = 1.0f ;
blendStartTime = currentTime - 1 ;
blendDuration = blendTime ;
blendStartValue = 0.0f ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : PlayAnim
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimBlend : : PlayAnim ( const idDeclModelDef * modelDef , int _animNum , int currentTime , int blendTime ) {
Reset ( modelDef ) ;
if ( ! modelDef ) {
return ;
}
const idAnim * _anim = modelDef - > GetAnim ( _animNum ) ;
if ( ! _anim ) {
return ;
}
const idMD5Anim * md5anim = _anim - > MD5Anim ( 0 ) ;
if ( modelDef - > Joints ( ) . Num ( ) ! = md5anim - > NumJoints ( ) ) {
gameLocal . Warning ( " Model '%s' has different # of joints than anim '%s' " , modelDef - > GetModelName ( ) , md5anim - > Name ( ) ) ;
return ;
}
animNum = _animNum ;
starttime = currentTime ;
endtime = starttime + _anim - > Length ( ) ;
cycle = 1 ;
animWeights [ 0 ] = 1.0f ;
// set up blend
blendEndValue = 1.0f ;
blendStartTime = currentTime - 1 ;
blendDuration = blendTime ;
blendStartValue = 0.0f ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : Clear
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimBlend : : Clear ( int currentTime , int clearTime ) {
if ( ! clearTime ) {
Reset ( modelDef ) ;
} else {
SetWeight ( 0.0f , currentTime , clearTime ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : IsDone
= = = = = = = = = = = = = = = = = = = = =
*/
bool idAnimBlend : : IsDone ( int currentTime ) const {
if ( ! frame & & ( endtime > 0 ) & & ( currentTime > = endtime ) ) {
return true ;
}
if ( ( blendEndValue < = 0.0f ) & & ( currentTime > = ( blendStartTime + blendDuration ) ) ) {
return true ;
}
return false ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : FrameHasChanged
= = = = = = = = = = = = = = = = = = = = =
*/
bool idAnimBlend : : FrameHasChanged ( int currentTime ) const {
// if we don't have an anim, no change
if ( ! animNum ) {
return false ;
}
// if anim is done playing, no change
if ( ( endtime > 0 ) & & ( currentTime > endtime ) ) {
return false ;
}
// if our blend weight changes, we need to update
if ( ( currentTime < ( blendStartTime + blendDuration ) & & ( blendStartValue ! = blendEndValue ) ) ) {
return true ;
}
// if we're a single frame anim and this isn't the frame we started on, we don't need to update
if ( ( frame | | ( NumFrames ( ) = = 1 ) ) & & ( currentTime ! = starttime ) ) {
return false ;
}
return true ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : GetCycleCount
= = = = = = = = = = = = = = = = = = = = =
*/
int idAnimBlend : : GetCycleCount ( void ) const {
return cycle ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : SetCycleCount
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimBlend : : SetCycleCount ( int count ) {
const idAnim * anim = Anim ( ) ;
if ( ! anim ) {
cycle = - 1 ;
endtime = 0 ;
} else {
cycle = count ;
if ( cycle < 0 ) {
cycle = - 1 ;
endtime = - 1 ;
} else if ( cycle = = 0 ) {
cycle = 1 ;
// most of the time we're running at the original frame rate, so avoid the int-to-float-to-int conversion
if ( rate = = 1.0f ) {
endtime = starttime - timeOffset + anim - > Length ( ) ;
} else if ( rate ! = 0.0f ) {
endtime = starttime - timeOffset + anim - > Length ( ) / rate ;
} else {
endtime = - 1 ;
}
} else {
// most of the time we're running at the original frame rate, so avoid the int-to-float-to-int conversion
if ( rate = = 1.0f ) {
endtime = starttime - timeOffset + anim - > Length ( ) * cycle ;
} else if ( rate ! = 0.0f ) {
endtime = starttime - timeOffset + ( anim - > Length ( ) * cycle ) / rate ;
} else {
endtime = - 1 ;
}
}
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : SetPlaybackRate
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimBlend : : SetPlaybackRate ( int currentTime , float newRate ) {
int animTime ;
if ( rate = = newRate ) {
return ;
}
animTime = AnimTime ( currentTime ) ;
if ( newRate = = 1.0f ) {
timeOffset = animTime - ( currentTime - starttime ) ;
} else {
timeOffset = animTime - ( currentTime - starttime ) * newRate ;
}
rate = newRate ;
// update the anim endtime
SetCycleCount ( cycle ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : GetPlaybackRate
= = = = = = = = = = = = = = = = = = = = =
*/
float idAnimBlend : : GetPlaybackRate ( void ) const {
return rate ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : SetStartTime
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimBlend : : SetStartTime ( int _startTime ) {
starttime = _startTime ;
// update the anim endtime
SetCycleCount ( cycle ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : GetStartTime
= = = = = = = = = = = = = = = = = = = = =
*/
int idAnimBlend : : GetStartTime ( void ) const {
if ( ! animNum ) {
return 0 ;
}
return starttime ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : GetEndTime
= = = = = = = = = = = = = = = = = = = = =
*/
int idAnimBlend : : GetEndTime ( void ) const {
if ( ! animNum ) {
return 0 ;
}
return endtime ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : PlayLength
= = = = = = = = = = = = = = = = = = = = =
*/
int idAnimBlend : : PlayLength ( void ) const {
if ( ! animNum ) {
return 0 ;
}
if ( endtime < 0 ) {
return - 1 ;
}
return endtime - starttime + timeOffset ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : AllowMovement
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimBlend : : AllowMovement ( bool allow ) {
allowMove = allow ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : AllowFrameCommands
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimBlend : : AllowFrameCommands ( bool allow ) {
allowFrameCommands = allow ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : Anim
= = = = = = = = = = = = = = = = = = = = =
*/
const idAnim * idAnimBlend : : Anim ( void ) const {
if ( ! modelDef ) {
return NULL ;
}
const idAnim * anim = modelDef - > GetAnim ( animNum ) ;
return anim ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : AnimNum
= = = = = = = = = = = = = = = = = = = = =
*/
int idAnimBlend : : AnimNum ( void ) const {
return animNum ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : AnimTime
= = = = = = = = = = = = = = = = = = = = =
*/
int idAnimBlend : : AnimTime ( int currentTime ) const {
int time ;
int length ;
const idAnim * anim = Anim ( ) ;
if ( anim ) {
if ( frame ) {
return FRAME2MS ( frame - 1 ) ;
}
// most of the time we're running at the original frame rate, so avoid the int-to-float-to-int conversion
if ( rate = = 1.0f ) {
time = currentTime - starttime + timeOffset ;
} else {
time = static_cast < int > ( ( currentTime - starttime ) * rate ) + timeOffset ;
}
// given enough time, we can easily wrap time around in our frame calculations, so
// keep cycling animations' time within the length of the anim.
length = anim - > Length ( ) ;
if ( ( cycle < 0 ) & & ( length > 0 ) ) {
time % = length ;
// time will wrap after 24 days (oh no!), resulting in negative results for the %.
// adding the length gives us the proper result.
if ( time < 0 ) {
time + = length ;
}
}
return time ;
} else {
return 0 ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : GetFrameNumber
= = = = = = = = = = = = = = = = = = = = =
*/
int idAnimBlend : : GetFrameNumber ( int currentTime ) const {
const idMD5Anim * md5anim ;
frameBlend_t frameinfo ;
int animTime ;
const idAnim * anim = Anim ( ) ;
if ( ! anim ) {
return 1 ;
}
if ( frame ) {
return frame ;
}
md5anim = anim - > MD5Anim ( 0 ) ;
animTime = AnimTime ( currentTime ) ;
md5anim - > ConvertTimeToFrame ( animTime , cycle , frameinfo ) ;
return frameinfo . frame1 + 1 ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : CallFrameCommands
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimBlend : : CallFrameCommands ( idEntity * ent , int fromtime , int totime ) const {
const idMD5Anim * md5anim ;
frameBlend_t frame1 ;
frameBlend_t frame2 ;
int fromFrameTime ;
int toFrameTime ;
if ( ! allowFrameCommands | | ! ent | | frame | | ( ( endtime > 0 ) & & ( fromtime > endtime ) ) ) {
return ;
}
const idAnim * anim = Anim ( ) ;
if ( ! anim | | ! anim - > HasFrameCommands ( ) ) {
return ;
}
if ( totime < = starttime ) {
// don't play until next frame or we'll play commands twice.
// this happens on the player sometimes.
return ;
}
fromFrameTime = AnimTime ( fromtime ) ;
toFrameTime = AnimTime ( totime ) ;
if ( toFrameTime < fromFrameTime ) {
toFrameTime + = anim - > Length ( ) ;
}
md5anim = anim - > MD5Anim ( 0 ) ;
md5anim - > ConvertTimeToFrame ( fromFrameTime , cycle , frame1 ) ;
md5anim - > ConvertTimeToFrame ( toFrameTime , cycle , frame2 ) ;
if ( fromFrameTime < = 0 ) {
// make sure first frame is called
anim - > CallFrameCommands ( ent , - 1 , frame2 . frame1 ) ;
} else {
anim - > CallFrameCommands ( ent , frame1 . frame1 , frame2 . frame1 ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : BlendAnim
= = = = = = = = = = = = = = = = = = = = =
*/
bool idAnimBlend : : BlendAnim ( int currentTime , int channel , int numJoints , idJointQuat * blendFrame , float & blendWeight , bool removeOriginOffset , bool overrideBlend , bool printInfo ) const {
int i ;
float lerp ;
float mixWeight ;
const idMD5Anim * md5anim ;
idJointQuat * ptr ;
frameBlend_t frametime ;
idJointQuat * jointFrame ;
idJointQuat * mixFrame ;
int numAnims ;
int time ;
const idAnim * anim = Anim ( ) ;
if ( ! anim ) {
return false ;
}
float weight = GetWeight ( currentTime ) ;
if ( blendWeight > 0.0f ) {
if ( ( endtime > = 0 ) & & ( currentTime > = endtime ) ) {
return false ;
}
if ( ! weight ) {
return false ;
}
if ( overrideBlend ) {
blendWeight = 1.0f - weight ;
}
}
if ( ( channel = = ANIMCHANNEL_ALL ) & & ! blendWeight ) {
// we don't need a temporary buffer, so just store it directly in the blend frame
jointFrame = blendFrame ;
} else {
// allocate a temporary buffer to copy the joints from
jointFrame = ( idJointQuat * ) _alloca16 ( numJoints * sizeof ( * jointFrame ) ) ;
}
time = AnimTime ( currentTime ) ;
numAnims = anim - > NumAnims ( ) ;
if ( numAnims = = 1 ) {
md5anim = anim - > MD5Anim ( 0 ) ;
if ( frame ) {
md5anim - > GetSingleFrame ( frame - 1 , jointFrame , modelDef - > GetChannelJoints ( channel ) , modelDef - > NumJointsOnChannel ( channel ) ) ;
} else {
md5anim - > ConvertTimeToFrame ( time , cycle , frametime ) ;
md5anim - > GetInterpolatedFrame ( frametime , jointFrame , modelDef - > GetChannelJoints ( channel ) , modelDef - > NumJointsOnChannel ( channel ) ) ;
}
} else {
//
// need to mix the multipoint anim together first
//
// allocate a temporary buffer to copy the joints to
mixFrame = ( idJointQuat * ) _alloca16 ( numJoints * sizeof ( * jointFrame ) ) ;
if ( ! frame ) {
anim - > MD5Anim ( 0 ) - > ConvertTimeToFrame ( time , cycle , frametime ) ;
}
ptr = jointFrame ;
mixWeight = 0.0f ;
for ( i = 0 ; i < numAnims ; i + + ) {
if ( animWeights [ i ] > 0.0f ) {
mixWeight + = animWeights [ i ] ;
lerp = animWeights [ i ] / mixWeight ;
md5anim = anim - > MD5Anim ( i ) ;
if ( frame ) {
md5anim - > GetSingleFrame ( frame - 1 , ptr , modelDef - > GetChannelJoints ( channel ) , modelDef - > NumJointsOnChannel ( channel ) ) ;
} else {
md5anim - > GetInterpolatedFrame ( frametime , ptr , modelDef - > GetChannelJoints ( channel ) , modelDef - > NumJointsOnChannel ( channel ) ) ;
}
// only blend after the first anim is mixed in
if ( ptr ! = jointFrame ) {
SIMDProcessor - > BlendJoints ( jointFrame , ptr , lerp , modelDef - > GetChannelJoints ( channel ) , modelDef - > NumJointsOnChannel ( channel ) ) ;
}
ptr = mixFrame ;
}
}
if ( ! mixWeight ) {
return false ;
}
}
if ( removeOriginOffset ) {
if ( allowMove ) {
# ifdef VELOCITY_MOVE
jointFrame [ 0 ] . t . x = 0.0f ;
# else
jointFrame [ 0 ] . t . Zero ( ) ;
# endif
}
if ( anim - > GetAnimFlags ( ) . anim_turn ) {
jointFrame [ 0 ] . q . Set ( - 0.70710677f , 0.0f , 0.0f , 0.70710677f ) ;
}
}
if ( ! blendWeight ) {
blendWeight = weight ;
if ( channel ! = ANIMCHANNEL_ALL ) {
const int * index = modelDef - > GetChannelJoints ( channel ) ;
const int num = modelDef - > NumJointsOnChannel ( channel ) ;
for ( i = 0 ; i < num ; i + + ) {
int j = index [ i ] ;
blendFrame [ j ] . t = jointFrame [ j ] . t ;
blendFrame [ j ] . q = jointFrame [ j ] . q ;
}
}
} else {
blendWeight + = weight ;
lerp = weight / blendWeight ;
SIMDProcessor - > BlendJoints ( blendFrame , jointFrame , lerp , modelDef - > GetChannelJoints ( channel ) , modelDef - > NumJointsOnChannel ( channel ) ) ;
}
if ( printInfo ) {
if ( frame ) {
gameLocal . Printf ( " %s: '%s', %d, %.2f%% \n " , channelNames [ channel ] , anim - > FullName ( ) , frame , weight * 100.0f ) ;
} else {
gameLocal . Printf ( " %s: '%s', %.3f, %.2f%% \n " , channelNames [ channel ] , anim - > FullName ( ) , ( float ) frametime . frame1 + frametime . backlerp , weight * 100.0f ) ;
}
}
return true ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : BlendOrigin
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimBlend : : BlendOrigin ( int currentTime , idVec3 & blendPos , float & blendWeight , bool removeOriginOffset ) const {
float lerp ;
idVec3 animpos ;
idVec3 pos ;
int time ;
int num ;
int i ;
if ( frame | | ( ( endtime > 0 ) & & ( currentTime > endtime ) ) ) {
return ;
}
const idAnim * anim = Anim ( ) ;
if ( ! anim ) {
return ;
}
if ( allowMove & & removeOriginOffset ) {
return ;
}
float weight = GetWeight ( currentTime ) ;
if ( ! weight ) {
return ;
}
time = AnimTime ( currentTime ) ;
pos . Zero ( ) ;
num = anim - > NumAnims ( ) ;
for ( i = 0 ; i < num ; i + + ) {
anim - > GetOrigin ( animpos , i , time , cycle ) ;
pos + = animpos * animWeights [ i ] ;
}
if ( ! blendWeight ) {
blendPos = pos ;
blendWeight = weight ;
} else {
lerp = weight / ( blendWeight + weight ) ;
blendPos + = lerp * ( pos - blendPos ) ;
blendWeight + = weight ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : BlendDelta
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimBlend : : BlendDelta ( int fromtime , int totime , idVec3 & blendDelta , float & blendWeight ) const {
idVec3 pos1 ;
idVec3 pos2 ;
idVec3 animpos ;
idVec3 delta ;
int time1 ;
int time2 ;
float lerp ;
int num ;
int i ;
if ( frame | | ! allowMove | | ( ( endtime > 0 ) & & ( fromtime > endtime ) ) ) {
return ;
}
const idAnim * anim = Anim ( ) ;
if ( ! anim ) {
return ;
}
float weight = GetWeight ( totime ) ;
if ( ! weight ) {
return ;
}
time1 = AnimTime ( fromtime ) ;
time2 = AnimTime ( totime ) ;
if ( time2 < time1 ) {
time2 + = anim - > Length ( ) ;
}
num = anim - > NumAnims ( ) ;
pos1 . Zero ( ) ;
pos2 . Zero ( ) ;
for ( i = 0 ; i < num ; i + + ) {
anim - > GetOrigin ( animpos , i , time1 , cycle ) ;
pos1 + = animpos * animWeights [ i ] ;
anim - > GetOrigin ( animpos , i , time2 , cycle ) ;
pos2 + = animpos * animWeights [ i ] ;
}
delta = pos2 - pos1 ;
if ( ! blendWeight ) {
blendDelta = delta ;
blendWeight = weight ;
} else {
lerp = weight / ( blendWeight + weight ) ;
blendDelta + = lerp * ( delta - blendDelta ) ;
blendWeight + = weight ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : BlendDeltaRotation
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimBlend : : BlendDeltaRotation ( int fromtime , int totime , idQuat & blendDelta , float & blendWeight ) const {
idQuat q1 ;
idQuat q2 ;
idQuat q3 ;
int time1 ;
int time2 ;
float lerp ;
float mixWeight ;
int num ;
int i ;
if ( frame | | ! allowMove | | ( ( endtime > 0 ) & & ( fromtime > endtime ) ) ) {
return ;
}
const idAnim * anim = Anim ( ) ;
if ( ! anim | | ! anim - > GetAnimFlags ( ) . anim_turn ) {
return ;
}
float weight = GetWeight ( totime ) ;
if ( ! weight ) {
return ;
}
time1 = AnimTime ( fromtime ) ;
time2 = AnimTime ( totime ) ;
if ( time2 < time1 ) {
time2 + = anim - > Length ( ) ;
}
q1 . Set ( 0.0f , 0.0f , 0.0f , 1.0f ) ;
q2 . Set ( 0.0f , 0.0f , 0.0f , 1.0f ) ;
mixWeight = 0.0f ;
num = anim - > NumAnims ( ) ;
for ( i = 0 ; i < num ; i + + ) {
if ( animWeights [ i ] > 0.0f ) {
mixWeight + = animWeights [ i ] ;
if ( animWeights [ i ] = = mixWeight ) {
anim - > GetOriginRotation ( q1 , i , time1 , cycle ) ;
anim - > GetOriginRotation ( q2 , i , time2 , cycle ) ;
} else {
lerp = animWeights [ i ] / mixWeight ;
anim - > GetOriginRotation ( q3 , i , time1 , cycle ) ;
q1 . Slerp ( q1 , q3 , lerp ) ;
anim - > GetOriginRotation ( q3 , i , time2 , cycle ) ;
q2 . Slerp ( q1 , q3 , lerp ) ;
}
}
}
q3 = q1 . Inverse ( ) * q2 ;
if ( ! blendWeight ) {
blendDelta = q3 ;
blendWeight = weight ;
} else {
lerp = weight / ( blendWeight + weight ) ;
blendDelta . Slerp ( blendDelta , q3 , lerp ) ;
blendWeight + = weight ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimBlend : : AddBounds
= = = = = = = = = = = = = = = = = = = = =
*/
bool idAnimBlend : : AddBounds ( int currentTime , idBounds & bounds , bool removeOriginOffset ) const {
int i ;
int num ;
idBounds b ;
int time ;
idVec3 pos ;
bool addorigin ;
if ( ( endtime > 0 ) & & ( currentTime > endtime ) ) {
return false ;
}
const idAnim * anim = Anim ( ) ;
if ( ! anim ) {
return false ;
}
float weight = GetWeight ( currentTime ) ;
if ( ! weight ) {
return false ;
}
time = AnimTime ( currentTime ) ;
num = anim - > NumAnims ( ) ;
addorigin = ! allowMove | | ! removeOriginOffset ;
for ( i = 0 ; i < num ; i + + ) {
if ( anim - > GetBounds ( b , i , time , cycle ) ) {
if ( addorigin ) {
anim - > GetOrigin ( pos , i , time , cycle ) ;
b . TranslateSelf ( pos ) ;
}
bounds . AddBounds ( b ) ;
}
}
return true ;
}
/***********************************************************************
idDeclModelDef
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
= = = = = = = = = = = = = = = = = = = = =
idDeclModelDef : : idDeclModelDef
= = = = = = = = = = = = = = = = = = = = =
*/
idDeclModelDef : : idDeclModelDef ( ) {
modelHandle = NULL ;
skin = NULL ;
offset . Zero ( ) ;
for ( int i = 0 ; i < ANIM_NumAnimChannels ; i + + ) {
channelJoints [ i ] . Clear ( ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idDeclModelDef : : ~ idDeclModelDef
= = = = = = = = = = = = = = = = = = = = =
*/
idDeclModelDef : : ~ idDeclModelDef ( ) {
FreeData ( ) ;
}
/*
= = = = = = = = = = = = = = = = =
idDeclModelDef : : Size
= = = = = = = = = = = = = = = = =
*/
size_t idDeclModelDef : : Size ( void ) const {
return sizeof ( idDeclModelDef ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idDeclModelDef : : CopyDecl
= = = = = = = = = = = = = = = = = = = = =
*/
void idDeclModelDef : : CopyDecl ( const idDeclModelDef * decl ) {
int i ;
FreeData ( ) ;
offset = decl - > offset ;
modelHandle = decl - > modelHandle ;
skin = decl - > skin ;
anims . SetNum ( decl - > anims . Num ( ) ) ;
for ( i = 0 ; i < anims . Num ( ) ; i + + ) {
anims [ i ] = new idAnim ( this , decl - > anims [ i ] ) ;
}
joints . SetNum ( decl - > joints . Num ( ) ) ;
memcpy ( joints . Ptr ( ) , decl - > joints . Ptr ( ) , decl - > joints . Num ( ) * sizeof ( joints [ 0 ] ) ) ;
jointParents . SetNum ( decl - > jointParents . Num ( ) ) ;
memcpy ( jointParents . Ptr ( ) , decl - > jointParents . Ptr ( ) , decl - > jointParents . Num ( ) * sizeof ( jointParents [ 0 ] ) ) ;
for ( i = 0 ; i < ANIM_NumAnimChannels ; i + + ) {
channelJoints [ i ] = decl - > channelJoints [ i ] ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idDeclModelDef : : FreeData
= = = = = = = = = = = = = = = = = = = = =
*/
void idDeclModelDef : : FreeData ( void ) {
anims . DeleteContents ( true ) ;
joints . Clear ( ) ;
jointParents . Clear ( ) ;
modelHandle = NULL ;
skin = NULL ;
offset . Zero ( ) ;
for ( int i = 0 ; i < ANIM_NumAnimChannels ; i + + ) {
channelJoints [ i ] . Clear ( ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idDeclModelDef : : DefaultDefinition
= = = = = = = = = = = = = = = =
*/
const char * idDeclModelDef : : DefaultDefinition ( void ) const {
return " { } " ;
}
/*
= = = = = = = = = = = = = = = = = = = =
idDeclModelDef : : FindJoint
= = = = = = = = = = = = = = = = = = = =
*/
const jointInfo_t * idDeclModelDef : : FindJoint ( const char * name ) const {
int i ;
const idMD5Joint * joint ;
if ( ! modelHandle ) {
return NULL ;
}
joint = modelHandle - > GetJoints ( ) ;
for ( i = 0 ; i < joints . Num ( ) ; i + + , joint + + ) {
if ( ! joint - > name . Icmp ( name ) ) {
return & joints [ i ] ;
}
}
return NULL ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idDeclModelDef : : ModelHandle
= = = = = = = = = = = = = = = = = = = = =
*/
idRenderModel * idDeclModelDef : : ModelHandle ( void ) const {
return ( idRenderModel * ) modelHandle ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idDeclModelDef : : GetJointList
= = = = = = = = = = = = = = = = = = = = =
*/
void idDeclModelDef : : GetJointList ( const char * jointnames , idList < jointHandle_t > & jointList ) const {
const char * pos ;
idStr jointname ;
const jointInfo_t * joint ;
const jointInfo_t * child ;
int i ;
int num ;
bool getChildren ;
bool subtract ;
if ( ! modelHandle ) {
return ;
}
jointList . Clear ( ) ;
num = modelHandle - > NumJoints ( ) ;
// scan through list of joints and add each to the joint list
pos = jointnames ;
while ( * pos ) {
// skip over whitespace
while ( ( * pos ! = 0 ) & & isspace ( * pos ) ) {
pos + + ;
}
if ( ! * pos ) {
// no more names
break ;
}
// copy joint name
jointname = " " ;
if ( * pos = = ' - ' ) {
subtract = true ;
pos + + ;
} else {
subtract = false ;
}
if ( * pos = = ' * ' ) {
getChildren = true ;
pos + + ;
} else {
getChildren = false ;
}
while ( ( * pos ! = 0 ) & & ! isspace ( * pos ) ) {
jointname + = * pos ;
pos + + ;
}
joint = FindJoint ( jointname ) ;
if ( ! joint ) {
gameLocal . Warning ( " Unknown joint '%s' in '%s' for model '%s' " , jointname . c_str ( ) , jointnames , GetName ( ) ) ;
continue ;
}
if ( ! subtract ) {
jointList . AddUnique ( joint - > num ) ;
} else {
jointList . Remove ( joint - > num ) ;
}
if ( getChildren ) {
// include all joint's children
child = joint + 1 ;
for ( i = joint - > num + 1 ; i < num ; i + + , child + + ) {
// all children of the joint should follow it in the list.
// once we reach a joint without a parent or with a parent
// who is earlier in the list than the specified joint, then
// we've gone through all it's children.
if ( child - > parentNum < joint - > num ) {
break ;
}
if ( ! subtract ) {
jointList . AddUnique ( child - > num ) ;
} else {
jointList . Remove ( child - > num ) ;
}
}
}
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idDeclModelDef : : Touch
= = = = = = = = = = = = = = = = = = = = =
*/
void idDeclModelDef : : Touch ( void ) const {
if ( modelHandle ) {
renderModelManager - > FindModel ( modelHandle - > Name ( ) ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idDeclModelDef : : GetDefaultSkin
= = = = = = = = = = = = = = = = = = = = =
*/
const idDeclSkin * idDeclModelDef : : GetDefaultSkin ( void ) const {
return skin ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idDeclModelDef : : GetDefaultPose
= = = = = = = = = = = = = = = = = = = = =
*/
const idJointQuat * idDeclModelDef : : GetDefaultPose ( void ) const {
return modelHandle - > GetDefaultPose ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idDeclModelDef : : SetupJoints
= = = = = = = = = = = = = = = = = = = = =
*/
void idDeclModelDef : : SetupJoints ( int * numJoints , idJointMat * * jointList , idBounds & frameBounds , bool removeOriginOffset ) const {
int num ;
const idJointQuat * pose ;
idJointMat * list ;
if ( ! modelHandle | | modelHandle - > IsDefaultModel ( ) ) {
Mem_Free16 ( ( * jointList ) ) ;
( * jointList ) = NULL ;
frameBounds . Clear ( ) ;
return ;
}
// get the number of joints
num = modelHandle - > NumJoints ( ) ;
if ( ! num ) {
gameLocal . Error ( " model '%s' has no joints " , modelHandle - > Name ( ) ) ;
}
// set up initial pose for model (with no pose, model is just a jumbled mess)
list = ( idJointMat * ) Mem_Alloc16 ( num * sizeof ( list [ 0 ] ) ) ;
pose = GetDefaultPose ( ) ;
// convert the joint quaternions to joint matrices
SIMDProcessor - > ConvertJointQuatsToJointMats ( list , pose , joints . Num ( ) ) ;
// check if we offset the model by the origin joint
if ( removeOriginOffset ) {
# ifdef VELOCITY_MOVE
list [ 0 ] . SetTranslation ( idVec3 ( offset . x , offset . y + pose [ 0 ] . t . y , offset . z + pose [ 0 ] . t . z ) ) ;
# else
list [ 0 ] . SetTranslation ( offset ) ;
# endif
} else {
list [ 0 ] . SetTranslation ( pose [ 0 ] . t + offset ) ;
}
// transform the joint hierarchy
SIMDProcessor - > TransformJoints ( list , jointParents . Ptr ( ) , 1 , joints . Num ( ) - 1 ) ;
* numJoints = num ;
* jointList = list ;
// get the bounds of the default pose
frameBounds = modelHandle - > Bounds ( NULL ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idDeclModelDef : : ParseAnim
= = = = = = = = = = = = = = = = = = = = =
*/
bool idDeclModelDef : : ParseAnim ( idLexer & src , int numDefaultAnims ) {
int i ;
int len ;
idAnim * anim ;
const idMD5Anim * md5anims [ ANIM_MaxSyncedAnims ] ;
const idMD5Anim * md5anim ;
idStr alias ;
idToken realname ;
idToken token ;
int numAnims ;
animFlags_t flags ;
numAnims = 0 ;
memset ( md5anims , 0 , sizeof ( md5anims ) ) ;
if ( ! src . ReadToken ( & realname ) ) {
src . Warning ( " Unexpected end of file " ) ;
MakeDefault ( ) ;
return false ;
}
alias = realname ;
for ( i = 0 ; i < anims . Num ( ) ; i + + ) {
if ( ! strcmp ( anims [ i ] - > FullName ( ) , realname ) ) {
break ;
}
}
if ( ( i < anims . Num ( ) ) & & ( i > = numDefaultAnims ) ) {
src . Warning ( " Duplicate anim '%s' " , realname . c_str ( ) ) ;
MakeDefault ( ) ;
return false ;
}
if ( i < numDefaultAnims ) {
anim = anims [ i ] ;
} else {
// create the alias associated with this animation
anim = new idAnim ( ) ;
anims . Append ( anim ) ;
}
// random anims end with a number. find the numeric suffix of the animation.
len = alias . Length ( ) ;
for ( i = len - 1 ; i > 0 ; i - - ) {
if ( ! isdigit ( alias [ i ] ) ) {
break ;
}
}
// check for zero length name, or a purely numeric name
if ( i < = 0 ) {
src . Warning ( " Invalid animation name '%s' " , alias . c_str ( ) ) ;
MakeDefault ( ) ;
return false ;
}
// remove the numeric suffix
alias . CapLength ( i + 1 ) ;
// parse the anims from the string
do {
if ( ! src . ReadToken ( & token ) ) {
src . Warning ( " Unexpected end of file " ) ;
MakeDefault ( ) ;
return false ;
}
// lookup the animation
md5anim = animationLib . GetAnim ( token ) ;
if ( ! md5anim ) {
src . Warning ( " Couldn't load anim '%s' " , token . c_str ( ) ) ;
MakeDefault ( ) ;
return false ;
}
md5anim - > CheckModelHierarchy ( modelHandle ) ;
if ( numAnims > 0 ) {
// make sure it's the same length as the other anims
if ( md5anim - > Length ( ) ! = md5anims [ 0 ] - > Length ( ) ) {
src . Warning ( " Anim '%s' does not match length of anim '%s' " , md5anim - > Name ( ) , md5anims [ 0 ] - > Name ( ) ) ;
MakeDefault ( ) ;
return false ;
}
}
if ( numAnims > = ANIM_MaxSyncedAnims ) {
src . Warning ( " Exceeded max synced anims (%d) " , ANIM_MaxSyncedAnims ) ;
MakeDefault ( ) ;
return false ;
}
// add it to our list
md5anims [ numAnims ] = md5anim ;
numAnims + + ;
} while ( src . CheckTokenString ( " , " ) ) ;
if ( ! numAnims ) {
src . Warning ( " No animation specified " ) ;
MakeDefault ( ) ;
return false ;
}
anim - > SetAnim ( this , realname , alias , numAnims , md5anims ) ;
memset ( & flags , 0 , sizeof ( flags ) ) ;
// parse any frame commands or animflags
if ( src . CheckTokenString ( " { " ) ) {
while ( 1 ) {
if ( ! src . ReadToken ( & token ) ) {
src . Warning ( " Unexpected end of file " ) ;
MakeDefault ( ) ;
return false ;
}
if ( token = = " } " ) {
break ;
} else if ( token = = " prevent_idle_override " ) {
flags . prevent_idle_override = true ;
} else if ( token = = " random_cycle_start " ) {
flags . random_cycle_start = true ;
} else if ( token = = " ai_no_turn " ) {
flags . ai_no_turn = true ;
} else if ( token = = " anim_turn " ) {
flags . anim_turn = true ;
} else if ( token = = " frame " ) {
// create a frame command
int framenum ;
const char * err ;
// make sure we don't have any line breaks while reading the frame command so the error line # will be correct
if ( ! src . ReadTokenOnLine ( & token ) ) {
src . Warning ( " Missing frame # after 'frame' " ) ;
MakeDefault ( ) ;
return false ;
}
if ( token . type = = TT_PUNCTUATION & & token = = " - " ) {
src . Warning ( " Invalid frame # after 'frame' " ) ;
MakeDefault ( ) ;
return false ;
} else if ( token . type ! = TT_NUMBER | | token . subtype = = TT_FLOAT ) {
src . Error ( " expected integer value, found '%s' " , token . c_str ( ) ) ;
}
// get the frame number
framenum = token . GetIntValue ( ) ;
// put the command on the specified frame of the animation
err = anim - > AddFrameCommand ( this , framenum , src , NULL ) ;
if ( err ) {
src . Warning ( " %s " , err ) ;
MakeDefault ( ) ;
return false ;
}
} else {
src . Warning ( " Unknown command '%s' " , token . c_str ( ) ) ;
MakeDefault ( ) ;
return false ;
}
}
}
// set the flags
anim - > SetAnimFlags ( flags ) ;
return true ;
}
/*
= = = = = = = = = = = = = = = =
idDeclModelDef : : Parse
= = = = = = = = = = = = = = = =
*/
bool idDeclModelDef : : Parse ( const char * text , const int textLength ) {
int i ;
int num ;
idStr filename ;
idStr extension ;
const idMD5Joint * md5joint ;
const idMD5Joint * md5joints ;
idLexer src ;
idToken token ;
idToken token2 ;
idStr jointnames ;
int channel ;
jointHandle_t jointnum ;
idList < jointHandle_t > jointList ;
int numDefaultAnims ;
src . LoadMemory ( text , textLength , GetFileName ( ) , GetLineNum ( ) ) ;
src . SetFlags ( DECL_LEXER_FLAGS ) ;
src . SkipUntilString ( " { " ) ;
numDefaultAnims = 0 ;
while ( 1 ) {
if ( ! src . ReadToken ( & token ) ) {
break ;
}
if ( ! token . Icmp ( " } " ) ) {
break ;
}
if ( token = = " inherit " ) {
if ( ! src . ReadToken ( & token2 ) ) {
src . Warning ( " Unexpected end of file " ) ;
MakeDefault ( ) ;
return false ;
}
const idDeclModelDef * copy = static_cast < const idDeclModelDef * > ( declManager - > FindType ( DECL_MODELDEF , token2 , false ) ) ;
if ( ! copy ) {
common - > Warning ( " Unknown model definition '%s' " , token2 . c_str ( ) ) ;
} else if ( copy - > GetState ( ) = = DS_DEFAULTED ) {
common - > Warning ( " inherited model definition '%s' defaulted " , token2 . c_str ( ) ) ;
MakeDefault ( ) ;
return false ;
} else {
CopyDecl ( copy ) ;
numDefaultAnims = anims . Num ( ) ;
}
} else if ( token = = " skin " ) {
if ( ! src . ReadToken ( & token2 ) ) {
src . Warning ( " Unexpected end of file " ) ;
MakeDefault ( ) ;
return false ;
}
skin = declManager - > FindSkin ( token2 ) ;
if ( ! skin ) {
src . Warning ( " Skin '%s' not found " , token2 . c_str ( ) ) ;
MakeDefault ( ) ;
return false ;
}
} else if ( token = = " mesh " ) {
if ( ! src . ReadToken ( & token2 ) ) {
src . Warning ( " Unexpected end of file " ) ;
MakeDefault ( ) ;
return false ;
}
filename = token2 ;
filename . ExtractFileExtension ( extension ) ;
if ( extension ! = MD5_MESH_EXT ) {
src . Warning ( " Invalid model for MD5 mesh " ) ;
MakeDefault ( ) ;
return false ;
}
modelHandle = renderModelManager - > FindModel ( filename ) ;
if ( ! modelHandle ) {
src . Warning ( " Model '%s' not found " , filename . c_str ( ) ) ;
MakeDefault ( ) ;
return false ;
}
if ( modelHandle - > IsDefaultModel ( ) ) {
src . Warning ( " Model '%s' defaulted " , filename . c_str ( ) ) ;
MakeDefault ( ) ;
return false ;
}
// get the number of joints
num = modelHandle - > NumJoints ( ) ;
if ( ! num ) {
src . Warning ( " Model '%s' has no joints " , filename . c_str ( ) ) ;
}
// set up the joint hierarchy
joints . SetGranularity ( 1 ) ;
joints . SetNum ( num ) ;
jointParents . SetNum ( num ) ;
channelJoints [ 0 ] . SetNum ( num ) ;
md5joints = modelHandle - > GetJoints ( ) ;
md5joint = md5joints ;
for ( i = 0 ; i < num ; i + + , md5joint + + ) {
joints [ i ] . channel = ANIMCHANNEL_ALL ;
joints [ i ] . num = static_cast < jointHandle_t > ( i ) ;
if ( md5joint - > parent ) {
joints [ i ] . parentNum = static_cast < jointHandle_t > ( md5joint - > parent - md5joints ) ;
} else {
joints [ i ] . parentNum = INVALID_JOINT ;
}
jointParents [ i ] = joints [ i ] . parentNum ;
channelJoints [ 0 ] [ i ] = i ;
}
} else if ( token = = " remove " ) {
// removes any anims whos name matches
if ( ! src . ReadToken ( & token2 ) ) {
src . Warning ( " Unexpected end of file " ) ;
MakeDefault ( ) ;
return false ;
}
num = 0 ;
for ( i = 0 ; i < anims . Num ( ) ; i + + ) {
if ( ( token2 = = anims [ i ] - > Name ( ) ) | | ( token2 = = anims [ i ] - > FullName ( ) ) ) {
delete anims [ i ] ;
anims . RemoveIndex ( i ) ;
if ( i > = numDefaultAnims ) {
src . Warning ( " Anim '%s' was not inherited. Anim should be removed from the model def. " , token2 . c_str ( ) ) ;
MakeDefault ( ) ;
return false ;
}
i - - ;
numDefaultAnims - - ;
num + + ;
continue ;
}
}
if ( ! num ) {
src . Warning ( " Couldn't find anim '%s' to remove " , token2 . c_str ( ) ) ;
MakeDefault ( ) ;
return false ;
}
} else if ( token = = " anim " ) {
if ( ! modelHandle ) {
src . Warning ( " Must specify mesh before defining anims " ) ;
MakeDefault ( ) ;
return false ;
}
if ( ! ParseAnim ( src , numDefaultAnims ) ) {
MakeDefault ( ) ;
return false ;
}
} else if ( token = = " offset " ) {
if ( ! src . Parse1DMatrix ( 3 , offset . ToFloatPtr ( ) ) ) {
src . Warning ( " Expected vector following 'offset' " ) ;
MakeDefault ( ) ;
return false ;
}
} else if ( token = = " channel " ) {
if ( ! modelHandle ) {
src . Warning ( " Must specify mesh before defining channels " ) ;
MakeDefault ( ) ;
return false ;
}
// set the channel for a group of joints
if ( ! src . ReadToken ( & token2 ) ) {
src . Warning ( " Unexpected end of file " ) ;
MakeDefault ( ) ;
return false ;
}
if ( ! src . CheckTokenString ( " ( " ) ) {
src . Warning ( " Expected { after '%s' \n " , token2 . c_str ( ) ) ;
MakeDefault ( ) ;
return false ;
}
for ( i = ANIMCHANNEL_ALL + 1 ; i < ANIM_NumAnimChannels ; i + + ) {
if ( ! idStr : : Icmp ( channelNames [ i ] , token2 ) ) {
break ;
}
}
if ( i > = ANIM_NumAnimChannels ) {
src . Warning ( " Unknown channel '%s' " , token2 . c_str ( ) ) ;
MakeDefault ( ) ;
return false ;
}
channel = i ;
jointnames = " " ;
while ( ! src . CheckTokenString ( " ) " ) ) {
if ( ! src . ReadToken ( & token2 ) ) {
src . Warning ( " Unexpected end of file " ) ;
MakeDefault ( ) ;
return false ;
}
jointnames + = token2 ;
if ( ( token2 ! = " * " ) & & ( token2 ! = " - " ) ) {
jointnames + = " " ;
}
}
GetJointList ( jointnames , jointList ) ;
channelJoints [ channel ] . SetNum ( jointList . Num ( ) ) ;
for ( num = i = 0 ; i < jointList . Num ( ) ; i + + ) {
jointnum = jointList [ i ] ;
if ( joints [ jointnum ] . channel ! = ANIMCHANNEL_ALL ) {
src . Warning ( " Joint '%s' assigned to multiple channels " , modelHandle - > GetJointName ( jointnum ) ) ;
continue ;
}
joints [ jointnum ] . channel = channel ;
channelJoints [ channel ] [ num + + ] = jointnum ;
}
channelJoints [ channel ] . SetNum ( num ) ;
} else {
src . Warning ( " unknown token '%s' " , token . c_str ( ) ) ;
MakeDefault ( ) ;
return false ;
}
}
// shrink the anim list down to save space
anims . SetGranularity ( 1 ) ;
anims . SetNum ( anims . Num ( ) ) ;
return true ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idDeclModelDef : : HasAnim
= = = = = = = = = = = = = = = = = = = = =
*/
bool idDeclModelDef : : HasAnim ( const char * name ) const {
int i ;
// find any animations with same name
for ( i = 0 ; i < anims . Num ( ) ; i + + ) {
if ( ! strcmp ( anims [ i ] - > Name ( ) , name ) ) {
return true ;
}
}
return false ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idDeclModelDef : : NumAnims
= = = = = = = = = = = = = = = = = = = = =
*/
int idDeclModelDef : : NumAnims ( void ) const {
return anims . Num ( ) + 1 ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idDeclModelDef : : GetSpecificAnim
Gets the exact anim for the name , without randomization .
= = = = = = = = = = = = = = = = = = = = =
*/
int idDeclModelDef : : GetSpecificAnim ( const char * name ) const {
int i ;
// find a specific animation
for ( i = 0 ; i < anims . Num ( ) ; i + + ) {
if ( ! strcmp ( anims [ i ] - > FullName ( ) , name ) ) {
return i + 1 ;
}
}
// didn't find it
return 0 ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idDeclModelDef : : GetAnim
= = = = = = = = = = = = = = = = = = = = =
*/
const idAnim * idDeclModelDef : : GetAnim ( int index ) const {
if ( ( index < 1 ) | | ( index > anims . Num ( ) ) ) {
return NULL ;
}
return anims [ index - 1 ] ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idDeclModelDef : : GetAnim
= = = = = = = = = = = = = = = = = = = = =
*/
int idDeclModelDef : : GetAnim ( const char * name ) const {
int i ;
int which ;
const int MAX_ANIMS = 64 ;
int animList [ MAX_ANIMS ] ;
int numAnims ;
int len ;
len = strlen ( name ) ;
if ( len & & idStr : : CharIsNumeric ( name [ len - 1 ] ) ) {
// find a specific animation
return GetSpecificAnim ( name ) ;
}
// find all animations with same name
numAnims = 0 ;
for ( i = 0 ; i < anims . Num ( ) ; i + + ) {
if ( ! strcmp ( anims [ i ] - > Name ( ) , name ) ) {
animList [ numAnims + + ] = i ;
if ( numAnims > = MAX_ANIMS ) {
break ;
}
}
}
if ( ! numAnims ) {
return 0 ;
}
// get a random anim
//FIXME: don't access gameLocal here?
which = gameLocal . random . RandomInt ( numAnims ) ;
return animList [ which ] + 1 ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idDeclModelDef : : GetSkin
= = = = = = = = = = = = = = = = = = = = =
*/
const idDeclSkin * idDeclModelDef : : GetSkin ( void ) const {
return skin ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idDeclModelDef : : GetModelName
= = = = = = = = = = = = = = = = = = = = =
*/
const char * idDeclModelDef : : GetModelName ( void ) const {
if ( modelHandle ) {
return modelHandle - > Name ( ) ;
} else {
return " " ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idDeclModelDef : : Joints
= = = = = = = = = = = = = = = = = = = = =
*/
const idList < jointInfo_t > & idDeclModelDef : : Joints ( void ) const {
return joints ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idDeclModelDef : : JointParents
= = = = = = = = = = = = = = = = = = = = =
*/
const int * idDeclModelDef : : JointParents ( void ) const {
return jointParents . Ptr ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idDeclModelDef : : NumJoints
= = = = = = = = = = = = = = = = = = = = =
*/
int idDeclModelDef : : NumJoints ( void ) const {
return joints . Num ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idDeclModelDef : : GetJoint
= = = = = = = = = = = = = = = = = = = = =
*/
const jointInfo_t * idDeclModelDef : : GetJoint ( int jointHandle ) const {
if ( ( jointHandle < 0 ) | | ( jointHandle > joints . Num ( ) ) ) {
gameLocal . Error ( " idDeclModelDef::GetJoint : joint handle out of range " ) ;
}
return & joints [ jointHandle ] ;
}
/*
= = = = = = = = = = = = = = = = = = = =
idDeclModelDef : : GetJointName
= = = = = = = = = = = = = = = = = = = =
*/
const char * idDeclModelDef : : GetJointName ( int jointHandle ) const {
const idMD5Joint * joint ;
if ( ! modelHandle ) {
return NULL ;
}
if ( ( jointHandle < 0 ) | | ( jointHandle > joints . Num ( ) ) ) {
gameLocal . Error ( " idDeclModelDef::GetJointName : joint handle out of range " ) ;
}
joint = modelHandle - > GetJoints ( ) ;
return joint [ jointHandle ] . name . c_str ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idDeclModelDef : : NumJointsOnChannel
= = = = = = = = = = = = = = = = = = = = =
*/
int idDeclModelDef : : NumJointsOnChannel ( int channel ) const {
if ( ( channel < 0 ) | | ( channel > = ANIM_NumAnimChannels ) ) {
gameLocal . Error ( " idDeclModelDef::NumJointsOnChannel : channel out of range " ) ;
}
return channelJoints [ channel ] . Num ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idDeclModelDef : : GetChannelJoints
= = = = = = = = = = = = = = = = = = = = =
*/
const int * idDeclModelDef : : GetChannelJoints ( int channel ) const {
if ( ( channel < 0 ) | | ( channel > = ANIM_NumAnimChannels ) ) {
gameLocal . Error ( " idDeclModelDef::GetChannelJoints : channel out of range " ) ;
}
return channelJoints [ channel ] . Ptr ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idDeclModelDef : : GetVisualOffset
= = = = = = = = = = = = = = = = = = = = =
*/
const idVec3 & idDeclModelDef : : GetVisualOffset ( void ) const {
return offset ;
}
/***********************************************************************
idAnimator
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : idAnimator
= = = = = = = = = = = = = = = = = = = = =
*/
idAnimator : : idAnimator ( ) {
int i , j ;
modelDef = NULL ;
entity = NULL ;
numJoints = 0 ;
joints = NULL ;
lastTransformTime = - 1 ;
stoppedAnimatingUpdate = false ;
removeOriginOffset = false ;
forceUpdate = false ;
frameBounds . Clear ( ) ;
AFPoseJoints . SetGranularity ( 1 ) ;
AFPoseJointMods . SetGranularity ( 1 ) ;
AFPoseJointFrame . SetGranularity ( 1 ) ;
ClearAFPose ( ) ;
for ( i = ANIMCHANNEL_ALL ; i < ANIM_NumAnimChannels ; i + + ) {
for ( j = 0 ; j < ANIM_MaxAnimsPerChannel ; j + + ) {
channels [ i ] [ j ] . Reset ( NULL ) ;
}
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : ~ idAnimator
= = = = = = = = = = = = = = = = = = = = =
*/
idAnimator : : ~ idAnimator ( ) {
FreeData ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : Allocated
= = = = = = = = = = = = = = = = = = = = =
*/
size_t idAnimator : : Allocated ( void ) const {
size_t size ;
size = jointMods . Allocated ( ) + numJoints * sizeof ( joints [ 0 ] ) + jointMods . Num ( ) * sizeof ( jointMods [ 0 ] ) + AFPoseJointMods . Allocated ( ) + AFPoseJointFrame . Allocated ( ) + AFPoseJoints . Allocated ( ) ;
return size ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : Save
archives object for save game file
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimator : : Save ( idSaveGame * savefile ) const {
int i ;
int j ;
savefile - > WriteModelDef ( modelDef ) ;
savefile - > WriteObject ( entity ) ;
savefile - > WriteInt ( jointMods . Num ( ) ) ;
for ( i = 0 ; i < jointMods . Num ( ) ; i + + ) {
savefile - > WriteInt ( jointMods [ i ] - > jointnum ) ;
savefile - > WriteMat3 ( jointMods [ i ] - > mat ) ;
savefile - > WriteVec3 ( jointMods [ i ] - > pos ) ;
savefile - > WriteInt ( ( int & ) jointMods [ i ] - > transform_pos ) ;
savefile - > WriteInt ( ( int & ) jointMods [ i ] - > transform_axis ) ;
}
savefile - > WriteInt ( numJoints ) ;
for ( i = 0 ; i < numJoints ; i + + ) {
float * data = joints [ i ] . ToFloatPtr ( ) ;
for ( j = 0 ; j < 12 ; j + + ) {
savefile - > WriteFloat ( data [ j ] ) ;
}
}
savefile - > WriteInt ( lastTransformTime ) ;
savefile - > WriteBool ( stoppedAnimatingUpdate ) ;
savefile - > WriteBool ( forceUpdate ) ;
savefile - > WriteBounds ( frameBounds ) ;
savefile - > WriteFloat ( AFPoseBlendWeight ) ;
savefile - > WriteInt ( AFPoseJoints . Num ( ) ) ;
for ( i = 0 ; i < AFPoseJoints . Num ( ) ; i + + ) {
savefile - > WriteInt ( AFPoseJoints [ i ] ) ;
}
savefile - > WriteInt ( AFPoseJointMods . Num ( ) ) ;
for ( i = 0 ; i < AFPoseJointMods . Num ( ) ; i + + ) {
savefile - > WriteInt ( ( int & ) AFPoseJointMods [ i ] . mod ) ;
savefile - > WriteMat3 ( AFPoseJointMods [ i ] . axis ) ;
savefile - > WriteVec3 ( AFPoseJointMods [ i ] . origin ) ;
}
savefile - > WriteInt ( AFPoseJointFrame . Num ( ) ) ;
for ( i = 0 ; i < AFPoseJointFrame . Num ( ) ; i + + ) {
savefile - > WriteFloat ( AFPoseJointFrame [ i ] . q . x ) ;
savefile - > WriteFloat ( AFPoseJointFrame [ i ] . q . y ) ;
savefile - > WriteFloat ( AFPoseJointFrame [ i ] . q . z ) ;
savefile - > WriteFloat ( AFPoseJointFrame [ i ] . q . w ) ;
savefile - > WriteVec3 ( AFPoseJointFrame [ i ] . t ) ;
}
savefile - > WriteBounds ( AFPoseBounds ) ;
savefile - > WriteInt ( AFPoseTime ) ;
savefile - > WriteBool ( removeOriginOffset ) ;
for ( i = ANIMCHANNEL_ALL ; i < ANIM_NumAnimChannels ; i + + ) {
for ( j = 0 ; j < ANIM_MaxAnimsPerChannel ; j + + ) {
channels [ i ] [ j ] . Save ( savefile ) ;
}
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : Restore
unarchives object from save game file
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimator : : Restore ( idRestoreGame * savefile ) {
int i ;
int j ;
int num ;
savefile - > ReadModelDef ( modelDef ) ;
savefile - > ReadObject ( reinterpret_cast < idClass * & > ( entity ) ) ;
savefile - > ReadInt ( num ) ;
jointMods . SetNum ( num ) ;
for ( i = 0 ; i < num ; i + + ) {
jointMods [ i ] = new jointMod_t ;
savefile - > ReadInt ( ( int & ) jointMods [ i ] - > jointnum ) ;
savefile - > ReadMat3 ( jointMods [ i ] - > mat ) ;
savefile - > ReadVec3 ( jointMods [ i ] - > pos ) ;
savefile - > ReadInt ( ( int & ) jointMods [ i ] - > transform_pos ) ;
savefile - > ReadInt ( ( int & ) jointMods [ i ] - > transform_axis ) ;
}
savefile - > ReadInt ( numJoints ) ;
joints = ( idJointMat * ) Mem_Alloc16 ( numJoints * sizeof ( joints [ 0 ] ) ) ;
for ( i = 0 ; i < numJoints ; i + + ) {
float * data = joints [ i ] . ToFloatPtr ( ) ;
for ( j = 0 ; j < 12 ; j + + ) {
savefile - > ReadFloat ( data [ j ] ) ;
}
}
savefile - > ReadInt ( lastTransformTime ) ;
savefile - > ReadBool ( stoppedAnimatingUpdate ) ;
savefile - > ReadBool ( forceUpdate ) ;
savefile - > ReadBounds ( frameBounds ) ;
savefile - > ReadFloat ( AFPoseBlendWeight ) ;
savefile - > ReadInt ( num ) ;
AFPoseJoints . SetGranularity ( 1 ) ;
AFPoseJoints . SetNum ( num ) ;
for ( i = 0 ; i < AFPoseJoints . Num ( ) ; i + + ) {
savefile - > ReadInt ( AFPoseJoints [ i ] ) ;
}
savefile - > ReadInt ( num ) ;
AFPoseJointMods . SetGranularity ( 1 ) ;
AFPoseJointMods . SetNum ( num ) ;
for ( i = 0 ; i < AFPoseJointMods . Num ( ) ; i + + ) {
savefile - > ReadInt ( ( int & ) AFPoseJointMods [ i ] . mod ) ;
savefile - > ReadMat3 ( AFPoseJointMods [ i ] . axis ) ;
savefile - > ReadVec3 ( AFPoseJointMods [ i ] . origin ) ;
}
savefile - > ReadInt ( num ) ;
AFPoseJointFrame . SetGranularity ( 1 ) ;
AFPoseJointFrame . SetNum ( num ) ;
for ( i = 0 ; i < AFPoseJointFrame . Num ( ) ; i + + ) {
savefile - > ReadFloat ( AFPoseJointFrame [ i ] . q . x ) ;
savefile - > ReadFloat ( AFPoseJointFrame [ i ] . q . y ) ;
savefile - > ReadFloat ( AFPoseJointFrame [ i ] . q . z ) ;
savefile - > ReadFloat ( AFPoseJointFrame [ i ] . q . w ) ;
savefile - > ReadVec3 ( AFPoseJointFrame [ i ] . t ) ;
}
savefile - > ReadBounds ( AFPoseBounds ) ;
savefile - > ReadInt ( AFPoseTime ) ;
savefile - > ReadBool ( removeOriginOffset ) ;
for ( i = ANIMCHANNEL_ALL ; i < ANIM_NumAnimChannels ; i + + ) {
for ( j = 0 ; j < ANIM_MaxAnimsPerChannel ; j + + ) {
channels [ i ] [ j ] . Restore ( savefile , modelDef ) ;
}
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : FreeData
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimator : : FreeData ( void ) {
int i , j ;
if ( entity ) {
entity - > BecomeInactive ( TH_ANIMATE ) ;
}
for ( i = ANIMCHANNEL_ALL ; i < ANIM_NumAnimChannels ; i + + ) {
for ( j = 0 ; j < ANIM_MaxAnimsPerChannel ; j + + ) {
channels [ i ] [ j ] . Reset ( NULL ) ;
}
}
jointMods . DeleteContents ( true ) ;
Mem_Free16 ( joints ) ;
joints = NULL ;
numJoints = 0 ;
modelDef = NULL ;
ForceUpdate ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : PushAnims
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimator : : PushAnims ( int channelNum , int currentTime , int blendTime ) {
int i ;
idAnimBlend * channel ;
channel = channels [ channelNum ] ;
if ( ! channel [ 0 ] . GetWeight ( currentTime ) | | ( channel [ 0 ] . starttime = = currentTime ) ) {
return ;
}
for ( i = ANIM_MaxAnimsPerChannel - 1 ; i > 0 ; i - - ) {
channel [ i ] = channel [ i - 1 ] ;
}
channel [ 0 ] . Reset ( modelDef ) ;
channel [ 1 ] . Clear ( currentTime , blendTime ) ;
ForceUpdate ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : SetModel
= = = = = = = = = = = = = = = = = = = = =
*/
idRenderModel * idAnimator : : SetModel ( const char * modelname ) {
int i , j ;
FreeData ( ) ;
// check if we're just clearing the model
if ( ! modelname | | ! * modelname ) {
return NULL ;
}
modelDef = static_cast < const idDeclModelDef * > ( declManager - > FindType ( DECL_MODELDEF , modelname , false ) ) ;
if ( ! modelDef ) {
return NULL ;
}
idRenderModel * renderModel = modelDef - > ModelHandle ( ) ;
if ( ! renderModel ) {
modelDef = NULL ;
return NULL ;
}
// make sure model hasn't been purged
modelDef - > Touch ( ) ;
modelDef - > SetupJoints ( & numJoints , & joints , frameBounds , removeOriginOffset ) ;
modelDef - > ModelHandle ( ) - > Reset ( ) ;
// set the modelDef on all channels
for ( i = ANIMCHANNEL_ALL ; i < ANIM_NumAnimChannels ; i + + ) {
for ( j = 0 ; j < ANIM_MaxAnimsPerChannel ; j + + ) {
channels [ i ] [ j ] . Reset ( modelDef ) ;
}
}
return modelDef - > ModelHandle ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : Size
= = = = = = = = = = = = = = = = = = = = =
*/
size_t idAnimator : : Size ( void ) const {
return sizeof ( * this ) + Allocated ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : SetEntity
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimator : : SetEntity ( idEntity * ent ) {
entity = ent ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : GetEntity
= = = = = = = = = = = = = = = = = = = = =
*/
idEntity * idAnimator : : GetEntity ( void ) const {
return entity ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : RemoveOriginOffset
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimator : : RemoveOriginOffset ( bool remove ) {
removeOriginOffset = remove ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : RemoveOrigin
= = = = = = = = = = = = = = = = = = = = =
*/
bool idAnimator : : RemoveOrigin ( void ) const {
return removeOriginOffset ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : GetJointList
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimator : : GetJointList ( const char * jointnames , idList < jointHandle_t > & jointList ) const {
if ( modelDef ) {
modelDef - > GetJointList ( jointnames , jointList ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : NumAnims
= = = = = = = = = = = = = = = = = = = = =
*/
int idAnimator : : NumAnims ( void ) const {
if ( ! modelDef ) {
return 0 ;
}
return modelDef - > NumAnims ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : GetAnim
= = = = = = = = = = = = = = = = = = = = =
*/
const idAnim * idAnimator : : GetAnim ( int index ) const {
if ( ! modelDef ) {
return NULL ;
}
return modelDef - > GetAnim ( index ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : GetAnim
= = = = = = = = = = = = = = = = = = = = =
*/
int idAnimator : : GetAnim ( const char * name ) const {
if ( ! modelDef ) {
return 0 ;
}
return modelDef - > GetAnim ( name ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : HasAnim
= = = = = = = = = = = = = = = = = = = = =
*/
bool idAnimator : : HasAnim ( const char * name ) const {
if ( ! modelDef ) {
return false ;
}
return modelDef - > HasAnim ( name ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : NumJoints
= = = = = = = = = = = = = = = = = = = = =
*/
int idAnimator : : NumJoints ( void ) const {
return numJoints ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : ModelHandle
= = = = = = = = = = = = = = = = = = = = =
*/
idRenderModel * idAnimator : : ModelHandle ( void ) const {
if ( ! modelDef ) {
return NULL ;
}
return modelDef - > ModelHandle ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : ModelDef
= = = = = = = = = = = = = = = = = = = = =
*/
const idDeclModelDef * idAnimator : : ModelDef ( void ) const {
return modelDef ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : CurrentAnim
= = = = = = = = = = = = = = = = = = = = =
*/
idAnimBlend * idAnimator : : CurrentAnim ( int channelNum ) {
if ( ( channelNum < 0 ) | | ( channelNum > = ANIM_NumAnimChannels ) ) {
gameLocal . Error ( " idAnimator::CurrentAnim : channel out of range " ) ;
}
return & channels [ channelNum ] [ 0 ] ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : Clear
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimator : : Clear ( int channelNum , int currentTime , int cleartime ) {
int i ;
idAnimBlend * blend ;
if ( ( channelNum < 0 ) | | ( channelNum > = ANIM_NumAnimChannels ) ) {
gameLocal . Error ( " idAnimator::Clear : channel out of range " ) ;
}
blend = channels [ channelNum ] ;
for ( i = 0 ; i < ANIM_MaxAnimsPerChannel ; i + + , blend + + ) {
blend - > Clear ( currentTime , cleartime ) ;
}
ForceUpdate ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : SetFrame
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimator : : SetFrame ( int channelNum , int animNum , int frame , int currentTime , int blendTime ) {
if ( ( channelNum < 0 ) | | ( channelNum > = ANIM_NumAnimChannels ) ) {
gameLocal . Error ( " idAnimator::SetFrame : channel out of range " ) ;
}
if ( ! modelDef | | ! modelDef - > GetAnim ( animNum ) ) {
return ;
}
PushAnims ( channelNum , currentTime , blendTime ) ;
channels [ channelNum ] [ 0 ] . SetFrame ( modelDef , animNum , frame , currentTime , blendTime ) ;
if ( entity ) {
entity - > BecomeActive ( TH_ANIMATE ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : CycleAnim
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimator : : CycleAnim ( int channelNum , int animNum , int currentTime , int blendTime ) {
if ( ( channelNum < 0 ) | | ( channelNum > = ANIM_NumAnimChannels ) ) {
gameLocal . Error ( " idAnimator::CycleAnim : channel out of range " ) ;
}
if ( ! modelDef | | ! modelDef - > GetAnim ( animNum ) ) {
return ;
}
PushAnims ( channelNum , currentTime , blendTime ) ;
channels [ channelNum ] [ 0 ] . CycleAnim ( modelDef , animNum , currentTime , blendTime ) ;
if ( entity ) {
entity - > BecomeActive ( TH_ANIMATE ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : PlayAnim
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimator : : PlayAnim ( int channelNum , int animNum , int currentTime , int blendTime ) {
if ( ( channelNum < 0 ) | | ( channelNum > = ANIM_NumAnimChannels ) ) {
gameLocal . Error ( " idAnimator::PlayAnim : channel out of range " ) ;
}
if ( ! modelDef | | ! modelDef - > GetAnim ( animNum ) ) {
return ;
}
PushAnims ( channelNum , currentTime , blendTime ) ;
channels [ channelNum ] [ 0 ] . PlayAnim ( modelDef , animNum , currentTime , blendTime ) ;
if ( entity ) {
entity - > BecomeActive ( TH_ANIMATE ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : SyncAnimChannels
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimator : : SyncAnimChannels ( int channelNum , int fromChannelNum , int currentTime , int blendTime ) {
if ( ( channelNum < 0 ) | | ( channelNum > = ANIM_NumAnimChannels ) | | ( fromChannelNum < 0 ) | | ( fromChannelNum > = ANIM_NumAnimChannels ) ) {
gameLocal . Error ( " idAnimator::SyncToChannel : channel out of range " ) ;
}
idAnimBlend & fromBlend = channels [ fromChannelNum ] [ 0 ] ;
idAnimBlend & toBlend = channels [ channelNum ] [ 0 ] ;
float weight = fromBlend . blendEndValue ;
if ( ( fromBlend . Anim ( ) ! = toBlend . Anim ( ) ) | | ( fromBlend . GetStartTime ( ) ! = toBlend . GetStartTime ( ) ) | | ( fromBlend . GetEndTime ( ) ! = toBlend . GetEndTime ( ) ) ) {
PushAnims ( channelNum , currentTime , blendTime ) ;
toBlend = fromBlend ;
toBlend . blendStartValue = 0.0f ;
toBlend . blendEndValue = 0.0f ;
}
toBlend . SetWeight ( weight , currentTime - 1 , blendTime ) ;
// disable framecommands on the current channel so that commands aren't called twice
toBlend . AllowFrameCommands ( false ) ;
if ( entity ) {
entity - > BecomeActive ( TH_ANIMATE ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : SetJointPos
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimator : : SetJointPos ( jointHandle_t jointnum , jointModTransform_t transform_type , const idVec3 & pos ) {
int i ;
jointMod_t * jointMod ;
if ( ! modelDef | | ! modelDef - > ModelHandle ( ) | | ( jointnum < 0 ) | | ( jointnum > = numJoints ) ) {
return ;
}
jointMod = NULL ;
for ( i = 0 ; i < jointMods . Num ( ) ; i + + ) {
if ( jointMods [ i ] - > jointnum = = jointnum ) {
jointMod = jointMods [ i ] ;
break ;
} else if ( jointMods [ i ] - > jointnum > jointnum ) {
break ;
}
}
if ( ! jointMod ) {
jointMod = new jointMod_t ;
jointMod - > jointnum = jointnum ;
jointMod - > mat . Identity ( ) ;
jointMod - > transform_axis = JOINTMOD_NONE ;
jointMods . Insert ( jointMod , i ) ;
}
jointMod - > pos = pos ;
jointMod - > transform_pos = transform_type ;
if ( entity ) {
entity - > BecomeActive ( TH_ANIMATE ) ;
}
ForceUpdate ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : SetJointAxis
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimator : : SetJointAxis ( jointHandle_t jointnum , jointModTransform_t transform_type , const idMat3 & mat ) {
int i ;
jointMod_t * jointMod ;
if ( ! modelDef | | ! modelDef - > ModelHandle ( ) | | ( jointnum < 0 ) | | ( jointnum > = numJoints ) ) {
return ;
}
jointMod = NULL ;
for ( i = 0 ; i < jointMods . Num ( ) ; i + + ) {
if ( jointMods [ i ] - > jointnum = = jointnum ) {
jointMod = jointMods [ i ] ;
break ;
} else if ( jointMods [ i ] - > jointnum > jointnum ) {
break ;
}
}
if ( ! jointMod ) {
jointMod = new jointMod_t ;
jointMod - > jointnum = jointnum ;
jointMod - > pos . Zero ( ) ;
jointMod - > transform_pos = JOINTMOD_NONE ;
jointMods . Insert ( jointMod , i ) ;
}
jointMod - > mat = mat ;
jointMod - > transform_axis = transform_type ;
if ( entity ) {
entity - > BecomeActive ( TH_ANIMATE ) ;
}
ForceUpdate ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : ClearJoint
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimator : : ClearJoint ( jointHandle_t jointnum ) {
int i ;
if ( ! modelDef | | ! modelDef - > ModelHandle ( ) | | ( jointnum < 0 ) | | ( jointnum > = numJoints ) ) {
return ;
}
for ( i = 0 ; i < jointMods . Num ( ) ; i + + ) {
if ( jointMods [ i ] - > jointnum = = jointnum ) {
delete jointMods [ i ] ;
jointMods . RemoveIndex ( i ) ;
ForceUpdate ( ) ;
break ;
} else if ( jointMods [ i ] - > jointnum > jointnum ) {
break ;
}
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : ClearAllJoints
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimator : : ClearAllJoints ( void ) {
if ( jointMods . Num ( ) ) {
ForceUpdate ( ) ;
}
jointMods . DeleteContents ( true ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : ClearAllAnims
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimator : : ClearAllAnims ( int currentTime , int cleartime ) {
int i ;
for ( i = 0 ; i < ANIM_NumAnimChannels ; i + + ) {
Clear ( i , currentTime , cleartime ) ;
}
ClearAFPose ( ) ;
ForceUpdate ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = =
idAnimator : : GetDelta
= = = = = = = = = = = = = = = = = = = =
*/
void idAnimator : : GetDelta ( int fromtime , int totime , idVec3 & delta ) const {
int i ;
const idAnimBlend * blend ;
float blendWeight ;
if ( ! modelDef | | ! modelDef - > ModelHandle ( ) | | ( fromtime = = totime ) ) {
delta . Zero ( ) ;
return ;
}
delta . Zero ( ) ;
blendWeight = 0.0f ;
blend = channels [ ANIMCHANNEL_ALL ] ;
for ( i = 0 ; i < ANIM_MaxAnimsPerChannel ; i + + , blend + + ) {
blend - > BlendDelta ( fromtime , totime , delta , blendWeight ) ;
}
if ( modelDef - > Joints ( ) [ 0 ] . channel ) {
blend = channels [ modelDef - > Joints ( ) [ 0 ] . channel ] ;
for ( i = 0 ; i < ANIM_MaxAnimsPerChannel ; i + + , blend + + ) {
blend - > BlendDelta ( fromtime , totime , delta , blendWeight ) ;
}
}
}
/*
= = = = = = = = = = = = = = = = = = = =
idAnimator : : GetDeltaRotation
= = = = = = = = = = = = = = = = = = = =
*/
bool idAnimator : : GetDeltaRotation ( int fromtime , int totime , idMat3 & delta ) const {
int i ;
const idAnimBlend * blend ;
float blendWeight ;
idQuat q ;
if ( ! modelDef | | ! modelDef - > ModelHandle ( ) | | ( fromtime = = totime ) ) {
delta . Identity ( ) ;
return false ;
}
q . Set ( 0.0f , 0.0f , 0.0f , 1.0f ) ;
blendWeight = 0.0f ;
blend = channels [ ANIMCHANNEL_ALL ] ;
for ( i = 0 ; i < ANIM_MaxAnimsPerChannel ; i + + , blend + + ) {
blend - > BlendDeltaRotation ( fromtime , totime , q , blendWeight ) ;
}
if ( modelDef - > Joints ( ) [ 0 ] . channel ) {
blend = channels [ modelDef - > Joints ( ) [ 0 ] . channel ] ;
for ( i = 0 ; i < ANIM_MaxAnimsPerChannel ; i + + , blend + + ) {
blend - > BlendDeltaRotation ( fromtime , totime , q , blendWeight ) ;
}
}
if ( blendWeight > 0.0f ) {
delta = q . ToMat3 ( ) ;
return true ;
} else {
delta . Identity ( ) ;
return false ;
}
}
/*
= = = = = = = = = = = = = = = = = = = =
idAnimator : : GetOrigin
= = = = = = = = = = = = = = = = = = = =
*/
void idAnimator : : GetOrigin ( int currentTime , idVec3 & pos ) const {
int i ;
const idAnimBlend * blend ;
float blendWeight ;
if ( ! modelDef | | ! modelDef - > ModelHandle ( ) ) {
pos . Zero ( ) ;
return ;
}
pos . Zero ( ) ;
blendWeight = 0.0f ;
blend = channels [ ANIMCHANNEL_ALL ] ;
for ( i = 0 ; i < ANIM_MaxAnimsPerChannel ; i + + , blend + + ) {
blend - > BlendOrigin ( currentTime , pos , blendWeight , removeOriginOffset ) ;
}
if ( modelDef - > Joints ( ) [ 0 ] . channel ) {
blend = channels [ modelDef - > Joints ( ) [ 0 ] . channel ] ;
for ( i = 0 ; i < ANIM_MaxAnimsPerChannel ; i + + , blend + + ) {
blend - > BlendOrigin ( currentTime , pos , blendWeight , removeOriginOffset ) ;
}
}
pos + = modelDef - > GetVisualOffset ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = =
idAnimator : : GetBounds
= = = = = = = = = = = = = = = = = = = =
*/
bool idAnimator : : GetBounds ( int currentTime , idBounds & bounds ) {
int i , j ;
const idAnimBlend * blend ;
int count ;
if ( ! modelDef | | ! modelDef - > ModelHandle ( ) ) {
return false ;
}
if ( AFPoseJoints . Num ( ) ) {
bounds = AFPoseBounds ;
count = 1 ;
} else {
bounds . Clear ( ) ;
count = 0 ;
}
blend = channels [ 0 ] ;
for ( i = ANIMCHANNEL_ALL ; i < ANIM_NumAnimChannels ; i + + ) {
for ( j = 0 ; j < ANIM_MaxAnimsPerChannel ; j + + , blend + + ) {
if ( blend - > AddBounds ( currentTime , bounds , removeOriginOffset ) ) {
count + + ;
}
}
}
if ( ! count ) {
if ( ! frameBounds . IsCleared ( ) ) {
bounds = frameBounds ;
return true ;
} else {
bounds . Zero ( ) ;
return false ;
}
}
bounds . TranslateSelf ( modelDef - > GetVisualOffset ( ) ) ;
if ( g_debugBounds . GetBool ( ) ) {
if ( bounds [ 1 ] [ 0 ] - bounds [ 0 ] [ 0 ] > 2048 | | bounds [ 1 ] [ 1 ] - bounds [ 0 ] [ 1 ] > 2048 ) {
if ( entity ) {
gameLocal . Warning ( " big frameBounds on entity '%s' with model '%s': %f,%f " , entity - > name . c_str ( ) , modelDef - > ModelHandle ( ) - > Name ( ) , bounds [ 1 ] [ 0 ] - bounds [ 0 ] [ 0 ] , bounds [ 1 ] [ 1 ] - bounds [ 0 ] [ 1 ] ) ;
} else {
gameLocal . Warning ( " big frameBounds on model '%s': %f,%f " , modelDef - > ModelHandle ( ) - > Name ( ) , bounds [ 1 ] [ 0 ] - bounds [ 0 ] [ 0 ] , bounds [ 1 ] [ 1 ] - bounds [ 0 ] [ 1 ] ) ;
}
}
}
frameBounds = bounds ;
return true ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : InitAFPose
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimator : : InitAFPose ( void ) {
if ( ! modelDef ) {
return ;
}
AFPoseJoints . SetNum ( modelDef - > Joints ( ) . Num ( ) , false ) ;
AFPoseJoints . SetNum ( 0 , false ) ;
AFPoseJointMods . SetNum ( modelDef - > Joints ( ) . Num ( ) , false ) ;
AFPoseJointFrame . SetNum ( modelDef - > Joints ( ) . Num ( ) , false ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : SetAFPoseJointMod
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimator : : SetAFPoseJointMod ( const jointHandle_t jointNum , const AFJointModType_t mod , const idMat3 & axis , const idVec3 & origin ) {
AFPoseJointMods [ jointNum ] . mod = mod ;
AFPoseJointMods [ jointNum ] . axis = axis ;
AFPoseJointMods [ jointNum ] . origin = origin ;
int index = idBinSearch_GreaterEqual < int > ( AFPoseJoints . Ptr ( ) , AFPoseJoints . Num ( ) , jointNum ) ;
if ( index > = AFPoseJoints . Num ( ) | | jointNum ! = AFPoseJoints [ index ] ) {
AFPoseJoints . Insert ( jointNum , index ) ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : FinishAFPose
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimator : : FinishAFPose ( int animNum , const idBounds & bounds , const int time ) {
int i , j ;
int numJoints ;
int parentNum ;
int jointMod ;
int jointNum ;
const int * jointParent ;
if ( ! modelDef ) {
return ;
}
const idAnim * anim = modelDef - > GetAnim ( animNum ) ;
if ( ! anim ) {
return ;
}
numJoints = modelDef - > Joints ( ) . Num ( ) ;
if ( ! numJoints ) {
return ;
}
idRenderModel * md5 = modelDef - > ModelHandle ( ) ;
const idMD5Anim * md5anim = anim - > MD5Anim ( 0 ) ;
if ( numJoints ! = md5anim - > NumJoints ( ) ) {
gameLocal . Warning ( " Model '%s' has different # of joints than anim '%s' " , md5 - > Name ( ) , md5anim - > Name ( ) ) ;
return ;
}
idJointQuat * jointFrame = ( idJointQuat * ) _alloca16 ( numJoints * sizeof ( * jointFrame ) ) ;
md5anim - > GetSingleFrame ( 0 , jointFrame , modelDef - > GetChannelJoints ( ANIMCHANNEL_ALL ) , modelDef - > NumJointsOnChannel ( ANIMCHANNEL_ALL ) ) ;
if ( removeOriginOffset ) {
# ifdef VELOCITY_MOVE
jointFrame [ 0 ] . t . x = 0.0f ;
# else
jointFrame [ 0 ] . t . Zero ( ) ;
# endif
}
idJointMat * joints = ( idJointMat * ) _alloca16 ( numJoints * sizeof ( * joints ) ) ;
// convert the joint quaternions to joint matrices
SIMDProcessor - > ConvertJointQuatsToJointMats ( joints , jointFrame , numJoints ) ;
// first joint is always root of entire hierarchy
if ( AFPoseJoints . Num ( ) & & AFPoseJoints [ 0 ] = = 0 ) {
switch ( AFPoseJointMods [ 0 ] . mod ) {
case AF_JOINTMOD_AXIS : {
joints [ 0 ] . SetRotation ( AFPoseJointMods [ 0 ] . axis ) ;
break ;
}
case AF_JOINTMOD_ORIGIN : {
joints [ 0 ] . SetTranslation ( AFPoseJointMods [ 0 ] . origin ) ;
break ;
}
case AF_JOINTMOD_BOTH : {
joints [ 0 ] . SetRotation ( AFPoseJointMods [ 0 ] . axis ) ;
joints [ 0 ] . SetTranslation ( AFPoseJointMods [ 0 ] . origin ) ;
break ;
}
}
j = 1 ;
} else {
j = 0 ;
}
// pointer to joint info
jointParent = modelDef - > JointParents ( ) ;
// transform the child joints
for ( i = 1 ; j < AFPoseJoints . Num ( ) ; j + + , i + + ) {
jointMod = AFPoseJoints [ j ] ;
// transform any joints preceding the joint modifier
SIMDProcessor - > TransformJoints ( joints , jointParent , i , jointMod - 1 ) ;
i = jointMod ;
parentNum = jointParent [ i ] ;
switch ( AFPoseJointMods [ jointMod ] . mod ) {
case AF_JOINTMOD_AXIS : {
joints [ i ] . SetRotation ( AFPoseJointMods [ jointMod ] . axis ) ;
joints [ i ] . SetTranslation ( joints [ parentNum ] . ToVec3 ( ) + joints [ i ] . ToVec3 ( ) * joints [ parentNum ] . ToMat3 ( ) ) ;
break ;
}
case AF_JOINTMOD_ORIGIN : {
joints [ i ] . SetRotation ( joints [ i ] . ToMat3 ( ) * joints [ parentNum ] . ToMat3 ( ) ) ;
joints [ i ] . SetTranslation ( AFPoseJointMods [ jointMod ] . origin ) ;
break ;
}
case AF_JOINTMOD_BOTH : {
joints [ i ] . SetRotation ( AFPoseJointMods [ jointMod ] . axis ) ;
joints [ i ] . SetTranslation ( AFPoseJointMods [ jointMod ] . origin ) ;
break ;
}
}
}
// transform the rest of the hierarchy
SIMDProcessor - > TransformJoints ( joints , jointParent , i , numJoints - 1 ) ;
// untransform hierarchy
SIMDProcessor - > UntransformJoints ( joints , jointParent , 1 , numJoints - 1 ) ;
// convert joint matrices back to joint quaternions
SIMDProcessor - > ConvertJointMatsToJointQuats ( AFPoseJointFrame . Ptr ( ) , joints , numJoints ) ;
// find all modified joints and their parents
bool * blendJoints = ( bool * ) _alloca16 ( numJoints * sizeof ( bool ) ) ;
memset ( blendJoints , 0 , numJoints * sizeof ( bool ) ) ;
// mark all modified joints and their parents
for ( i = 0 ; i < AFPoseJoints . Num ( ) ; i + + ) {
for ( jointNum = AFPoseJoints [ i ] ; jointNum ! = INVALID_JOINT ; jointNum = jointParent [ jointNum ] ) {
blendJoints [ jointNum ] = true ;
}
}
// lock all parents of modified joints
AFPoseJoints . SetNum ( 0 , false ) ;
for ( i = 0 ; i < numJoints ; i + + ) {
if ( blendJoints [ i ] ) {
AFPoseJoints . Append ( i ) ;
}
}
AFPoseBounds = bounds ;
AFPoseTime = time ;
ForceUpdate ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : SetAFPoseBlendWeight
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimator : : SetAFPoseBlendWeight ( float blendWeight ) {
AFPoseBlendWeight = blendWeight ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : BlendAFPose
= = = = = = = = = = = = = = = = = = = = =
*/
bool idAnimator : : BlendAFPose ( idJointQuat * blendFrame ) const {
if ( ! AFPoseJoints . Num ( ) ) {
return false ;
}
SIMDProcessor - > BlendJoints ( blendFrame , AFPoseJointFrame . Ptr ( ) , AFPoseBlendWeight , AFPoseJoints . Ptr ( ) , AFPoseJoints . Num ( ) ) ;
return true ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : ClearAFPose
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimator : : ClearAFPose ( void ) {
if ( AFPoseJoints . Num ( ) ) {
ForceUpdate ( ) ;
}
AFPoseBlendWeight = 1.0f ;
AFPoseJoints . SetNum ( 0 , false ) ;
AFPoseBounds . Clear ( ) ;
AFPoseTime = 0 ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : ServiceAnims
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimator : : ServiceAnims ( int fromtime , int totime ) {
int i , j ;
idAnimBlend * blend ;
if ( ! modelDef ) {
return ;
}
if ( modelDef - > ModelHandle ( ) ) {
blend = channels [ 0 ] ;
for ( i = 0 ; i < ANIM_NumAnimChannels ; i + + ) {
for ( j = 0 ; j < ANIM_MaxAnimsPerChannel ; j + + , blend + + ) {
blend - > CallFrameCommands ( entity , fromtime , totime ) ;
}
}
}
if ( ! IsAnimating ( totime ) ) {
stoppedAnimatingUpdate = true ;
if ( entity ) {
entity - > BecomeInactive ( TH_ANIMATE ) ;
// present one more time with stopped animations so the renderer can properly recreate interactions
entity - > BecomeActive ( TH_UPDATEVISUALS ) ;
}
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : IsAnimating
= = = = = = = = = = = = = = = = = = = = =
*/
bool idAnimator : : IsAnimating ( int currentTime ) const {
int i , j ;
const idAnimBlend * blend ;
if ( ! modelDef | | ! modelDef - > ModelHandle ( ) ) {
return false ;
}
// if animating with an articulated figure
if ( AFPoseJoints . Num ( ) & & currentTime < = AFPoseTime ) {
return true ;
}
blend = channels [ 0 ] ;
for ( i = 0 ; i < ANIM_NumAnimChannels ; i + + ) {
for ( j = 0 ; j < ANIM_MaxAnimsPerChannel ; j + + , blend + + ) {
if ( ! blend - > IsDone ( currentTime ) ) {
return true ;
}
}
}
return false ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : FrameHasChanged
= = = = = = = = = = = = = = = = = = = = =
*/
bool idAnimator : : FrameHasChanged ( int currentTime ) const {
int i , j ;
const idAnimBlend * blend ;
if ( ! modelDef | | ! modelDef - > ModelHandle ( ) ) {
return false ;
}
// if animating with an articulated figure
if ( AFPoseJoints . Num ( ) & & currentTime < = AFPoseTime ) {
return true ;
}
blend = channels [ 0 ] ;
for ( i = 0 ; i < ANIM_NumAnimChannels ; i + + ) {
for ( j = 0 ; j < ANIM_MaxAnimsPerChannel ; j + + , blend + + ) {
if ( blend - > FrameHasChanged ( currentTime ) ) {
return true ;
}
}
}
if ( forceUpdate & & IsAnimating ( currentTime ) ) {
return true ;
}
return false ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : CreateFrame
= = = = = = = = = = = = = = = = = = = = =
*/
bool idAnimator : : CreateFrame ( int currentTime , bool force ) {
int i , j ;
int numJoints ;
int parentNum ;
bool hasAnim ;
bool debugInfo ;
float baseBlend ;
float blendWeight ;
const idAnimBlend * blend ;
const int * jointParent ;
const jointMod_t * jointMod ;
const idJointQuat * defaultPose ;
static idCVar r_showSkel ( " r_showSkel " , " 0 " , CVAR_RENDERER | CVAR_INTEGER , " " , 0 , 2 , idCmdSystem : : ArgCompletion_Integer < 0 , 2 > ) ;
if ( gameLocal . inCinematic & & gameLocal . skipCinematic ) {
return false ;
}
if ( ! modelDef | | ! modelDef - > ModelHandle ( ) ) {
return false ;
}
if ( ! force & & ! r_showSkel . GetInteger ( ) ) {
if ( lastTransformTime = = currentTime ) {
return false ;
}
if ( lastTransformTime ! = - 1 & & ! stoppedAnimatingUpdate & & ! IsAnimating ( currentTime ) ) {
return false ;
}
}
lastTransformTime = currentTime ;
stoppedAnimatingUpdate = false ;
if ( entity & & ( ( g_debugAnim . GetInteger ( ) = = entity - > entityNumber ) | | ( g_debugAnim . GetInteger ( ) = = - 2 ) ) ) {
debugInfo = true ;
gameLocal . Printf ( " --------------- \n %d: entity '%s': \n " , gameLocal . time , entity - > GetName ( ) ) ;
gameLocal . Printf ( " model '%s': \n " , modelDef - > GetModelName ( ) ) ;
} else {
debugInfo = false ;
}
// init the joint buffer
if ( AFPoseJoints . Num ( ) ) {
// initialize with AF pose anim for the case where there are no other animations and no AF pose joint modifications
defaultPose = AFPoseJointFrame . Ptr ( ) ;
} else {
defaultPose = modelDef - > GetDefaultPose ( ) ;
}
if ( ! defaultPose ) {
//gameLocal.Warning( "idAnimator::CreateFrame: no defaultPose on '%s'", modelDef->Name() );
return false ;
}
numJoints = modelDef - > Joints ( ) . Num ( ) ;
idJointQuat * jointFrame = ( idJointQuat * ) _alloca16 ( numJoints * sizeof ( jointFrame [ 0 ] ) ) ;
SIMDProcessor - > Memcpy ( jointFrame , defaultPose , numJoints * sizeof ( jointFrame [ 0 ] ) ) ;
hasAnim = false ;
// blend the all channel
baseBlend = 0.0f ;
blend = channels [ ANIMCHANNEL_ALL ] ;
for ( j = 0 ; j < ANIM_MaxAnimsPerChannel ; j + + , blend + + ) {
if ( blend - > BlendAnim ( currentTime , ANIMCHANNEL_ALL , numJoints , jointFrame , baseBlend , removeOriginOffset , false , debugInfo ) ) {
hasAnim = true ;
if ( baseBlend > = 1.0f ) {
break ;
}
}
}
// only blend other channels if there's enough space to blend into
if ( baseBlend < 1.0f ) {
for ( i = ANIMCHANNEL_ALL + 1 ; i < ANIM_NumAnimChannels ; i + + ) {
if ( ! modelDef - > NumJointsOnChannel ( i ) ) {
continue ;
}
if ( i = = ANIMCHANNEL_EYELIDS ) {
// eyelids blend over any previous anims, so skip it and blend it later
continue ;
}
blendWeight = baseBlend ;
blend = channels [ i ] ;
for ( j = 0 ; j < ANIM_MaxAnimsPerChannel ; j + + , blend + + ) {
if ( blend - > BlendAnim ( currentTime , i , numJoints , jointFrame , blendWeight , removeOriginOffset , false , debugInfo ) ) {
hasAnim = true ;
if ( blendWeight > = 1.0f ) {
// fully blended
break ;
}
}
}
if ( debugInfo & & ! AFPoseJoints . Num ( ) & & ! blendWeight ) {
gameLocal . Printf ( " %d: %s using default pose in model '%s' \n " , gameLocal . time , channelNames [ i ] , modelDef - > GetModelName ( ) ) ;
}
}
}
// blend in the eyelids
if ( modelDef - > NumJointsOnChannel ( ANIMCHANNEL_EYELIDS ) ) {
blend = channels [ ANIMCHANNEL_EYELIDS ] ;
blendWeight = baseBlend ;
for ( j = 0 ; j < ANIM_MaxAnimsPerChannel ; j + + , blend + + ) {
if ( blend - > BlendAnim ( currentTime , ANIMCHANNEL_EYELIDS , numJoints , jointFrame , blendWeight , removeOriginOffset , true , debugInfo ) ) {
hasAnim = true ;
if ( blendWeight > = 1.0f ) {
// fully blended
break ;
}
}
}
}
// blend the articulated figure pose
if ( BlendAFPose ( jointFrame ) ) {
hasAnim = true ;
}
if ( ! hasAnim & & ! jointMods . Num ( ) ) {
// no animations were updated
return false ;
}
// convert the joint quaternions to rotation matrices
SIMDProcessor - > ConvertJointQuatsToJointMats ( joints , jointFrame , numJoints ) ;
// check if we need to modify the origin
if ( jointMods . Num ( ) & & ( jointMods [ 0 ] - > jointnum = = 0 ) ) {
jointMod = jointMods [ 0 ] ;
switch ( jointMod - > transform_axis ) {
case JOINTMOD_NONE :
break ;
case JOINTMOD_LOCAL :
joints [ 0 ] . SetRotation ( jointMod - > mat * joints [ 0 ] . ToMat3 ( ) ) ;
break ;
case JOINTMOD_WORLD :
joints [ 0 ] . SetRotation ( joints [ 0 ] . ToMat3 ( ) * jointMod - > mat ) ;
break ;
case JOINTMOD_LOCAL_OVERRIDE :
case JOINTMOD_WORLD_OVERRIDE :
joints [ 0 ] . SetRotation ( jointMod - > mat ) ;
break ;
}
switch ( jointMod - > transform_pos ) {
case JOINTMOD_NONE :
break ;
case JOINTMOD_LOCAL :
joints [ 0 ] . SetTranslation ( joints [ 0 ] . ToVec3 ( ) + jointMod - > pos ) ;
break ;
case JOINTMOD_LOCAL_OVERRIDE :
case JOINTMOD_WORLD :
case JOINTMOD_WORLD_OVERRIDE :
joints [ 0 ] . SetTranslation ( jointMod - > pos ) ;
break ;
}
j = 1 ;
} else {
j = 0 ;
}
// add in the model offset
joints [ 0 ] . SetTranslation ( joints [ 0 ] . ToVec3 ( ) + modelDef - > GetVisualOffset ( ) ) ;
// pointer to joint info
jointParent = modelDef - > JointParents ( ) ;
// add in any joint modifications
for ( i = 1 ; j < jointMods . Num ( ) ; j + + , i + + ) {
jointMod = jointMods [ j ] ;
// transform any joints preceding the joint modifier
SIMDProcessor - > TransformJoints ( joints , jointParent , i , jointMod - > jointnum - 1 ) ;
i = jointMod - > jointnum ;
parentNum = jointParent [ i ] ;
// modify the axis
switch ( jointMod - > transform_axis ) {
case JOINTMOD_NONE :
joints [ i ] . SetRotation ( joints [ i ] . ToMat3 ( ) * joints [ parentNum ] . ToMat3 ( ) ) ;
break ;
case JOINTMOD_LOCAL :
joints [ i ] . SetRotation ( jointMod - > mat * ( joints [ i ] . ToMat3 ( ) * joints [ parentNum ] . ToMat3 ( ) ) ) ;
break ;
case JOINTMOD_LOCAL_OVERRIDE :
joints [ i ] . SetRotation ( jointMod - > mat * joints [ parentNum ] . ToMat3 ( ) ) ;
break ;
case JOINTMOD_WORLD :
joints [ i ] . SetRotation ( ( joints [ i ] . ToMat3 ( ) * joints [ parentNum ] . ToMat3 ( ) ) * jointMod - > mat ) ;
break ;
case JOINTMOD_WORLD_OVERRIDE :
joints [ i ] . SetRotation ( jointMod - > mat ) ;
break ;
}
// modify the position
switch ( jointMod - > transform_pos ) {
case JOINTMOD_NONE :
joints [ i ] . SetTranslation ( joints [ parentNum ] . ToVec3 ( ) + joints [ i ] . ToVec3 ( ) * joints [ parentNum ] . ToMat3 ( ) ) ;
break ;
case JOINTMOD_LOCAL :
joints [ i ] . SetTranslation ( joints [ parentNum ] . ToVec3 ( ) + ( joints [ i ] . ToVec3 ( ) + jointMod - > pos ) * joints [ parentNum ] . ToMat3 ( ) ) ;
break ;
case JOINTMOD_LOCAL_OVERRIDE :
joints [ i ] . SetTranslation ( joints [ parentNum ] . ToVec3 ( ) + jointMod - > pos * joints [ parentNum ] . ToMat3 ( ) ) ;
break ;
case JOINTMOD_WORLD :
joints [ i ] . SetTranslation ( joints [ parentNum ] . ToVec3 ( ) + joints [ i ] . ToVec3 ( ) * joints [ parentNum ] . ToMat3 ( ) + jointMod - > pos ) ;
break ;
case JOINTMOD_WORLD_OVERRIDE :
joints [ i ] . SetTranslation ( jointMod - > pos ) ;
break ;
}
}
// transform the rest of the hierarchy
SIMDProcessor - > TransformJoints ( joints , jointParent , i , numJoints - 1 ) ;
return true ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : ForceUpdate
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimator : : ForceUpdate ( void ) {
lastTransformTime = - 1 ;
forceUpdate = true ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : ClearForceUpdate
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimator : : ClearForceUpdate ( void ) {
forceUpdate = false ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : GetJointTransform > gamex86 . dll ! idAnimator : : ForceUpdate ( ) Line 4268 C + +
= = = = = = = = = = = = = = = = = = = = =
*/
bool idAnimator : : GetJointTransform ( jointHandle_t jointHandle , int currentTime , idVec3 & offset , idMat3 & axis ) {
if ( ! modelDef | | ( jointHandle < 0 ) | | ( jointHandle > = modelDef - > NumJoints ( ) ) ) {
return false ;
}
CreateFrame ( currentTime , false ) ;
offset = joints [ jointHandle ] . ToVec3 ( ) ;
axis = joints [ jointHandle ] . ToMat3 ( ) ;
return true ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : GetJointLocalTransform
= = = = = = = = = = = = = = = = = = = = =
*/
bool idAnimator : : GetJointLocalTransform ( jointHandle_t jointHandle , int currentTime , idVec3 & offset , idMat3 & axis ) {
if ( ! modelDef ) {
return false ;
}
const idList < jointInfo_t > & modelJoints = modelDef - > Joints ( ) ;
if ( ( jointHandle < 0 ) | | ( jointHandle > = modelJoints . Num ( ) ) ) {
return false ;
}
// FIXME: overkill
CreateFrame ( currentTime , false ) ;
if ( jointHandle > 0 ) {
idJointMat m = joints [ jointHandle ] ;
m / = joints [ modelJoints [ jointHandle ] . parentNum ] ;
offset = m . ToVec3 ( ) ;
axis = m . ToMat3 ( ) ;
} else {
offset = joints [ jointHandle ] . ToVec3 ( ) ;
axis = joints [ jointHandle ] . ToMat3 ( ) ;
}
return true ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : GetJointHandle
= = = = = = = = = = = = = = = = = = = = =
*/
jointHandle_t idAnimator : : GetJointHandle ( const char * name ) const {
if ( ! modelDef | | ! modelDef - > ModelHandle ( ) ) {
return INVALID_JOINT ;
}
return modelDef - > ModelHandle ( ) - > GetJointHandle ( name ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : GetJointName
= = = = = = = = = = = = = = = = = = = = =
*/
const char * idAnimator : : GetJointName ( jointHandle_t handle ) const {
if ( ! modelDef | | ! modelDef - > ModelHandle ( ) ) {
return " " ;
}
return modelDef - > ModelHandle ( ) - > GetJointName ( handle ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : GetChannelForJoint
= = = = = = = = = = = = = = = = = = = = =
*/
int idAnimator : : GetChannelForJoint ( jointHandle_t joint ) const {
if ( ! modelDef ) {
gameLocal . Error ( " idAnimator::GetChannelForJoint: NULL model " ) ;
}
if ( ( joint < 0 ) | | ( joint > = numJoints ) ) {
gameLocal . Error ( " idAnimator::GetChannelForJoint: invalid joint num (%d) " , joint ) ;
}
return modelDef - > GetJoint ( joint ) - > channel ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : GetFirstChild
= = = = = = = = = = = = = = = = = = = = =
*/
jointHandle_t idAnimator : : GetFirstChild ( const char * name ) const {
return GetFirstChild ( GetJointHandle ( name ) ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : GetFirstChild
= = = = = = = = = = = = = = = = = = = = =
*/
jointHandle_t idAnimator : : GetFirstChild ( jointHandle_t jointnum ) const {
int i ;
int num ;
const jointInfo_t * joint ;
if ( ! modelDef ) {
return INVALID_JOINT ;
}
num = modelDef - > NumJoints ( ) ;
if ( ! num ) {
return jointnum ;
}
joint = modelDef - > GetJoint ( 0 ) ;
for ( i = 0 ; i < num ; i + + , joint + + ) {
if ( joint - > parentNum = = jointnum ) {
return ( jointHandle_t ) joint - > num ;
}
}
return jointnum ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : GetJoints
= = = = = = = = = = = = = = = = = = = = =
*/
void idAnimator : : GetJoints ( int * numJoints , idJointMat * * jointsPtr ) {
* numJoints = this - > numJoints ;
* jointsPtr = this - > joints ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : GetAnimFlags
= = = = = = = = = = = = = = = = = = = = =
*/
const animFlags_t idAnimator : : GetAnimFlags ( int animNum ) const {
animFlags_t result ;
const idAnim * anim = GetAnim ( animNum ) ;
if ( anim ) {
return anim - > GetAnimFlags ( ) ;
}
memset ( & result , 0 , sizeof ( result ) ) ;
return result ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : NumFrames
= = = = = = = = = = = = = = = = = = = = =
*/
int idAnimator : : NumFrames ( int animNum ) const {
const idAnim * anim = GetAnim ( animNum ) ;
if ( anim ) {
return anim - > NumFrames ( ) ;
} else {
return 0 ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : NumSyncedAnims
= = = = = = = = = = = = = = = = = = = = =
*/
int idAnimator : : NumSyncedAnims ( int animNum ) const {
const idAnim * anim = GetAnim ( animNum ) ;
if ( anim ) {
return anim - > NumAnims ( ) ;
} else {
return 0 ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : AnimName
= = = = = = = = = = = = = = = = = = = = =
*/
const char * idAnimator : : AnimName ( int animNum ) const {
const idAnim * anim = GetAnim ( animNum ) ;
if ( anim ) {
return anim - > Name ( ) ;
} else {
return " " ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : AnimFullName
= = = = = = = = = = = = = = = = = = = = =
*/
const char * idAnimator : : AnimFullName ( int animNum ) const {
const idAnim * anim = GetAnim ( animNum ) ;
if ( anim ) {
return anim - > FullName ( ) ;
} else {
return " " ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : AnimLength
= = = = = = = = = = = = = = = = = = = = =
*/
int idAnimator : : AnimLength ( int animNum ) const {
const idAnim * anim = GetAnim ( animNum ) ;
if ( anim ) {
return anim - > Length ( ) ;
} else {
return 0 ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idAnimator : : TotalMovementDelta
= = = = = = = = = = = = = = = = = = = = =
*/
const idVec3 & idAnimator : : TotalMovementDelta ( int animNum ) const {
const idAnim * anim = GetAnim ( animNum ) ;
if ( anim ) {
return anim - > TotalMovementDelta ( ) ;
} else {
return vec3_origin ;
}
}
/***********************************************************************
Util functions
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
= = = = = = = = = = = = = = = = = = = = =
ANIM_GetModelDefFromEntityDef
= = = = = = = = = = = = = = = = = = = = =
*/
const idDeclModelDef * ANIM_GetModelDefFromEntityDef ( const idDict * args ) {
const idDeclModelDef * modelDef ;
idStr name = args - > GetString ( " model " ) ;
modelDef = static_cast < const idDeclModelDef * > ( declManager - > FindType ( DECL_MODELDEF , name , false ) ) ;
if ( modelDef & & modelDef - > ModelHandle ( ) ) {
return modelDef ;
}
return NULL ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idGameEdit : : ANIM_GetModelFromEntityDef
= = = = = = = = = = = = = = = = = = = = =
*/
idRenderModel * idGameEdit : : ANIM_GetModelFromEntityDef ( const idDict * args ) {
idRenderModel * model ;
const idDeclModelDef * modelDef ;
model = NULL ;
idStr name = args - > GetString ( " model " ) ;
modelDef = static_cast < const idDeclModelDef * > ( declManager - > FindType ( DECL_MODELDEF , name , false ) ) ;
if ( modelDef ) {
model = modelDef - > ModelHandle ( ) ;
}
if ( ! model ) {
model = renderModelManager - > FindModel ( name ) ;
}
if ( model & & model - > IsDefaultModel ( ) ) {
return NULL ;
}
return model ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idGameEdit : : ANIM_GetModelFromEntityDef
= = = = = = = = = = = = = = = = = = = = =
*/
idRenderModel * idGameEdit : : ANIM_GetModelFromEntityDef ( const char * classname ) {
const idDict * args ;
args = gameLocal . FindEntityDefDict ( classname , false ) ;
if ( ! args ) {
return NULL ;
}
return ANIM_GetModelFromEntityDef ( args ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idGameEdit : : ANIM_GetModelOffsetFromEntityDef
= = = = = = = = = = = = = = = = = = = = =
*/
const idVec3 & idGameEdit : : ANIM_GetModelOffsetFromEntityDef ( const char * classname ) {
const idDict * args ;
const idDeclModelDef * modelDef ;
args = gameLocal . FindEntityDefDict ( classname , false ) ;
if ( ! args ) {
return vec3_origin ;
}
modelDef = ANIM_GetModelDefFromEntityDef ( args ) ;
if ( ! modelDef ) {
return vec3_origin ;
}
return modelDef - > GetVisualOffset ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idGameEdit : : ANIM_GetModelFromName
= = = = = = = = = = = = = = = = = = = = =
*/
idRenderModel * idGameEdit : : ANIM_GetModelFromName ( const char * modelName ) {
const idDeclModelDef * modelDef ;
idRenderModel * model ;
model = NULL ;
modelDef = static_cast < const idDeclModelDef * > ( declManager - > FindType ( DECL_MODELDEF , modelName , false ) ) ;
if ( modelDef ) {
model = modelDef - > ModelHandle ( ) ;
}
if ( ! model ) {
model = renderModelManager - > FindModel ( modelName ) ;
}
return model ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idGameEdit : : ANIM_GetAnimFromEntityDef
= = = = = = = = = = = = = = = = = = = = =
*/
const idMD5Anim * idGameEdit : : ANIM_GetAnimFromEntityDef ( const char * classname , const char * animname ) {
const idDict * args ;
const idMD5Anim * md5anim ;
const idAnim * anim ;
int animNum ;
const char * modelname ;
const idDeclModelDef * modelDef ;
args = gameLocal . FindEntityDefDict ( classname , false ) ;
if ( ! args ) {
return NULL ;
}
md5anim = NULL ;
modelname = args - > GetString ( " model " ) ;
modelDef = static_cast < const idDeclModelDef * > ( declManager - > FindType ( DECL_MODELDEF , modelname , false ) ) ;
if ( modelDef ) {
animNum = modelDef - > GetAnim ( animname ) ;
if ( animNum ) {
anim = modelDef - > GetAnim ( animNum ) ;
if ( anim ) {
md5anim = anim - > MD5Anim ( 0 ) ;
}
}
}
return md5anim ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idGameEdit : : ANIM_GetNumAnimsFromEntityDef
= = = = = = = = = = = = = = = = = = = = =
*/
int idGameEdit : : ANIM_GetNumAnimsFromEntityDef ( const idDict * args ) {
const char * modelname ;
const idDeclModelDef * modelDef ;
modelname = args - > GetString ( " model " ) ;
modelDef = static_cast < const idDeclModelDef * > ( declManager - > FindType ( DECL_MODELDEF , modelname , false ) ) ;
if ( modelDef ) {
return modelDef - > NumAnims ( ) ;
}
return 0 ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idGameEdit : : ANIM_GetAnimNameFromEntityDef
= = = = = = = = = = = = = = = = = = = = =
*/
const char * idGameEdit : : ANIM_GetAnimNameFromEntityDef ( const idDict * args , int animNum ) {
const char * modelname ;
const idDeclModelDef * modelDef ;
modelname = args - > GetString ( " model " ) ;
modelDef = static_cast < const idDeclModelDef * > ( declManager - > FindType ( DECL_MODELDEF , modelname , false ) ) ;
if ( modelDef ) {
const idAnim * anim = modelDef - > GetAnim ( animNum ) ;
if ( anim ) {
return anim - > FullName ( ) ;
}
}
return " " ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idGameEdit : : ANIM_GetAnim
= = = = = = = = = = = = = = = = = = = = =
*/
const idMD5Anim * idGameEdit : : ANIM_GetAnim ( const char * fileName ) {
return animationLib . GetAnim ( fileName ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idGameEdit : : ANIM_GetLength
= = = = = = = = = = = = = = = = = = = = =
*/
int idGameEdit : : ANIM_GetLength ( const idMD5Anim * anim ) {
if ( ! anim ) {
return 0 ;
}
return anim - > Length ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idGameEdit : : ANIM_GetNumFrames
= = = = = = = = = = = = = = = = = = = = =
*/
int idGameEdit : : ANIM_GetNumFrames ( const idMD5Anim * anim ) {
if ( ! anim ) {
return 0 ;
}
return anim - > NumFrames ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = =
idGameEdit : : ANIM_CreateAnimFrame
= = = = = = = = = = = = = = = = = = = = =
*/
void idGameEdit : : ANIM_CreateAnimFrame ( const idRenderModel * model , const idMD5Anim * anim , int numJoints , idJointMat * joints , int time , const idVec3 & offset , bool remove_origin_offset ) {
int i ;
frameBlend_t frame ;
const idMD5Joint * md5joints ;
int * index ;
if ( ! model | | model - > IsDefaultModel ( ) | | ! anim ) {
return ;
}
if ( numJoints ! = model - > NumJoints ( ) ) {
gameLocal . Error ( " ANIM_CreateAnimFrame: different # of joints in renderEntity_t than in model (%s) " , model - > Name ( ) ) ;
}
if ( ! model - > NumJoints ( ) ) {
// FIXME: Print out a warning?
return ;
}
if ( ! joints ) {
gameLocal . Error ( " ANIM_CreateAnimFrame: NULL joint frame pointer on model (%s) " , model - > Name ( ) ) ;
}
if ( numJoints ! = anim - > NumJoints ( ) ) {
gameLocal . Warning ( " Model '%s' has different # of joints than anim '%s' " , model - > Name ( ) , anim - > Name ( ) ) ;
for ( i = 0 ; i < numJoints ; i + + ) {
joints [ i ] . SetRotation ( mat3_identity ) ;
joints [ i ] . SetTranslation ( offset ) ;
}
return ;
}
// create index for all joints
index = ( int * ) _alloca16 ( numJoints * sizeof ( int ) ) ;
for ( i = 0 ; i < numJoints ; i + + ) {
index [ i ] = i ;
}
// create the frame
anim - > ConvertTimeToFrame ( time , 1 , frame ) ;
idJointQuat * jointFrame = ( idJointQuat * ) _alloca16 ( numJoints * sizeof ( * jointFrame ) ) ;
anim - > GetInterpolatedFrame ( frame , jointFrame , index , numJoints ) ;
// convert joint quaternions to joint matrices
SIMDProcessor - > ConvertJointQuatsToJointMats ( joints , jointFrame , numJoints ) ;
// first joint is always root of entire hierarchy
if ( remove_origin_offset ) {
joints [ 0 ] . SetTranslation ( offset ) ;
} else {
joints [ 0 ] . SetTranslation ( joints [ 0 ] . ToVec3 ( ) + offset ) ;
}
// transform the children
md5joints = model - > GetJoints ( ) ;
for ( i = 1 ; i < numJoints ; i + + ) {
joints [ i ] * = joints [ md5joints [ i ] . parent - md5joints ] ;
}
}
/*
= = = = = = = = = = = = = = = = = = = = =
idGameEdit : : ANIM_CreateMeshForAnim
= = = = = = = = = = = = = = = = = = = = =
*/
idRenderModel * idGameEdit : : ANIM_CreateMeshForAnim ( idRenderModel * model , const char * classname , const char * animname , int frame , bool remove_origin_offset ) {
renderEntity_t ent ;
const idDict * args ;
const char * temp ;
idRenderModel * newmodel ;
const idMD5Anim * md5anim ;
idStr filename ;
idStr extension ;
const idAnim * anim ;
int animNum ;
idVec3 offset ;
const idDeclModelDef * modelDef ;
if ( ! model | | model - > IsDefaultModel ( ) ) {
return NULL ;
}
args = gameLocal . FindEntityDefDict ( classname , false ) ;
if ( ! args ) {
return NULL ;
}
memset ( & ent , 0 , sizeof ( ent ) ) ;
ent . bounds . Clear ( ) ;
ent . suppressSurfaceInViewID = 0 ;
modelDef = ANIM_GetModelDefFromEntityDef ( args ) ;
if ( modelDef ) {
animNum = modelDef - > GetAnim ( animname ) ;
if ( ! animNum ) {
return NULL ;
}
anim = modelDef - > GetAnim ( animNum ) ;
if ( ! anim ) {
return NULL ;
}
md5anim = anim - > MD5Anim ( 0 ) ;
ent . customSkin = modelDef - > GetDefaultSkin ( ) ;
offset = modelDef - > GetVisualOffset ( ) ;
} else {
filename = animname ;
filename . ExtractFileExtension ( extension ) ;
if ( ! extension . Length ( ) ) {
animname = args - > GetString ( va ( " anim %s " , animname ) ) ;
}
md5anim = animationLib . GetAnim ( animname ) ;
offset . Zero ( ) ;
}
if ( ! md5anim ) {
return NULL ;
}
temp = args - > GetString ( " skin " , " " ) ;
if ( temp [ 0 ] ) {
ent . customSkin = declManager - > FindSkin ( temp ) ;
}
ent . numJoints = model - > NumJoints ( ) ;
ent . joints = ( idJointMat * ) Mem_Alloc16 ( ent . numJoints * sizeof ( * ent . joints ) ) ;
ANIM_CreateAnimFrame ( model , md5anim , ent . numJoints , ent . joints , FRAME2MS ( frame ) , offset , remove_origin_offset ) ;
newmodel = model - > InstantiateDynamicModel ( & ent , NULL , NULL ) ;
Mem_Free16 ( ent . joints ) ;
ent . joints = NULL ;
return newmodel ;
}