halve warm start impulse to reduce jitter

This commit is contained in:
jacob 2024-10-10 10:29:35 -05:00
parent bc19bd816d
commit 9b4cfa345d
4 changed files with 71 additions and 33 deletions

View File

@ -87,6 +87,7 @@ struct collider_collision_points_result collider_collision_points(struct collide
/* TODO: Parameterize */ /* TODO: Parameterize */
const f32 tolerance = 0.005f; /* How close can shapes be before collision is considered */ const f32 tolerance = 0.005f; /* How close can shapes be before collision is considered */
//const f32 tolerance = 0.05f; /* How close can shapes be before collision is considered */
const f32 min_unique_pt_dist_sq = 0.0001f * 0.0001f; const f32 min_unique_pt_dist_sq = 0.0001f * 0.0001f;
const u32 max_epa_iterations = 64; /* To prevent extremely large prototypes when origin is in exact center of rounded feature */ const u32 max_epa_iterations = 64; /* To prevent extremely large prototypes when origin is in exact center of rounded feature */
@ -247,6 +248,7 @@ struct collider_collision_points_result collider_collision_points(struct collide
* ========================== */ * ========================== */
const f32 epa_epsilon_sq = 0.001f * 0.001f; const f32 epa_epsilon_sq = 0.001f * 0.001f;
//const f32 epa_epsilon_sq = F32_INFINITY;
proto = arena_dry_push(scratch.arena, struct v2); proto = arena_dry_push(scratch.arena, struct v2);
proto_count = 0; proto_count = 0;
@ -409,7 +411,7 @@ struct collider_collision_points_result collider_collision_points(struct collide
struct v2 vap = v2_sub(p, a); struct v2 vap = v2_sub(p, a);
struct v2 vpb = v2_sub(b, p); struct v2 vpb = v2_sub(b, p);
#if 0 #if 1
/* Swap a & b depending on winding order */ /* Swap a & b depending on winding order */
if (v2_wedge(vap, vpb) < 0) { if (v2_wedge(vap, vpb) < 0) {
u32 tmp_u32 = a_i; u32 tmp_u32 = a_i;
@ -452,7 +454,7 @@ struct collider_collision_points_result collider_collision_points(struct collide
struct v2 vap = v2_sub(p, a); struct v2 vap = v2_sub(p, a);
struct v2 vpb = v2_sub(b, p); struct v2 vpb = v2_sub(b, p);
#if 0 #if 1
/* Swap a & b depending on winding order */ /* Swap a & b depending on winding order */
if (v2_wedge(vap, vpb) > 0) { if (v2_wedge(vap, vpb) > 0) {
u32 tmp_u32 = a_i; u32 tmp_u32 = a_i;
@ -482,6 +484,22 @@ struct collider_collision_points_result collider_collision_points(struct collide
} }
} }
#if 1
if (radius0 > 0.0) {
struct v2 scale = xform_get_scale(xf0);
struct v2 normal_radius = v2_mul_v2(v2_mul(normal, radius0), scale);
a0 = v2_add(a0, normal_radius);
b0 = v2_add(b0, normal_radius);
}
if (radius1 > 0.0) {
struct v2 scale = xform_get_scale(xf1);
struct v2 normal_radius = v2_mul_v2(v2_mul(normal, radius1), scale);
a1 = v2_sub(a1, normal_radius);
b1 = v2_sub(b1, normal_radius);
}
#endif
f32 a0t = 0; f32 a0t = 0;
f32 a1t = 0; f32 a1t = 0;
f32 b0t = 0; f32 b0t = 0;
@ -697,7 +715,6 @@ b32 collider_collision_boolean(struct collider_shape *shape0, struct collider_sh
#if 0 #if 0
struct collider_collision_points_result collider_collision_points(struct collider_shape *shape0, struct collider_shape *shape1, struct xform xf0, struct xform xf1) struct collider_collision_points_result collider_collision_points(struct collider_shape *shape0, struct collider_shape *shape1, struct xform xf0, struct xform xf1)
{ {

View File

@ -81,6 +81,9 @@ struct contact {
f32 inv_i1; f32 inv_i1;
b32 persisted; b32 persisted;
/* Debugging */
struct v2 dbg_pt;
}; };

View File

@ -222,8 +222,8 @@ INTERNAL void spawn_test_entities(f32 offset)
//entity_enable_prop(e, ENTITY_PROP_PLAYER_CONTROLLED); //entity_enable_prop(e, ENTITY_PROP_PLAYER_CONTROLLED);
//e->control_force = 4500; //e->control_force = 4500;
//e->control_force = 1200; e->control_force = 1200;
e->control_force = 250; //e->control_force = 250;
e->control_torque = 10; e->control_torque = 10;
e->control.focus = V2(0, -1); e->control.focus = V2(0, -1);
@ -488,6 +488,11 @@ INTERNAL void create_contact_manifolds(void)
contact->point_local_e1 = xform_invert_mul_v2(e1_xf, point); contact->point_local_e1 = xform_invert_mul_v2(e1_xf, point);
contact->starting_separation = sep; contact->starting_separation = sep;
/* TODO: Remove this (debugging) */
{
contact->dbg_pt = point;
}
{ {
f32 scale0 = math_fabs(xform_get_determinant(e0_xf)); f32 scale0 = math_fabs(xform_get_determinant(e0_xf));
f32 scale1 = math_fabs(xform_get_determinant(e1_xf)); f32 scale1 = math_fabs(xform_get_determinant(e1_xf));
@ -580,7 +585,7 @@ INTERNAL void warm_start_contacts(void)
struct v2 vcp1 = v2_sub(p1, e1_xf.og); 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)); 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)); v0 = v2_sub(v0, v2_mul(impulse, contact->inv_m0));
v1 = v2_add(v1, v2_mul(impulse, contact->inv_m1)); v1 = v2_add(v1, v2_mul(impulse, contact->inv_m1));
@ -668,23 +673,22 @@ INTERNAL void solve_collisions(f32 dt, b32 apply_bias)
f32 mass_scale = 1.0f; f32 mass_scale = 1.0f;
f32 impulse_scale = 0.0f; f32 impulse_scale = 0.0f;
if (apply_bias) { /* Only apply speculative if applying bias */
if (separation > 0.0f) { if (separation > 0.0f) {
velocity_bias = separation / dt; velocity_bias = separation / dt;
} else { } else if (apply_bias) {
/* Soft constraint */ /* Soft constraint */
f32 contact_damping_ratio = 10.0f; f32 contact_damping_ratio = 10.0f;
f32 contact_hertz = (GAME_FPS * GAME_PHYSICS_SUBSTEPS) / 8.f; 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; f32 contact_pushout_velocity = 3.0f;
velocity_bias = max_f32(softness.bias_rate * separation, -contact_pushout_velocity); velocity_bias = max_f32(softness.bias_rate * separation, -contact_pushout_velocity);
mass_scale = softness.mass_scale; mass_scale = softness.mass_scale;
impulse_scale = softness.impulse_scale; impulse_scale = softness.impulse_scale;
}
} }
struct v2 vel0 = v2_add(v0, v2_perp_mul(vcp0, w0)); struct v2 vel0 = v2_add(v0, v2_perp_mul(vcp0, w0));
@ -1027,12 +1031,18 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
ent->local_collider.count = 2; ent->local_collider.count = 2;
ent->local_collider.radius = 0.25; ent->local_collider.radius = 0.25;
#elif 1 #elif 1
#if 0
/* "Bad" winding order */
ent->local_collider.points[0] = V2(-0.5, 0.5); ent->local_collider.points[0] = V2(-0.5, 0.5);
ent->local_collider.points[1] = V2(0.5, 0.5); ent->local_collider.points[1] = V2(0.5, 0.5);
//ent->local_collider.points[1] = V2(0, 0.5);
ent->local_collider.points[2] = V2(0, -0.5); ent->local_collider.points[2] = V2(0, -0.5);
#else
ent->local_collider.points[0] = V2(0, -0.5);
ent->local_collider.points[1] = V2(0.5, 0.5);
ent->local_collider.points[2] = V2(-0.5, 0.5);
#endif
ent->local_collider.count = 3; ent->local_collider.count = 3;
//ent->local_collider.radius = 0.25; ent->local_collider.radius = 0.25;
//ent->local_collider.radius = math_fabs(math_sin(G.tick.time) / 3); //ent->local_collider.radius = math_fabs(math_sin(G.tick.time) / 3);
#else #else
ent->local_collider.radius = 0.25; ent->local_collider.radius = 0.25;

View File

@ -1012,6 +1012,8 @@ INTERNAL void user_update(void)
struct xform e0_xf = entity_get_xform(e0); struct xform e0_xf = entity_get_xform(e0);
struct xform e1_xf = entity_get_xform(e1); struct xform e1_xf = entity_get_xform(e1);
(UNUSED)e0_xf;
(UNUSED)e1_xf;
struct collider_shape e0_collider = e0->local_collider; struct collider_shape e0_collider = e0->local_collider;
struct collider_shape e1_collider = e1->local_collider; struct collider_shape e1_collider = e1->local_collider;
@ -1109,9 +1111,13 @@ INTERNAL void user_update(void)
f32 radius = 5; f32 radius = 5;
for (u32 i = 0; i < ent->num_contacts; ++i) { for (u32 i = 0; i < ent->num_contacts; ++i) {
struct contact contact = ent->contacts[i]; struct contact contact = ent->contacts[i];
#if 0
struct v2 p0 = xform_mul_v2(e0_xf, contact.point_local_e0); struct v2 p0 = xform_mul_v2(e0_xf, contact.point_local_e0);
struct v2 p1 = xform_mul_v2(e1_xf, contact.point_local_e1); struct v2 p1 = xform_mul_v2(e1_xf, contact.point_local_e1);
struct v2 point = v2_add(p0, v2_mul(v2_sub(p1, p0), 0.5f)); struct v2 point = v2_add(p0, v2_mul(v2_sub(p1, p0), 0.5f));
#else
struct v2 point = contact.dbg_pt;
#endif
/* Draw point */ /* Draw point */
{ {
//u32 color = contact.persisted ? RGBA_32_F(1, 1, 0, 0.50) : RGBA_32_F(1, 0, 0, 0.50); //u32 color = contact.persisted ? RGBA_32_F(1, 1, 0, 0.50) : RGBA_32_F(1, 0, 0, 0.50);
@ -1130,7 +1136,7 @@ INTERNAL void user_update(void)
struct v2 end = xform_mul_v2(G.world_view, v2_add(point, v2_mul(v2_norm(ent->manifold_normal), len))); struct v2 end = xform_mul_v2(G.world_view, v2_add(point, v2_mul(v2_norm(ent->manifold_normal), len)));
draw_solid_arrow_line(G.viewport_canvas, start, end, arrow_thickness, arrow_height, color); draw_solid_arrow_line(G.viewport_canvas, start, end, arrow_thickness, arrow_height, color);
} }
#if 1 #if 0
/* Draw info text */ /* Draw info text */
{ {
struct font *disp_font = font_load_async(STR("res/fonts/fixedsys.ttf"), 12.0f); struct font *disp_font = font_load_async(STR("res/fonts/fixedsys.ttf"), 12.0f);
@ -1172,20 +1178,22 @@ INTERNAL void user_update(void)
{ {
f32 thickness = 2; f32 thickness = 2;
f32 radius = 4; f32 radius = 4;
u32 color = RGBA_32_F(1, 0, 1, 0.5); u32 color_line = RGBA_32_F(1, 0, 1, 0.5);
u32 color_a = RGBA_32_F(1, 0, 0, 0.5);
u32 color_b = RGBA_32_F(0, 1, 0, 0.5);
{ {
struct v2 start = xform_mul_v2(G.world_view, ent->res.a0); struct v2 a = xform_mul_v2(G.world_view, ent->res.a0);
struct v2 end = xform_mul_v2(G.world_view, ent->res.b0); struct v2 b = xform_mul_v2(G.world_view, ent->res.b0);
draw_solid_line(G.viewport_canvas, start, end, thickness, color); draw_solid_line(G.viewport_canvas, a, b, thickness, color_line);
draw_solid_circle(G.viewport_canvas, start, radius, color, 10); draw_solid_circle(G.viewport_canvas, a, radius, color_a, 10);
draw_solid_circle(G.viewport_canvas, end, radius, color, 10); draw_solid_circle(G.viewport_canvas, b, radius, color_b, 10);
} }
{ {
struct v2 start = xform_mul_v2(G.world_view, ent->res.a1); struct v2 a = xform_mul_v2(G.world_view, ent->res.a1);
struct v2 end = xform_mul_v2(G.world_view, ent->res.b1); struct v2 b = xform_mul_v2(G.world_view, ent->res.b1);
draw_solid_line(G.viewport_canvas, start, end, thickness, color); draw_solid_line(G.viewport_canvas, a, b, thickness, color_line);
draw_solid_circle(G.viewport_canvas, start, radius, color, 10); draw_solid_circle(G.viewport_canvas, a, radius, color_a, 10);
draw_solid_circle(G.viewport_canvas, end, radius, color, 10); draw_solid_circle(G.viewport_canvas, b, radius, color_b, 10);
} }
} }
#endif #endif