interp tick ratio rather than time offset. set world tick timestamp at beginning of frame

This commit is contained in:
jacob 2024-03-13 14:00:56 -05:00
parent 8f33957bf9
commit bac001947b
4 changed files with 24 additions and 21 deletions

View File

@ -11,4 +11,11 @@
#define VSYNC_ENABLED 0
#define GAME_FPS 30
#define USER_FRAME_LIMIT 300
/* How many ticks back in time should the user blend between?
* Delay ms = USER_INTERP_OFFSET_TICK_RATIO * Game tick rate
* E.g: At 1.5, the user thread will render 49.5ms back in time (if game thread runs at 30FPS)
*/
#define USER_INTERP_OFFSET_TICK_RATIO 1.5

View File

@ -13,7 +13,6 @@ GLOBAL struct {
b32 shutdown;
struct sys_thread game_thread;
f64 timescale;
struct world world;
/* Game thread input */
@ -66,9 +65,7 @@ INTERNAL struct game_cmd_array pop_cmds(struct arena *arena)
INTERNAL void publish_game_tick(void)
{
__prof;
sys_mutex_lock(&L.published_tick_mutex);
L.world.tick_published_ts = sys_timestamp();
world_copy_replace(&L.published_tick, &L.world);
sys_mutex_unlock(&L.published_tick_mutex);
}
@ -211,7 +208,8 @@ INTERNAL void game_update(void)
}
++L.world.tick_id;
L.world.dt = max_f64(0.0, (1.0 / GAME_FPS) * L.timescale);
L.world.tick_ts = sys_timestamp();
L.world.dt = max_f64(0.0, (1.0 / GAME_FPS) * L.world.timescale);
L.world.time += L.world.dt;
struct entity_array entities_array = world_get_entities(&L.world);
@ -454,7 +452,7 @@ INTERNAL void game_update(void)
if (entity_has_prop(ent, ENTITY_PROP_TEST_SOUND_EMITTER)) {
struct mixer_desc desc = ent->sound_desc;
desc.speed = L.timescale;
desc.speed = L.world.timescale;
desc.pos = ent->world_xform.og;
struct sound *sound = sound_load_async(ent->sound_name, 0);
b32 played = ent->sound_handle.gen != 0;
@ -486,7 +484,7 @@ INTERNAL void game_thread_entry_point(void *arg)
{
(UNUSED)arg;
sys_timestamp_t last_frame_ts = 0;
f64 target_dt = GAME_FPS > 0 ? (1.0 / GAME_FPS) : 0;
f64 target_dt = GAME_FPS > (0) ? (1.0 / GAME_FPS) : 0;
while (!L.shutdown) {
__profscope(game_update_w_sleep);
sleep_frame(last_frame_ts, target_dt);
@ -509,7 +507,7 @@ void game_startup(void)
L.published_tick_mutex = sys_mutex_alloc();
L.timescale = 1.0;
L.world.timescale = 1.0;
L.game_thread = sys_thread_init(&game_thread_entry_point, NULL, STR("[P2] Game thread"));
}

View File

@ -19,10 +19,6 @@
#include "sound.h"
#include "mixer.h"
/* How far back in time should the user blend between game ticks (in addition
* to the existing 1-tick delay) */
#define USER_INTERP_DELAY 0.005
struct view {
f32 px_per_unit;
@ -213,13 +209,13 @@ INTERNAL struct interp_ticks pull_ticks(f64 blend_time)
struct world *from_tick = oldest_tick;
struct world *to_tick = newest_tick;
for (struct blend_tick *bt = L.head_blend_tick; bt; bt = bt->next) {
f64 bt_time = sys_timestamp_seconds(bt->world.tick_published_ts);
f64 bt_time = sys_timestamp_seconds(bt->world.tick_ts);
if (bt_time < blend_time && bt_time > sys_timestamp_seconds(from_tick->tick_published_ts)) {
if (bt_time < blend_time && bt_time > sys_timestamp_seconds(from_tick->tick_ts)) {
from_tick = &bt->world;
}
if (bt_time > blend_time && bt_time < sys_timestamp_seconds(to_tick->tick_published_ts)) {
if (bt_time > blend_time && bt_time < sys_timestamp_seconds(to_tick->tick_ts)) {
to_tick = &bt->world;
}
}
@ -231,8 +227,8 @@ INTERNAL struct interp_ticks pull_ticks(f64 blend_time)
u64 bts_to_free_count = 0;
for (struct blend_tick *bt = L.head_blend_tick; bt; bt = bt->next) {
f64 bt_time = sys_timestamp_seconds(bt->world.tick_published_ts);
if (bt_time < sys_timestamp_seconds(from_tick->tick_published_ts)) {
f64 bt_time = sys_timestamp_seconds(bt->world.tick_ts);
if (bt_time < sys_timestamp_seconds(from_tick->tick_ts)) {
*arena_push(scratch.arena, struct blend_tick *) = bt;
++bts_to_free_count;
}
@ -588,7 +584,7 @@ INTERNAL void user_update(void)
/* Pull ticks */
/* FIXME: use real game DT */
f64 blend_time_offset = USER_INTERP_DELAY + (1.0 / GAME_FPS);
f64 blend_time_offset = (1.0 / GAME_FPS) * USER_INTERP_OFFSET_TICK_RATIO;
f64 blend_time = L.time > blend_time_offset ? L.time - blend_time_offset : 0;
struct interp_ticks interp_ticks = pull_ticks(blend_time);
@ -599,8 +595,8 @@ INTERNAL void user_update(void)
{
__profscope(produce_interpolated_tick);
f64 t0_time = sys_timestamp_seconds(t0->tick_published_ts);
f64 t1_time = sys_timestamp_seconds(t1->tick_published_ts);
f64 t0_time = sys_timestamp_seconds(t0->tick_ts);
f64 t1_time = sys_timestamp_seconds(t1->tick_ts);
f32 tick_blend = 0;
if (t1_time > t0_time) {
@ -939,7 +935,7 @@ INTERNAL void user_thread_entry_point(void *arg)
(UNUSED)arg;
sys_timestamp_t last_frame_ts = 0;
f64 target_dt = USER_FRAME_LIMIT > 0 ? (1.0 / USER_FRAME_LIMIT) : 0;
f64 target_dt = USER_FRAME_LIMIT > (0) ? (1.0 / USER_FRAME_LIMIT) : 0;
while (!L.shutdown) {
__profscope(user_update_w_sleep);

View File

@ -5,8 +5,10 @@
struct world {
u64 tick_id; /* Starts at 1 */
u64 tick_published_ts;
u64 tick_ts; /* When was this tick simulated in program time */
/* World time */
f64 timescale;
f64 dt;
f64 time;