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}
|
drive_wheels := []physics.Suspension_Constraint_Handle{wheel_rl, wheel_rr}
|
||||||
turn_wheels := []physics.Suspension_Constraint_Handle{wheel_fl, wheel_fr}
|
turn_wheels := []physics.Suspension_Constraint_Handle{wheel_fl, wheel_fr}
|
||||||
|
front_wheels := turn_wheels
|
||||||
|
back_wheels := drive_wheels
|
||||||
|
|
||||||
DRIVE_IMPULSE :: 10000
|
DRIVE_IMPULSE :: 2000
|
||||||
BRAKE_IMPULSE :: 10000
|
BRAKE_IMPULSE :: 500
|
||||||
TURN_ANGLE :: -f32(20) * math.RAD_PER_DEG
|
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 {
|
for wheel_handle in drive_wheels {
|
||||||
wheel := physics.get_suspension_constraint(sim_state, wheel_handle)
|
wheel := physics.get_suspension_constraint(sim_state, wheel_handle)
|
||||||
|
|
||||||
wheel.drive_impulse = 0
|
wheel.drive_impulse = 0
|
||||||
wheel.brake_impulse = 0
|
|
||||||
|
|
||||||
if rl.IsKeyDown(.W) && !g_mem.free_cam {
|
if rl.IsKeyDown(.W) && !g_mem.free_cam {
|
||||||
wheel.drive_impulse = DRIVE_IMPULSE
|
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)
|
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)
|
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) {
|
body_get_shape_offset_local :: proc(body: Body_Ptr) -> (offset: Vec3) {
|
||||||
#partial switch s in body.shape {
|
#partial switch s in body.shape {
|
||||||
case Internal_Shape_Convex:
|
case Internal_Shape_Convex:
|
||||||
|
@ -120,49 +120,51 @@ Collision_Shape :: union {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Suspension_Constraint :: struct {
|
Suspension_Constraint :: struct {
|
||||||
alive: bool,
|
alive: bool,
|
||||||
// Pos relative to the body
|
// Pos relative to the body
|
||||||
rel_pos: Vec3,
|
rel_pos: Vec3,
|
||||||
// Dir relative to the body
|
// Dir relative to the body
|
||||||
rel_dir: Vec3,
|
rel_dir: Vec3,
|
||||||
// Handle of the rigid body
|
// Handle of the rigid body
|
||||||
body: Body_Handle,
|
body: Body_Handle,
|
||||||
// Wheel radius
|
// Wheel radius
|
||||||
radius: f32,
|
radius: f32,
|
||||||
// Wheel mass
|
// Wheel mass
|
||||||
mass: f32,
|
mass: f32,
|
||||||
// Rest distance
|
// Rest distance
|
||||||
rest: f32,
|
rest: f32,
|
||||||
// Frequency of the spring, affects stiffness
|
// Frequency of the spring, affects stiffness
|
||||||
natural_frequency: f32,
|
natural_frequency: f32,
|
||||||
// How much to damp velocity of the spring
|
// How much to damp velocity of the spring
|
||||||
damping: f32,
|
damping: f32,
|
||||||
|
|
||||||
// Runtime state
|
// Runtime state
|
||||||
|
|
||||||
// Accumulated impulse
|
// Accumulated impulse
|
||||||
spring_impulse: f32,
|
spring_impulse: f32,
|
||||||
lateral_impulse: f32,
|
lateral_impulse: f32,
|
||||||
longitudinal_impulse: f32,
|
longitudinal_impulse: f32,
|
||||||
|
brake_friction_impulse: f32,
|
||||||
|
|
||||||
// Inverse inertia along wheel rotation axis
|
// Inverse inertia along wheel rotation axis
|
||||||
inv_inertia: f32,
|
inv_inertia: f32,
|
||||||
|
|
||||||
// Rotation
|
// Rotation
|
||||||
q: f32,
|
q: f32,
|
||||||
// Angular velocity
|
// Angular velocity
|
||||||
w: f32,
|
w: f32,
|
||||||
hit: bool,
|
hit: bool,
|
||||||
hit_point: Vec3,
|
hit_point: Vec3,
|
||||||
// rel_hit_point = rel_pos + rel_dir * hit_t
|
// rel_hit_point = rel_pos + rel_dir * hit_t
|
||||||
hit_t: f32,
|
hit_t: f32,
|
||||||
turn_angle: f32,
|
turn_angle: f32,
|
||||||
drive_impulse: f32,
|
drive_impulse: f32,
|
||||||
brake_impulse: f32,
|
// Impulse of brake pad on brake disc, set outsie
|
||||||
applied_impulse: Vec3,
|
brake_impulse: f32,
|
||||||
|
applied_impulse: Vec3,
|
||||||
|
|
||||||
// Free list
|
// Free list
|
||||||
next_plus_one: i32,
|
next_plus_one: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Index plus one, so handle 0 maps to invalid body
|
// 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},
|
{wheel_world_pos, pos2},
|
||||||
collision.plane_from_point_normal({}, collision.Vec3{0, 1, 0}),
|
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_vel_at_contact_patch := body_velocity_at_point(body, v.hit_point)
|
||||||
body_velocity_at_point(body, v.hit_point) + (v.radius * v.w * forward)
|
|
||||||
|
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 {
|
if v.hit {
|
||||||
|
|
||||||
|
// Spring force
|
||||||
{
|
{
|
||||||
bias_coef, mass_coef, impulse_coef := calculate_soft_constraint_params(
|
bias_coef, mass_coef, impulse_coef := calculate_soft_constraint_params(
|
||||||
v.natural_frequency,
|
v.natural_frequency,
|
||||||
@ -508,7 +542,7 @@ pgs_solve_suspension :: proc(sim_state: ^Sim_State, config: Solver_Config, dt: f
|
|||||||
separation := v.rest - x
|
separation := v.rest - x
|
||||||
|
|
||||||
incremental_impulse :=
|
incremental_impulse :=
|
||||||
-inv_w * mass_coef * (vel + separation * bias_coef) -
|
-inv_w_normal * mass_coef * (vel + separation * bias_coef) -
|
||||||
impulse_coef * v.spring_impulse
|
impulse_coef * v.spring_impulse
|
||||||
v.spring_impulse += incremental_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)
|
right := wheel_get_right_vec(body, v)
|
||||||
|
|
||||||
|
contact_patch_linear_vel :=
|
||||||
|
body_vel_at_contact_patch + (v.radius * v.w * forward)
|
||||||
|
|
||||||
// Longitudinal friction
|
// Longitudinal friction
|
||||||
if true {
|
if true {
|
||||||
vel_long := lg.dot(contact_patch_linear_vel, forward)
|
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 := f32(1)
|
||||||
friction_clamp := abs(v.spring_impulse) * friction
|
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(
|
new_total_impulse := clamp(
|
||||||
v.longitudinal_impulse + incremental_impulse,
|
v.longitudinal_impulse + incremental_impulse,
|
||||||
-friction_clamp,
|
-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
|
applied_impulse := new_total_impulse - v.longitudinal_impulse
|
||||||
v.longitudinal_impulse = new_total_impulse
|
v.longitudinal_impulse = new_total_impulse
|
||||||
|
|
||||||
|
apply_velocity_correction(body, applied_impulse * forward, v.hit_point)
|
||||||
v.w += v.inv_inertia * applied_impulse
|
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
|
// Lateral friction
|
||||||
if true {
|
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)
|
lateral_vel := lg.dot(right, vel_contact)
|
||||||
|
|
||||||
friction := f32(1)
|
friction := f32(1)
|
||||||
friction_clamp := -v.spring_impulse * friction
|
friction_clamp := -v.spring_impulse * friction
|
||||||
|
|
||||||
incremental_impulse := -inv_w * lateral_vel
|
incremental_impulse := -inv_w_normal * lateral_vel
|
||||||
new_total_impulse := clamp(
|
new_total_impulse := clamp(
|
||||||
v.lateral_impulse + incremental_impulse,
|
v.lateral_impulse + incremental_impulse,
|
||||||
-friction_clamp,
|
-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
|
applied_impulse := new_total_impulse - v.lateral_impulse
|
||||||
v.lateral_impulse = new_total_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 {
|
} else {
|
||||||
v.lateral_impulse = 0
|
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 {
|
if s.hit {
|
||||||
body := get_body(sim_state, s.body)
|
body := get_body(sim_state, s.body)
|
||||||
p := body_local_to_world(body, s.rel_pos)
|
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)
|
right := wheel_get_right_vec(body, s)
|
||||||
|
|
||||||
apply_velocity_correction(
|
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.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.longitudinal_impulse
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s.w += s.inv_inertia * s.brake_friction_impulse
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user