ValveSoftware / halflife

Half-Life 1 engine based games
Other
3.63k stars 618 forks source link

Models stutter due to client side interpolation #3228

Open SamVanheer opened 2 years ago

SamVanheer commented 2 years ago

When Half-Life 1 was updated to handle studio model rendering in the client dll with SDK 2.0 a bug started occurring where studio models moved by other entities like func_tracktrain would stutter.

Here's a video that shows the stuttering as well as the expected behavior: video

The most likely cause is that the time value used by model rendering is being overwritten by an older time value used by the client side prediction code. The animation time values jump back and forth from the present to the past in a way that causes interpolation to sometimes interpolate to some point in the future and sometimes to some point in the past, causing the model to "pinball" between the past and future interpolated positions.

The cause of this is somewhere in the engine, not fixable in SDK code as-is. A workaround exists to disable interpolation in these cases to prevent the stuttering effect from occurring, originally provided by Uncle Mike on the HLFX forums: https://hlfx.ru/forum/showthread.php?s=&threadid=15&highlight=%C8%ED%F2%E5%F0%EF%EE%EB%FF%F6%E8%FF

(Unfortunately you need an account to access this thread)

The changes required are as follows:

Change this line: https://github.com/ValveSoftware/halflife/blob/c7240b965743a53a29491dd49320c88eecf6257b/dlls/nihilanth.cpp#L291

To this:

pev->flags |= FL_MONSTER | FL_FLY;

Change this line: https://github.com/ValveSoftware/halflife/blob/c7240b965743a53a29491dd49320c88eecf6257b/dlls/osprey.cpp#L156

To this:

pev->flags |= FL_MONSTER | FL_FLY;

(the same change is needed in Opposing Force's Black Ops Osprey code)

After this line: https://github.com/ValveSoftware/halflife/blob/c7240b965743a53a29491dd49320c88eecf6257b/dlls/cbase.h#L149

Add this:

/**
*   @brief Entity flags sent to the client in ::AddToFullPack
*/
byte m_EFlags = 0;

After this line: https://github.com/ValveSoftware/halflife/blob/c7240b965743a53a29491dd49320c88eecf6257b/dlls/cbase.cpp#L586

Add this:

DEFINE_FIELD(CBaseEntity, m_EFlags, FIELD_CHARACTER),

After this line: https://github.com/ValveSoftware/halflife/blob/c7240b965743a53a29491dd49320c88eecf6257b/dlls/tentacle.cpp#L258

Add this:

//Always interpolate tentacles since they don't actually move.
m_EFlags |= EFLAG_SLERP;

After this line: https://github.com/ValveSoftware/halflife/blob/c7240b965743a53a29491dd49320c88eecf6257b/dlls/client.cpp#L1097

Add this:

auto entity = reinterpret_cast<CBaseEntity*>(GET_PRIVATE(ent));

Change this logic: https://github.com/ValveSoftware/halflife/blob/c7240b965743a53a29491dd49320c88eecf6257b/dlls/client.cpp#L1194-L1201

To this:

if ((ent->v.flags & FL_FLY) != 0)
{
    state->eflags |= EFLAG_SLERP;
}
else
{
    state->eflags &= ~EFLAG_SLERP;
}

state->eflags |= entity->m_EFlags;

Change this logic: https://github.com/ValveSoftware/halflife/blob/c7240b965743a53a29491dd49320c88eecf6257b/cl_dll/StudioModelRenderer.cpp#L474-L477

To this:

const auto pseqdesc = (mstudioseqdesc_t*)((byte*)m_pStudioHeader + m_pStudioHeader->seqindex) + m_pCurrentEntity->curstate.sequence;

if ((pseqdesc->motiontype & STUDIO_LX) != 0 || (m_pCurrentEntity->curstate.eflags & EFLAG_SLERP) != 0)
{
    for (i = 0; i < 3; i++)
    {
        modelpos[i] += (m_pCurrentEntity->origin[i] - m_pCurrentEntity->latched.prevorigin[i]) * f;
    }
}

These changes restrict model interpolation to animations that have movement on the X axis and entities that have interpolation enabled, which is enabled for any entity that sets the FL_FLY flag. Entities can also force interpolation by setting the EFLAG_SLERP flag on CBaseEntity::m_EFlags.

Tentacles will not interpolate correctly when loading a save game made before these code changes were applied.

A better solution would be to identify the cause of the bug (likely the incorrect time values) and fixing that, but that would require an investigation and testing to verify that the fix doesn't break anything that may be depending on this buggy behavior somehow.

di57inct commented 2 years ago

Is this somehow related to the bug where if a player would stand on top of another crouching player his camera would stutter vertically?

SamVanheer commented 2 years ago

Is this somehow related to the bug where if a player would stand on top of another crouching player his camera would stutter vertically?

I don't think so, this only affects the model's render position, not the player's camera position.

di57inct commented 2 years ago

Understood. Thanks.

SamVanheer commented 2 years ago

Added additional step to fix monster_osprey not interpolating.

SamVanheer commented 2 years ago

Added additional steps to fix monster_tentacle not interpolating.