Skip to content

Commit 7bb0b26

Browse files
committed
perf: add animation attachment deferral
this skips a pre-mature/extra bone setup during particle simulation and flexing by allowing for the last frame's attachment position to be used technically this is a bit of a hack but it works well from my analysis. it gets rid of almost all of the particle cost in team fights besides sprite rendering
1 parent 57fcefd commit 7bb0b26

File tree

10 files changed

+65
-7
lines changed

10 files changed

+65
-7
lines changed

src/game/client/c_baseanimating.cpp

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1092,6 +1092,7 @@ CStudioHdr *C_BaseAnimating::OnNewModel()
10921092
}
10931093
}
10941094
m_BoneAccessor.Init( this, m_CachedBoneData.Base() ); // Always call this in case the studiohdr_t has changed.
1095+
m_iAccumulatedBoneMask = 0; // Reset the accumulated bone mask.
10951096

10961097
// Free any IK data
10971098
if (m_pIk)
@@ -2029,18 +2030,24 @@ bool C_BaseAnimating::PutAttachment( int number, const matrix3x4_t &attachmentTo
20292030
return false;
20302031

20312032
CAttachmentData *pAtt = &m_Attachments[number-1];
2032-
if ( gpGlobals->frametime > 0 && pAtt->m_nLastFramecount > 0 && pAtt->m_nLastFramecount == gpGlobals->framecount - 1 )
2033+
if ( gpGlobals->frametime > 0 && pAtt->m_nLastFramecount > 0 && pAtt->m_nLastFramecount < gpGlobals->framecount )
20332034
{
20342035
Vector vecPreviousOrigin, vecOrigin;
20352036
MatrixPosition( pAtt->m_AttachmentToWorld, vecPreviousOrigin );
20362037
MatrixPosition( attachmentToWorld, vecOrigin );
2037-
pAtt->m_vOriginVelocity = (vecOrigin - vecPreviousOrigin) / gpGlobals->frametime;
2038+
// compensate for the fact that the previous origin could have been multiple frames behind
2039+
pAtt->m_vOriginVelocity = (vecOrigin - vecPreviousOrigin) / (gpGlobals->frametime * (gpGlobals->framecount - pAtt->m_nLastFramecount));
2040+
// only update the frame count if the position changed, so we don't have to recompute attachments
2041+
if ( !pAtt->m_vOriginVelocity.IsZero(0.00001f) )
2042+
{
2043+
pAtt->m_nLastFramecount = gpGlobals->framecount;
2044+
}
20382045
}
20392046
else
20402047
{
20412048
pAtt->m_vOriginVelocity.Init();
2049+
pAtt->m_nLastFramecount = gpGlobals->framecount;
20422050
}
2043-
pAtt->m_nLastFramecount = gpGlobals->framecount;
20442051
pAtt->m_bAnglesComputed = false;
20452052
pAtt->m_AttachmentToWorld = attachmentToWorld;
20462053

@@ -2051,6 +2058,20 @@ bool C_BaseAnimating::PutAttachment( int number, const matrix3x4_t &attachmentTo
20512058
return true;
20522059
}
20532060

2061+
bool C_BaseAnimating::GetAttachmentDeferred( int number, matrix3x4_t& matrix )
2062+
{
2063+
if (number < 1 || number > m_Attachments.Count())
2064+
return false;
2065+
2066+
// allow visual effects (eg. particles) to be a frame behind bone setup so that there are not messy dependencies.
2067+
CAttachmentData* pAtt = &m_Attachments[number - 1];
2068+
const bool bShouldUpdate = pAtt->m_nLastFramecount < gpGlobals->framecount - 1;
2069+
if ( bShouldUpdate && !CalcAttachments() )
2070+
return false;
2071+
2072+
matrix = pAtt->m_AttachmentToWorld;
2073+
return true;
2074+
}
20542075

20552076
bool C_BaseAnimating::SetupBones_AttachmentHelper( CStudioHdr *hdr )
20562077
{
@@ -2896,7 +2917,9 @@ bool C_BaseAnimating::SetupBones( matrix3x4_t *pBoneToWorldOut, int nMaxBones, i
28962917
m_flLastBoneSetupTime = currentTime;
28972918
}
28982919
m_iPrevBoneMask = m_iAccumulatedBoneMask;
2899-
m_iAccumulatedBoneMask = 0;
2920+
// Keep record of the fact that we've used attachments. Because of deferred attachments, we can't keep track from the previous frame.
2921+
//m_iAccumulatedBoneMask = 0;
2922+
m_iAccumulatedBoneMask = m_iAccumulatedBoneMask & BONE_USED_BY_ATTACHMENT;
29002923

29012924
#ifdef STUDIO_ENABLE_PERF_COUNTERS
29022925
CStudioHdr *hdr = GetModelPtr();

src/game/client/c_baseanimating.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ class C_BaseAnimating : public C_BaseEntity, private IModelLoadCallback
265265
// Attachments.
266266
bool GetAttachment( const char *szName, Vector &absOrigin );
267267
bool GetAttachment( const char *szName, Vector &absOrigin, QAngle &absAngles );
268+
virtual bool GetAttachmentDeferred( int number, matrix3x4_t &matrix );
268269

269270
// Inherited from C_BaseEntity
270271
virtual bool GetAttachment( int number, Vector &origin );

src/game/client/c_baseflex.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -574,7 +574,7 @@ Vector C_BaseFlex::SetViewTarget( CStudioHdr *pStudioHdr )
574574
if (m_iEyeAttachment > 0)
575575
{
576576
matrix3x4_t attToWorld;
577-
if (!GetAttachment( m_iEyeAttachment, attToWorld ))
577+
if (!GetAttachmentDeferred( m_iEyeAttachment, attToWorld ))
578578
{
579579
return Vector( 0, 0, 0);
580580
}

src/game/client/tf/c_tf_player.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1330,6 +1330,20 @@ bool C_TFRagdoll::GetAttachment( int iAttachment, matrix3x4_t &attachmentToWorld
13301330
}
13311331
}
13321332

1333+
bool C_TFRagdoll::GetAttachmentDeferred( int iAttachment, matrix3x4_t &attachmentToWorld )
1334+
{
1335+
int iHeadAttachment = LookupAttachment( "head" );
1336+
if ( IsDecapitation() && (iAttachment == iHeadAttachment) )
1337+
{
1338+
MatrixCopy( m_mHeadAttachment, attachmentToWorld );
1339+
return true;
1340+
}
1341+
else
1342+
{
1343+
return BaseClass::GetAttachmentDeferred( iAttachment, attachmentToWorld );
1344+
}
1345+
}
1346+
13331347
//-----------------------------------------------------------------------------
13341348
// Purpose:
13351349
// Input : -

src/game/client/tf/c_tf_player.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,6 +1064,7 @@ class C_TFRagdoll : public C_BaseFlex
10641064
int GetDamageCustom() { return m_iDamageCustom; }
10651065

10661066
virtual bool GetAttachment( int iAttachment, matrix3x4_t &attachmentToWorld );
1067+
virtual bool GetAttachmentDeferred( int iAttachment, matrix3x4_t &attachmentToWorld );
10671068

10681069
int GetClass() { return m_iClass; }
10691070

src/game/shared/baseviewmodel_shared.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,15 @@ bool CBaseViewModel::GetAttachment( int number, matrix3x4_t &matrix )
654654
return BaseClass::GetAttachment( number, matrix );
655655
}
656656

657+
bool C_BaseViewModel::GetAttachmentDeferred( int number, matrix3x4_t &matrix )
658+
{
659+
// Update priority for your own viewmodel (no deferral)
660+
if ( m_hWeapon.Get() && m_hWeapon.Get()->WantsToOverrideViewmodelAttachments() )
661+
return m_hWeapon.Get()->GetAttachment(number, matrix);
662+
663+
return BaseClass::GetAttachment( number, matrix );
664+
}
665+
657666
//-----------------------------------------------------------------------------
658667
// Purpose:
659668
//-----------------------------------------------------------------------------

src/game/shared/baseviewmodel_shared.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,7 @@ class CBaseViewModel : public CBaseAnimating, public IHasOwner
168168
// Attachments
169169
virtual int LookupAttachment( const char *pAttachmentName );
170170
virtual bool GetAttachment( int number, matrix3x4_t &matrix );
171+
virtual bool GetAttachmentDeferred( int number, matrix3x4_t &matrix );
171172
virtual bool GetAttachment( int number, Vector &origin );
172173
virtual bool GetAttachment( int number, Vector &origin, QAngle &angles );
173174
virtual bool GetAttachmentVelocity( int number, Vector &originVel, Quaternion &angleVel );

src/game/shared/econ/econ_entity.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1983,6 +1983,14 @@ bool CEconEntity::GetAttachment( int number, matrix3x4_t &matrix )
19831983
return BaseClass::GetAttachment( number, matrix );
19841984
}
19851985

