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,
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)
}

View File

@ -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]

View File

@ -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)
}