proper sim blending
This commit is contained in:
parent
e1e19d6aca
commit
9800cb9f04
@ -267,8 +267,7 @@ P_Anim P_AnimFromEnt(P_Frame *frame, P_Ent *ent)
|
||||
result.span = SPR_SpanKeyFromName(Lit("roll"));
|
||||
result.weapon_over = 1;
|
||||
}
|
||||
// else if (Vec2LenSq(ent->control.move) > (0.01 * 0.01))
|
||||
else if (0)
|
||||
else if (Vec2LenSq(ent->control.move) > (0.01 * 0.01))
|
||||
{
|
||||
result.span = SPR_SpanKeyFromName(Lit("walk"));
|
||||
if (ent->is_guy)
|
||||
|
||||
@ -257,7 +257,7 @@ void V_DrawPoint(Vec2 p, Vec4 srgb)
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Timeline helpers
|
||||
|
||||
void V_PushTimelineMarker(i64 time_ns, Vec4 color, b32 transient)
|
||||
void V_PushTimelineMarker(f64 tick, Vec4 color, b32 transient)
|
||||
{
|
||||
V_Frame *prev_frame = V_PrevFrame();
|
||||
if (!prev_frame->prev_timeline.paused)
|
||||
@ -271,7 +271,7 @@ void V_PushTimelineMarker(i64 time_ns, Vec4 color, b32 transient)
|
||||
{
|
||||
marker = PushStruct(V.persistent_markers_arena, V_TimelineMarker);
|
||||
}
|
||||
marker->time_ns = time_ns;
|
||||
marker->tick = tick;
|
||||
marker->color = color;
|
||||
}
|
||||
}
|
||||
@ -386,41 +386,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
P_SimStatistics sim_stats = Zi;
|
||||
|
||||
P_World *sim_world = P_AcquireWorld();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// FIXME: Move this
|
||||
|
||||
Struct(V_Prediction)
|
||||
{
|
||||
i64 base_time_ns;
|
||||
i64 predict_from;
|
||||
i64 predict_to;
|
||||
P_World *world;
|
||||
};
|
||||
|
||||
i64 cur_prediction_seq = 0;
|
||||
|
||||
V_Prediction predictions[V_MaxInterpRatio] = Zi;
|
||||
for (i64 prediction_idx = 0; prediction_idx < countof(predictions); ++prediction_idx)
|
||||
{
|
||||
predictions[prediction_idx].world = P_AcquireWorld();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
P_World *predict_world = P_AcquireWorld();
|
||||
|
||||
i64 local_controls_cap = NextPow2U64(SIM_MAX_PING * SIM_TICKS_PER_SECOND);
|
||||
P_Control *local_controls = PushStructs(perm, P_Control, local_controls_cap);
|
||||
@ -639,7 +605,8 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
frame->desired_sim_key = prev_frame->desired_sim_key;
|
||||
frame->target_predict_tick_accum = prev_frame->target_predict_tick_accum;
|
||||
frame->predict_tick_accum = prev_frame->predict_tick_accum;
|
||||
frame->blend_tick = prev_frame->blend_tick;
|
||||
frame->blend_sim_tick = prev_frame->blend_sim_tick;
|
||||
frame->blend_predict_tick = prev_frame->blend_predict_tick;
|
||||
frame->af = prev_frame->af;
|
||||
|
||||
frame->tick = V.cur_frame_tick;
|
||||
@ -1460,8 +1427,8 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
// We cannot simulate backwards
|
||||
frame->predict_tick_accum = MaxF64(prev_frame->predict_tick_accum, frame->predict_tick_accum);
|
||||
|
||||
// V_PushTimelineMarker(frame->predict_tick_accum * SIM_TICK_INTERVAL_NS, Color_Red, 1);
|
||||
// V_PushTimelineMarker(frame->target_predict_tick_accum * SIM_TICK_INTERVAL_NS, Color_Yellow, 1);
|
||||
// V_PushTimelineMarker(frame->predict_tick_accum, Color_Red, 1);
|
||||
// V_PushTimelineMarker(frame->target_predict_tick_accum, Color_Yellow, 1);
|
||||
}
|
||||
i64 prev_frame_predict_to = FloorF64(prev_frame->predict_tick_accum);
|
||||
i64 predict_to = FloorF64(frame->predict_tick_accum);
|
||||
@ -1626,7 +1593,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
}
|
||||
|
||||
P_Frame *ack_frame = P_FrameFromTick(sim_world, ack);
|
||||
V_PushTimelineMarker(ack_frame->time_ns, Color_Green, 1);
|
||||
V_PushTimelineMarker(ack, Color_Green, 1);
|
||||
|
||||
//////////////////////////////
|
||||
//- Predict
|
||||
@ -1644,38 +1611,36 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
// TODO: Remove this
|
||||
// TODO: Delete all frames except for prediction base & remote ack
|
||||
// TODO: Limit max sim frames stored
|
||||
// Clear received sim frames
|
||||
{
|
||||
i64 bottom_tick = I64Max;
|
||||
{
|
||||
bottom_tick = MinI64(bottom_tick, ack_mirror);
|
||||
bottom_tick = MinI64(bottom_tick, first_predict_tick);
|
||||
bottom_tick = MinI64(bottom_tick, last_predict_tick);
|
||||
bottom_tick = MinI64(bottom_tick, ack);
|
||||
|
||||
// FIXME: Enable this
|
||||
// P_ClearFrames(sim_world, I64Min, bottom_tick - 1);
|
||||
P_ClearFrames(sim_world, I64Min, bottom_tick - 100);
|
||||
bottom_tick = MinI64(bottom_tick, ack - V_MaxInterpRatio);
|
||||
}
|
||||
P_ClearFrames(sim_world, I64Min, bottom_tick - 1);
|
||||
}
|
||||
// P_ClearFrames(sim_world, I64Min, ack - SIM_TICKS_PER_SECOND);
|
||||
// P_ClearFrames(sim_world, I64Min, sim_world->last_frame->tick - 1);
|
||||
|
||||
// Clear predicted frames
|
||||
{
|
||||
i64 bottom_tick = I64Max;
|
||||
{
|
||||
bottom_tick = MinI64(bottom_tick, first_predict_tick);
|
||||
bottom_tick = MinI64(bottom_tick, ack - V_MaxInterpRatio);
|
||||
}
|
||||
P_ClearFrames(predict_world, I64Min, bottom_tick - 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Push prediction if new frame received from server
|
||||
V_Prediction *cur_prediction = &predictions[cur_prediction_seq % countof(predictions)];
|
||||
V_Prediction *prev_prediction = &predictions[MaxI64(cur_prediction_seq - 1, 0) % countof(predictions)];
|
||||
if (ack != prev_frame_ack)
|
||||
{
|
||||
cur_prediction_seq += 1;
|
||||
prev_prediction = cur_prediction;
|
||||
cur_prediction = &predictions[cur_prediction_seq % countof(predictions)];
|
||||
|
||||
cur_prediction->base_time_ns = ack_frame->time_ns;
|
||||
cur_prediction->predict_from = ack_frame->tick;
|
||||
cur_prediction->predict_to = predict_to;
|
||||
if (ack != prev_frame_ack)
|
||||
{
|
||||
V_PushTimelineMarker(ack_frame->time_ns, Color_Green, 0);
|
||||
}
|
||||
V_PushTimelineMarker(ack, Color_Green, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -1683,7 +1648,6 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
|
||||
|
||||
// Predict
|
||||
P_World *predict_world = cur_prediction->world;
|
||||
P_Frame *predict_frame = predict_world->last_frame;
|
||||
{
|
||||
if (predict_world->tiles_hash != sim_world->tiles_hash)
|
||||
@ -1693,12 +1657,6 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
}
|
||||
predict_world->seed = sim_world->seed;
|
||||
|
||||
// FIXME: Enable this
|
||||
// P_ClearFrames(predict_world, I64Min, MinI64(first_predict_tick - 1, prev_frame->blend_from_tick - 1));
|
||||
// P_ClearFrames(predict_world, I64Min, MinI64(first_predict_tick - 2, prev_frame->blend_from_tick - 1));
|
||||
// P_ClearFrames(predict_world, I64Min, MinI64(first_predict_tick - V_MaxInterpRatio, prev_frame->blend_from_tick - 1));
|
||||
P_ClearFrames(predict_world, I64Min, MinI64(first_predict_tick - V_MaxInterpRatio, prev_frame->blend_from_tick - 100));
|
||||
|
||||
predict_frame = P_PushFrame(predict_world, P_FrameFromTick(sim_world, first_predict_tick), first_predict_tick);
|
||||
|
||||
for (i64 predict_tick = first_predict_tick + 1; predict_tick <= last_predict_tick; ++predict_tick)
|
||||
@ -1732,7 +1690,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
P_tl.debug_draw_enabled = old_debug_draw;
|
||||
P_tl.debug_tint = old_debug_tint;
|
||||
|
||||
V_PushTimelineMarker(predict_frame->time_ns, Color_Purple, 0);
|
||||
V_PushTimelineMarker(predict_frame->tick, Color_Purple, 0);
|
||||
}
|
||||
|
||||
predict_frame = predict_world->last_frame;
|
||||
@ -1740,9 +1698,66 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
|
||||
// TODO: Extract information that occurred between first & last prediction, like bullet hits etc?
|
||||
|
||||
V_PushTimelineMarker(predict_frame->time_ns, Color_Purple, 1);
|
||||
V_PushTimelineMarker(predict_frame->tick, Color_Purple, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
//- Compute blend ticks
|
||||
|
||||
{
|
||||
// How many ticks back in time should the user thread blend between?
|
||||
// <Delay> = <USER_INTERP_RATIO> * <Tick interval>
|
||||
// E.g: At 1.5, the world will render 75ms back in time if the sim runs at 50tps
|
||||
f64 interp_ratio = TweakFloat("Interpolation ratio", 1.2, 0, V_MaxInterpRatio);
|
||||
|
||||
//- Blended sim tick
|
||||
f64 target_blend_sim_tick = (f64)ack - interp_ratio;
|
||||
{
|
||||
f64 lerp_rate = SaturateF64(5.0 * frame->dt);
|
||||
frame->blend_sim_tick += frame->dt * SIM_TICKS_PER_SECOND;
|
||||
{
|
||||
frame->blend_sim_tick = LerpF64(frame->blend_sim_tick, target_blend_sim_tick, lerp_rate);
|
||||
if ((prev_frame_ack == 0 && ack != 0) || AbsF64(frame->blend_sim_tick - ack) > SIM_TICKS_PER_SECOND)
|
||||
{
|
||||
frame->blend_sim_tick = target_blend_sim_tick;
|
||||
LogDebugF("Sim blend reset");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//- Blended prediction tick
|
||||
f64 target_blend_predict_tick = frame->predict_tick_accum - interp_ratio;
|
||||
{
|
||||
f64 lerp_rate = SaturateF64(2.0 * frame->dt);
|
||||
frame->blend_predict_tick += frame->dt * SIM_TICKS_PER_SECOND;
|
||||
{
|
||||
frame->blend_predict_tick = LerpF64(frame->blend_predict_tick, target_blend_predict_tick, lerp_rate);
|
||||
if ((prev_frame_ack == 0 && ack != 0) || AbsF64(frame->blend_predict_tick - ack) > SIM_TICKS_PER_SECOND)
|
||||
{
|
||||
frame->blend_predict_tick = target_blend_predict_tick;
|
||||
LogDebugF("Prediction blend reset");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
V_PushTimelineMarker(frame->blend_sim_tick, Color_Orange, 1);
|
||||
V_PushTimelineMarker(frame->blend_predict_tick, Color_Red, 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
//- Update local world
|
||||
|
||||
@ -1767,191 +1782,84 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
frame->local_world->seed = predict_world->seed;
|
||||
P_ClearFrames(frame->local_world, I64Min, I64Max);
|
||||
|
||||
// Warm start
|
||||
frame->blend_tick += frame->dt * SIM_TICKS_PER_SECOND;
|
||||
|
||||
// How many ticks back in time should the user thread blend between?
|
||||
// <Delay> = <USER_INTERP_RATIO> * <Tick interval>
|
||||
// E.g: At 1.5, the world will render 75ms back in time if the sim runs at 50tps
|
||||
// f32 interp_ratio = TweakFloat("Interpolation ratio", 1.2, 0, V_MaxInterpRatio);
|
||||
f32 interp_ratio = TweakFloat("Interpolation ratio", 1.2, 0, V_MaxInterpRatio);
|
||||
|
||||
// {
|
||||
// frame->blend_tick = frame->predict_tick_accum - interp_ratio;
|
||||
// }
|
||||
|
||||
f64 target_blend_tick = frame->predict_tick_accum - interp_ratio;
|
||||
{
|
||||
f64 lerp_rate = 5.0 * frame->dt;
|
||||
lerp_rate = SaturateF64(lerp_rate);
|
||||
frame->blend_tick = LerpF64(frame->blend_tick, target_blend_tick, lerp_rate);
|
||||
if ((prev_frame_ack == 0 && ack != 0) || AbsF64(frame->blend_tick - ack) > SIM_TICKS_PER_SECOND)
|
||||
{
|
||||
frame->blend_tick = target_blend_tick;
|
||||
LogDebugF("Blend reset");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// V_PushTimelineMarker(target_blend_tick * SIM_TICK_INTERVAL_NS, Color_Cyan, 1);
|
||||
V_PushTimelineMarker(frame->blend_tick * SIM_TICK_INTERVAL_NS, Color_Orange, 1);
|
||||
|
||||
if (TweakBool("Interpolation enabled", 1))
|
||||
{
|
||||
P_Frame *left_predict_frame = &P_NilFrame;
|
||||
P_Frame *right_predict_frame = &P_NilFrame;
|
||||
|
||||
// Locate left & right frames
|
||||
// Locate sim keyframes
|
||||
P_Frame *left_sim_frame = &P_NilFrame;
|
||||
P_Frame *right_sim_frame = &P_NilFrame;
|
||||
{
|
||||
for (
|
||||
i64 prediction_seq = cur_prediction_seq;
|
||||
prediction_seq >= MaxI64(cur_prediction_seq - countof(predictions), 0);
|
||||
--prediction_seq
|
||||
)
|
||||
{
|
||||
b32 should_search_right = P_IsFrameNil(right_predict_frame);
|
||||
b32 should_search_left = P_IsFrameNil(left_predict_frame);
|
||||
|
||||
// Locate right frame
|
||||
if (should_search_right)
|
||||
{
|
||||
i64 tmp_prediction_idx = prediction_seq % countof(predictions);
|
||||
V_Prediction *prediction = &predictions[tmp_prediction_idx];
|
||||
P_World *tmp_world = prediction->world;
|
||||
for (P_Frame *tmp_right_frame = tmp_world->last_frame; !P_IsFrameNil(tmp_right_frame); tmp_right_frame = tmp_right_frame->prev)
|
||||
for (P_Frame *tmp_right_frame = ack_frame; !P_IsFrameNil(tmp_right_frame); tmp_right_frame = tmp_right_frame->prev)
|
||||
{
|
||||
P_Frame *tmp_left_frame = tmp_right_frame->prev;
|
||||
if (tmp_right_frame->tick >= frame->blend_tick && tmp_left_frame->tick <= frame->blend_tick)
|
||||
if (tmp_right_frame->tick >= frame->blend_sim_tick && tmp_left_frame->tick <= frame->blend_sim_tick)
|
||||
{
|
||||
right_sim_frame = tmp_right_frame;
|
||||
left_sim_frame = tmp_left_frame;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (P_IsFrameNil(left_sim_frame) || P_IsFrameNil(right_sim_frame))
|
||||
{
|
||||
LogDebugF("Missing sim blend");
|
||||
right_sim_frame = ack_frame;
|
||||
left_sim_frame = right_sim_frame;
|
||||
V_PushTimelineMarker(frame->blend_sim_tick, Color_Orange, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Locate predicted keyframes
|
||||
P_Frame *left_predict_frame = &P_NilFrame;
|
||||
P_Frame *right_predict_frame = &P_NilFrame;
|
||||
{
|
||||
for (P_Frame *tmp_right_frame = predict_world->last_frame; !P_IsFrameNil(tmp_right_frame); tmp_right_frame = tmp_right_frame->prev)
|
||||
{
|
||||
P_Frame *tmp_left_frame = tmp_right_frame->prev;
|
||||
if (tmp_right_frame->tick >= frame->blend_predict_tick && tmp_left_frame->tick <= frame->blend_predict_tick)
|
||||
{
|
||||
right_predict_frame = tmp_right_frame;
|
||||
left_predict_frame = tmp_left_frame;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Locate left frame
|
||||
if (should_search_left)
|
||||
{
|
||||
i64 tmp_prediction_idx = MaxI64((prediction_seq - 1), 0) % countof(predictions);
|
||||
V_Prediction *prediction = &predictions[tmp_prediction_idx];
|
||||
P_World *tmp_world = prediction->world;
|
||||
for (P_Frame *tmp_frame = tmp_world->last_frame; !P_IsFrameNil(tmp_frame); tmp_frame = tmp_frame->prev)
|
||||
{
|
||||
if (tmp_frame->tick <= frame->blend_tick)
|
||||
{
|
||||
left_predict_frame = tmp_frame;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// V_PushTimelineMarker(left_time_ns, Color_Cyan, 1);
|
||||
// V_PushTimelineMarker(right_time_ns, Color_Orange, 1);
|
||||
|
||||
if (!should_search_right && !should_search_left)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (P_IsFrameNil(left_predict_frame) || P_IsFrameNil(right_predict_frame))
|
||||
{
|
||||
LogDebugF("Missing blend");
|
||||
|
||||
LogDebugF("Missing prediction blend");
|
||||
right_predict_frame = predict_world->last_frame;
|
||||
left_predict_frame = right_predict_frame;
|
||||
|
||||
V_PushTimelineMarker(frame->blend_tick * SIM_TICK_INTERVAL_NS, Color_Red, 0);
|
||||
V_PushTimelineMarker(frame->blend_predict_tick, Color_Red, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
frame->blend_from_tick = left_predict_frame->tick;
|
||||
frame->blend_to_tick = right_predict_frame->tick;
|
||||
|
||||
local_frame = P_PushFrame(frame->local_world, left_predict_frame, left_predict_frame->tick);
|
||||
{
|
||||
P_Frame *left_sim_frame = left_predict_frame;
|
||||
P_Frame *right_sim_frame = right_predict_frame;
|
||||
|
||||
// P_Frame *left_sim_frame = predict_world->first_frame;
|
||||
// P_Frame *right_sim_frame = left_sim_frame->next;
|
||||
|
||||
// P_Frame *right_sim_frame = P_FrameFromTick(predict_world, first_predict_tick);
|
||||
// P_Frame *left_sim_frame = right_sim_frame->prev;
|
||||
|
||||
|
||||
// P_Frame *right_sim_frame = P_FrameFromTick(sim_world, ack - 1);
|
||||
// P_Frame *left_sim_frame = right_sim_frame->prev;
|
||||
|
||||
// P_Frame *right_sim_frame = P_FrameFromTick(sim_world, right_predict_frame->src_tick);
|
||||
// P_Frame *left_sim_frame = right_sim_frame->prev;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// P_Frame *left_sim_frame = P_FrameFromTick(prev_predict_world, left_predict_frame->base_predict_from);
|
||||
// P_Frame *right_sim_frame = P_FrameFromTick(predict_world, right_predict_frame->base_predict_from);
|
||||
|
||||
// P_Frame *left_sim_frame = P_FrameFromTick(prev_predict_world, left_predict_frame->base_predict_to);
|
||||
// P_Frame *right_sim_frame = P_FrameFromTick(predict_world, right_predict_frame->base_predict_to);
|
||||
|
||||
|
||||
|
||||
|
||||
// V_PushTimelineMarker(left_predict_frame->base_predict_from * SIM_TICK_INTERVAL_NS, Color_Yellow, 1);
|
||||
// V_PushTimelineMarker(right_predict_frame->base_predict_from * SIM_TICK_INTERVAL_NS, Color_Yellow, 1);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// f64 blend_t = (f64)(V.blend_time_ns - left_predict_frame->base_time_ns) / (f64)(right_predict_frame->base_time_ns - left_predict_frame->base_time_ns);
|
||||
// f64 blend_t = (f64)(V.blend_time_ns - left_predict_frame->time_ns) / (f64)(right_predict_frame->time_ns - left_predict_frame->time_ns);
|
||||
f64 blend_t = (f64)(frame->blend_tick - left_predict_frame->tick) / (f64)(right_predict_frame->tick - left_predict_frame->tick);
|
||||
|
||||
if (IsInf(blend_t))
|
||||
f64 sim_blend_t = (f64)(frame->blend_sim_tick - left_sim_frame->tick) / (f64)(right_sim_frame->tick - left_sim_frame->tick);
|
||||
f64 predict_blend_t = (f64)(frame->blend_predict_tick - left_predict_frame->tick) / (f64)(right_predict_frame->tick - left_predict_frame->tick);
|
||||
if (IsInf(sim_blend_t) || IsNan(sim_blend_t))
|
||||
{
|
||||
blend_t = 1;
|
||||
sim_blend_t = 1;
|
||||
}
|
||||
if (IsInf(predict_blend_t) || IsNan(predict_blend_t))
|
||||
{
|
||||
predict_blend_t = 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (P_Ent *ent = P_FirstEnt(local_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
|
||||
{
|
||||
// if (ent->sim)
|
||||
P_Ent *left = ent;
|
||||
P_Ent *right = ent;
|
||||
// if (ent->sim)
|
||||
if (0)
|
||||
f32 blend_t = 0;
|
||||
if (ent->sim)
|
||||
{
|
||||
left = P_EntFromKey(left_predict_frame, ent->key);
|
||||
right = P_EntFromKey(right_predict_frame, ent->key);
|
||||
blend_t = predict_blend_t;
|
||||
}
|
||||
else
|
||||
{
|
||||
left = P_EntFromKey(left_sim_frame, ent->key);
|
||||
right = P_EntFromKey(right_sim_frame, ent->key);
|
||||
blend_t = sim_blend_t;
|
||||
}
|
||||
|
||||
ent->exists = LerpF32(left->exists, right->exists, blend_t);
|
||||
@ -1988,275 +1896,6 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// P_Frame *prev_local_frame = prev_frame->local_world->last_frame;
|
||||
// P_Frame *local_frame = &P_NilFrame;
|
||||
// {
|
||||
// if (frame->local_world->tiles_hash != predict_world->tiles_hash)
|
||||
// {
|
||||
// frame->local_world->tiles_hash = predict_world->tiles_hash;
|
||||
// CopyStructs(frame->local_world->tiles, predict_world->tiles, P_TilesCount);
|
||||
// frame->tiles_dirty = 1;
|
||||
// }
|
||||
// frame->local_world->seed = predict_world->seed;
|
||||
// P_ClearFrames(frame->local_world, I64Min, I64Max);
|
||||
|
||||
// // Warm start
|
||||
// frame->blend_tick += frame->dt * SIM_TICKS_PER_SECOND;
|
||||
|
||||
// // How many ticks back in time should the user thread blend between?
|
||||
// // <Delay> = <USER_INTERP_RATIO> * <Tick interval>
|
||||
// // E.g: At 1.5, the world will render 75ms back in time if the sim runs at 50tps
|
||||
// // f32 interp_ratio = TweakFloat("Interpolation ratio", 1.2, 0, V_MaxInterpRatio);
|
||||
// f32 interp_ratio = TweakFloat("Interpolation ratio", 1.2, 0, V_MaxInterpRatio);
|
||||
|
||||
// // {
|
||||
// // frame->blend_tick = frame->predict_tick_accum - interp_ratio;
|
||||
// // }
|
||||
|
||||
// f64 target_blend_tick = frame->predict_tick_accum - interp_ratio;
|
||||
// {
|
||||
// f64 lerp_rate = 5.0 * frame->dt;
|
||||
// lerp_rate = SaturateF64(lerp_rate);
|
||||
// frame->blend_tick = LerpF64(frame->blend_tick, target_blend_tick, lerp_rate);
|
||||
// if ((prev_frame_ack == 0 && ack != 0) || AbsF64(frame->blend_tick - ack) > SIM_TICKS_PER_SECOND)
|
||||
// {
|
||||
// frame->blend_tick = target_blend_tick;
|
||||
// LogDebugF("Blend reset");
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// // V_PushTimelineMarker(target_blend_tick * SIM_TICK_INTERVAL_NS, Color_Cyan, 1);
|
||||
// V_PushTimelineMarker(frame->blend_tick * SIM_TICK_INTERVAL_NS, Color_Orange, 1);
|
||||
|
||||
// if (TweakBool("Interpolation enabled", 1))
|
||||
// {
|
||||
// P_Frame *left_predict_frame = &P_NilFrame;
|
||||
// P_Frame *right_predict_frame = &P_NilFrame;
|
||||
|
||||
// // Locate left & right frames
|
||||
// {
|
||||
// for (
|
||||
// i64 prediction_seq = cur_prediction_seq;
|
||||
// prediction_seq >= MaxI64(cur_prediction_seq - countof(predict_worlds), 0);
|
||||
// --prediction_seq
|
||||
// )
|
||||
// {
|
||||
// b32 should_search_right = P_IsFrameNil(right_predict_frame);
|
||||
// b32 should_search_left = P_IsFrameNil(left_predict_frame);
|
||||
|
||||
// // Locate right frame
|
||||
// if (should_search_right)
|
||||
// {
|
||||
// i64 tmp_world_idx = prediction_seq % countof(predict_worlds);
|
||||
// P_World *tmp_world = predict_worlds[tmp_world_idx];
|
||||
// for (P_Frame *tmp_right_frame = tmp_world->last_frame; !P_IsFrameNil(tmp_right_frame); tmp_right_frame = tmp_right_frame->prev)
|
||||
// {
|
||||
// P_Frame *tmp_left_frame = tmp_right_frame->prev;
|
||||
// if (tmp_right_frame->tick >= frame->blend_tick && tmp_left_frame->tick <= frame->blend_tick)
|
||||
// {
|
||||
// right_predict_frame = tmp_right_frame;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// // Locate left frame
|
||||
// if (should_search_left)
|
||||
// {
|
||||
// i64 tmp_world_idx = MaxI64((prediction_seq - 1), 0) % countof(predict_worlds);
|
||||
// P_World *tmp_world = predict_worlds[tmp_world_idx];
|
||||
// for (P_Frame *tmp_frame = tmp_world->last_frame; !P_IsFrameNil(tmp_frame); tmp_frame = tmp_frame->prev)
|
||||
// {
|
||||
// if (tmp_frame->tick <= frame->blend_tick)
|
||||
// {
|
||||
// left_predict_frame = tmp_frame;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// // V_PushTimelineMarker(left_time_ns, Color_Cyan, 1);
|
||||
// // V_PushTimelineMarker(right_time_ns, Color_Orange, 1);
|
||||
|
||||
// if (!should_search_right && !should_search_left)
|
||||
// {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
|
||||
// if (P_IsFrameNil(left_predict_frame) || P_IsFrameNil(right_predict_frame))
|
||||
// {
|
||||
// LogDebugF("Missing blend");
|
||||
|
||||
// right_predict_frame = predict_world->last_frame;
|
||||
// left_predict_frame = right_predict_frame;
|
||||
|
||||
// V_PushTimelineMarker(frame->blend_tick * SIM_TICK_INTERVAL_NS, Color_Red, 0);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
// frame->blend_from_tick = left_predict_frame->tick;
|
||||
// frame->blend_to_tick = right_predict_frame->tick;
|
||||
|
||||
// local_frame = P_PushFrame(frame->local_world, left_predict_frame, left_predict_frame->tick);
|
||||
// {
|
||||
// P_Frame *left_sim_frame = left_predict_frame;
|
||||
// P_Frame *right_sim_frame = right_predict_frame;
|
||||
|
||||
// // P_Frame *left_sim_frame = predict_world->first_frame;
|
||||
// // P_Frame *right_sim_frame = left_sim_frame->next;
|
||||
|
||||
// // P_Frame *right_sim_frame = P_FrameFromTick(predict_world, first_predict_tick);
|
||||
// // P_Frame *left_sim_frame = right_sim_frame->prev;
|
||||
|
||||
|
||||
// // P_Frame *right_sim_frame = P_FrameFromTick(sim_world, ack - 1);
|
||||
// // P_Frame *left_sim_frame = right_sim_frame->prev;
|
||||
|
||||
// // P_Frame *right_sim_frame = P_FrameFromTick(sim_world, right_predict_frame->src_tick);
|
||||
// // P_Frame *left_sim_frame = right_sim_frame->prev;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// // P_Frame *left_sim_frame = P_FrameFromTick(prev_predict_world, left_predict_frame->base_predict_from);
|
||||
// // P_Frame *right_sim_frame = P_FrameFromTick(predict_world, right_predict_frame->base_predict_from);
|
||||
|
||||
// // P_Frame *left_sim_frame = P_FrameFromTick(prev_predict_world, left_predict_frame->base_predict_to);
|
||||
// // P_Frame *right_sim_frame = P_FrameFromTick(predict_world, right_predict_frame->base_predict_to);
|
||||
|
||||
|
||||
|
||||
|
||||
// V_PushTimelineMarker(left_predict_frame->base_predict_from * SIM_TICK_INTERVAL_NS, Color_Yellow, 1);
|
||||
// V_PushTimelineMarker(right_predict_frame->base_predict_from * SIM_TICK_INTERVAL_NS, Color_Yellow, 1);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// // f64 blend_t = (f64)(V.blend_time_ns - left_predict_frame->base_time_ns) / (f64)(right_predict_frame->base_time_ns - left_predict_frame->base_time_ns);
|
||||
// // f64 blend_t = (f64)(V.blend_time_ns - left_predict_frame->time_ns) / (f64)(right_predict_frame->time_ns - left_predict_frame->time_ns);
|
||||
// f64 blend_t = (f64)(frame->blend_tick - left_predict_frame->tick) / (f64)(right_predict_frame->tick - left_predict_frame->tick);
|
||||
|
||||
// if (IsInf(blend_t))
|
||||
// {
|
||||
// blend_t = 1;
|
||||
// }
|
||||
|
||||
|
||||
|
||||
// for (P_Ent *ent = P_FirstEnt(local_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
|
||||
// {
|
||||
// P_Ent *left = ent;
|
||||
// P_Ent *right = ent;
|
||||
// // if (ent->sim)
|
||||
// if (0)
|
||||
// {
|
||||
// left = P_EntFromKey(left_predict_frame, ent->key);
|
||||
// right = P_EntFromKey(right_predict_frame, ent->key);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// left = P_EntFromKey(left_sim_frame, ent->key);
|
||||
// right = P_EntFromKey(right_sim_frame, ent->key);
|
||||
// }
|
||||
|
||||
// ent->exists = LerpF32(left->exists, right->exists, blend_t);
|
||||
// if (!P_IsEntNil(right) && right->continuity_gen == left->continuity_gen)
|
||||
// {
|
||||
// ent->health = LerpF32(left->health, right->health, blend_t);
|
||||
// ent->xf.t = LerpVec2(left->xf.t, right->xf.t, blend_t);
|
||||
// ent->xf.r = SlerpVec2(left->xf.r, right->xf.r, blend_t);
|
||||
// ent->walk_time_accum_ns = LerpI64(left->walk_time_accum_ns, right->walk_time_accum_ns, blend_t);
|
||||
// ent->v = LerpVec2(left->v, right->v, blend_t);
|
||||
// ent->w = LerpF32(left->w, right->w, blend_t);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// local_frame = P_PushFrame(frame->local_world, predict_world->last_frame, predict_world->last_frame->tick);
|
||||
// }
|
||||
|
||||
|
||||
// P_DebugDrawFrame(local_frame);
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////
|
||||
//- Query local player
|
||||
|
||||
@ -4631,8 +4270,8 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
// FIXME: Remove this
|
||||
PERSIST i64 last_timeline_matchup_ns = 0;
|
||||
PERSIST i64 last_timeline_reset_ns = 0;
|
||||
PERSIST i64 timeline_start_ns = 0;
|
||||
PERSIST i64 current_marker_time_ns = 0;
|
||||
PERSIST f64 timeline_start_tick = 0;
|
||||
PERSIST f64 current_marker_tick = 0;
|
||||
|
||||
b32 was_locked = prev_frame->prev_timeline.locked;
|
||||
b32 was_paused = prev_frame->prev_timeline.paused;
|
||||
@ -4643,16 +4282,16 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
|
||||
f64 unlocked_timeline_span_seconds = 2;
|
||||
f64 locked_timeline_span_seconds = 1;
|
||||
i64 timeline_span_ns = NsFromSeconds(is_locked ? locked_timeline_span_seconds : unlocked_timeline_span_seconds);
|
||||
f64 timeline_span_ticks = (is_locked ? locked_timeline_span_seconds : unlocked_timeline_span_seconds) * SIM_TICKS_PER_SECOND;
|
||||
|
||||
// Current frame time marker
|
||||
if (!was_paused)
|
||||
{
|
||||
current_marker_time_ns = frame->time_ns - last_timeline_matchup_ns + timeline_start_ns;
|
||||
current_marker_tick = ((f64)(frame->time_ns - last_timeline_matchup_ns) / SIM_TICK_INTERVAL_NS) + timeline_start_tick;
|
||||
}
|
||||
if (is_locked)
|
||||
{
|
||||
// V_PushTimelineMarker(current_marker_time_ns, Color_White, 1);
|
||||
// V_PushTimelineMarker(current_marker_tick, Color_White, 1);
|
||||
}
|
||||
|
||||
if (is_showing)
|
||||
@ -4667,9 +4306,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
f32 timeline_opacity = 0.75;
|
||||
f32 marker_opacity = 0.75;
|
||||
|
||||
// i64 timeline_span_ns = NsFromSeconds(10);
|
||||
|
||||
i64 timeline_end_ns = timeline_start_ns + timeline_span_ns;
|
||||
f64 timeline_end_tick = timeline_start_tick + timeline_span_ticks;
|
||||
|
||||
UI_Size transient_marker_width = UI_FNT(0.1, 1);
|
||||
UI_Size transient_marker_height = UI_FNT(2, 1);
|
||||
@ -4700,8 +4337,8 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
marker_offset.x = timeline_width.v * 0.5;
|
||||
if (is_locked)
|
||||
{
|
||||
i64 offset_ns = current_marker_time_ns;
|
||||
marker_offset.x += -((f64)(offset_ns - timeline_start_ns) / (f64)timeline_span_ns) * timeline_width.v;
|
||||
f64 offset_ticks = current_marker_tick;
|
||||
marker_offset.x += -(offset_ticks - timeline_start_tick) / (timeline_span_ticks) * timeline_width.v;
|
||||
}
|
||||
|
||||
//- Build markers
|
||||
@ -4729,7 +4366,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
|
||||
Vec4 marker_color = marker->color;
|
||||
|
||||
f64 marker_ratio = (f64)(marker->time_ns - timeline_start_ns) / (f64)timeline_span_ns;
|
||||
f64 marker_ratio = (marker->tick - timeline_start_tick) / timeline_span_ticks;
|
||||
Vec2 marker_pos = timeline_pos;
|
||||
if (is_transient)
|
||||
{
|
||||
@ -4763,7 +4400,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
UI_PopCP(UI_TopCP());
|
||||
}
|
||||
|
||||
i64 reset_span_ns = timeline_span_ns * 0.5;
|
||||
i64 reset_span_ns = (timeline_span_ticks * SIM_TICK_INTERVAL_NS) * 0.5;
|
||||
b32 is_first_ack = prev_frame_ack == 0 && ack != 0;
|
||||
b32 should_reset = (
|
||||
!is_paused && (
|
||||
@ -4777,7 +4414,7 @@ void V_TickForever(WaveLaneCtx *lane)
|
||||
if (!is_locked && should_reset || is_first_ack || is_showing != was_showing)
|
||||
{
|
||||
last_timeline_matchup_ns = frame->time_ns;
|
||||
timeline_start_ns = frame->predict_tick_accum * SIM_TICK_INTERVAL_NS;
|
||||
timeline_start_tick = frame->predict_tick_accum;
|
||||
}
|
||||
if (should_reset)
|
||||
{
|
||||
|
||||
@ -224,7 +224,7 @@ Enum(V_DrawFlag)
|
||||
Struct(V_TimelineMarker)
|
||||
{
|
||||
Vec4 color;
|
||||
i64 time_ns;
|
||||
f64 tick;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
@ -249,10 +249,9 @@ Struct(V_Frame)
|
||||
NET_Key desired_sim_key;
|
||||
f64 target_predict_tick_accum;
|
||||
f64 predict_tick_accum;
|
||||
f64 blend_tick;
|
||||
|
||||
i64 blend_from_tick;
|
||||
i64 blend_to_tick;
|
||||
f64 blend_sim_tick;
|
||||
f64 blend_predict_tick;
|
||||
|
||||
Button held_buttons[Button_COUNT];
|
||||
V_Palette palette;
|
||||
@ -327,7 +326,7 @@ void V_DrawPoint(Vec2 p, Vec4 srgb);
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Timeline helpers
|
||||
|
||||
void V_PushTimelineMarker(i64 time_ns, Vec4 color, b32 transient);
|
||||
void V_PushTimelineMarker(f64 tick, Vec4 color, b32 transient);
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//~ Theme
|
||||
|
||||
Loading…
Reference in New Issue
Block a user