1986+
bool C_EconEntity::GetAttachmentDeferred( int number, matrix3x4_t &matrix )
1987+
{
1988+
if ( m_hViewmodelAttachment )
1989+
return m_hViewmodelAttachment->GetAttachmentDeferred( number, matrix );
1990+
1991+
return BaseClass::GetAttachmentDeferred( number, matrix );
1992+
}
1993+
19861994
//-----------------------------------------------------------------------------
19871995
// Purpose:
19881996
//-----------------------------------------------------------------------------

src/game/shared/econ/econ_entity.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ class CEconEntity : public CBaseAnimating, public IHasAttributes
117117
virtual bool GetAttachment( const char *szName, Vector &absOrigin ) { return BaseClass::GetAttachment(szName,absOrigin); }
118118
virtual bool GetAttachment( const char *szName, Vector &absOrigin, QAngle &absAngles ) { return BaseClass::GetAttachment(szName,absOrigin,absAngles); }
119119
virtual bool GetAttachment( int number, matrix3x4_t &matrix );
120+
virtual bool GetAttachmentDeferred( int number, matrix3x4_t &matrix );
120121
virtual bool GetAttachment( int number, Vector &origin );
121122
virtual bool GetAttachment( int number, Vector &origin, QAngle &angles );
122123
virtual bool GetAttachmentVelocity( int number, Vector &originVel, Quaternion &angleVel );

src/game/shared/particle_property.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -605,10 +605,10 @@ void CParticleProperty::UpdateControlPoint( ParticleEffectList_t *pEffect, int i
605605
{
606606
matrix3x4_t attachmentToWorld;
607607

608-
if ( !pAnimating->GetAttachment( pPoint->iAttachmentPoint, attachmentToWorld ) )
608+
if ( !pAnimating->GetAttachmentDeferred( pPoint->iAttachmentPoint, attachmentToWorld ) )
609609
{
610610
// try C_BaseAnimating if attach point is not on the weapon
611-
if ( !pAnimating->C_BaseAnimating::GetAttachment( pPoint->iAttachmentPoint, attachmentToWorld ) )
611+
if ( !pAnimating->C_BaseAnimating::GetAttachmentDeferred( pPoint->iAttachmentPoint, attachmentToWorld ) )
612612
{
613613
Warning( "Cannot update control point %d for effect '%s'.\n", pPoint->iAttachmentPoint, pEffect->pParticleEffect->GetEffectName() );
614614
// Remove the effect cause this warning means something is orphaned

0 commit comments

Comments
 (0)