This commit is contained in:
ficool2 2025-04-03 15:59:08 +03:00 committed by GitHub
commit 0e5f8da6a4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 48 additions and 3 deletions

View file

@ -1603,7 +1603,25 @@ void C_BaseAnimating::BuildTransformations( CStudioHdr *hdr, Vector *pos, Quater
}
}
if ( m_pRagdoll )
{
C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
if ( pPlayer )
{
// When the local player is spectating a ragdoll, they are copying the root physics bone
// Afterwards, physics simulation of ragdolls happens and updates the bones
// ... But after that, the ragdoll is drawn with the NEW bones
// which leads to the camera and rendering being out of sync with each other and causing visible jittering
// The workaround for this problem is to render the ragdoll with the last frame's bone data
C_BaseEntity* pObserverTarget = pPlayer->GetObserverTarget();
if ( pObserverTarget
&& pObserverTarget->IsPlayer()
&& static_cast< C_BasePlayer* >( pObserverTarget )->GetRepresentativeRagdoll() == m_pRagdoll )
{
m_pRagdoll->AcquireOrCopyBoneCache( m_CachedBoneData.Base(), m_CachedBoneData.Count() );
}
}
}
}
//-----------------------------------------------------------------------------

View file

@ -28,7 +28,7 @@ CRagdoll::CRagdoll()
m_ragdoll.listCount = 0;
m_vecLastOrigin.Init();
m_flLastOriginChangeTime = - 1.0f;
m_flBoneCacheTime = -FLT_MAX;
m_lastUpdate = -FLT_MAX;
}
@ -174,6 +174,31 @@ void CRagdoll::RagdollBone( C_BaseEntity *ent, mstudiobone_t *pbones, int boneCo
}
}
void CRagdoll::AcquireOrCopyBoneCache( matrix3x4_t* pOutBonesToWorld, int boneCount )
{
// acquire cache if not setup
if ( m_BoneCache.Count() != boneCount )
{
m_BoneCache.CopyArray( pOutBonesToWorld, boneCount );
m_flBoneCacheTime = gpGlobals->curtime;
}
// copy cache out if called again in same frame
else if ( gpGlobals->curtime == m_flBoneCacheTime )
{
memcpy( pOutBonesToWorld, m_BoneCache.Base(), boneCount * sizeof(matrix3x4_t) );
}
// copy out our cache and acquire the old one
else
{
size_t uBoneDataSize = boneCount * sizeof(matrix3x4_t);
matrix3x4_t* pTempBoneData = (matrix3x4_t*)stackalloc( uBoneDataSize );
memcpy( pTempBoneData, pOutBonesToWorld, uBoneDataSize );
memcpy( pOutBonesToWorld, m_BoneCache.Base(), uBoneDataSize );
memcpy( m_BoneCache.Base(), pTempBoneData, uBoneDataSize );
m_flBoneCacheTime = gpGlobals->curtime;
}
}
const Vector& CRagdoll::GetRagdollOrigin( )
{
m_ragdoll.list[0].pObject->GetPosition( &m_origin, 0 );

View file

@ -60,10 +60,10 @@ public:
bool bFixedConstraints=false );
virtual void RagdollBone( C_BaseEntity *ent, mstudiobone_t *pbones, int boneCount, bool *boneSimulated, CBoneAccessor &pBoneToWorld );
void AcquireOrCopyBoneCache( matrix3x4_t* pBonesToWorld, int boneCount );
virtual const Vector& GetRagdollOrigin( );
virtual void GetRagdollBounds( Vector &theMins, Vector &theMaxs );
void BuildRagdollBounds( C_BaseEntity *ent );
virtual IPhysicsObject *GetElement( int elementNum );
virtual IPhysicsConstraintGroup *GetConstraintGroup() { return m_ragdoll.pGroup; }
virtual void DrawWireframe();
@ -101,6 +101,8 @@ private:
bool m_allAsleep;
Vector m_vecLastOrigin;
float m_flLastOriginChangeTime;
CUtlVector< matrix3x4_t > m_BoneCache;
float m_flBoneCacheTime;
#if RAGDOLL_VISUALIZE
matrix3x4_t m_savedBone1[MAXSTUDIOBONES];