Implement simulation rewind

This commit is contained in:
sergeypdev 2025-02-09 19:54:44 +04:00
parent aa1dab6079
commit c2b831a4d6
3 changed files with 24 additions and 6 deletions

View File

@ -58,6 +58,7 @@ Runtime_World :: struct {
camera: rl.Camera3D, camera: rl.Camera3D,
orbit_camera: Orbit_Camera, orbit_camera: Orbit_Camera,
dt: f32, dt: f32,
rewind_simulation: bool,
step_simulation: bool, step_simulation: bool,
single_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 runtime_world.dt = dt
should_single_step := rl.IsKeyPressed(.PERIOD) 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.step_simulation = !g_mem.physics_pause || should_single_step
runtime_world.single_step_simulation = should_single_step runtime_world.single_step_simulation = should_single_step
} }
@ -629,6 +631,9 @@ draw :: proc() {
car_model.transform = car_matrix car_model.transform = car_matrix
if !runtime_world.pause { 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( physics.simulate(
&world.physics_scene, &world.physics_scene,
&runtime_world.solver_state, &runtime_world.solver_state,
@ -638,6 +643,7 @@ draw :: proc() {
step_mode = g_mem.physics_pause ? physics.Step_Mode.Single : physics.Step_Mode.Accumulated_Time, 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) // 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{} g_mem^ = Game_Memory{}
physics.init_physics_scene(&g_mem.runtime_world.world.physics_scene, 100)
game_hot_reloaded(g_mem) game_hot_reloaded(g_mem)
} }

View File

@ -40,7 +40,7 @@ draw_debug_shape :: proc(
draw_debug_scene :: proc(scene: ^Scene) { draw_debug_scene :: proc(scene: ^Scene) {
tracy.Zone() tracy.Zone()
sim_state := get_next_sim_state(scene) sim_state := get_sim_state(scene)
for _, i in sim_state.bodies { for _, i in sim_state.bodies {
body := &sim_state.bodies_slice[i] body := &sim_state.bodies_slice[i]

View File

@ -25,10 +25,14 @@ Sim_State :: struct {
} }
Scene :: struct { Scene :: struct {
simulation_states: [2]Sim_State, simulation_states: []Sim_State,
simulation_state_index: i32, 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 { Body :: struct {
// Is this body alive (if not it doesn't exist) // Is this body alive (if not it doesn't exist)
alive: bool, alive: bool,
@ -132,19 +136,24 @@ _invalid_body_slice := _invalid_body[:]
_invalid_suspension_constraint: #soa[1]Suspension_Constraint _invalid_suspension_constraint: #soa[1]Suspension_Constraint
_invalid_suspension_constraint_slice := _invalid_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 { get_sim_state :: proc(scene: ^Scene) -> ^Sim_State {
return &scene.simulation_states[scene.simulation_state_index] return &scene.simulation_states[scene.simulation_state_index]
} }
get_prev_sim_state :: proc(scene: ^Scene) -> ^Sim_State { 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 :: proc(scene: ^Scene) -> ^Sim_State {
get_next_sim_state :: get_prev_sim_state return &scene.simulation_states[(scene.simulation_state_index + 1) %% i32(len(scene.simulation_states))]
}
flip_sim_state :: proc(scene: ^Scene) { 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 /// 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 { for &sim_state in scene.simulation_states {
destry_sim_state(&sim_state) destry_sim_state(&sim_state)
} }
delete(scene.simulation_states)
} }