From c2b831a4d68f1fbc60a78f964a7e1a08839190c2 Mon Sep 17 00:00:00 2001 From: sergeypdev Date: Sun, 9 Feb 2025 19:54:44 +0400 Subject: [PATCH] Implement simulation rewind --- game/game.odin | 8 ++++++++ game/physics/debug.odin | 2 +- game/physics/scene.odin | 20 +++++++++++++++----- 3 files changed, 24 insertions(+), 6 deletions(-) diff --git a/game/game.odin b/game/game.odin index d326946..a226e92 100644 --- a/game/game.odin +++ b/game/game.odin @@ -58,6 +58,7 @@ Runtime_World :: struct { camera: rl.Camera3D, orbit_camera: Orbit_Camera, dt: f32, + rewind_simulation: bool, step_simulation: bool, single_step_simulation: bool, } @@ -420,6 +421,7 @@ update_runtime_world :: proc(runtime_world: ^Runtime_World, dt: f32) { runtime_world.dt = dt should_single_step := rl.IsKeyPressed(.PERIOD) + runtime_world.rewind_simulation = rl.IsKeyPressed(.COMMA) runtime_world.step_simulation = !g_mem.physics_pause || should_single_step runtime_world.single_step_simulation = should_single_step } @@ -629,6 +631,9 @@ draw :: proc() { car_model.transform = car_matrix if !runtime_world.pause { + if runtime_world.rewind_simulation { + world.physics_scene.simulation_state_index = physics.get_prev_sim_state_index(&world.physics_scene) + } else { physics.simulate( &world.physics_scene, &runtime_world.solver_state, @@ -637,6 +642,7 @@ draw :: proc() { commit = runtime_world.step_simulation, step_mode = g_mem.physics_pause ? physics.Step_Mode.Single : physics.Step_Mode.Accumulated_Time, ) + } } // rl.DrawModel(car_model, physics.body_get_shape_pos(car_body), 1, rl.WHITE) @@ -944,6 +950,8 @@ game_init :: proc() { g_mem^ = Game_Memory{} + physics.init_physics_scene(&g_mem.runtime_world.world.physics_scene, 100) + game_hot_reloaded(g_mem) } diff --git a/game/physics/debug.odin b/game/physics/debug.odin index ac16f22..21c3178 100644 --- a/game/physics/debug.odin +++ b/game/physics/debug.odin @@ -40,7 +40,7 @@ draw_debug_shape :: proc( draw_debug_scene :: proc(scene: ^Scene) { tracy.Zone() - sim_state := get_next_sim_state(scene) + sim_state := get_sim_state(scene) for _, i in sim_state.bodies { body := &sim_state.bodies_slice[i] diff --git a/game/physics/scene.odin b/game/physics/scene.odin index 5fdebaf..f81cdb8 100644 --- a/game/physics/scene.odin +++ b/game/physics/scene.odin @@ -25,10 +25,14 @@ Sim_State :: struct { } Scene :: struct { - simulation_states: [2]Sim_State, + simulation_states: []Sim_State, simulation_state_index: i32, } +init_physics_scene :: proc(scene: ^Scene, max_history := int(2)) { + scene.simulation_states = make([]Sim_State, max(max_history, 2)) +} + Body :: struct { // Is this body alive (if not it doesn't exist) alive: bool, @@ -132,19 +136,24 @@ _invalid_body_slice := _invalid_body[:] _invalid_suspension_constraint: #soa[1]Suspension_Constraint _invalid_suspension_constraint_slice := _invalid_suspension_constraint[:] +get_prev_sim_state_index :: proc(scene: ^Scene) -> i32 { + return (scene.simulation_state_index - 1) %% i32(len(scene.simulation_states)) +} + get_sim_state :: proc(scene: ^Scene) -> ^Sim_State { return &scene.simulation_states[scene.simulation_state_index] } get_prev_sim_state :: proc(scene: ^Scene) -> ^Sim_State { - return &scene.simulation_states[(scene.simulation_state_index + 1) % 2] + return &scene.simulation_states[get_prev_sim_state_index(scene)] } -// lol -get_next_sim_state :: get_prev_sim_state +get_next_sim_state :: proc(scene: ^Scene) -> ^Sim_State { + return &scene.simulation_states[(scene.simulation_state_index + 1) %% i32(len(scene.simulation_states))] +} flip_sim_state :: proc(scene: ^Scene) { - scene.simulation_state_index = (scene.simulation_state_index + 1) % 2 + scene.simulation_state_index = (scene.simulation_state_index + 1) %% i32(len(scene.simulation_states)) } /// Returns pointer to soa slice. NEVER STORE IT @@ -361,4 +370,5 @@ destroy_physics_scene :: proc(scene: ^Scene) { for &sim_state in scene.simulation_states { destry_sim_state(&sim_state) } + delete(scene.simulation_states) }