From e618ad95203d72380cd38124b446dfd71a663e86 Mon Sep 17 00:00:00 2001 From: sergeypdev Date: Thu, 9 Jan 2025 15:07:19 +0400 Subject: [PATCH] Timestep independence, finally --- .nvim.lua | 2 ++ game/game.odin | 33 ++++++++++++++++++++------------- game/physics/simulation.odin | 13 +++++++------ 3 files changed, 29 insertions(+), 19 deletions(-) create mode 100644 .nvim.lua diff --git a/.nvim.lua b/.nvim.lua new file mode 100644 index 0000000..b563699 --- /dev/null +++ b/.nvim.lua @@ -0,0 +1,2 @@ +vim.opt_global.makeprg = "./build_hot_reload.sh" +vim.opt.errorformat = "%f(%l:%c)\\ %m" diff --git a/game/game.odin b/game/game.odin index bad2b1e..329c04f 100644 --- a/game/game.odin +++ b/game/game.odin @@ -62,7 +62,7 @@ Car :: struct { } SOLVER_CONFIG :: physics.Solver_Config { - timestep = 1.0 / 120, + timestep = 1.0 / 104, gravity = rl.Vector3{0, -9.8, 0}, substreps_minus_one = 4 - 1, } @@ -245,20 +245,20 @@ update_runtime_world :: proc(runtime_world: ^Runtime_World, dt: f32) { }, ) - car_body := physics.get_body(&world.physics_scene, runtime_world.car_handle) + // car_body := physics.get_body(&world.physics_scene, runtime_world.car_handle) camera := &runtime_world.camera camera.up = rl.Vector3{0, 1, 0} camera.fovy = 60 camera.projection = .PERSPECTIVE - camera.position = physics.body_local_to_world( - car_body, - physics.body_world_to_local( - car_body, - physics.body_local_to_world(car_body, rl.Vector3{1, 0, -2}), - ), - ) + // camera.position = physics.body_local_to_world( + // car_body, + // physics.body_world_to_local( + // car_body, + // physics.body_local_to_world(car_body, rl.Vector3{1, 0, -2}), + // ), + // ) camera.target = physics.get_body(&world.physics_scene, runtime_world.car_handle).x if runtime_world.camera.position == {} { runtime_world.camera.position = runtime_world.camera.target - rl.Vector3{10, 0, 10} @@ -333,8 +333,8 @@ update_runtime_world :: proc(runtime_world: ^Runtime_World, dt: f32) { drive_wheels := []physics.Suspension_Constraint_Handle{wheel_rl, wheel_rr} turn_wheels := []physics.Suspension_Constraint_Handle{wheel_fl, wheel_fr} - DRIVE_IMPULSE :: 1 - BRAKE_IMPULSE :: 2 + DRIVE_IMPULSE :: 20 + BRAKE_IMPULSE :: 50 TURN_ANGLE :: -f32(30) * math.RAD_PER_DEG for wheel_handle in drive_wheels { @@ -520,7 +520,12 @@ draw :: proc() { car_matrix := rl.QuaternionToMatrix(car_body.q) car_model.transform = car_matrix - rl.DrawModel(car_model, car_body.x + runtime_world.car_com, 1, rl.WHITE) + rl.DrawModel( + car_model, + physics.body_local_to_world(car_body, -runtime_world.car_com), + 1, + rl.WHITE, + ) } else { if g_mem.draw_car { rl.DrawModel(car_model, 0, 1, rl.WHITE) @@ -572,6 +577,8 @@ draw :: proc() { rl.BeginMode2D(ui_camera()) defer rl.EndMode2D() + rl.DrawFPS(0, 0) + if g_mem.editor { rl.DrawText("Editor", 5, 5, 8, rl.ORANGE) @@ -782,7 +789,7 @@ game_init_window :: proc() { rl.InitWindow(1280, 720, "Odin + Raylib + Hot Reload template!") rl.SetExitKey(.KEY_NULL) rl.SetWindowPosition(200, 200) - rl.SetTargetFPS(60) + rl.SetTargetFPS(120) } @(export) diff --git a/game/physics/simulation.odin b/game/physics/simulation.odin index 69e2d4f..68b3ba4 100644 --- a/game/physics/simulation.odin +++ b/game/physics/simulation.odin @@ -48,7 +48,7 @@ simulate :: proc(scene: ^Scene, state: ^Solver_State, config: Solver_Config, dt: state.accumulated_time += dt num_steps := 0 - for state.accumulated_time > config.timestep { + for state.accumulated_time >= config.timestep { num_steps += 1 state.accumulated_time -= config.timestep @@ -135,17 +135,21 @@ simulate_step :: proc(scene: ^Scene, config: Solver_Config) { for _, i in scene.suspension_constraints { v := &scene.suspension_constraints_slice[i] if v.alive { + body_idx := int(v.body) - 1 body := get_body(scene, v.body) if body.alive && v.hit { + prev_x, prev_q := body_states[body_idx].prev_x, body_states[body_idx].prev_q + wheel_world_pos := body_local_to_world(body, v.rel_pos) + prev_wheel_world_pos := prev_x + lg.quaternion_mul_vector3(prev_q, v.rel_pos) + + vel_3d := (wheel_world_pos - prev_wheel_world_pos) * inv_dt dir := body_local_to_world_vec(body, v.rel_dir) body_state := body_states[i32(v.body) - 1] // Spring damping if true { - vel_3d := body_velocity_at_local_point(body, wheel_world_pos - body.x) - vel := lg.dot(vel_3d, dir) damping := -vel * min(v.damping * dt, 1) @@ -166,8 +170,6 @@ simulate_step :: proc(scene: ^Scene, config: Solver_Config) { total_impulse := v.drive_impulse - v.brake_impulse forward := body_local_to_world_vec(body, rl.Vector3{0, 0, 1}) - corr := total_impulse * forward * dt - apply_constraint_correction_unilateral( dt, body, @@ -176,7 +178,6 @@ simulate_step :: proc(scene: ^Scene, config: Solver_Config) { forward, wheel_world_pos, ) - apply_correction(body, corr, wheel_world_pos) body_solve_velocity(body, body_state, inv_dt) }