@@ -1216,6 +1216,9 @@ CStudioHdr *C_BaseAnimating::OnNewModel()
12161216 }
12171217 m_BoneAccessor.Init ( this , m_CachedBoneData.Base () ); // Always call this in case the studiohdr_t has changed.
12181218
1219+ // Reset the accumulated bone mask.
1220+ m_iAccumulatedBoneMask = 0 ;
1221+
12191222 // Free any IK data
12201223 if (m_pIk)
12211224 {
@@ -2286,16 +2289,24 @@ bool C_BaseAnimating::PutAttachment( int number, const matrix3x4_t &attachmentTo
22862289 return false ;
22872290
22882291 CAttachmentData *pAtt = &m_Attachments[number-1 ];
2289- if ( gpGlobals->frametime > 0 && pAtt->m_nLastFramecount > 0 && pAtt->m_nLastFramecount == gpGlobals->framecount - 1 )
2292+ if ( gpGlobals->frametime > 0 && pAtt->m_nLastFramecount > 0 && pAtt->m_nLastFramecount < gpGlobals->framecount )
22902293 {
22912294 Vector vecPreviousOrigin, vecOrigin;
22922295 MatrixPosition ( pAtt->m_AttachmentToWorld , vecPreviousOrigin );
22932296 MatrixPosition ( attachmentToWorld, vecOrigin );
2294- pAtt->m_vOriginVelocity = (vecOrigin - vecPreviousOrigin) / gpGlobals->frametime ;
2297+
2298+ // compensate for the fact that the previous origin could have been multiple frames behind
2299+ pAtt->m_vOriginVelocity = (vecOrigin - vecPreviousOrigin) / (gpGlobals->frametime * (gpGlobals->framecount - pAtt->m_nLastFramecount ));
2300+ // only update the frame count if the position changed, so we don't have to recompute attachments
2301+ if ( !pAtt->m_vOriginVelocity .IsZero ( 0 .00001f ) )
2302+ {
2303+ pAtt->m_nLastFramecount = gpGlobals->framecount ;
2304+ }
22952305 }
22962306 else
22972307 {
22982308 pAtt->m_vOriginVelocity .Init ();
2309+ pAtt->m_nLastFramecount = gpGlobals->framecount ;
22992310 }
23002311 pAtt->m_nLastFramecount = gpGlobals->framecount ;
23012312 pAtt->m_bAnglesComputed = false ;
@@ -2308,6 +2319,20 @@ bool C_BaseAnimating::PutAttachment( int number, const matrix3x4_t &attachmentTo
23082319 return true ;
23092320}
23102321
2322+ bool C_BaseAnimating::GetAttachmentDeferred ( int number, matrix3x4_t & matrix )
2323+ {
2324+ if ( number < 1 || number > m_Attachments.Count () )
2325+ return false ;
2326+
2327+ // allow visual effects (eg. particles) to be a frame behind bone setup so that there are not messy dependencies.
2328+ CAttachmentData* pAtt = &m_Attachments[number - 1 ];
2329+ const bool bShouldUpdate = pAtt->m_nLastFramecount < gpGlobals->framecount - 1 ;
2330+ if ( bShouldUpdate && !CalcAttachments () )
2331+ return false ;
2332+
2333+ matrix = pAtt->m_AttachmentToWorld ;
2334+ return true ;
2335+ }
23112336
23122337bool C_BaseAnimating::SetupBones_AttachmentHelper ( CStudioHdr *hdr )
23132338{
@@ -3122,6 +3147,22 @@ bool C_BaseAnimating::SetupBones( matrix3x4_t *pBoneToWorldOut, int nMaxBones, i
31223147 }
31233148 }
31243149
3150+ // If we're setting up LOD N, we have set up all lower LODs also
3151+ // because lower LODs always use subsets of the bones of higher LODs.
3152+ int nLOD = 0 ;
3153+ int nMask = BONE_USED_BY_VERTEX_LOD0 ;
3154+
3155+ for ( ; nLOD < MAX_NUM_LODS ; ++nLOD, nMask <<= 1 )
3156+ {
3157+ if ( boneMask & nMask )
3158+ break ;
3159+ }
3160+
3161+ for ( ; nLOD < MAX_NUM_LODS ; ++nLOD, nMask <<= 1 )
3162+ {
3163+ boneMask |= nMask;
3164+ }
3165+
31253166#ifdef DEBUG_BONE_SETUP_THREADING
31263167 if ( cl_warn_thread_contested_bone_setup.GetBool () )
31273168 {
@@ -3154,7 +3195,9 @@ bool C_BaseAnimating::SetupBones( matrix3x4_t *pBoneToWorldOut, int nMaxBones, i
31543195 m_flLastBoneSetupTime = currentTime;
31553196 }
31563197 m_iPrevBoneMask = m_iAccumulatedBoneMask;
3157- m_iAccumulatedBoneMask = 0 ;
3198+
3199+ // Keep record of the fact that we've used attachments. Because of deferred attachments, we can't keep track from the previous frame.
3200+ m_iAccumulatedBoneMask = m_iAccumulatedBoneMask & BONE_USED_BY_ATTACHMENT ;
31583201
31593202#ifdef STUDIO_ENABLE_PERF_COUNTERS
31603203 CStudioHdr *hdr = GetModelPtr ();
@@ -3189,7 +3232,7 @@ bool C_BaseAnimating::SetupBones( matrix3x4_t *pBoneToWorldOut, int nMaxBones, i
31893232 return false ;
31903233
31913234 // Setup our transform based on render angles and origin.
3192- matrix3x4_t parentTransform;
3235+ ALIGN16 matrix3x4_t parentTransform ALIGN16_POST ;
31933236 AngleMatrix ( GetRenderAngles (), GetRenderOrigin (), parentTransform );
31943237
31953238 // Load the boneMask with the total of what was asked for last frame.
0 commit comments