Fixed server side setupbones
This commit is contained in:
parent
259c05ac75
commit
1da7d763fe
9 changed files with 63 additions and 272 deletions
|
@ -1972,8 +1972,10 @@ void C_BaseAnimating::StandardBlendingRules( CStudioHdr *hdr, Vector pos[], Quat
|
|||
// debugoverlay->AddTextOverlay( GetAbsOrigin() + Vector( 0, 0, 64 ), 0, 0, "%30s %6.2f : %6.2f", hdr->pSeqdesc( GetSequence() )->pszLabel( ), fCycle, 1.0 );
|
||||
|
||||
// TODO_ENHANCED: Do that only for client side animations
|
||||
// if (m_bClientSideAnimation)
|
||||
if (m_bClientSideAnimation)
|
||||
{
|
||||
MaintainSequenceTransitions( boneSetup, fCycle, currentTime, pos, q );
|
||||
}
|
||||
|
||||
AccumulateLayers( boneSetup, pos, q, currentTime );
|
||||
|
||||
|
@ -2743,82 +2745,6 @@ void C_BaseAnimating::ThreadedBoneSetup()
|
|||
g_PreviousBoneSetups.RemoveAll();
|
||||
}
|
||||
|
||||
void C_BaseAnimating::BuildMatricesWithBoneMerge(
|
||||
const CStudioHdr *pStudioHdr,
|
||||
const QAngle& angles,
|
||||
const Vector& origin,
|
||||
const Vector pos[MAXSTUDIOBONES],
|
||||
const Quaternion q[MAXSTUDIOBONES],
|
||||
matrix3x4_t bonetoworld[MAXSTUDIOBONES],
|
||||
C_BaseAnimating *pParent,
|
||||
CBoneCache *pParentCache
|
||||
)
|
||||
{
|
||||
CStudioHdr *fhdr = pParent->GetModelPtr();
|
||||
mstudiobone_t *pbones = pStudioHdr->pBone( 0 );
|
||||
|
||||
matrix3x4_t rotationmatrix; // model to world transformation
|
||||
AngleMatrix( angles, origin, rotationmatrix);
|
||||
|
||||
for ( int i=0; i < pStudioHdr->numbones(); i++ )
|
||||
{
|
||||
// Now find the bone in the parent entity.
|
||||
bool merged = false;
|
||||
int parentBoneIndex = Studio_BoneIndexByName( fhdr, pbones[i].pszName() );
|
||||
if ( parentBoneIndex >= 0 )
|
||||
{
|
||||
matrix3x4_t *pMat = pParentCache->GetCachedBone( parentBoneIndex );
|
||||
if ( pMat )
|
||||
{
|
||||
MatrixCopy( *pMat, bonetoworld[ i ] );
|
||||
merged = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !merged )
|
||||
{
|
||||
// If we get down here, then the bone wasn't merged.
|
||||
matrix3x4_t bonematrix;
|
||||
QuaternionMatrix( q[i], pos[i], bonematrix );
|
||||
|
||||
if (pbones[i].parent == -1)
|
||||
{
|
||||
ConcatTransforms (rotationmatrix, bonematrix, bonetoworld[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
ConcatTransforms (bonetoworld[pbones[i].parent], bonematrix, bonetoworld[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void C_BaseAnimating::GetSkeleton( CStudioHdr *pStudioHdr, Vector pos[], Quaternion q[], int boneMask, float currentTime )
|
||||
{
|
||||
if(!pStudioHdr)
|
||||
{
|
||||
Assert(!"C_BaseAnimating::GetSkeleton() without a model");
|
||||
return;
|
||||
}
|
||||
|
||||
IBoneSetup boneSetup( pStudioHdr, boneMask, m_flPoseParameter );
|
||||
boneSetup.InitPose( pos, q );
|
||||
|
||||
boneSetup.AccumulatePose( pos, q, GetSequence(), GetCycle(), 1.0, currentTime, m_pIk );
|
||||
|
||||
if ( m_pIk )
|
||||
{
|
||||
CIKContext auto_ik;
|
||||
auto_ik.Init( pStudioHdr, GetRenderAngles(), GetRenderOrigin(), currentTime, 0, boneMask );
|
||||
boneSetup.CalcAutoplaySequences( pos, q, currentTime, &auto_ik );
|
||||
}
|
||||
else
|
||||
{
|
||||
boneSetup.CalcAutoplaySequences( pos, q, currentTime, NULL );
|
||||
}
|
||||
boneSetup.CalcBoneAdj( pos, q, m_flEncodedController );
|
||||
}
|
||||
|
||||
bool C_BaseAnimating::SetupBones( matrix3x4_t *pBoneToWorldOut, int nMaxBones, int boneMask, float currentTime )
|
||||
{
|
||||
VPROF_BUDGET( "C_BaseAnimating::SetupBones", VPROF_BUDGETGROUP_CLIENT_ANIMATION );
|
||||
|
@ -2972,8 +2898,10 @@ bool C_BaseAnimating::SetupBones( matrix3x4_t *pBoneToWorldOut, int nMaxBones, i
|
|||
// NOTE: For model scaling, we need to opt out of IK because it will mark the bones as already being calculated
|
||||
if ( !IsModelScaled() )
|
||||
{
|
||||
// only allocate an ik block if the npc can use it
|
||||
if ( !m_pIk && hdr->numikchains() > 0 && !(m_EntClientFlags & ENTCLIENTFLAG_DONTUSEIK) )
|
||||
// only allocate an ik block if the npc can use it
|
||||
// The flag is now completely ignored to match server bones!
|
||||
// If it doesn't work well, blame models.
|
||||
if ( !m_pIk && hdr->numikchains() > 0 /* && !(m_EntClientFlags & ENTCLIENTFLAG_DONTUSEIK) */ )
|
||||
{
|
||||
m_pIk = new CIKContext;
|
||||
}
|
||||
|
|
|
@ -99,8 +99,8 @@ public:
|
|||
|
||||
enum
|
||||
{
|
||||
NUM_POSEPAREMETERS = 24,
|
||||
NUM_BONECTRLS = 4
|
||||
NUM_POSEPAREMETERS = MAXSTUDIOPOSEPARAM,
|
||||
NUM_BONECTRLS = MAXSTUDIOBONECTRLS
|
||||
};
|
||||
|
||||
C_BaseAnimating();
|
||||
|
@ -144,11 +144,6 @@ public:
|
|||
virtual int VPhysicsGetObjectList( IPhysicsObject **pList, int listMax );
|
||||
|
||||
// model specific
|
||||
void BuildMatricesWithBoneMerge( const CStudioHdr *pStudioHdr, const QAngle& angles,
|
||||
const Vector& origin, const Vector pos[MAXSTUDIOBONES],
|
||||
const Quaternion q[MAXSTUDIOBONES], matrix3x4_t bonetoworld[MAXSTUDIOBONES],
|
||||
CBaseAnimating *pParent, CBoneCache *pParentCache );
|
||||
virtual void GetSkeleton( CStudioHdr *pStudioHdr, Vector pos[], Quaternion q[], int boneMask, float currentTime );
|
||||
virtual bool SetupBones( matrix3x4_t *pBoneToWorldOut, int nMaxBones, int boneMask, float currentTime );
|
||||
virtual void UpdateIKLocks( float currentTime );
|
||||
virtual void CalculateIKLocks( float currentTime );
|
||||
|
|
|
@ -370,66 +370,3 @@ CStudioHdr *C_BaseAnimatingOverlay::OnNewModel()
|
|||
|
||||
return hdr;
|
||||
}
|
||||
|
||||
void C_BaseAnimatingOverlay::GetSkeleton( CStudioHdr* pStudioHdr, Vector pos[], Quaternion q[], int boneMask, float currentTime )
|
||||
{
|
||||
if(!pStudioHdr)
|
||||
{
|
||||
Assert(!"C_BaseAnimating::GetSkeleton() without a model");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!pStudioHdr->SequencesAvailable())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
float poseparameters[MAXSTUDIOPOSEPARAM];
|
||||
GetPoseParameters(pStudioHdr, poseparameters);
|
||||
|
||||
IBoneSetup boneSetup( pStudioHdr, boneMask, poseparameters );
|
||||
boneSetup.InitPose( pos, q );
|
||||
|
||||
boneSetup.AccumulatePose( pos, q, GetSequence(), GetCycle(), 1.0, currentTime, m_pIk );
|
||||
|
||||
// sort the layers
|
||||
int layer[MAX_OVERLAYS] = {};
|
||||
int i;
|
||||
for (i = 0; i < m_AnimOverlay.Count(); i++)
|
||||
{
|
||||
layer[i] = MAX_OVERLAYS;
|
||||
}
|
||||
for (i = 0; i < m_AnimOverlay.Count(); i++)
|
||||
{
|
||||
CAnimationLayer &pLayer = m_AnimOverlay[i];
|
||||
if( (pLayer.m_flWeight > 0) && pLayer.IsActive() && pLayer.m_nOrder >= 0 && pLayer.m_nOrder < m_AnimOverlay.Count())
|
||||
{
|
||||
layer[pLayer.m_nOrder] = i;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < m_AnimOverlay.Count(); i++)
|
||||
{
|
||||
if (layer[i] >= 0 && layer[i] < m_AnimOverlay.Count())
|
||||
{
|
||||
CAnimationLayer &pLayer = m_AnimOverlay[layer[i]];
|
||||
// UNDONE: Is it correct to use overlay weight for IK too?
|
||||
boneSetup.AccumulatePose( pos, q, pLayer.m_nSequence, pLayer.m_flCycle, pLayer.m_flWeight, currentTime, m_pIk );
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_pIk )
|
||||
{
|
||||
CIKContext auto_ik;
|
||||
auto_ik.Init( pStudioHdr, GetRenderAngles(), GetRenderOrigin(), currentTime, 0, boneMask );
|
||||
boneSetup.CalcAutoplaySequences( pos, q, currentTime, &auto_ik );
|
||||
}
|
||||
else
|
||||
{
|
||||
boneSetup.CalcAutoplaySequences(pos, q, currentTime, NULL);
|
||||
}
|
||||
|
||||
float controllers[MAXSTUDIOBONECTRLS];
|
||||
GetBoneControllers(controllers);
|
||||
|
||||
boneSetup.CalcBoneAdj( pos, q, controllers );
|
||||
}
|
|
@ -38,7 +38,6 @@ public:
|
|||
// model specific
|
||||
virtual void AccumulateLayers( IBoneSetup &boneSetup, Vector pos[], Quaternion q[], float currentTime );
|
||||
virtual void DoAnimationEvents( CStudioHdr *pStudioHdr );
|
||||
virtual void GetSkeleton( CStudioHdr *pStudioHdr, Vector pos[], Quaternion q[], int boneMask, float currentTime );
|
||||
|
||||
enum
|
||||
{
|
||||
|
|
|
@ -4294,11 +4294,12 @@ void C_BaseEntity::CalcAbsolutePosition( )
|
|||
return;
|
||||
}
|
||||
|
||||
if ( IsEffectActive(EF_BONEMERGE) )
|
||||
{
|
||||
MoveToAimEnt();
|
||||
return;
|
||||
}
|
||||
// TODO_ENHANCED: this should be safe to remove.
|
||||
// if ( IsEffectActive(EF_BONEMERGE) )
|
||||
// {
|
||||
// MoveToAimEnt();
|
||||
// return;
|
||||
// }
|
||||
|
||||
// Construct the entity-to-world matrix
|
||||
// Start with making an entity-to-parent matrix
|
||||
|
|
|
@ -203,8 +203,9 @@ C_CHostage::C_CHostage()
|
|||
m_flLastBodyYaw = 0;
|
||||
m_createdLowViolenceRagdoll = false;
|
||||
|
||||
// TODO: Get IK working on the steep slopes CS has, then enable it on characters.
|
||||
m_EntClientFlags |= ENTCLIENTFLAG_DONTUSEIK;
|
||||
// TODO: Get IK working on the steep slopes CS has, then enable it on characters.
|
||||
// Breaks server side setup bones !
|
||||
// m_EntClientFlags |= ENTCLIENTFLAG_DONTUSEIK;
|
||||
|
||||
// set the model so the PlayerAnimState uses the Hostage activities/sequences
|
||||
SetModelName( "models/Characters/Hostage_01.mdl" );
|
||||
|
|
|
@ -2601,100 +2601,9 @@ float C_CSPlayer::GetDeathCamInterpolationTime()
|
|||
|
||||
}
|
||||
|
||||
ConVar cl_server_setup_bones("cl_server_setup_bones", "1");
|
||||
|
||||
bool C_CSPlayer::SetupBones( matrix3x4_t *pBoneToWorldOut, int nMaxBones, int boneMask, float currentTime )
|
||||
{
|
||||
if (cl_server_setup_bones.GetBool())
|
||||
{
|
||||
AUTO_LOCK( m_BoneSetupLock );
|
||||
|
||||
MDLCACHE_CRITICAL_SECTION();
|
||||
|
||||
Assert( GetModelPtr() );
|
||||
|
||||
CStudioHdr *pStudioHdr = GetModelPtr( );
|
||||
|
||||
if(!pStudioHdr)
|
||||
{
|
||||
Assert(!"C_BaseAnimating::GetSkeleton() without a model");
|
||||
return false;
|
||||
}
|
||||
|
||||
Assert( !IsEFlagSet( EFL_SETTING_UP_BONES ) );
|
||||
|
||||
AddEFlags( EFL_SETTING_UP_BONES );
|
||||
|
||||
Vector pos[MAXSTUDIOBONES];
|
||||
Quaternion q[MAXSTUDIOBONES];
|
||||
|
||||
// adjust hit boxes based on IK driven offset
|
||||
Vector adjOrigin = GetRenderOrigin();
|
||||
|
||||
if ( m_pIk )
|
||||
{
|
||||
// FIXME: pass this into Studio_BuildMatrices to skip transforms
|
||||
CBoneBitList boneComputed;
|
||||
m_iIKCounter++;
|
||||
m_pIk->Init( pStudioHdr, GetRenderAngles(), adjOrigin, currentTime, m_iIKCounter, boneMask );
|
||||
GetSkeleton( pStudioHdr, pos, q, boneMask, currentTime );
|
||||
|
||||
m_pIk->UpdateTargets( pos, q, m_BoneAccessor.GetBoneArrayForWrite(), boneComputed );
|
||||
CalculateIKLocks( currentTime );
|
||||
m_pIk->SolveDependencies( pos, q, m_BoneAccessor.GetBoneArrayForWrite(), boneComputed );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Msg( "%.03f : %s:%s\n", gpGlobals->curtime, GetClassname(), GetEntityName().ToCStr() );
|
||||
GetSkeleton( pStudioHdr, pos, q, boneMask, currentTime );
|
||||
}
|
||||
|
||||
CBaseAnimating *pParent = dynamic_cast< CBaseAnimating* >( GetMoveParent() );
|
||||
if ( pParent )
|
||||
{
|
||||
// We're doing bone merging, so do special stuff here.
|
||||
CBoneCache *pParentCache = pParent->GetBoneCache(pParent->GetModelPtr());
|
||||
if ( pParentCache )
|
||||
{
|
||||
BuildMatricesWithBoneMerge(
|
||||
pStudioHdr,
|
||||
GetRenderAngles(),
|
||||
adjOrigin,
|
||||
pos,
|
||||
q,
|
||||
m_BoneAccessor.GetBoneArrayForWrite(),
|
||||
pParent,
|
||||
pParentCache );
|
||||
|
||||
RemoveEFlags( EFL_SETTING_UP_BONES );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
Studio_BuildMatrices(
|
||||
pStudioHdr,
|
||||
GetRenderAngles(),
|
||||
adjOrigin,
|
||||
pos,
|
||||
q,
|
||||
-1,
|
||||
GetModelScale(), // Scaling
|
||||
m_BoneAccessor.GetBoneArrayForWrite(),
|
||||
boneMask );
|
||||
|
||||
RemoveEFlags(EFL_SETTING_UP_BONES);
|
||||
|
||||
if ( pBoneToWorldOut )
|
||||
{
|
||||
memcpy( pBoneToWorldOut, m_BoneAccessor.GetBoneArrayForWrite(), sizeof( matrix3x4_t ) * MAXSTUDIOBONES );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return BaseClass::SetupBones( pBoneToWorldOut, nMaxBones, boneMask, currentTime );
|
||||
}
|
||||
return BaseClass::SetupBones( pBoneToWorldOut, nMaxBones, boneMask, currentTime );
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
|
|
|
@ -1800,31 +1800,46 @@ void CBaseAnimating::SetupBones( matrix3x4_t *pBoneToWorld, int boneMask )
|
|||
// adjust hit boxes based on IK driven offset
|
||||
Vector adjOrigin = GetAbsOrigin() + Vector( 0, 0, m_flEstIkOffset );
|
||||
|
||||
if ( CanSkipAnimation() )
|
||||
// NOTE: For model scaling, we need to opt out of IK because it will mark the bones as already being calculated
|
||||
if ( !IsModelScaled() )
|
||||
{
|
||||
IBoneSetup boneSetup( pStudioHdr, boneMask, GetPoseParameterArray() );
|
||||
boneSetup.InitPose( pos, q );
|
||||
// Msg( "%.03f : %s:%s not in pvs\n", gpGlobals->curtime, GetClassname(), GetEntityName().ToCStr() );
|
||||
// only allocate an ik block if the npc can use it
|
||||
if ( !m_pIk && pStudioHdr->numikchains() > 0 )
|
||||
{
|
||||
m_pIk = new CIKContext;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reset the IK
|
||||
if ( m_pIk )
|
||||
{
|
||||
// FIXME: pass this into Studio_BuildMatrices to skip transforms
|
||||
CBoneBitList boneComputed;
|
||||
m_iIKCounter++;
|
||||
m_pIk->Init( pStudioHdr, GetAbsAngles(), adjOrigin, gpGlobals->curtime, m_iIKCounter, boneMask );
|
||||
GetSkeleton( pStudioHdr, pos, q, boneMask );
|
||||
delete m_pIk;
|
||||
m_pIk = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
m_pIk->UpdateTargets( pos, q, pBoneToWorld, boneComputed );
|
||||
CalculateIKLocks( gpGlobals->curtime );
|
||||
m_pIk->SolveDependencies( pos, q, pBoneToWorld, boneComputed );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Msg( "%.03f : %s:%s\n", gpGlobals->curtime, GetClassname(), GetEntityName().ToCStr() );
|
||||
GetSkeleton( pStudioHdr, pos, q, boneMask );
|
||||
}
|
||||
if ( m_pIk )
|
||||
{
|
||||
m_pIk->Init( pStudioHdr, GetAbsAngles(), GetAbsOrigin(), gpGlobals->curtime, m_iIKCounter, boneMask );
|
||||
}
|
||||
|
||||
if ( m_pIk )
|
||||
{
|
||||
// FIXME: pass this into Studio_BuildMatrices to skip transforms
|
||||
CBoneBitList boneComputed;
|
||||
m_iIKCounter++;
|
||||
m_pIk->Init( pStudioHdr, GetAbsAngles(), adjOrigin, gpGlobals->curtime, m_iIKCounter, boneMask );
|
||||
GetSkeleton( pStudioHdr, pos, q, boneMask );
|
||||
|
||||
m_pIk->UpdateTargets( pos, q, pBoneToWorld, boneComputed );
|
||||
CalculateIKLocks( gpGlobals->curtime );
|
||||
m_pIk->SolveDependencies( pos, q, pBoneToWorld, boneComputed );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Msg( "%.03f : %s:%s\n", gpGlobals->curtime, GetClassname(), GetEntityName().ToCStr() );
|
||||
GetSkeleton( pStudioHdr, pos, q, boneMask );
|
||||
}
|
||||
|
||||
CBaseAnimating *pParent = dynamic_cast< CBaseAnimating* >( GetMoveParent() );
|
||||
|
|
|
@ -41,8 +41,8 @@ public:
|
|||
|
||||
enum
|
||||
{
|
||||
NUM_POSEPAREMETERS = 24,
|
||||
NUM_BONECTRLS = 4
|
||||
NUM_POSEPAREMETERS = MAXSTUDIOPOSEPARAM,
|
||||
NUM_BONECTRLS = MAXSTUDIOBONECTRLS
|
||||
};
|
||||
|
||||
DECLARE_DATADESC();
|
||||
|
@ -161,6 +161,8 @@ public:
|
|||
bool HasPoseParameter( int iSequence, int iParameter );
|
||||
float EdgeLimitPoseParameter( int iParameter, float flValue, float flBase = 0.0f );
|
||||
|
||||
inline bool IsModelScaled() const;
|
||||
|
||||
protected:
|
||||
// The modus operandi for pose parameters is that you should not use the const char * version of the functions
|
||||
// in general code -- it causes many many string comparisons, which is slower than you think. Better is to
|
||||
|
@ -518,6 +520,10 @@ inline void CBaseAnimating::SetCycle( float flCycle )
|
|||
m_flCycle = flCycle;
|
||||
}
|
||||
|
||||
inline bool CBaseAnimating::IsModelScaled() const
|
||||
{
|
||||
return ( m_flModelScale > 1.0f+FLT_EPSILON || m_flModelScale < 1.0f-FLT_EPSILON );
|
||||
}
|
||||
|
||||
EXTERN_SEND_TABLE(DT_BaseAnimating);
|
||||
|
||||
|
|
Loading…
Reference in a new issue