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,
|
solver_state: physics.Solver_State,
|
||||||
car_com: rl.Vector3,
|
car_com: rl.Vector3,
|
||||||
car_handle: physics.Body_Handle,
|
car_handle: physics.Body_Handle,
|
||||||
|
engine_handle: physics.Engine_Handle,
|
||||||
camera_yaw_pitch: rl.Vector2,
|
camera_yaw_pitch: rl.Vector2,
|
||||||
camera_speed: f32,
|
camera_speed: f32,
|
||||||
camera: rl.Camera3D,
|
camera: rl.Camera3D,
|
||||||
@ -331,7 +332,7 @@ update_runtime_world :: proc(runtime_world: ^Runtime_World, dt: f32) {
|
|||||||
radius := f32(0.2888)
|
radius := f32(0.2888)
|
||||||
wheel_front_z := f32(1.3)
|
wheel_front_z := f32(1.3)
|
||||||
wheel_back_z := f32(-1.1)
|
wheel_back_z := f32(-1.1)
|
||||||
wheel_mass := f32(30)
|
wheel_mass := f32(14)
|
||||||
|
|
||||||
wheel_fl := physics.immediate_suspension_constraint(
|
wheel_fl := physics.immediate_suspension_constraint(
|
||||||
&world.physics_scene,
|
&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,
|
&world.physics_scene,
|
||||||
&runtime_world.solver_state,
|
&runtime_world.solver_state,
|
||||||
#hash("engine", "fnv32a"),
|
#hash("engine", "fnv32a"),
|
||||||
physics.Engine_Config {
|
physics.Engine_Config {
|
||||||
rpm_torque_curve = assets.get_curve_2d(&g_mem.assetman, "assets/ae86_rpm_torque.csv").points,
|
rpm_torque_curve = assets.get_curve_2d(&g_mem.assetman, "assets/ae86_rpm_torque.csv").points,
|
||||||
lowest_rpm = 1000,
|
lowest_rpm = 1000,
|
||||||
inertia = 10,
|
inertia = 0.0264,
|
||||||
internal_friction = 8,
|
internal_friction = 0.00,
|
||||||
gear_ratios = []f32{3.48, 3.587, 2.022, 1.384, 1, 0.861},
|
gear_ratios = []f32{3.48, 3.587, 2.022, 1.384, 1, 0.861},
|
||||||
axle = physics.Drive_Axle_Config {
|
axle = physics.Drive_Axle_Config {
|
||||||
wheels = {wheel_rl, wheel_rr},
|
wheels = {wheel_rl, wheel_rr},
|
||||||
wheel_count = 2,
|
wheel_count = 2,
|
||||||
diff_type = .Fixed,
|
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
|
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)
|
car_body := physics.get_body(sim_state, runtime_world.car_handle)
|
||||||
turn_vel_correction := clamp(30.0 / linalg.length(car_body.v), 0, 1)
|
turn_vel_correction := clamp(30.0 / linalg.length(car_body.v), 0, 1)
|
||||||
@ -867,13 +876,17 @@ draw :: proc() {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
car := physics.get_body(sim_state, runtime_world.car_handle)
|
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(
|
rl.DrawText(
|
||||||
fmt.ctprintf(
|
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.x,
|
||||||
car.v,
|
car.v,
|
||||||
car.w,
|
engine.gear,
|
||||||
SOLVER_CONFIG.gravity,
|
physics.lookup_gear_ratio(gear_ratios, engine.gear),
|
||||||
|
physics.angular_velocity_to_rpm(engine.w),
|
||||||
|
linalg.length(car.v) * 3.6,
|
||||||
),
|
),
|
||||||
5,
|
5,
|
||||||
32,
|
32,
|
||||||
|
@ -12,6 +12,7 @@ import "core:slice"
|
|||||||
import "game:container/spanpool"
|
import "game:container/spanpool"
|
||||||
import "libs:tracy"
|
import "libs:tracy"
|
||||||
|
|
||||||
|
_ :: log
|
||||||
_ :: rand
|
_ :: rand
|
||||||
_ :: math
|
_ :: math
|
||||||
_ :: fmt
|
_ :: 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) {
|
pgs_solve_engines :: proc(sim_state: ^Sim_State, config: Solver_Config, dt: f32, inv_dt: f32) {
|
||||||
for &engine in sim_state.engines {
|
for &engine in sim_state.engines {
|
||||||
if engine.alive {
|
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
|
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
|
// Internal Friction
|
||||||
{
|
{
|
||||||
delta_omega := -engine.w
|
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
|
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
|
// Transmission
|
||||||
{
|
{
|
||||||
// TODO: update from game
|
gear_ratio := lookup_gear_ratio(gear_ratios, engine.gear)
|
||||||
engine.gear = 1
|
|
||||||
|
|
||||||
power_split := 1.0 / f32(engine.axle.wheel_count)
|
if engine.gear != 0 {
|
||||||
for i in 0 ..< engine.axle.wheel_count {
|
for i in 0 ..< engine.axle.wheel_count {
|
||||||
drive_wheel := &engine.axle.wheels[i]
|
drive_wheel := &engine.axle.wheels[i]
|
||||||
wheel := get_suspension_constraint(sim_state, drive_wheel.wheel)
|
wheel := get_suspension_constraint(sim_state, drive_wheel.wheel)
|
||||||
|
|
||||||
ratio := gear_ratios[1] * engine.axle.final_drive_ratio
|
ratio := gear_ratio * engine.axle.final_drive_ratio
|
||||||
inv_ratio := f32(1.0 / ratio)
|
inv_ratio := f32(1.0 / (ratio))
|
||||||
|
|
||||||
w1 := wheel.inv_inertia
|
w1 := wheel.inv_inertia
|
||||||
w2 := f32(1.0 / (engine.inertia * ratio))
|
w2 := f32(1.0 / (engine.inertia * ratio * ratio))
|
||||||
|
|
||||||
w := w1 + w2
|
w := w1 + w2
|
||||||
inv_w := f32(1.0 / w)
|
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
|
incremental_impulse := -inv_w * delta_omega
|
||||||
drive_wheel.impulse += incremental_impulse
|
// drive_wheel.impulse += incremental_impulse
|
||||||
|
|
||||||
wheel.w += -incremental_impulse * wheel.inv_inertia * inv_ratio
|
wheel.w += incremental_impulse * w1 * inv_ratio
|
||||||
engine.w += -(incremental_impulse / engine.inertia)
|
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
|
e.w += e.friction_impulse / e.inertia
|
||||||
|
|
||||||
|
if true {
|
||||||
|
if e.gear != 0 {
|
||||||
for i in 0 ..< e.axle.wheel_count {
|
for i in 0 ..< e.axle.wheel_count {
|
||||||
drive_wheel := &e.axle.wheels[i]
|
drive_wheel := &e.axle.wheels[i]
|
||||||
wheel := get_suspension_constraint(sim_state, drive_wheel.wheel)
|
wheel := get_suspension_constraint(sim_state, drive_wheel.wheel)
|
||||||
|
|
||||||
ratio := gear_ratios[1] * e.axle.final_drive_ratio
|
ratio :=
|
||||||
|
lookup_gear_ratio(gear_ratios, e.gear) * e.axle.final_drive_ratio
|
||||||
inv_ratio := f32(1.0 / ratio)
|
inv_ratio := f32(1.0 / ratio)
|
||||||
|
|
||||||
wheel.w += -drive_wheel.impulse * wheel.inv_inertia * inv_ratio
|
wheel.w += drive_wheel.impulse * wheel.inv_inertia * inv_ratio
|
||||||
e.w += -(drive_wheel.impulse / e.inertia)
|
e.w += (drive_wheel.impulse / (e.inertia * ratio * ratio))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,14 +23,14 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": null,
|
"execution_count": 29,
|
||||||
"id": "3074424c",
|
"id": "3074424c",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
{
|
||||||
"data": {
|
"data": {
|
||||||
"application/vnd.jupyter.widget-view+json": {
|
"application/vnd.jupyter.widget-view+json": {
|
||||||
"model_id": "dfc8c93ea1774a788835f524f65b6843",
|
"model_id": "c2fcd32bbbd1482ebe2be970bfe3ed33",
|
||||||
"version_major": 2,
|
"version_major": 2,
|
||||||
"version_minor": 0
|
"version_minor": 0
|
||||||
},
|
},
|
||||||
@ -58,7 +58,7 @@
|
|||||||
"10"
|
"10"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"execution_count": 28,
|
"execution_count": 29,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"output_type": "execute_result"
|
"output_type": "execute_result"
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user