2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Doom 3 BFG Edition GPL Source Code
2012-11-28 15:47:07 +00:00
Copyright ( C ) 1993 - 2012 id Software LLC , a ZeniMax Media company .
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
This file is part of the Doom 3 BFG Edition GPL Source Code ( " Doom 3 BFG Edition Source Code " ) .
2012-11-26 18:58:24 +00:00
Doom 3 BFG Edition 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 BFG Edition 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 BFG Edition Source Code . If not , see < http : //www.gnu.org/licenses/>.
In addition , the Doom 3 BFG Edition 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 BFG Edition 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 .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-12-22 15:18:19 +00:00
# include "precompiled.h"
2012-11-26 18:58:24 +00:00
# pragma hdrstop
# include "Game_local.h"
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Articulated figure controller .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
# define ARTICULATED_FIGURE_ANIM "af_pose"
# define POSE_BOUNDS_EXPANSION 5.0f
/*
= = = = = = = = = = = = = = = =
idAF : : idAF
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idAF : : idAF ( )
{
2012-11-26 18:58:24 +00:00
self = NULL ;
animator = NULL ;
modifiedAnim = 0 ;
baseOrigin . Zero ( ) ;
baseAxis . Identity ( ) ;
poseTime = - 1 ;
restStartTime = - 1 ;
isLoaded = false ;
isActive = false ;
hasBindConstraints = false ;
}
/*
= = = = = = = = = = = = = = = =
idAF : : ~ idAF
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idAF : : ~ idAF ( )
{
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = =
idAF : : Save
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAF : : Save ( idSaveGame * savefile ) const
{
2012-11-26 18:58:24 +00:00
savefile - > WriteObject ( self ) ;
savefile - > WriteString ( GetName ( ) ) ;
savefile - > WriteBool ( hasBindConstraints ) ;
savefile - > WriteVec3 ( baseOrigin ) ;
savefile - > WriteMat3 ( baseAxis ) ;
savefile - > WriteInt ( poseTime ) ;
savefile - > WriteInt ( restStartTime ) ;
savefile - > WriteBool ( isLoaded ) ;
savefile - > WriteBool ( isActive ) ;
savefile - > WriteStaticObject ( physicsObj ) ;
}
/*
= = = = = = = = = = = = = = = =
idAF : : Restore
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAF : : Restore ( idRestoreGame * savefile )
{
savefile - > ReadObject ( reinterpret_cast < idClass * & > ( self ) ) ;
2012-11-26 18:58:24 +00:00
savefile - > ReadString ( name ) ;
savefile - > ReadBool ( hasBindConstraints ) ;
savefile - > ReadVec3 ( baseOrigin ) ;
savefile - > ReadMat3 ( baseAxis ) ;
savefile - > ReadInt ( poseTime ) ;
savefile - > ReadInt ( restStartTime ) ;
savefile - > ReadBool ( isLoaded ) ;
savefile - > ReadBool ( isActive ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
animator = NULL ;
modifiedAnim = 0 ;
2012-11-28 15:47:07 +00:00
if ( self )
{
2012-11-26 18:58:24 +00:00
SetAnimator ( self - > GetAnimator ( ) ) ;
Load ( self , name ) ;
2012-11-28 15:47:07 +00:00
if ( hasBindConstraints )
{
2012-11-26 18:58:24 +00:00
AddBindConstraints ( ) ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadStaticObject ( physicsObj ) ;
2012-11-28 15:47:07 +00:00
if ( self )
{
if ( isActive )
{
2012-11-26 18:58:24 +00:00
// clear all animations
animator - > ClearAllAnims ( gameLocal . time , 0 ) ;
animator - > ClearAllJoints ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// switch to articulated figure physics
self - > RestorePhysics ( & physicsObj ) ;
physicsObj . EnableClip ( ) ;
}
UpdateAnimation ( ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idAF : : UpdateAnimation
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idAF : : UpdateAnimation ( )
{
2012-11-26 18:58:24 +00:00
int i ;
idVec3 origin , renderOrigin , bodyOrigin ;
idMat3 axis , renderAxis , bodyAxis ;
2012-11-28 15:47:07 +00:00
renderEntity_t * renderEntity ;
if ( ! IsLoaded ( ) )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
if ( ! IsActive ( ) )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderEntity = self - > GetRenderEntity ( ) ;
2012-11-28 15:47:07 +00:00
if ( ! renderEntity )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
if ( physicsObj . IsAtRest ( ) )
{
if ( restStartTime = = physicsObj . GetRestStartTime ( ) )
{
2012-11-26 18:58:24 +00:00
return false ;
}
restStartTime = physicsObj . GetRestStartTime ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// get the render position
origin = physicsObj . GetOrigin ( 0 ) ;
axis = physicsObj . GetAxis ( 0 ) ;
renderAxis = baseAxis . Transpose ( ) * axis ;
renderOrigin = origin - baseOrigin * renderAxis ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// create an animation frame which reflects the current pose of the articulated figure
animator - > InitAFPose ( ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < jointMods . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
// check for the origin joint
2012-11-28 15:47:07 +00:00
if ( jointMods [ i ] . jointHandle = = 0 )
{
2012-11-26 18:58:24 +00:00
continue ;
}
bodyOrigin = physicsObj . GetOrigin ( jointMods [ i ] . bodyId ) ;
bodyAxis = physicsObj . GetAxis ( jointMods [ i ] . bodyId ) ;
axis = jointMods [ i ] . jointBodyAxis . Transpose ( ) * ( bodyAxis * renderAxis . Transpose ( ) ) ;
origin = ( bodyOrigin - jointMods [ i ] . jointBodyOrigin * axis - renderOrigin ) * renderAxis . Transpose ( ) ;
animator - > SetAFPoseJointMod ( jointMods [ i ] . jointHandle , jointMods [ i ] . jointMod , axis , origin ) ;
}
animator - > FinishAFPose ( modifiedAnim , GetBounds ( ) . Expand ( POSE_BOUNDS_EXPANSION ) , gameLocal . time ) ;
animator - > SetAFPoseBlendWeight ( 1.0f ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return true ;
}
/*
= = = = = = = = = = = = = = = =
idAF : : GetBounds
returns bounds for the current pose
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idBounds idAF : : GetBounds ( ) const
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
idAFBody * body ;
2012-11-26 18:58:24 +00:00
idVec3 origin , entityOrigin ;
idMat3 axis , entityAxis ;
idBounds bounds , b ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bounds . Clear ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// get model base transform
origin = physicsObj . GetOrigin ( 0 ) ;
axis = physicsObj . GetAxis ( 0 ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
entityAxis = baseAxis . Transpose ( ) * axis ;
entityOrigin = origin - baseOrigin * entityAxis ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// get bounds relative to base
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < jointMods . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
body = physicsObj . GetBody ( jointMods [ i ] . bodyId ) ;
origin = ( body - > GetWorldOrigin ( ) - entityOrigin ) * entityAxis . Transpose ( ) ;
axis = body - > GetWorldAxis ( ) * entityAxis . Transpose ( ) ;
b . FromTransformedBounds ( body - > GetClipModel ( ) - > GetBounds ( ) , origin , axis ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bounds + = b ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return bounds ;
}
/*
= = = = = = = = = = = = = = = =
idAF : : SetupPose
Transforms the articulated figure to match the current animation pose of the given entity .
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAF : : SetupPose ( idEntity * ent , int time )
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
idAFBody * body ;
2012-11-26 18:58:24 +00:00
idVec3 origin ;
idMat3 axis ;
2012-11-28 15:47:07 +00:00
idAnimator * animatorPtr ;
renderEntity_t * renderEntity ;
if ( ! IsLoaded ( ) | | ! ent )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
animatorPtr = ent - > GetAnimator ( ) ;
2012-11-28 15:47:07 +00:00
if ( ! animatorPtr )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderEntity = ent - > GetRenderEntity ( ) ;
2012-11-28 15:47:07 +00:00
if ( ! renderEntity )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if the animation is driven by the physics
2012-11-28 15:47:07 +00:00
if ( self - > GetPhysics ( ) = = & physicsObj )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if the pose was already updated this frame
2012-11-28 15:47:07 +00:00
if ( poseTime = = time )
{
2012-11-26 18:58:24 +00:00
return ;
}
poseTime = time ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < jointMods . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
body = physicsObj . GetBody ( jointMods [ i ] . bodyId ) ;
animatorPtr - > GetJointTransform ( jointMods [ i ] . jointHandle , time , origin , axis ) ;
body - > SetWorldOrigin ( renderEntity - > origin + ( origin + jointMods [ i ] . jointBodyOrigin * axis ) * renderEntity - > axis ) ;
body - > SetWorldAxis ( jointMods [ i ] . jointBodyAxis * axis * renderEntity - > axis ) ;
}
2012-11-28 15:47:07 +00:00
if ( isActive )
{
2012-11-26 18:58:24 +00:00
physicsObj . UpdateClipModels ( ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idAF : : ChangePose
Change the articulated figure to match the current animation pose of the given entity
and set the velocity relative to the previous pose .
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAF : : ChangePose ( idEntity * ent , int time )
{
2012-11-26 18:58:24 +00:00
int i ;
float invDelta ;
2012-11-28 15:47:07 +00:00
idAFBody * body ;
2012-11-26 18:58:24 +00:00
idVec3 origin , lastOrigin ;
idMat3 axis ;
2012-11-28 15:47:07 +00:00
idAnimator * animatorPtr ;
renderEntity_t * renderEntity ;
if ( ! IsLoaded ( ) | | ! ent )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
animatorPtr = ent - > GetAnimator ( ) ;
2012-11-28 15:47:07 +00:00
if ( ! animatorPtr )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
renderEntity = ent - > GetRenderEntity ( ) ;
2012-11-28 15:47:07 +00:00
if ( ! renderEntity )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if the animation is driven by the physics
2012-11-28 15:47:07 +00:00
if ( self - > GetPhysics ( ) = = & physicsObj )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if the pose was already updated this frame
2012-11-28 15:47:07 +00:00
if ( poseTime = = time )
{
2012-11-26 18:58:24 +00:00
return ;
}
invDelta = 1.0f / MS2SEC ( time - poseTime ) ;
poseTime = time ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < jointMods . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
body = physicsObj . GetBody ( jointMods [ i ] . bodyId ) ;
animatorPtr - > GetJointTransform ( jointMods [ i ] . jointHandle , time , origin , axis ) ;
lastOrigin = body - > GetWorldOrigin ( ) ;
body - > SetWorldOrigin ( renderEntity - > origin + ( origin + jointMods [ i ] . jointBodyOrigin * axis ) * renderEntity - > axis ) ;
body - > SetWorldAxis ( jointMods [ i ] . jointBodyAxis * axis * renderEntity - > axis ) ;
body - > SetLinearVelocity ( ( body - > GetWorldOrigin ( ) - lastOrigin ) * invDelta ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
physicsObj . UpdateClipModels ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idAF : : EntitiesTouchingAF
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idAF : : EntitiesTouchingAF ( afTouch_t touchList [ MAX_GENTITIES ] ) const
{
2012-11-26 18:58:24 +00:00
int i , j , numClipModels ;
2012-11-28 15:47:07 +00:00
idAFBody * body ;
idClipModel * cm ;
idClipModel * clipModels [ MAX_GENTITIES ] ;
2012-11-26 18:58:24 +00:00
int numTouching ;
2012-11-28 15:47:07 +00:00
if ( ! IsLoaded ( ) )
{
2012-11-26 18:58:24 +00:00
return 0 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
numTouching = 0 ;
numClipModels = gameLocal . clip . ClipModelsTouchingBounds ( physicsObj . GetAbsBounds ( ) , - 1 , clipModels , MAX_GENTITIES ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < jointMods . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
body = physicsObj . GetBody ( jointMods [ i ] . bodyId ) ;
2012-11-28 15:47:07 +00:00
for ( j = 0 ; j < numClipModels ; j + + )
{
2012-11-26 18:58:24 +00:00
cm = clipModels [ j ] ;
2012-11-28 15:47:07 +00:00
if ( ! cm | | cm - > GetEntity ( ) = = self )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( ! cm - > IsTraceModel ( ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( ! body - > GetClipModel ( ) - > GetAbsBounds ( ) . IntersectsBounds ( cm - > GetAbsBounds ( ) ) )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( gameLocal . clip . ContentsModel ( body - > GetWorldOrigin ( ) , body - > GetClipModel ( ) , body - > GetWorldAxis ( ) , - 1 , cm - > Handle ( ) , cm - > GetOrigin ( ) , cm - > GetAxis ( ) ) )
{
2012-11-26 18:58:24 +00:00
touchList [ numTouching ] . touchedByBody = body ;
touchList [ numTouching ] . touchedClipModel = cm ;
touchList [ numTouching ] . touchedEnt = cm - > GetEntity ( ) ;
numTouching + + ;
clipModels [ j ] = NULL ;
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return numTouching ;
}
/*
= = = = = = = = = = = = = = = =
idAF : : BodyForClipModelId
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idAF : : BodyForClipModelId ( int id ) const
{
if ( id > = 0 )
{
2012-11-26 18:58:24 +00:00
return id ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
id = CLIPMODEL_ID_TO_JOINT_HANDLE ( id ) ;
2012-11-28 15:47:07 +00:00
if ( id < jointBody . Num ( ) )
{
2012-11-26 18:58:24 +00:00
return jointBody [ id ] ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
return 0 ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idAF : : GetPhysicsToVisualTransform
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAF : : GetPhysicsToVisualTransform ( idVec3 & origin , idMat3 & axis ) const
{
2012-11-26 18:58:24 +00:00
origin = - baseOrigin ;
axis = baseAxis . Transpose ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idAF : : GetImpactInfo
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAF : : GetImpactInfo ( idEntity * ent , int id , const idVec3 & point , impactInfo_t * info )
{
2012-11-26 18:58:24 +00:00
SetupPose ( self , gameLocal . time ) ;
physicsObj . GetImpactInfo ( BodyForClipModelId ( id ) , point , info ) ;
}
/*
= = = = = = = = = = = = = = = =
idAF : : ApplyImpulse
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAF : : ApplyImpulse ( idEntity * ent , int id , const idVec3 & point , const idVec3 & impulse )
{
2012-11-26 18:58:24 +00:00
SetupPose ( self , gameLocal . time ) ;
physicsObj . ApplyImpulse ( BodyForClipModelId ( id ) , point , impulse ) ;
}
/*
= = = = = = = = = = = = = = = =
idAF : : AddForce
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAF : : AddForce ( idEntity * ent , int id , const idVec3 & point , const idVec3 & force )
{
2012-11-26 18:58:24 +00:00
SetupPose ( self , gameLocal . time ) ;
physicsObj . AddForce ( BodyForClipModelId ( id ) , point , force ) ;
}
/*
= = = = = = = = = = = = = = = =
idAF : : AddBody
Adds a body .
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAF : : AddBody ( idAFBody * body , const idJointMat * joints , const char * jointName , const AFJointModType_t mod )
{
2012-11-26 18:58:24 +00:00
int index ;
jointHandle_t handle ;
idVec3 origin ;
idMat3 axis ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
handle = animator - > GetJointHandle ( jointName ) ;
2012-11-28 15:47:07 +00:00
if ( handle = = INVALID_JOINT )
{
gameLocal . Error ( " idAF for entity '%s' at (%s) modifies unknown joint '%s' " , self - > name . c_str ( ) , self - > GetPhysics ( ) - > GetOrigin ( ) . ToString ( 0 ) , jointName ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
assert ( handle < animator - > NumJoints ( ) ) ;
origin = joints [ handle ] . ToVec3 ( ) ;
axis = joints [ handle ] . ToMat3 ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
index = jointMods . Num ( ) ;
jointMods . SetNum ( index + 1 ) ;
jointMods [ index ] . bodyId = physicsObj . GetBodyId ( body ) ;
jointMods [ index ] . jointHandle = handle ;
jointMods [ index ] . jointMod = mod ;
jointMods [ index ] . jointBodyOrigin = ( body - > GetWorldOrigin ( ) - origin ) * axis . Transpose ( ) ;
jointMods [ index ] . jointBodyAxis = body - > GetWorldAxis ( ) * axis . Transpose ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idAF : : SetBase
Sets the base body .
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAF : : SetBase ( idAFBody * body , const idJointMat * joints )
{
2012-11-26 18:58:24 +00:00
physicsObj . ForceBodyId ( body , 0 ) ;
baseOrigin = body - > GetWorldOrigin ( ) ;
baseAxis = body - > GetWorldAxis ( ) ;
AddBody ( body , joints , animator - > GetJointName ( animator - > GetFirstChild ( " origin " ) ) , AF_JOINTMOD_AXIS ) ;
}
/*
= = = = = = = = = = = = = = = =
idAF : : LoadBody
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idAF : : LoadBody ( const idDeclAF_Body * fb , const idJointMat * joints )
{
2012-11-26 18:58:24 +00:00
int id , i ;
float length , mass ;
idTraceModel trm ;
2012-11-28 15:47:07 +00:00
idClipModel * clip ;
idAFBody * body ;
2012-11-26 18:58:24 +00:00
idMat3 axis , inertiaTensor ;
idVec3 centerOfMass , origin ;
idBounds bounds ;
idList < jointHandle_t , TAG_AF > jointList ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
origin = fb - > origin . ToVec3 ( ) ;
axis = fb - > angles . ToMat3 ( ) ;
bounds [ 0 ] = fb - > v1 . ToVec3 ( ) ;
bounds [ 1 ] = fb - > v2 . ToVec3 ( ) ;
2012-11-28 15:47:07 +00:00
switch ( fb - > modelType )
{
case TRM_BOX :
{
2012-11-26 18:58:24 +00:00
trm . SetupBox ( bounds ) ;
break ;
}
2012-11-28 15:47:07 +00:00
case TRM_OCTAHEDRON :
{
2012-11-26 18:58:24 +00:00
trm . SetupOctahedron ( bounds ) ;
break ;
}
2012-11-28 15:47:07 +00:00
case TRM_DODECAHEDRON :
{
2012-11-26 18:58:24 +00:00
trm . SetupDodecahedron ( bounds ) ;
break ;
}
2012-11-28 15:47:07 +00:00
case TRM_CYLINDER :
{
2012-11-26 18:58:24 +00:00
trm . SetupCylinder ( bounds , fb - > numSides ) ;
break ;
}
2012-11-28 15:47:07 +00:00
case TRM_CONE :
{
2012-11-26 18:58:24 +00:00
// place the apex at the origin
bounds [ 0 ] . z - = bounds [ 1 ] . z ;
bounds [ 1 ] . z = 0.0f ;
trm . SetupCone ( bounds , fb - > numSides ) ;
break ;
}
2012-11-28 15:47:07 +00:00
case TRM_BONE :
{
2012-11-26 18:58:24 +00:00
// direction of bone
axis [ 2 ] = fb - > v2 . ToVec3 ( ) - fb - > v1 . ToVec3 ( ) ;
length = axis [ 2 ] . Normalize ( ) ;
// axis of bone trace model
axis [ 2 ] . NormalVectors ( axis [ 0 ] , axis [ 1 ] ) ;
axis [ 1 ] = - axis [ 1 ] ;
// create bone trace model
trm . SetupBone ( length , fb - > width ) ;
break ;
}
default :
assert ( 0 ) ;
break ;
}
trm . GetMassProperties ( 1.0f , mass , centerOfMass , inertiaTensor ) ;
trm . Translate ( - centerOfMass ) ;
origin + = centerOfMass * axis ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
body = physicsObj . GetBody ( fb - > name ) ;
2012-11-28 15:47:07 +00:00
if ( body )
{
2012-11-26 18:58:24 +00:00
clip = body - > GetClipModel ( ) ;
2012-11-28 15:47:07 +00:00
if ( ! clip - > IsEqual ( trm ) )
{
clip = new ( TAG_PHYSICS_CLIP_AF ) idClipModel ( trm ) ;
2012-11-26 18:58:24 +00:00
clip - > SetContents ( fb - > contents ) ;
clip - > Link ( gameLocal . clip , self , 0 , origin , axis ) ;
body - > SetClipModel ( clip ) ;
}
clip - > SetContents ( fb - > contents ) ;
body - > SetDensity ( fb - > density , fb - > inertiaScale ) ;
body - > SetWorldOrigin ( origin ) ;
body - > SetWorldAxis ( axis ) ;
id = physicsObj . GetBodyId ( body ) ;
}
2012-11-28 15:47:07 +00:00
else
{
clip = new ( TAG_PHYSICS_CLIP_AF ) idClipModel ( trm ) ;
2012-11-26 18:58:24 +00:00
clip - > SetContents ( fb - > contents ) ;
clip - > Link ( gameLocal . clip , self , 0 , origin , axis ) ;
2012-11-28 15:47:07 +00:00
body = new ( TAG_PHYSICS_AF ) idAFBody ( fb - > name , clip , fb - > density ) ;
if ( fb - > inertiaScale ! = mat3_identity )
{
2012-11-26 18:58:24 +00:00
body - > SetDensity ( fb - > density , fb - > inertiaScale ) ;
}
id = physicsObj . AddBody ( body ) ;
}
2012-11-28 15:47:07 +00:00
if ( fb - > linearFriction ! = - 1.0f )
{
2012-11-26 18:58:24 +00:00
body - > SetFriction ( fb - > linearFriction , fb - > angularFriction , fb - > contactFriction ) ;
}
body - > SetClipMask ( fb - > clipMask ) ;
body - > SetSelfCollision ( fb - > selfCollision ) ;
2012-11-28 15:47:07 +00:00
if ( fb - > jointName = = " origin " )
{
2012-11-26 18:58:24 +00:00
SetBase ( body , joints ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
AFJointModType_t mod ;
2012-11-28 15:47:07 +00:00
if ( fb - > jointMod = = DECLAF_JOINTMOD_AXIS )
{
2012-11-26 18:58:24 +00:00
mod = AF_JOINTMOD_AXIS ;
2012-11-28 15:47:07 +00:00
}
else if ( fb - > jointMod = = DECLAF_JOINTMOD_ORIGIN )
{
2012-11-26 18:58:24 +00:00
mod = AF_JOINTMOD_ORIGIN ;
2012-11-28 15:47:07 +00:00
}
else if ( fb - > jointMod = = DECLAF_JOINTMOD_BOTH )
{
2012-11-26 18:58:24 +00:00
mod = AF_JOINTMOD_BOTH ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
mod = AF_JOINTMOD_AXIS ;
}
AddBody ( body , joints , fb - > jointName , mod ) ;
}
2012-11-28 15:47:07 +00:00
if ( fb - > frictionDirection . ToVec3 ( ) ! = vec3_origin )
{
2012-11-26 18:58:24 +00:00
body - > SetFrictionDirection ( fb - > frictionDirection . ToVec3 ( ) ) ;
}
2012-11-28 15:47:07 +00:00
if ( fb - > contactMotorDirection . ToVec3 ( ) ! = vec3_origin )
{
2012-11-26 18:58:24 +00:00
body - > SetContactMotorDirection ( fb - > contactMotorDirection . ToVec3 ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// update table to find the nearest articulated figure body for a joint of the skeletal model
animator - > GetJointList ( fb - > containedJoints , jointList ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < jointList . Num ( ) ; i + + )
{
if ( jointBody [ jointList [ i ] ] ! = - 1 )
{
2012-11-26 18:58:24 +00:00
gameLocal . Warning ( " %s: joint '%s' is already contained by body '%s' " ,
2012-11-28 15:47:07 +00:00
name . c_str ( ) , animator - > GetJointName ( ( jointHandle_t ) jointList [ i ] ) ,
physicsObj . GetBody ( jointBody [ jointList [ i ] ] ) - > GetName ( ) . c_str ( ) ) ;
2012-11-26 18:58:24 +00:00
}
jointBody [ jointList [ i ] ] = id ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return true ;
}
/*
= = = = = = = = = = = = = = = =
idAF : : LoadConstraint
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idAF : : LoadConstraint ( const idDeclAF_Constraint * fc )
{
idAFBody * body1 , * body2 ;
2012-11-26 18:58:24 +00:00
idAngles angles ;
2012-11-28 15:47:07 +00:00
idMat3 axis ;
2012-11-26 18:58:24 +00:00
body1 = physicsObj . GetBody ( fc - > body1 ) ;
body2 = physicsObj . GetBody ( fc - > body2 ) ;
2012-11-28 15:47:07 +00:00
switch ( fc - > type )
{
case DECLAF_CONSTRAINT_FIXED :
{
idAFConstraint_Fixed * c ;
c = static_cast < idAFConstraint_Fixed * > ( physicsObj . GetConstraint ( fc - > name ) ) ;
if ( c )
{
2012-11-26 18:58:24 +00:00
c - > SetBody1 ( body1 ) ;
c - > SetBody2 ( body2 ) ;
}
2012-11-28 15:47:07 +00:00
else
{
c = new ( TAG_PHYSICS_AF ) idAFConstraint_Fixed ( fc - > name , body1 , body2 ) ;
2012-11-26 18:58:24 +00:00
physicsObj . AddConstraint ( c ) ;
}
break ;
}
2012-11-28 15:47:07 +00:00
case DECLAF_CONSTRAINT_BALLANDSOCKETJOINT :
{
idAFConstraint_BallAndSocketJoint * c ;
c = static_cast < idAFConstraint_BallAndSocketJoint * > ( physicsObj . GetConstraint ( fc - > name ) ) ;
if ( c )
{
2012-11-26 18:58:24 +00:00
c - > SetBody1 ( body1 ) ;
c - > SetBody2 ( body2 ) ;
}
2012-11-28 15:47:07 +00:00
else
{
c = new ( TAG_PHYSICS_AF ) idAFConstraint_BallAndSocketJoint ( fc - > name , body1 , body2 ) ;
2012-11-26 18:58:24 +00:00
physicsObj . AddConstraint ( c ) ;
}
c - > SetAnchor ( fc - > anchor . ToVec3 ( ) ) ;
c - > SetFriction ( fc - > friction ) ;
2012-11-28 15:47:07 +00:00
switch ( fc - > limit )
{
case idDeclAF_Constraint : : LIMIT_CONE :
{
2012-11-26 18:58:24 +00:00
c - > SetConeLimit ( fc - > limitAxis . ToVec3 ( ) , fc - > limitAngles [ 0 ] , fc - > shaft [ 0 ] . ToVec3 ( ) ) ;
break ;
}
2012-11-28 15:47:07 +00:00
case idDeclAF_Constraint : : LIMIT_PYRAMID :
{
2012-11-26 18:58:24 +00:00
angles = fc - > limitAxis . ToVec3 ( ) . ToAngles ( ) ;
angles . roll = fc - > limitAngles [ 2 ] ;
axis = angles . ToMat3 ( ) ;
c - > SetPyramidLimit ( axis [ 0 ] , axis [ 1 ] , fc - > limitAngles [ 0 ] , fc - > limitAngles [ 1 ] , fc - > shaft [ 0 ] . ToVec3 ( ) ) ;
break ;
}
2012-11-28 15:47:07 +00:00
default :
{
2012-11-26 18:58:24 +00:00
c - > SetNoLimit ( ) ;
break ;
}
}
break ;
}
2012-11-28 15:47:07 +00:00
case DECLAF_CONSTRAINT_UNIVERSALJOINT :
{
idAFConstraint_UniversalJoint * c ;
c = static_cast < idAFConstraint_UniversalJoint * > ( physicsObj . GetConstraint ( fc - > name ) ) ;
if ( c )
{
2012-11-26 18:58:24 +00:00
c - > SetBody1 ( body1 ) ;
c - > SetBody2 ( body2 ) ;
}
2012-11-28 15:47:07 +00:00
else
{
c = new ( TAG_PHYSICS_AF ) idAFConstraint_UniversalJoint ( fc - > name , body1 , body2 ) ;
2012-11-26 18:58:24 +00:00
physicsObj . AddConstraint ( c ) ;
}
c - > SetAnchor ( fc - > anchor . ToVec3 ( ) ) ;
c - > SetShafts ( fc - > shaft [ 0 ] . ToVec3 ( ) , fc - > shaft [ 1 ] . ToVec3 ( ) ) ;
c - > SetFriction ( fc - > friction ) ;
2012-11-28 15:47:07 +00:00
switch ( fc - > limit )
{
case idDeclAF_Constraint : : LIMIT_CONE :
{
2012-11-26 18:58:24 +00:00
c - > SetConeLimit ( fc - > limitAxis . ToVec3 ( ) , fc - > limitAngles [ 0 ] ) ;
break ;
}
2012-11-28 15:47:07 +00:00
case idDeclAF_Constraint : : LIMIT_PYRAMID :
{
2012-11-26 18:58:24 +00:00
angles = fc - > limitAxis . ToVec3 ( ) . ToAngles ( ) ;
angles . roll = fc - > limitAngles [ 2 ] ;
axis = angles . ToMat3 ( ) ;
c - > SetPyramidLimit ( axis [ 0 ] , axis [ 1 ] , fc - > limitAngles [ 0 ] , fc - > limitAngles [ 1 ] ) ;
break ;
}
2012-11-28 15:47:07 +00:00
default :
{
2012-11-26 18:58:24 +00:00
c - > SetNoLimit ( ) ;
break ;
}
}
break ;
}
2012-11-28 15:47:07 +00:00
case DECLAF_CONSTRAINT_HINGE :
{
idAFConstraint_Hinge * c ;
c = static_cast < idAFConstraint_Hinge * > ( physicsObj . GetConstraint ( fc - > name ) ) ;
if ( c )
{
2012-11-26 18:58:24 +00:00
c - > SetBody1 ( body1 ) ;
c - > SetBody2 ( body2 ) ;
}
2012-11-28 15:47:07 +00:00
else
{
c = new ( TAG_PHYSICS_AF ) idAFConstraint_Hinge ( fc - > name , body1 , body2 ) ;
2012-11-26 18:58:24 +00:00
physicsObj . AddConstraint ( c ) ;
}
c - > SetAnchor ( fc - > anchor . ToVec3 ( ) ) ;
c - > SetAxis ( fc - > axis . ToVec3 ( ) ) ;
c - > SetFriction ( fc - > friction ) ;
2012-11-28 15:47:07 +00:00
switch ( fc - > limit )
{
case idDeclAF_Constraint : : LIMIT_CONE :
{
2012-11-26 18:58:24 +00:00
idVec3 left , up , axis , shaft ;
fc - > axis . ToVec3 ( ) . OrthogonalBasis ( left , up ) ;
axis = left * idRotation ( vec3_origin , fc - > axis . ToVec3 ( ) , fc - > limitAngles [ 0 ] ) ;
shaft = left * idRotation ( vec3_origin , fc - > axis . ToVec3 ( ) , fc - > limitAngles [ 2 ] ) ;
c - > SetLimit ( axis , fc - > limitAngles [ 1 ] , shaft ) ;
break ;
}
2012-11-28 15:47:07 +00:00
default :
{
2012-11-26 18:58:24 +00:00
c - > SetNoLimit ( ) ;
break ;
}
}
break ;
}
2012-11-28 15:47:07 +00:00
case DECLAF_CONSTRAINT_SLIDER :
{
idAFConstraint_Slider * c ;
c = static_cast < idAFConstraint_Slider * > ( physicsObj . GetConstraint ( fc - > name ) ) ;
if ( c )
{
2012-11-26 18:58:24 +00:00
c - > SetBody1 ( body1 ) ;
c - > SetBody2 ( body2 ) ;
}
2012-11-28 15:47:07 +00:00
else
{
c = new ( TAG_PHYSICS_AF ) idAFConstraint_Slider ( fc - > name , body1 , body2 ) ;
2012-11-26 18:58:24 +00:00
physicsObj . AddConstraint ( c ) ;
}
c - > SetAxis ( fc - > axis . ToVec3 ( ) ) ;
break ;
}
2012-11-28 15:47:07 +00:00
case DECLAF_CONSTRAINT_SPRING :
{
idAFConstraint_Spring * c ;
c = static_cast < idAFConstraint_Spring * > ( physicsObj . GetConstraint ( fc - > name ) ) ;
if ( c )
{
2012-11-26 18:58:24 +00:00
c - > SetBody1 ( body1 ) ;
c - > SetBody2 ( body2 ) ;
}
2012-11-28 15:47:07 +00:00
else
{
c = new ( TAG_PHYSICS_AF ) idAFConstraint_Spring ( fc - > name , body1 , body2 ) ;
2012-11-26 18:58:24 +00:00
physicsObj . AddConstraint ( c ) ;
}
c - > SetAnchor ( fc - > anchor . ToVec3 ( ) , fc - > anchor2 . ToVec3 ( ) ) ;
c - > SetSpring ( fc - > stretch , fc - > compress , fc - > damping , fc - > restLength ) ;
c - > SetLimit ( fc - > minLength , fc - > maxLength ) ;
break ;
}
}
return true ;
}
/*
= = = = = = = = = = = = = = = =
GetJointTransform
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
static bool GetJointTransform ( void * model , const idJointMat * frame , const char * jointName , idVec3 & origin , idMat3 & axis )
{
2012-11-26 18:58:24 +00:00
jointHandle_t joint ;
2012-11-28 15:47:07 +00:00
joint = reinterpret_cast < idAnimator * > ( model ) - > GetJointHandle ( jointName ) ;
if ( ( joint > = 0 ) & & ( joint < reinterpret_cast < idAnimator * > ( model ) - > NumJoints ( ) ) )
{
2012-11-26 18:58:24 +00:00
origin = frame [ joint ] . ToVec3 ( ) ;
axis = frame [ joint ] . ToMat3 ( ) ;
return true ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
return false ;
}
}
/*
= = = = = = = = = = = = = = = =
idAF : : Load
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idAF : : Load ( idEntity * ent , const char * fileName )
{
2012-11-26 18:58:24 +00:00
int i , j ;
2012-11-28 15:47:07 +00:00
const idDeclAF * file ;
const idDeclModelDef * modelDef ;
idRenderModel * model ;
2012-11-26 18:58:24 +00:00
int numJoints ;
2012-11-28 15:47:07 +00:00
idJointMat * joints ;
2012-11-26 18:58:24 +00:00
assert ( ent ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
self = ent ;
physicsObj . SetSelf ( self ) ;
2012-11-28 15:47:07 +00:00
if ( animator = = NULL )
{
gameLocal . Warning ( " Couldn't load af '%s' for entity '%s' at (%s): NULL animator \n " , name . c_str ( ) , ent - > name . c_str ( ) , ent - > GetPhysics ( ) - > GetOrigin ( ) . ToString ( 0 ) ) ;
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
name = fileName ;
name . StripFileExtension ( ) ;
2012-11-28 15:47:07 +00:00
file = static_cast < const idDeclAF * > ( declManager - > FindType ( DECL_AF , name ) ) ;
if ( ! file )
{
gameLocal . Warning ( " Couldn't load af '%s' for entity '%s' at (%s) \n " , name . c_str ( ) , ent - > name . c_str ( ) , ent - > GetPhysics ( ) - > GetOrigin ( ) . ToString ( 0 ) ) ;
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
if ( file - > bodies . Num ( ) = = 0 | | file - > bodies [ 0 ] - > jointName ! = " origin " )
{
2012-11-26 18:58:24 +00:00
gameLocal . Warning ( " idAF::Load: articulated figure '%s' for entity '%s' at (%s) has no body which modifies the origin joint. " ,
2012-11-28 15:47:07 +00:00
name . c_str ( ) , ent - > name . c_str ( ) , ent - > GetPhysics ( ) - > GetOrigin ( ) . ToString ( 0 ) ) ;
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
modelDef = animator - > ModelDef ( ) ;
2012-11-28 15:47:07 +00:00
if ( modelDef = = NULL | | modelDef - > GetState ( ) = = DS_DEFAULTED )
{
2012-11-26 18:58:24 +00:00
gameLocal . Warning ( " idAF::Load: articulated figure '%s' for entity '%s' at (%s) has no or defaulted modelDef '%s' " ,
2012-11-28 15:47:07 +00:00
name . c_str ( ) , ent - > name . c_str ( ) , ent - > GetPhysics ( ) - > GetOrigin ( ) . ToString ( 0 ) , modelDef ? modelDef - > GetName ( ) : " " ) ;
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
model = animator - > ModelHandle ( ) ;
2012-11-28 15:47:07 +00:00
if ( model = = NULL | | model - > IsDefaultModel ( ) )
{
2012-11-26 18:58:24 +00:00
gameLocal . Warning ( " idAF::Load: articulated figure '%s' for entity '%s' at (%s) has no or defaulted model '%s' " ,
2012-11-28 15:47:07 +00:00
name . c_str ( ) , ent - > name . c_str ( ) , ent - > GetPhysics ( ) - > GetOrigin ( ) . ToString ( 0 ) , model ? model - > Name ( ) : " " ) ;
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// get the modified animation
modifiedAnim = animator - > GetAnim ( ARTICULATED_FIGURE_ANIM ) ;
2012-11-28 15:47:07 +00:00
if ( ! modifiedAnim )
{
2012-11-26 18:58:24 +00:00
gameLocal . Warning ( " idAF::Load: articulated figure '%s' for entity '%s' at (%s) has no modified animation '%s' " ,
2012-11-28 15:47:07 +00:00
name . c_str ( ) , ent - > name . c_str ( ) , ent - > GetPhysics ( ) - > GetOrigin ( ) . ToString ( 0 ) , ARTICULATED_FIGURE_ANIM ) ;
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// create the animation frame used to setup the articulated figure
numJoints = animator - > NumJoints ( ) ;
2012-11-28 15:47:07 +00:00
joints = ( idJointMat * ) _alloca16 ( numJoints * sizeof ( joints [ 0 ] ) ) ;
2012-11-26 18:58:24 +00:00
gameEdit - > ANIM_CreateAnimFrame ( model , animator - > GetAnim ( modifiedAnim ) - > MD5Anim ( 0 ) , numJoints , joints , 1 , animator - > ModelDef ( ) - > GetVisualOffset ( ) , animator - > RemoveOrigin ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set all vector positions from model joints
file - > Finish ( GetJointTransform , joints , animator ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// initialize articulated figure physics
physicsObj . SetGravity ( gameLocal . GetGravity ( ) ) ;
physicsObj . SetClipMask ( file - > clipMask ) ;
physicsObj . SetDefaultFriction ( file - > defaultLinearFriction , file - > defaultAngularFriction , file - > defaultContactFriction ) ;
physicsObj . SetSuspendSpeed ( file - > suspendVelocity , file - > suspendAcceleration ) ;
physicsObj . SetSuspendTolerance ( file - > noMoveTime , file - > noMoveTranslation , file - > noMoveRotation ) ;
physicsObj . SetSuspendTime ( file - > minMoveTime , file - > maxMoveTime ) ;
physicsObj . SetSelfCollision ( file - > selfCollision ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// clear the list with transforms from joints to bodies
jointMods . SetNum ( 0 ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// clear the joint to body conversion list
jointBody . AssureSize ( animator - > NumJoints ( ) ) ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < jointBody . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
jointBody [ i ] = - 1 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// delete any bodies in the physicsObj that are no longer in the idDeclAF
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < physicsObj . GetNumBodies ( ) ; i + + )
{
idAFBody * body = physicsObj . GetBody ( i ) ;
for ( j = 0 ; j < file - > bodies . Num ( ) ; j + + )
{
if ( file - > bodies [ j ] - > name . Icmp ( body - > GetName ( ) ) = = 0 )
{
2012-11-26 18:58:24 +00:00
break ;
}
}
2012-11-28 15:47:07 +00:00
if ( j > = file - > bodies . Num ( ) )
{
2012-11-26 18:58:24 +00:00
physicsObj . DeleteBody ( i ) ;
i - - ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// delete any constraints in the physicsObj that are no longer in the idDeclAF
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < physicsObj . GetNumConstraints ( ) ; i + + )
{
idAFConstraint * constraint = physicsObj . GetConstraint ( i ) ;
for ( j = 0 ; j < file - > constraints . Num ( ) ; j + + )
{
2012-11-26 18:58:24 +00:00
// idADConstraint enum is a superset of declADConstraint, so the cast is valid
2012-11-28 15:47:07 +00:00
if ( file - > constraints [ j ] - > name . Icmp ( constraint - > GetName ( ) ) = = 0 & &
( constraintType_t ) ( file - > constraints [ j ] - > type ) = = constraint - > GetType ( ) )
{
2012-11-26 18:58:24 +00:00
break ;
}
}
2012-11-28 15:47:07 +00:00
if ( j > = file - > constraints . Num ( ) )
{
2012-11-26 18:58:24 +00:00
physicsObj . DeleteConstraint ( i ) ;
i - - ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// load bodies from the file
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < file - > bodies . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
LoadBody ( file - > bodies [ i ] , joints ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// load constraints from the file
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < file - > constraints . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
LoadConstraint ( file - > constraints [ i ] ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
physicsObj . UpdateClipModels ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check if each joint is contained by a body
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < animator - > NumJoints ( ) ; i + + )
{
if ( jointBody [ i ] = = - 1 )
{
2012-11-26 18:58:24 +00:00
gameLocal . Warning ( " idAF::Load: articulated figure '%s' for entity '%s' at (%s) joint '%s' is not contained by a body " ,
2012-11-28 15:47:07 +00:00
name . c_str ( ) , self - > name . c_str ( ) , self - > GetPhysics ( ) - > GetOrigin ( ) . ToString ( 0 ) , animator - > GetJointName ( ( jointHandle_t ) i ) ) ;
2012-11-26 18:58:24 +00:00
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
physicsObj . SetMass ( file - > totalMass ) ;
physicsObj . SetChanged ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// disable the articulated figure for collision detection until activated
physicsObj . DisableClip ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
isLoaded = true ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return true ;
}
/*
= = = = = = = = = = = = = = = =
idAF : : Start
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAF : : Start ( )
{
if ( ! IsLoaded ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
// clear all animations
animator - > ClearAllAnims ( gameLocal . time , 0 ) ;
animator - > ClearAllJoints ( ) ;
// switch to articulated figure physics
self - > SetPhysics ( & physicsObj ) ;
// start the articulated figure physics simulation
physicsObj . EnableClip ( ) ;
physicsObj . Activate ( ) ;
isActive = true ;
}
/*
= = = = = = = = = = = = = = = =
idAF : : TestSolid
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idAF : : TestSolid ( ) const
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
idAFBody * body ;
2012-11-26 18:58:24 +00:00
trace_t trace ;
idStr str ;
bool solid ;
2012-11-28 15:47:07 +00:00
if ( ! IsLoaded ( ) )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
if ( ! af_testSolid . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
solid = false ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < physicsObj . GetNumBodies ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
body = physicsObj . GetBody ( i ) ;
2012-11-28 15:47:07 +00:00
if ( gameLocal . clip . Translation ( trace , body - > GetWorldOrigin ( ) , body - > GetWorldOrigin ( ) , body - > GetClipModel ( ) , body - > GetWorldAxis ( ) , body - > GetClipMask ( ) , self ) )
{
2012-11-26 18:58:24 +00:00
float depth = idMath : : Fabs ( trace . c . point * trace . c . normal - trace . c . dist ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
body - > SetWorldOrigin ( body - > GetWorldOrigin ( ) + trace . c . normal * ( depth + 8.0f ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
gameLocal . DWarning ( " %s: body '%s' stuck in %d (normal = %.2f %.2f %.2f, depth = %.2f) " , self - > name . c_str ( ) ,
2012-11-28 15:47:07 +00:00
body - > GetName ( ) . c_str ( ) , trace . c . contents , trace . c . normal . x , trace . c . normal . y , trace . c . normal . z , depth ) ;
2012-11-26 18:58:24 +00:00
solid = true ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
}
}
return solid ;
}
/*
= = = = = = = = = = = = = = = =
idAF : : StartFromCurrentPose
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAF : : StartFromCurrentPose ( int inheritVelocityTime )
{
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
if ( ! IsLoaded ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if the ragdoll should inherit velocity from the animation
2012-11-28 15:47:07 +00:00
if ( inheritVelocityTime > 0 )
{
2012-11-26 18:58:24 +00:00
// make sure the ragdoll is at rest
physicsObj . PutToRest ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set the pose for some time back
SetupPose ( self , gameLocal . time - inheritVelocityTime ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// change the pose for the current time and set velocities
ChangePose ( self , gameLocal . time ) ;
}
2012-11-28 15:47:07 +00:00
else
{
2012-11-26 18:58:24 +00:00
// transform the articulated figure to reflect the current animation pose
SetupPose ( self , gameLocal . time ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
physicsObj . UpdateClipModels ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
TestSolid ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
Start ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
UpdateAnimation ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// update the render entity origin and axis
self - > UpdateModel ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// make sure the renderer gets the updated origin and axis
self - > Present ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idAF : : Stop
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAF : : Stop ( )
{
2012-11-26 18:58:24 +00:00
// disable the articulated figure for collision detection
physicsObj . UnlinkClip ( ) ;
isActive = false ;
}
/*
= = = = = = = = = = = = = = = =
idAF : : Rest
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAF : : Rest ( )
{
2012-11-26 18:58:24 +00:00
physicsObj . PutToRest ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idAF : : SetConstraintPosition
Only moves constraints that bind the entity to another entity .
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAF : : SetConstraintPosition ( const char * name , const idVec3 & pos )
{
idAFConstraint * constraint ;
2012-11-26 18:58:24 +00:00
constraint = GetPhysics ( ) - > GetConstraint ( name ) ;
2012-11-28 15:47:07 +00:00
if ( ! constraint )
{
2012-11-26 18:58:24 +00:00
gameLocal . Warning ( " can't find a constraint with the name '%s' " , name ) ;
return ;
}
2012-11-28 15:47:07 +00:00
if ( constraint - > GetBody2 ( ) ! = NULL )
{
2012-11-26 18:58:24 +00:00
gameLocal . Warning ( " constraint '%s' does not bind to another entity " , name ) ;
return ;
}
2012-11-28 15:47:07 +00:00
switch ( constraint - > GetType ( ) )
{
case CONSTRAINT_BALLANDSOCKETJOINT :
{
idAFConstraint_BallAndSocketJoint * bs = static_cast < idAFConstraint_BallAndSocketJoint * > ( constraint ) ;
2012-11-26 18:58:24 +00:00
bs - > Translate ( pos - bs - > GetAnchor ( ) ) ;
break ;
}
2012-11-28 15:47:07 +00:00
case CONSTRAINT_UNIVERSALJOINT :
{
idAFConstraint_UniversalJoint * uj = static_cast < idAFConstraint_UniversalJoint * > ( constraint ) ;
2012-11-26 18:58:24 +00:00
uj - > Translate ( pos - uj - > GetAnchor ( ) ) ;
break ;
}
2012-11-28 15:47:07 +00:00
case CONSTRAINT_HINGE :
{
idAFConstraint_Hinge * hinge = static_cast < idAFConstraint_Hinge * > ( constraint ) ;
2012-11-26 18:58:24 +00:00
hinge - > Translate ( pos - hinge - > GetAnchor ( ) ) ;
break ;
}
2012-11-28 15:47:07 +00:00
default :
{
2012-11-26 18:58:24 +00:00
gameLocal . Warning ( " cannot set the constraint position for '%s' " , name ) ;
break ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idAF : : SaveState
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAF : : SaveState ( idDict & args ) const
{
2012-11-26 18:58:24 +00:00
int i ;
2012-11-28 15:47:07 +00:00
idAFBody * body ;
2012-11-26 18:58:24 +00:00
idStr key , value ;
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < jointMods . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
body = physicsObj . GetBody ( jointMods [ i ] . bodyId ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
key = " body " + body - > GetName ( ) ;
value = body - > GetWorldOrigin ( ) . ToString ( 8 ) ;
value + = " " ;
value + = body - > GetWorldAxis ( ) . ToAngles ( ) . ToString ( 8 ) ;
args . Set ( key , value ) ;
}
}
/*
= = = = = = = = = = = = = = = =
idAF : : LoadState
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAF : : LoadState ( const idDict & args )
{
const idKeyValue * kv ;
2012-11-26 18:58:24 +00:00
idStr name ;
2012-11-28 15:47:07 +00:00
idAFBody * body ;
2012-11-26 18:58:24 +00:00
idVec3 origin ;
idAngles angles ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
kv = args . MatchPrefix ( " body " , NULL ) ;
2012-11-28 15:47:07 +00:00
while ( kv )
{
2012-11-26 18:58:24 +00:00
name = kv - > GetKey ( ) ;
name . Strip ( " body " ) ;
body = physicsObj . GetBody ( name ) ;
2012-11-28 15:47:07 +00:00
if ( body )
{
2012-11-26 18:58:24 +00:00
sscanf ( kv - > GetValue ( ) , " %f %f %f %f %f %f " , & origin . x , & origin . y , & origin . z , & angles . pitch , & angles . yaw , & angles . roll ) ;
body - > SetWorldOrigin ( origin ) ;
body - > SetWorldAxis ( angles . ToMat3 ( ) ) ;
}
2012-11-28 15:47:07 +00:00
else
{
gameLocal . Warning ( " Unknown body part %s in articulated figure %s " , name . c_str ( ) , this - > name . c_str ( ) ) ;
}
2012-11-26 18:58:24 +00:00
kv = args . MatchPrefix ( " body " , kv ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
physicsObj . UpdateClipModels ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idAF : : AddBindConstraints
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAF : : AddBindConstraints ( )
{
const idKeyValue * kv ;
2012-11-26 18:58:24 +00:00
idStr name ;
2012-11-28 15:47:07 +00:00
idAFBody * body ;
2012-11-26 18:58:24 +00:00
idLexer lexer ;
idToken type , bodyName , jointName ;
idVec3 origin , renderOrigin ;
idMat3 axis , renderAxis ;
2012-11-28 15:47:07 +00:00
if ( ! IsLoaded ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
const idDict & args = self - > spawnArgs ;
2012-11-26 18:58:24 +00:00
// get the render position
origin = physicsObj . GetOrigin ( 0 ) ;
axis = physicsObj . GetAxis ( 0 ) ;
renderAxis = baseAxis . Transpose ( ) * axis ;
renderOrigin = origin - baseOrigin * renderAxis ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// parse all the bind constraints
2012-11-28 15:47:07 +00:00
for ( kv = args . MatchPrefix ( " bindConstraint " , NULL ) ; kv ; kv = args . MatchPrefix ( " bindConstraint " , kv ) )
{
2012-11-26 18:58:24 +00:00
name = kv - > GetKey ( ) ;
name . Strip ( " bindConstraint " ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
lexer . LoadMemory ( kv - > GetValue ( ) , kv - > GetValue ( ) . Length ( ) , kv - > GetKey ( ) ) ;
lexer . ReadToken ( & type ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
lexer . ReadToken ( & bodyName ) ;
body = physicsObj . GetBody ( bodyName ) ;
2012-11-28 15:47:07 +00:00
if ( ! body )
{
2012-11-26 18:58:24 +00:00
gameLocal . Warning ( " idAF::AddBindConstraints: body '%s' not found on entity '%s' " , bodyName . c_str ( ) , self - > name . c_str ( ) ) ;
lexer . FreeSource ( ) ;
continue ;
}
2012-11-28 15:47:07 +00:00
if ( type . Icmp ( " fixed " ) = = 0 )
{
idAFConstraint_Fixed * c ;
c = new ( TAG_PHYSICS_AF ) idAFConstraint_Fixed ( name , body , NULL ) ;
2012-11-26 18:58:24 +00:00
physicsObj . AddConstraint ( c ) ;
}
2012-11-28 15:47:07 +00:00
else if ( type . Icmp ( " ballAndSocket " ) = = 0 )
{
idAFConstraint_BallAndSocketJoint * c ;
c = new ( TAG_PHYSICS_AF ) idAFConstraint_BallAndSocketJoint ( name , body , NULL ) ;
2012-11-26 18:58:24 +00:00
physicsObj . AddConstraint ( c ) ;
lexer . ReadToken ( & jointName ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
jointHandle_t joint = animator - > GetJointHandle ( jointName ) ;
2012-11-28 15:47:07 +00:00
if ( joint = = INVALID_JOINT )
{
2012-11-26 18:58:24 +00:00
gameLocal . Warning ( " idAF::AddBindConstraints: joint '%s' not found " , jointName . c_str ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
animator - > GetJointTransform ( joint , gameLocal . time , origin , axis ) ;
c - > SetAnchor ( renderOrigin + origin * renderAxis ) ;
}
2012-11-28 15:47:07 +00:00
else if ( type . Icmp ( " universal " ) = = 0 )
{
idAFConstraint_UniversalJoint * c ;
c = new ( TAG_PHYSICS_AF ) idAFConstraint_UniversalJoint ( name , body , NULL ) ;
2012-11-26 18:58:24 +00:00
physicsObj . AddConstraint ( c ) ;
lexer . ReadToken ( & jointName ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
jointHandle_t joint = animator - > GetJointHandle ( jointName ) ;
2012-11-28 15:47:07 +00:00
if ( joint = = INVALID_JOINT )
{
2012-11-26 18:58:24 +00:00
gameLocal . Warning ( " idAF::AddBindConstraints: joint '%s' not found " , jointName . c_str ( ) ) ;
}
animator - > GetJointTransform ( joint , gameLocal . time , origin , axis ) ;
c - > SetAnchor ( renderOrigin + origin * renderAxis ) ;
c - > SetShafts ( idVec3 ( 0 , 0 , 1 ) , idVec3 ( 0 , 0 , - 1 ) ) ;
}
2012-11-28 15:47:07 +00:00
else
{
2012-11-26 18:58:24 +00:00
gameLocal . Warning ( " idAF::AddBindConstraints: unknown constraint type '%s' on entity '%s' " , type . c_str ( ) , self - > name . c_str ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
lexer . FreeSource ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
hasBindConstraints = true ;
}
/*
= = = = = = = = = = = = = = = =
idAF : : RemoveBindConstraints
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idAF : : RemoveBindConstraints ( )
{
const idKeyValue * kv ;
if ( ! IsLoaded ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
const idDict & args = self - > spawnArgs ;
2012-11-26 18:58:24 +00:00
idStr name ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
kv = args . MatchPrefix ( " bindConstraint " , NULL ) ;
2012-11-28 15:47:07 +00:00
while ( kv )
{
2012-11-26 18:58:24 +00:00
name = kv - > GetKey ( ) ;
name . Strip ( " bindConstraint " ) ;
2012-11-28 15:47:07 +00:00
if ( physicsObj . GetConstraint ( name ) )
{
physicsObj . DeleteConstraint ( name ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
kv = args . MatchPrefix ( " bindConstraint " , kv ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
hasBindConstraints = false ;
}