Files
shadow-over-bishkek001/CHARACTER_INTERPOLATION.md
T

77 lines
3.7 KiB
Markdown

# Character Presentation Interpolation
The authoritative game simulation still advances in exact 100 ms ticks. Character
interpolation is a rendering-only feature and does not modify `CharacterState`,
network commands, tick IDs, state hashes, or deterministic lockstep behavior.
## How it works
Each runtime `Character` keeps two presentation samples:
- `previous`: the visual values received at the preceding completed simulation tick;
- `current`: the visual values received at the latest completed simulation tick.
Rendering calculates an alpha from the real elapsed time since the latest completed
tick, clamped to the 100 ms simulation interval. It renders the delayed
`previous -> current` transition. This introduces at most one simulation tick of
presentation latency, but it avoids predicting a state that has not arrived from
the authoritative simulation.
The following values are interpolated:
- Position uses linear interpolation.
- Facing angle uses the shortest angular path, including wraparound at ±π.
- Animation frame remains fractional and is interpolated when both samples use
the same animation state. Looping clips treat the last frame to first frame
transition as a cyclic interval instead of interpolating backward through the
entire clip.
The interpolated values are used by mesh, weapon, shadow, night-lighting, name,
and health-bar rendering. The local camera and shadow-map center follow the same
interpolated player position; otherwise the camera would jump to the newest
authoritative position while the player model was still in its presentation
transition. Gameplay queries, commands, callbacks, collision, and presentation
events continue to use the authoritative snapshot.
## Other presentation animations
Teleport-zone star particles are advanced by `Location::updatePresentation()`
once per render frame using the real frame delta. They are no longer advanced
only from the 100 ms simulation-tick callback, so their visual motion remains
continuous without affecting teleport activation or other authoritative state.
Dialogue typewriter text and cutscene presentation timers use the same
per-render-frame path. This keeps character reveals, subtitle timing, fades, and
cutscene image poses smooth instead of stepping in 100 ms increments.
Interactive objects retain authoritative move, rotate, scale, and fade tasks on
the simulation tick. Their previous and current visual transforms are sampled
at tick boundaries and interpolated only while drawing, so doors and similar
objects remain logically deterministic while their presentation is smooth.
The same render-only sampling is used for `NpcCar` taxi visuals. Its position,
body rotation, wheel rotation, and steering angle are interpolated for drawing;
the authoritative taxi movement and waypoint logic remain fixed-step.
## Animation skinning
GPU and CPU bone interpolation receive the fractional render frame instead of an
integer-truncated frame. Bone positions are linearly interpolated and bone
rotations use spherical interpolation as before. Frames at the end of a clip are
clamped to the final keyframe.
## Discontinuities
The presentation buffer is reset instead of blended when a character is first
observed, changes animation state or enabled state, or has not received a tick
for a sufficiently long gap. This prevents stale positions, animation clips, or
disabled characters from producing visible interpolation artifacts.
## Local and networked games
Local games continue accumulating wall-clock remainder time and executing exact
100 ms simulation updates. Networked games continue consuming only contiguous
server tick messages. Both paths publish completed snapshots to the same runtime
presentation objects; interpolation only changes how those snapshots are drawn
between updates.