ignore speculative bias during relaxation for stabililty

This commit is contained in:
jacob 2024-10-08 19:34:52 -05:00
parent ac042a3306
commit 33b32e849c
3 changed files with 49 additions and 36 deletions

View File

@ -85,7 +85,7 @@ struct collider_collision_points_result collider_collision_points(struct collide
(UNUSED)radius1;
/* TODO: Parameterize */
const f32 tolerance = 0.005f;
const f32 tolerance = 0.001f;
const f32 min_unique_pt_dist_sq = 0.001f * 0.001f;
b32 colliding = false;
@ -130,6 +130,7 @@ struct collider_collision_points_result collider_collision_points(struct collide
m = menkowski_point(shape0, shape1, xf0, xf1, dir);
/* Check that new point is far enough away from existing point */
if (v2_len_sq(v2_sub(m, s.a)) < min_unique_pt_dist_sq) {
simplex_is_closest_edge = true;
done = true;
break;
}
@ -172,7 +173,7 @@ struct collider_collision_points_result collider_collision_points(struct collide
struct v2 rab_dir = v2_perp_towards_dir(vab, v2_neg(vac));
struct v2 rac_dir = v2_perp_towards_dir(vac, v2_neg(vab));
struct v2 rbc_dir = v2_perp_towards_dir(vbc, vab);
#if 0
#if 1
voronoi_mask |= (v2_dot(rab_dir, v2_neg(s.a)) > 0) << 0; /* Regions ab, a, and b*/
voronoi_mask |= (v2_dot(rac_dir, v2_neg(s.a)) > 0) << 1; /* Regions ac, a, and c */
voronoi_mask |= (v2_dot(rbc_dir, v2_neg(s.b)) > 0) << 2; /* Regions bc, b, and c */
@ -344,18 +345,27 @@ struct collider_collision_points_result collider_collision_points(struct collide
}
proto[pen_pe_index] = m;
}
} else if (simplex_is_closest_edge && s.len > 1) {
/* Shapes are not overlapping (origin is outside of simplex). Project
* origin to determine if distance is within tolerance. */
ASSERT(s.len == 2);
struct v2 vab = v2_sub(s.b, s.a);
struct v2 vao = v2_neg(s.a);
f32 ratio = clamp_f32(v2_dot(vab, vao) / v2_dot(vab, vab), 0, 1);
struct v2 p = v2_add(s.a, v2_mul(vab, ratio));
if (v2_len_sq(p) <= (tolerance * tolerance)) {
res.path = 2;
normal = v2_norm(dir);
colliding = true;
} else if (simplex_is_closest_edge) {
if (s.len == 1) {
struct v2 p = v2_neg(s.a);
if (v2_len_sq(p) <= (tolerance * tolerance)) {
res.path = 2;
normal = v2_norm(dir);
colliding = true;
}
} else {
/* Shapes are not overlapping (origin is outside of simplex). Project
* origin to determine if distance is within tolerance. */
ASSERT(s.len == 2);
struct v2 vab = v2_sub(s.b, s.a);
struct v2 vao = v2_neg(s.a);
f32 ratio = clamp_f32(v2_dot(vab, vao) / v2_dot(vab, vab), 0, 1);
struct v2 p = v2_add(s.a, v2_mul(vab, ratio));
if (v2_len_sq(p) <= (tolerance * tolerance)) {
res.path = 2;
normal = v2_norm(dir);
colliding = true;
}
}
}

View File

@ -166,15 +166,15 @@ INTERNAL void spawn_test_entities(f32 offset)
entity_enable_prop(e, ENTITY_PROP_PLAYER_CONTROLLED);
//e->control_force = 4500;
e->control_force = 1200;
//e->control_force = 250;
//e->control_force = 1200;
e->control_force = 250;
e->control_torque = 10;
e->control.focus = V2(0, -1);
entity_enable_prop(e, ENTITY_PROP_PHYSICAL);
e->mass_unscaled = 100;
//e->inertia_unscaled = F32_INFINITY;
e->inertia_unscaled = 25;
e->inertia_unscaled = F32_INFINITY;
//e->inertia_unscaled = 25;
e->linear_ground_friction = 1000;
e->angular_ground_friction = 100;
@ -212,8 +212,8 @@ INTERNAL void spawn_test_entities(f32 offset)
//struct v2 pos = V2(0.5, 29);
//struct v2 pos = V2(0.5, 24);
//struct v2 pos = V2(1, -1);
struct v2 size = V2(1, 1);
//struct v2 size = V2(500, 50);
//struct v2 size = V2(1, 1);
struct v2 size = V2(500, 1);
//f32 rot = PI / 4;
f32 rot = 0;
struct entity *e = entity_alloc(root);
@ -523,7 +523,7 @@ INTERNAL void warm_start_contacts(void)
struct v2 vcp1 = v2_sub(p1, e1_xf.og);
struct v2 impulse = v2_add(v2_mul(normal, contact->normal_impulse), v2_mul(tangent, contact->tangent_impulse));
impulse = v2_mul(impulse, 0.5f);
//impulse = v2_mul(impulse, 0.5f);
v0 = v2_sub(v0, v2_mul(impulse, contact->inv_m0));
v1 = v2_add(v1, v2_mul(impulse, contact->inv_m1));
@ -611,21 +611,23 @@ INTERNAL void solve_collisions(f32 dt, b32 apply_bias)
f32 mass_scale = 1.0f;
f32 impulse_scale = 0.0f;
if (separation > 0.0f) {
velocity_bias = separation / dt;
} else if (apply_bias) {
/* Soft constraint */
if (apply_bias) {
if (separation > 0.0f) {
velocity_bias = separation / dt;
} else {
/* Soft constraint */
f32 contact_damping_ratio = 10.0f;
f32 contact_hertz = (GAME_FPS * GAME_PHYSICS_SUBSTEPS) / 8.f;
f32 contact_damping_ratio = 10.0f;
f32 contact_hertz = (GAME_FPS * GAME_PHYSICS_SUBSTEPS) / 8.f;
struct soft_result softness = make_soft(contact_hertz, contact_damping_ratio, dt);
struct soft_result softness = make_soft(contact_hertz, contact_damping_ratio, dt);
f32 contact_pushout_velocity = 3.0f;
velocity_bias = max_f32(softness.bias_rate * separation, -contact_pushout_velocity);
f32 contact_pushout_velocity = 3.0f;
velocity_bias = max_f32(softness.bias_rate * separation, -contact_pushout_velocity);
mass_scale = softness.mass_scale;
impulse_scale = softness.impulse_scale;
mass_scale = softness.mass_scale;
impulse_scale = softness.impulse_scale;
}
}
struct v2 vel0 = v2_add(v0, v2_perp_mul(vcp0, w0));
@ -954,7 +956,6 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
{
struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, STR("shape"), ent->animation_frame);
ent->local_collider = collider_from_quad(xform_mul_quad(ent->sprite_local_xform, quad_from_rect(slice.rect)));
ent->local_collider.radius = 0.1;
if (entity_has_prop(ent, ENTITY_PROP_PLAYER_CONTROLLED)) {
#if 0
@ -1357,7 +1358,7 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
* Create ground friction force (gravity)
* ========================== */
#if 1
#if 0
/* TODO: Do this globally rather than creating entities for constant forces */
for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) {
struct entity *ent = &store->entities[entity_index];

View File

@ -146,6 +146,8 @@ struct user_startup_receipt user_startup(struct work_startup_receipt *work_sr,
G.window = window;
sys_window_register_event_callback(G.window, &window_event_callback);
G.debug_draw = true;
G.user_thread = sys_thread_alloc(&user_thread_entry_point, NULL, STR("[P1] User thread"));
app_register_exit_callback(&user_shutdown);
@ -994,9 +996,9 @@ INTERNAL void user_update(void)
if (entity_has_prop(ent, ENTITY_PROP_PHYSICAL)) {
struct collider_shape collider = ent->local_collider;
u32 color = ent->colliding ? RGBA_32_F(1, 1, 1, 0.5) : RGBA_32_F(1, 1, 0, 0.25);
f32 thickness = 1;
f32 thickness = 2;
//u32 detail = 32;
u32 detail = 256;
u32 detail = 512;
//draw_solid_collider_line(G.viewport_canvas, collider, xform_mul(G.world_view, xf), thickness, color, detail);
draw_solid_collider_line(G.viewport_canvas, G.world_view, collider, xf, thickness, color, detail);
}