diff options
| author | John Schoenick <[email protected]> | 2015-09-09 18:35:41 -0700 |
|---|---|---|
| committer | John Schoenick <[email protected]> | 2015-09-09 18:35:41 -0700 |
| commit | 0d8dceea4310fde5706b3ce1c70609d72a38efdf (patch) | |
| tree | c831ef32c2c801a5c5a80401736b52c7b5a528ec /mp/src/game/client/c_baseanimating.cpp | |
| parent | Updated the SDK with the latest code from the TF and HL2 branches. (diff) | |
| download | source-sdk-2013-0d8dceea4310fde5706b3ce1c70609d72a38efdf.tar.xz source-sdk-2013-0d8dceea4310fde5706b3ce1c70609d72a38efdf.zip | |
Diffstat (limited to 'mp/src/game/client/c_baseanimating.cpp')
| -rw-r--r-- | mp/src/game/client/c_baseanimating.cpp | 168 |
1 files changed, 140 insertions, 28 deletions
diff --git a/mp/src/game/client/c_baseanimating.cpp b/mp/src/game/client/c_baseanimating.cpp index 75c9d7a8..78bc38be 100644 --- a/mp/src/game/client/c_baseanimating.cpp +++ b/mp/src/game/client/c_baseanimating.cpp @@ -79,6 +79,11 @@ const float RUN_SPEED_ESTIMATE_SQR = 150.0f * 150.0f; static ConVar dbganimmodel( "dbganimmodel", "" ); #endif +#if defined( STAGING_ONLY ) + static ConVar dbg_bonestack_perturb( "dbg_bonestack_perturb", "0", 0); + static CInterlockedInt dbg_bonestack_reentrant_count = 0; +#endif // STAGING_ONLY + mstudioevent_t *GetEventIndexForSequence( mstudioseqdesc_t &seqdesc ); C_EntityDissolve *DissolveEffect( C_BaseEntity *pTarget, float flTime ); @@ -632,7 +637,10 @@ void C_ClientRagdoll::Release( void ) } ClientEntityList().RemoveEntity( GetClientHandle() ); - partition->Remove( PARTITION_CLIENT_SOLID_EDICTS | PARTITION_CLIENT_RESPONSIVE_EDICTS | PARTITION_CLIENT_NON_STATIC_EDICTS, CollisionProp()->GetPartitionHandle() ); + if ( CollisionProp()->GetPartitionHandle() != PARTITION_INVALID_HANDLE ) + { + partition->Remove( PARTITION_CLIENT_SOLID_EDICTS | PARTITION_CLIENT_RESPONSIVE_EDICTS | PARTITION_CLIENT_NON_STATIC_EDICTS, CollisionProp()->GetPartitionHandle() ); + } RemoveFromLeafSystem(); BaseClass::Release(); @@ -744,15 +752,25 @@ C_BaseAnimating::~C_BaseAnimating() int i = g_PreviousBoneSetups.Find( this ); if ( i != -1 ) g_PreviousBoneSetups.FastRemove( i ); - RemoveFromClientSideAnimationList(); TermRopes(); + + Assert( !m_pRagdoll ); + delete m_pRagdollInfo; - Assert(!m_pRagdoll); + m_pRagdollInfo = NULL; + delete m_pIk; + m_pIk = NULL; + delete m_pBoneMergeCache; + m_pBoneMergeCache = NULL; + Studio_DestroyBoneCache( m_hitboxBoneCacheHandle ); + delete m_pJiggleBones; + m_pJiggleBones = NULL; + InvalidateMdlCache(); // Kill off anything bone attached to us. @@ -852,7 +870,7 @@ void C_BaseAnimating::UpdateRelevantInterpolatedVars() { MDLCACHE_CRITICAL_SECTION(); // Remove any interpolated vars that need to be removed. - if ( !GetPredictable() && !IsClientCreated() && GetModelPtr() && GetModelPtr()->SequencesAvailable() ) + if ( !IsMarkedForDeletion() && !GetPredictable() && !IsClientCreated() && GetModelPtr() && GetModelPtr()->SequencesAvailable() ) { AddBaseAnimatingInterpolatedVars(); } @@ -892,6 +910,17 @@ void C_BaseAnimating::RemoveBaseAnimatingInterpolatedVars() } } +/* + From Ken: Lock() and Unlock() are render frame only, it’s just so the mdlcache + doesn’t toss the memory when it reshuffles the data, or at least used to. I + don't have any idea if mdlcache even does that anymore, but at one point it would + happily throw away the animation data if you ran out of memory on the + consoles. Jay adds: Ken is correct and the pointer should be valid until the end + of the frame lock (provided you are within a MDLCACHE_LOCK() block or whatever + + Jay also recommends running with a forced small cache size (1MB) to put maximum + pressure on the cache when testing changes. Look for datacache ConVar in datacache.cpp. + */ void C_BaseAnimating::LockStudioHdr() { Assert( m_hStudioHdr == MDLHANDLE_INVALID && m_pStudioHdr == NULL ); @@ -963,6 +992,9 @@ void C_BaseAnimating::UnlockStudioHdr() mdlcache->UnlockStudioHdr( m_hStudioHdr ); } m_hStudioHdr = MDLHANDLE_INVALID; + + delete m_pStudioHdr; + m_pStudioHdr = NULL; } } @@ -1511,10 +1543,21 @@ void C_BaseAnimating::BuildTransformations( CStudioHdr *hdr, Vector *pos, Quater if (pbones[i].parent == -1) { ConcatTransforms( cameraTransform, bonematrix, goalMX ); - } + } else { - ConcatTransforms( GetBone( pbones[i].parent ), bonematrix, goalMX ); + // If the parent bone has been scaled (like with BuildBigHeadTransformations) + // scale it back down so the jiggly bones show up non-scaled in the correct location. + matrix3x4_t parentMX = GetBone( pbones[i].parent ); + + float fScale = Square( parentMX[0][0] ) + Square( parentMX[1][0] ) + Square( parentMX[2][0] ); + if ( fScale > Square( 1.0001f ) ) + { + fScale = 1.0f / FastSqrt( fScale ); + MatrixScaleBy( fScale, parentMX ); + } + + ConcatTransforms( parentMX, bonematrix, goalMX ); } // get jiggle properties from QC data @@ -1995,10 +2038,10 @@ bool C_BaseAnimating::PutAttachment( int number, const matrix3x4_t &attachmentTo } -void C_BaseAnimating::SetupBones_AttachmentHelper( CStudioHdr *hdr ) +bool C_BaseAnimating::SetupBones_AttachmentHelper( CStudioHdr *hdr ) { - if ( !hdr || !hdr->GetNumAttachments() ) - return; + if ( !hdr ) + return false; // calculate attachment points matrix3x4_t world; @@ -2024,6 +2067,8 @@ void C_BaseAnimating::SetupBones_AttachmentHelper( CStudioHdr *hdr ) FormatViewModelAttachment( i, world ); PutAttachment( i + 1, world ); } + + return true; } bool C_BaseAnimating::CalcAttachments() @@ -2214,18 +2259,36 @@ bool C_BaseAnimating::GetSoundSpatialization( SpatializationInfo_t& info ) return true; } - +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- bool C_BaseAnimating::IsViewModel() const { return false; } +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void C_BaseAnimating::UpdateOnRemove( void ) +{ + RemoveFromClientSideAnimationList( true ); + + BaseClass::UpdateOnRemove(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- bool C_BaseAnimating::IsMenuModel() const { return false; } // UNDONE: Seems kind of silly to have this when we also have the cached bones in C_BaseAnimating +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- CBoneCache *C_BaseAnimating::GetBoneCache( CStudioHdr *pStudioHdr ) { int boneMask = BONE_USED_BY_HITBOX; @@ -2908,10 +2971,14 @@ bool C_BaseAnimating::SetupBones( matrix3x4_t *pBoneToWorldOut, int nMaxBones, i if( !( oldReadableBones & BONE_USED_BY_ATTACHMENT ) && ( boneMask & BONE_USED_BY_ATTACHMENT ) ) { - SetupBones_AttachmentHelper( hdr ); + if ( !SetupBones_AttachmentHelper( hdr ) ) + { + DevWarning( 2, "SetupBones: SetupBones_AttachmentHelper failed.\n" ); + return false; + } } } - + // Do they want to get at the bone transforms? If it's just making sure an aiment has // its bones setup, it doesn't need the transforms yet. if ( pBoneToWorldOut ) @@ -2922,7 +2989,7 @@ bool C_BaseAnimating::SetupBones( matrix3x4_t *pBoneToWorldOut, int nMaxBones, i } else { - Warning( "SetupBones: invalid bone array size (%d - needs %d)\n", nMaxBones, m_CachedBoneData.Count() ); + ExecuteNTimes( 25, Warning( "SetupBones: invalid bone array size (%d - needs %d)\n", nMaxBones, m_CachedBoneData.Count() ) ); return false; } } @@ -2989,6 +3056,9 @@ struct BoneAccess char const *tag; }; +// the modelcache critical section is insufficient for preventing us from getting into the bone cache at the same time. +// The bonecache itself is protected by a mutex, but the actual bone access stack needs to be protected separately. +static CThreadFastMutex g_BoneAccessMutex; static CUtlVector< BoneAccess > g_BoneAccessStack; static BoneAccess g_BoneAcessBase; @@ -3003,6 +3073,9 @@ bool C_BaseAnimating::IsBoneAccessAllowed() const // (static function) void C_BaseAnimating::PushAllowBoneAccess( bool bAllowForNormalModels, bool bAllowForViewModels, char const *tagPush ) { + AUTO_LOCK( g_BoneAccessMutex ); + STAGING_ONLY_EXEC( ReentrancyVerifier rv( &dbg_bonestack_reentrant_count, dbg_bonestack_perturb.GetInt() ) ); + BoneAccess save = g_BoneAcessBase; g_BoneAccessStack.AddToTail( save ); @@ -3014,6 +3087,9 @@ void C_BaseAnimating::PushAllowBoneAccess( bool bAllowForNormalModels, bool bAll void C_BaseAnimating::PopBoneAccess( char const *tagPop ) { + AUTO_LOCK( g_BoneAccessMutex ); + STAGING_ONLY_EXEC( ReentrancyVerifier rv( &dbg_bonestack_reentrant_count, dbg_bonestack_perturb.GetInt() ) ); + // Validate that pop matches the push Assert( ( g_BoneAcessBase.tag == tagPop ) || ( g_BoneAcessBase.tag && g_BoneAcessBase.tag != ( char const * ) 1 && tagPop && tagPop != ( char const * ) 1 && !strcmp( g_BoneAcessBase.tag, tagPop ) ) ); int lastIndex = g_BoneAccessStack.Count() - 1; @@ -3481,7 +3557,7 @@ void C_BaseAnimating::DoAnimationEvents( CStudioHdr *pStudioHdr ) } // Necessary to get the next loop working - m_flPrevEventCycle = -0.01; + m_flPrevEventCycle = flEventCycle - 0.001f; } for (int i = 0; i < (int)seqdesc.numevents; i++) @@ -4496,7 +4572,7 @@ void C_BaseAnimating::OnPreDataChanged( DataUpdateType_t updateType ) m_bLastClientSideFrameReset = m_bClientSideFrameReset; } -void C_BaseAnimating::ForceSetupBonesAtTime( matrix3x4_t *pBonesOut, float flTime ) +bool C_BaseAnimating::ForceSetupBonesAtTime( matrix3x4_t *pBonesOut, float flTime ) { // blow the cached prev bones InvalidateBoneCache(); @@ -4505,13 +4581,18 @@ void C_BaseAnimating::ForceSetupBonesAtTime( matrix3x4_t *pBonesOut, float flTim Interpolate( flTime ); // Setup bone state at the given time - SetupBones( pBonesOut, MAXSTUDIOBONES, BONE_USED_BY_ANYTHING, flTime ); + return SetupBones( pBonesOut, MAXSTUDIOBONES, BONE_USED_BY_ANYTHING, flTime ); } -void C_BaseAnimating::GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matrix3x4_t *pDeltaBones1, matrix3x4_t *pCurrentBones, float boneDt ) +bool C_BaseAnimating::GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matrix3x4_t *pDeltaBones1, matrix3x4_t *pCurrentBones, float boneDt ) { - ForceSetupBonesAtTime( pDeltaBones0, gpGlobals->curtime - boneDt ); - ForceSetupBonesAtTime( pDeltaBones1, gpGlobals->curtime ); + bool bSuccess = true; + + if ( !ForceSetupBonesAtTime( pDeltaBones0, gpGlobals->curtime - boneDt ) ) + bSuccess = false; + if ( !ForceSetupBonesAtTime( pDeltaBones1, gpGlobals->curtime ) ) + bSuccess = false; + float ragdollCreateTime = PhysGetSyncCreateTime(); if ( ragdollCreateTime != gpGlobals->curtime ) { @@ -4519,12 +4600,15 @@ void C_BaseAnimating::GetRagdollInitBoneArrays( matrix3x4_t *pDeltaBones0, matri // so initialize the ragdoll at that time so that it will reach the current // position at curtime. Otherwise the ragdoll will simulate forward from curtime // and pop into the future a bit at this point of transition - ForceSetupBonesAtTime( pCurrentBones, ragdollCreateTime ); + if ( !ForceSetupBonesAtTime( pCurrentBones, ragdollCreateTime ) ) + bSuccess = false; } else { memcpy( pCurrentBones, m_CachedBoneData.Base(), sizeof( matrix3x4_t ) * m_CachedBoneData.Count() ); } + + return bSuccess; } C_BaseAnimating *C_BaseAnimating::CreateRagdollCopy() @@ -4592,14 +4676,32 @@ C_BaseAnimating *C_BaseAnimating::BecomeRagdollOnClient() { MoveToLastReceivedPosition( true ); GetAbsOrigin(); + C_BaseAnimating *pRagdoll = CreateRagdollCopy(); + if ( pRagdoll ) + { + matrix3x4_t boneDelta0[MAXSTUDIOBONES]; + matrix3x4_t boneDelta1[MAXSTUDIOBONES]; + matrix3x4_t currentBones[MAXSTUDIOBONES]; + const float boneDt = 0.1f; + + bool bInitAsClient = false; + bool bInitBoneArrays = GetRagdollInitBoneArrays( boneDelta0, boneDelta1, currentBones, boneDt ); + + if ( bInitBoneArrays ) + { + bInitAsClient = pRagdoll->InitAsClientRagdoll( boneDelta0, boneDelta1, currentBones, boneDt ); + } + + if ( !bInitAsClient || !bInitBoneArrays ) + { + Warning( "C_BaseAnimating::BecomeRagdollOnClient failed. pRagdoll:%p bInitBoneArrays:%d bInitAsClient:%d\n", + pRagdoll, bInitBoneArrays, bInitAsClient ); + pRagdoll->Release(); + return NULL; + } + } - matrix3x4_t boneDelta0[MAXSTUDIOBONES]; - matrix3x4_t boneDelta1[MAXSTUDIOBONES]; - matrix3x4_t currentBones[MAXSTUDIOBONES]; - const float boneDt = 0.1f; - GetRagdollInitBoneArrays( boneDelta0, boneDelta1, currentBones, boneDt ); - pRagdoll->InitAsClientRagdoll( boneDelta0, boneDelta1, currentBones, boneDt ); return pRagdoll; } @@ -5512,6 +5614,13 @@ int C_BaseAnimating::SelectWeightedSequence ( int activity ) } +int C_BaseAnimating::SelectWeightedSequenceFromModifiers( Activity activity, CUtlSymbol *pActivityModifiers, int iModifierCount ) +{ + Assert( activity != ACT_INVALID ); + Assert( GetModelPtr() ); + return GetModelPtr()->SelectWeightedSequenceFromModifiers( activity, pActivityModifiers, iModifierCount ); +} + //========================================================= //========================================================= int C_BaseAnimating::LookupPoseParameter( CStudioHdr *pstudiohdr, const char *szName ) @@ -6018,7 +6127,7 @@ void C_BaseAnimating::AddToClientSideAnimationList() UpdateRelevantInterpolatedVars(); } -void C_BaseAnimating::RemoveFromClientSideAnimationList() +void C_BaseAnimating::RemoveFromClientSideAnimationList( bool bBeingDestroyed /*= false*/ ) { // Not in list yet if ( INVALID_CLIENTSIDEANIMATION_LIST_HANDLE == m_ClientSideAnimationListHandle ) @@ -6049,7 +6158,10 @@ void C_BaseAnimating::RemoveFromClientSideAnimationList() // Invalidate our handle no matter what. m_ClientSideAnimationListHandle = INVALID_CLIENTSIDEANIMATION_LIST_HANDLE; - UpdateRelevantInterpolatedVars(); + if ( !bBeingDestroyed ) + { + UpdateRelevantInterpolatedVars(); + } } |