Gears and engine->wheel power transfer. Not working well yet, it's losing a lot of power somewhere. Maybe it needs to be a position constraint
This commit is contained in:
parent
c3945a80e5
commit
cbe0dd20e5
@ -53,6 +53,7 @@ Runtime_World :: struct {
|
||||
solver_state: physics.Solver_State,
|
||||
car_com: rl.Vector3,
|
||||
car_handle: physics.Body_Handle,
|
||||
engine_handle: physics.Engine_Handle,
|
||||
camera_yaw_pitch: rl.Vector2,
|
||||
camera_speed: f32,
|
||||
camera: rl.Camera3D,
|
||||
@ -331,7 +332,7 @@ update_runtime_world :: proc(runtime_world: ^Runtime_World, dt: f32) {
|
||||
radius := f32(0.2888)
|
||||
wheel_front_z := f32(1.3)
|
||||
wheel_back_z := f32(-1.1)
|
||||
wheel_mass := f32(30)
|
||||
wheel_mass := f32(14)
|
||||
|
||||
wheel_fl := physics.immediate_suspension_constraint(
|
||||
&world.physics_scene,
|
||||
@ -394,21 +395,21 @@ update_runtime_world :: proc(runtime_world: ^Runtime_World, dt: f32) {
|
||||
},
|
||||
)
|
||||
|
||||
engine := physics.immediate_engine(
|
||||
runtime_world.engine_handle = physics.immediate_engine(
|
||||
&world.physics_scene,
|
||||
&runtime_world.solver_state,
|
||||
#hash("engine", "fnv32a"),
|
||||
physics.Engine_Config {
|
||||
rpm_torque_curve = assets.get_curve_2d(&g_mem.assetman, "assets/ae86_rpm_torque.csv").points,
|
||||
lowest_rpm = 1000,
|
||||
inertia = 10,
|
||||
internal_friction = 8,
|
||||
inertia = 0.0264,
|
||||
internal_friction = 0.00,
|
||||
gear_ratios = []f32{3.48, 3.587, 2.022, 1.384, 1, 0.861},
|
||||
axle = physics.Drive_Axle_Config {
|
||||
wheels = {wheel_rl, wheel_rr},
|
||||
wheel_count = 2,
|
||||
diff_type = .Fixed,
|
||||
final_drive_ratio = 4.3,
|
||||
final_drive_ratio = 4.1,
|
||||
},
|
||||
},
|
||||
)
|
||||
@ -445,7 +446,15 @@ update_runtime_world :: proc(runtime_world: ^Runtime_World, dt: f32) {
|
||||
wheel.brake_impulse = brake_input * (1.0 - BRAKE_BIAS) * BRAKE_IMPULSE
|
||||
}
|
||||
|
||||
physics.get_engine(sim_state, engine).throttle = gas_input
|
||||
engine := physics.get_engine(sim_state, runtime_world.engine_handle)
|
||||
engine.throttle = gas_input
|
||||
|
||||
if rl.IsKeyPressed(.LEFT_SHIFT) || rl.IsGamepadButtonPressed(0, .RIGHT_FACE_DOWN) {
|
||||
engine.gear += 1
|
||||
}
|
||||
if rl.IsKeyPressed(.LEFT_CONTROL) || rl.IsGamepadButtonPressed(0, .RIGHT_FACE_LEFT) {
|
||||
engine.gear -= 1
|
||||
}
|
||||
|
||||
car_body := physics.get_body(sim_state, runtime_world.car_handle)
|
||||
turn_vel_correction := clamp(30.0 / linalg.length(car_body.v), 0, 1)
|
||||
@ -867,13 +876,17 @@ draw :: proc() {
|
||||
}
|
||||
} else {
|
||||
car := physics.get_body(sim_state, runtime_world.car_handle)
|
||||
engine := physics.get_engine(sim_state, runtime_world.engine_handle)
|
||||
gear_ratios := physics.get_gear_ratios(sim_state, engine.gear_ratios)
|
||||
rl.DrawText(
|
||||
fmt.ctprintf(
|
||||
"p: %v\nv: %v\nw: %v\ng: %v",
|
||||
"p: %v\nv: %v\ngear: %v\nratio: %v\nrpm: %v\nspeed: %v km/h",
|
||||
car.x,
|
||||
car.v,
|
||||
car.w,
|
||||
SOLVER_CONFIG.gravity,
|
||||
engine.gear,
|
||||
physics.lookup_gear_ratio(gear_ratios, engine.gear),
|
||||
physics.angular_velocity_to_rpm(engine.w),
|
||||
linalg.length(car.v) * 3.6,
|
||||
),
|
||||
5,
|
||||
32,
|
||||
|
@ -12,6 +12,7 @@ import "core:slice"
|
||||
import "game:container/spanpool"
|
||||
import "libs:tracy"
|
||||
|
||||
_ :: log
|
||||
_ :: rand
|
||||
_ :: math
|
||||
_ :: fmt
|
||||
@ -484,6 +485,23 @@ pgs_solve_contacts :: proc(
|
||||
}
|
||||
}
|
||||
|
||||
// Returns index into the gear ratios array
|
||||
// -1 (revers) mapped to 0
|
||||
// 1..N mapped to 0..N-1
|
||||
lookup_gear_ratio :: #force_inline proc(gear_ratios: []f32, gear: i32) -> (ratio: f32) {
|
||||
assert(len(gear_ratios) > 1)
|
||||
if gear == 0 {
|
||||
return 0
|
||||
} else {
|
||||
index := int(gear + 1)
|
||||
if index > 0 {
|
||||
index -= 1
|
||||
}
|
||||
index = clamp(index, 0, len(gear_ratios) - 1)
|
||||
return gear_ratios[index]
|
||||
}
|
||||
}
|
||||
|
||||
pgs_solve_engines :: proc(sim_state: ^Sim_State, config: Solver_Config, dt: f32, inv_dt: f32) {
|
||||
for &engine in sim_state.engines {
|
||||
if engine.alive {
|
||||
@ -506,6 +524,38 @@ pgs_solve_engines :: proc(sim_state: ^Sim_State, config: Solver_Config, dt: f32,
|
||||
engine.w += applied_impulse / engine.inertia
|
||||
}
|
||||
|
||||
|
||||
// Throttle
|
||||
{
|
||||
rpm := angular_velocity_to_rpm(engine.w)
|
||||
|
||||
torque: f32
|
||||
|
||||
idx, _ := slice.binary_search_by(
|
||||
rpm_torque_curve,
|
||||
rpm,
|
||||
proc(a: [2]f32, k: f32) -> slice.Ordering {
|
||||
return slice.cmp(a[0], k)
|
||||
},
|
||||
)
|
||||
|
||||
if idx > 0 && idx < len(rpm_torque_curve) - 1 {
|
||||
cur_point := rpm_torque_curve[idx]
|
||||
next_point := rpm_torque_curve[idx + 1]
|
||||
rpm_diff := next_point[0] - cur_point[0]
|
||||
alpha := (rpm - cur_point[0]) / rpm_diff
|
||||
|
||||
torque = math.lerp(cur_point[1], next_point[1], alpha)
|
||||
} else {
|
||||
torque = rpm_torque_curve[math.clamp(idx, 0, len(rpm_torque_curve) - 1)][1]
|
||||
}
|
||||
|
||||
log.debugf("torque: %v Nm", torque)
|
||||
torque *= engine.throttle
|
||||
|
||||
engine.w += (torque / engine.inertia) * dt
|
||||
}
|
||||
|
||||
// Internal Friction
|
||||
{
|
||||
delta_omega := -engine.w
|
||||
@ -532,67 +582,34 @@ pgs_solve_engines :: proc(sim_state: ^Sim_State, config: Solver_Config, dt: f32,
|
||||
engine.w += applied_impulse / engine.inertia
|
||||
}
|
||||
|
||||
// Throttle
|
||||
{
|
||||
rpm := angular_velocity_to_rpm(engine.w)
|
||||
|
||||
torque: f32
|
||||
|
||||
idx, _ := slice.binary_search_by(
|
||||
rpm_torque_curve,
|
||||
rpm,
|
||||
proc(a: [2]f32, k: f32) -> slice.Ordering {
|
||||
return slice.cmp(a[0], k)
|
||||
},
|
||||
)
|
||||
|
||||
if idx > 0 && idx < len(rpm_torque_curve) - 1 {
|
||||
cur_point := rpm_torque_curve[idx]
|
||||
next_point := rpm_torque_curve[idx + 1]
|
||||
rpm_diff := next_point[0] - cur_point[0]
|
||||
alpha := (rpm - cur_point[0]) / rpm_diff
|
||||
|
||||
torque = math.lerp(cur_point[1], next_point[1], alpha)
|
||||
} else {
|
||||
torque = rpm_torque_curve[math.clamp(idx, 0, len(rpm_torque_curve) - 1)][1]
|
||||
}
|
||||
|
||||
torque *= engine.throttle
|
||||
|
||||
engine.w += torque / engine.inertia
|
||||
}
|
||||
|
||||
// Transmission
|
||||
{
|
||||
// TODO: update from game
|
||||
engine.gear = 1
|
||||
gear_ratio := lookup_gear_ratio(gear_ratios, engine.gear)
|
||||
|
||||
power_split := 1.0 / f32(engine.axle.wheel_count)
|
||||
for i in 0 ..< engine.axle.wheel_count {
|
||||
drive_wheel := &engine.axle.wheels[i]
|
||||
wheel := get_suspension_constraint(sim_state, drive_wheel.wheel)
|
||||
if engine.gear != 0 {
|
||||
for i in 0 ..< engine.axle.wheel_count {
|
||||
drive_wheel := &engine.axle.wheels[i]
|
||||
wheel := get_suspension_constraint(sim_state, drive_wheel.wheel)
|
||||
|
||||
ratio := gear_ratios[1] * engine.axle.final_drive_ratio
|
||||
inv_ratio := f32(1.0 / ratio)
|
||||
ratio := gear_ratio * engine.axle.final_drive_ratio
|
||||
inv_ratio := f32(1.0 / (ratio))
|
||||
|
||||
w1 := wheel.inv_inertia
|
||||
w2 := f32(1.0 / (engine.inertia * ratio))
|
||||
w1 := wheel.inv_inertia
|
||||
w2 := f32(1.0 / (engine.inertia * ratio * ratio))
|
||||
|
||||
w := w1 + w2
|
||||
inv_w := f32(1.0 / w)
|
||||
w := w1 + w2
|
||||
inv_w := f32(1.0 / w)
|
||||
|
||||
delta_omega := -engine.w - wheel.w * ratio
|
||||
delta_omega := wheel.w * ratio - (-engine.w)
|
||||
|
||||
incremental_impulse := -inv_w * delta_omega * power_split
|
||||
drive_wheel.impulse += incremental_impulse
|
||||
incremental_impulse := -inv_w * delta_omega
|
||||
// drive_wheel.impulse += incremental_impulse
|
||||
|
||||
wheel.w += -incremental_impulse * wheel.inv_inertia * inv_ratio
|
||||
engine.w += -(incremental_impulse / engine.inertia)
|
||||
wheel.w += incremental_impulse * w1 * inv_ratio
|
||||
engine.w += incremental_impulse / (engine.inertia * ratio * ratio)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// tracy.Plot("rpm", f64(angular_velocity_to_rpm(engine.w)))
|
||||
log.debugf("rpm: %v", angular_velocity_to_rpm(engine.w))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -844,15 +861,20 @@ pgs_substep :: proc(sim_state: ^Sim_State, config: Solver_Config, dt: f32, inv_d
|
||||
|
||||
e.w += e.friction_impulse / e.inertia
|
||||
|
||||
for i in 0 ..< e.axle.wheel_count {
|
||||
drive_wheel := &e.axle.wheels[i]
|
||||
wheel := get_suspension_constraint(sim_state, drive_wheel.wheel)
|
||||
if true {
|
||||
if e.gear != 0 {
|
||||
for i in 0 ..< e.axle.wheel_count {
|
||||
drive_wheel := &e.axle.wheels[i]
|
||||
wheel := get_suspension_constraint(sim_state, drive_wheel.wheel)
|
||||
|
||||
ratio := gear_ratios[1] * e.axle.final_drive_ratio
|
||||
inv_ratio := f32(1.0 / ratio)
|
||||
ratio :=
|
||||
lookup_gear_ratio(gear_ratios, e.gear) * e.axle.final_drive_ratio
|
||||
inv_ratio := f32(1.0 / ratio)
|
||||
|
||||
wheel.w += -drive_wheel.impulse * wheel.inv_inertia * inv_ratio
|
||||
e.w += -(drive_wheel.impulse / e.inertia)
|
||||
wheel.w += drive_wheel.impulse * wheel.inv_inertia * inv_ratio
|
||||
e.w += (drive_wheel.impulse / (e.inertia * ratio * ratio))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,14 +23,14 @@
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"execution_count": 29,
|
||||
"id": "3074424c",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"application/vnd.jupyter.widget-view+json": {
|
||||
"model_id": "dfc8c93ea1774a788835f524f65b6843",
|
||||
"model_id": "c2fcd32bbbd1482ebe2be970bfe3ed33",
|
||||
"version_major": 2,
|
||||
"version_minor": 0
|
||||
},
|
||||
@ -58,7 +58,7 @@
|
||||
"10"
|
||||
]
|
||||
},
|
||||
"execution_count": 28,
|
||||
"execution_count": 29,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user