Proper brake force using friction
This commit is contained in:
parent
bf7b7e6ae3
commit
8caf47003e
@ -390,24 +390,41 @@ 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}
|
||||
front_wheels := turn_wheels
|
||||
back_wheels := drive_wheels
|
||||
|
||||
DRIVE_IMPULSE :: 10000
|
||||
BRAKE_IMPULSE :: 10000
|
||||
DRIVE_IMPULSE :: 2000
|
||||
BRAKE_IMPULSE :: 500
|
||||
TURN_ANGLE :: -f32(20) * math.RAD_PER_DEG
|
||||
// 68% front, 32% rear
|
||||
BRAKE_BIAS :: f32(0.68)
|
||||
|
||||
for wheel_handle in front_wheels {
|
||||
wheel := physics.get_suspension_constraint(sim_state, wheel_handle)
|
||||
|
||||
wheel.brake_impulse = 0
|
||||
if (rl.IsKeyDown(.S)) {
|
||||
wheel.brake_impulse = BRAKE_BIAS * BRAKE_IMPULSE
|
||||
}
|
||||
}
|
||||
|
||||
for wheel_handle in back_wheels {
|
||||
wheel := physics.get_suspension_constraint(sim_state, wheel_handle)
|
||||
|
||||
wheel.brake_impulse = 0
|
||||
if (rl.IsKeyDown(.S)) {
|
||||
wheel.brake_impulse = (1.0 - BRAKE_BIAS) * BRAKE_IMPULSE
|
||||
}
|
||||
}
|
||||
|
||||
for wheel_handle in drive_wheels {
|
||||
wheel := physics.get_suspension_constraint(sim_state, wheel_handle)
|
||||
|
||||
wheel.drive_impulse = 0
|
||||
wheel.brake_impulse = 0
|
||||
|
||||
if rl.IsKeyDown(.W) && !g_mem.free_cam {
|
||||
wheel.drive_impulse = DRIVE_IMPULSE
|
||||
}
|
||||
|
||||
if rl.IsKeyDown(.S) && !g_mem.free_cam {
|
||||
wheel.brake_impulse = BRAKE_IMPULSE
|
||||
}
|
||||
}
|
||||
|
||||
car_body := physics.get_body(sim_state, runtime_world.car_handle)
|
||||
|
@ -75,6 +75,17 @@ wheel_get_right_vec :: #force_inline proc(
|
||||
return body_local_to_world_vec(body, local_right)
|
||||
}
|
||||
|
||||
wheel_get_forward_vec :: #force_inline proc(
|
||||
body: Body_Ptr,
|
||||
wheel: Suspension_Constraint_Ptr,
|
||||
) -> Vec3 {
|
||||
local_right := lg.quaternion_mul_vector3(
|
||||
lg.quaternion_angle_axis(wheel.turn_angle, Vec3{0, 1, 0}),
|
||||
Vec3{0, 0, 1},
|
||||
)
|
||||
return body_local_to_world_vec(body, local_right)
|
||||
}
|
||||
|
||||
body_get_shape_offset_local :: proc(body: Body_Ptr) -> (offset: Vec3) {
|
||||
#partial switch s in body.shape {
|
||||
case Internal_Shape_Convex:
|
||||
|
@ -120,49 +120,51 @@ Collision_Shape :: union {
|
||||
}
|
||||
|
||||
Suspension_Constraint :: struct {
|
||||
alive: bool,
|
||||
alive: bool,
|
||||
// Pos relative to the body
|
||||
rel_pos: Vec3,
|
||||
rel_pos: Vec3,
|
||||
// Dir relative to the body
|
||||
rel_dir: Vec3,
|
||||
rel_dir: Vec3,
|
||||
// Handle of the rigid body
|
||||
body: Body_Handle,
|
||||
body: Body_Handle,
|
||||
// Wheel radius
|
||||
radius: f32,
|
||||
radius: f32,
|
||||
// Wheel mass
|
||||
mass: f32,
|
||||
mass: f32,
|
||||
// Rest distance
|
||||
rest: f32,
|
||||
rest: f32,
|
||||
// Frequency of the spring, affects stiffness
|
||||
natural_frequency: f32,
|
||||
natural_frequency: f32,
|
||||
// How much to damp velocity of the spring
|
||||
damping: f32,
|
||||
damping: f32,
|
||||
|
||||
// Runtime state
|
||||
|
||||
// Accumulated impulse
|
||||
spring_impulse: f32,
|
||||
lateral_impulse: f32,
|
||||
longitudinal_impulse: f32,
|
||||
spring_impulse: f32,
|
||||
lateral_impulse: f32,
|
||||
longitudinal_impulse: f32,
|
||||
brake_friction_impulse: f32,
|
||||
|
||||
// Inverse inertia along wheel rotation axis
|
||||
inv_inertia: f32,
|
||||
inv_inertia: f32,
|
||||
|
||||
// Rotation
|
||||
q: f32,
|
||||
q: f32,
|
||||
// Angular velocity
|
||||
w: f32,
|
||||
hit: bool,
|
||||
hit_point: Vec3,
|
||||
w: f32,
|
||||
hit: bool,
|
||||
hit_point: Vec3,
|
||||
// rel_hit_point = rel_pos + rel_dir * hit_t
|
||||
hit_t: f32,
|
||||
turn_angle: f32,
|
||||
drive_impulse: f32,
|
||||
brake_impulse: f32,
|
||||
applied_impulse: Vec3,
|
||||
hit_t: f32,
|
||||
turn_angle: f32,
|
||||
drive_impulse: f32,
|
||||
// Impulse of brake pad on brake disc, set outsie
|
||||
brake_impulse: f32,
|
||||
applied_impulse: Vec3,
|
||||
|
||||
// Free list
|
||||
next_plus_one: i32,
|
||||
next_plus_one: i32,
|
||||
}
|
||||
|
||||
// Index plus one, so handle 0 maps to invalid body
|
||||
|
@ -488,14 +488,48 @@ pgs_solve_suspension :: proc(sim_state: ^Sim_State, config: Solver_Config, dt: f
|
||||
{wheel_world_pos, pos2},
|
||||
collision.plane_from_point_normal({}, collision.Vec3{0, 1, 0}),
|
||||
)
|
||||
forward := body_local_to_world_vec(body, Vec3{0, 0, 1})
|
||||
forward := wheel_get_forward_vec(body, v)
|
||||
|
||||
contact_patch_linear_vel :=
|
||||
body_velocity_at_point(body, v.hit_point) + (v.radius * v.w * forward)
|
||||
body_vel_at_contact_patch := body_velocity_at_point(body, v.hit_point)
|
||||
|
||||
w_normal := get_body_angular_inverse_mass(body, dir)
|
||||
inv_w_normal := 1.0 / w_normal
|
||||
|
||||
// Drive force
|
||||
if true {
|
||||
total_impulse := -v.drive_impulse
|
||||
|
||||
v.w += v.inv_inertia * total_impulse * dt
|
||||
}
|
||||
|
||||
// Brake force
|
||||
if true {
|
||||
// How strong is brake pad pushing against brake disc
|
||||
brake_pad_impulse := v.brake_impulse
|
||||
|
||||
if brake_pad_impulse != 0 {
|
||||
// TODO: figure out what's the realistic value
|
||||
brake_friction := f32(1.0)
|
||||
friction_clamp := brake_pad_impulse * brake_friction
|
||||
|
||||
incremental_impulse := (1.0 / v.inv_inertia) * -v.w
|
||||
new_total_impulse := clamp(
|
||||
v.brake_friction_impulse + incremental_impulse,
|
||||
-friction_clamp,
|
||||
friction_clamp,
|
||||
)
|
||||
applied_impulse := new_total_impulse - v.brake_friction_impulse
|
||||
v.brake_friction_impulse = new_total_impulse
|
||||
|
||||
v.w += v.inv_inertia * applied_impulse
|
||||
} else {
|
||||
v.brake_friction_impulse = 0
|
||||
}
|
||||
}
|
||||
|
||||
w := get_body_angular_inverse_mass(body, dir)
|
||||
inv_w := 1.0 / w
|
||||
if v.hit {
|
||||
|
||||
// Spring force
|
||||
{
|
||||
bias_coef, mass_coef, impulse_coef := calculate_soft_constraint_params(
|
||||
v.natural_frequency,
|
||||
@ -508,7 +542,7 @@ pgs_solve_suspension :: proc(sim_state: ^Sim_State, config: Solver_Config, dt: f
|
||||
separation := v.rest - x
|
||||
|
||||
incremental_impulse :=
|
||||
-inv_w * mass_coef * (vel + separation * bias_coef) -
|
||||
-inv_w_normal * mass_coef * (vel + separation * bias_coef) -
|
||||
impulse_coef * v.spring_impulse
|
||||
v.spring_impulse += incremental_impulse
|
||||
|
||||
@ -517,6 +551,9 @@ pgs_solve_suspension :: proc(sim_state: ^Sim_State, config: Solver_Config, dt: f
|
||||
|
||||
right := wheel_get_right_vec(body, v)
|
||||
|
||||
contact_patch_linear_vel :=
|
||||
body_vel_at_contact_patch + (v.radius * v.w * forward)
|
||||
|
||||
// Longitudinal friction
|
||||
if true {
|
||||
vel_long := lg.dot(contact_patch_linear_vel, forward)
|
||||
@ -524,7 +561,12 @@ pgs_solve_suspension :: proc(sim_state: ^Sim_State, config: Solver_Config, dt: f
|
||||
friction := f32(1)
|
||||
friction_clamp := abs(v.spring_impulse) * friction
|
||||
|
||||
incremental_impulse := -v.inv_inertia * vel_long
|
||||
w_body := get_body_inverse_mass(body, forward, v.hit_point)
|
||||
|
||||
w_long := w_body + v.inv_inertia
|
||||
inv_w_long := 1.0 / w_long
|
||||
|
||||
incremental_impulse := -inv_w_long * vel_long
|
||||
new_total_impulse := clamp(
|
||||
v.longitudinal_impulse + incremental_impulse,
|
||||
-friction_clamp,
|
||||
@ -533,30 +575,19 @@ pgs_solve_suspension :: proc(sim_state: ^Sim_State, config: Solver_Config, dt: f
|
||||
applied_impulse := new_total_impulse - v.longitudinal_impulse
|
||||
v.longitudinal_impulse = new_total_impulse
|
||||
|
||||
apply_velocity_correction(body, applied_impulse * forward, v.hit_point)
|
||||
v.w += v.inv_inertia * applied_impulse
|
||||
}
|
||||
|
||||
// Drive forces
|
||||
if true {
|
||||
total_impulse := v.drive_impulse - v.brake_impulse
|
||||
|
||||
apply_velocity_correction(
|
||||
body,
|
||||
total_impulse * forward * dt,
|
||||
wheel_world_pos,
|
||||
)
|
||||
}
|
||||
|
||||
// Lateral friction
|
||||
if true {
|
||||
vel_contact := body_velocity_at_point(body, wheel_world_pos)
|
||||
vel_contact := body_vel_at_contact_patch
|
||||
|
||||
lateral_vel := lg.dot(right, vel_contact)
|
||||
|
||||
friction := f32(1)
|
||||
friction_clamp := -v.spring_impulse * friction
|
||||
|
||||
incremental_impulse := -inv_w * lateral_vel
|
||||
incremental_impulse := -inv_w_normal * lateral_vel
|
||||
new_total_impulse := clamp(
|
||||
v.lateral_impulse + incremental_impulse,
|
||||
-friction_clamp,
|
||||
@ -565,7 +596,7 @@ pgs_solve_suspension :: proc(sim_state: ^Sim_State, config: Solver_Config, dt: f
|
||||
applied_impulse := new_total_impulse - v.lateral_impulse
|
||||
v.lateral_impulse = new_total_impulse
|
||||
|
||||
apply_velocity_correction(body, applied_impulse * right, wheel_world_pos)
|
||||
apply_velocity_correction(body, applied_impulse * right, v.hit_point)
|
||||
}
|
||||
} else {
|
||||
v.lateral_impulse = 0
|
||||
@ -618,6 +649,8 @@ pgs_substep :: proc(sim_state: ^Sim_State, config: Solver_Config, dt: f32, inv_d
|
||||
if s.hit {
|
||||
body := get_body(sim_state, s.body)
|
||||
p := body_local_to_world(body, s.rel_pos)
|
||||
hit_p := body_local_to_world(body, s.rel_pos + s.rel_dir * s.hit_t)
|
||||
forward := wheel_get_forward_vec(body, s)
|
||||
right := wheel_get_right_vec(body, s)
|
||||
|
||||
apply_velocity_correction(
|
||||
@ -627,8 +660,11 @@ pgs_substep :: proc(sim_state: ^Sim_State, config: Solver_Config, dt: f32, inv_d
|
||||
)
|
||||
apply_velocity_correction(body, s.lateral_impulse * right, p)
|
||||
|
||||
apply_velocity_correction(body, s.longitudinal_impulse * forward, hit_p)
|
||||
s.w += s.inv_inertia * s.longitudinal_impulse
|
||||
}
|
||||
|
||||
s.w += s.inv_inertia * s.brake_friction_impulse
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user