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 */
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 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 = F32_INFINITY;
proto = arena_dry_push(scratch.arena, struct v2);
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 vpb = v2_sub(b, p);
#if 0
#if 1
/* Swap a & b depending on winding order */
if (v2_wedge(vap, vpb) < 0) {
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 vpb = v2_sub(b, p);
#if 0
#if 1
/* Swap a & b depending on winding order */
if (v2_wedge(vap, vpb) > 0) {
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 a1t = 0;
f32 b0t = 0;
@ -697,7 +715,6 @@ b32 collider_collision_boolean(struct collider_shape *shape0, struct collider_sh
#if 0
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;
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);
//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);
@ -488,6 +488,11 @@ INTERNAL void create_contact_manifolds(void)
contact->point_local_e1 = xform_invert_mul_v2(e1_xf, point);
contact->starting_separation = sep;
/* TODO: Remove this (debugging) */
{
contact->dbg_pt = point;
}
{
f32 scale0 = math_fabs(xform_get_determinant(e0_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 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));
@ -668,10 +673,10 @@ INTERNAL void solve_collisions(f32 dt, b32 apply_bias)
f32 mass_scale = 1.0f;
f32 impulse_scale = 0.0f;
if (apply_bias) {
/* Only apply speculative if applying bias */
if (separation > 0.0f) {
velocity_bias = separation / dt;
} else {
} else if (apply_bias) {
/* Soft constraint */
f32 contact_damping_ratio = 10.0f;
@ -685,7 +690,6 @@ INTERNAL void solve_collisions(f32 dt, b32 apply_bias)
mass_scale = softness.mass_scale;
impulse_scale = softness.impulse_scale;
}
}
struct v2 vel0 = v2_add(v0, v2_perp_mul(vcp0, w0));
struct v2 vel1 = v2_add(v1, v2_perp_mul(vcp1, w1));
@ -1027,12 +1031,18 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
ent->local_collider.count = 2;
ent->local_collider.radius = 0.25;
#elif 1
#if 0
/* "Bad" winding order */
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, 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.radius = 0.25;
ent->local_collider.radius = 0.25;
//ent->local_collider.radius = math_fabs(math_sin(G.tick.time) / 3);
#else
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 e1_xf = entity_get_xform(e1);
(UNUSED)e0_xf;
(UNUSED)e1_xf;
struct collider_shape e0_collider = e0->local_collider;
struct collider_shape e1_collider = e1->local_collider;
@ -1109,9 +1111,13 @@ INTERNAL void user_update(void)
f32 radius = 5;
for (u32 i = 0; i < ent->num_contacts; ++i) {
struct contact contact = ent->contacts[i];
#if 0
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 point = v2_add(p0, v2_mul(v2_sub(p1, p0), 0.5f));
#else
struct v2 point = contact.dbg_pt;
#endif
/* Draw point */
{
//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)));
draw_solid_arrow_line(G.viewport_canvas, start, end, arrow_thickness, arrow_height, color);
}
#if 1
#if 0
/* Draw info text */
{
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 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 end = xform_mul_v2(G.world_view, ent->res.b0);
draw_solid_line(G.viewport_canvas, start, end, thickness, color);
draw_solid_circle(G.viewport_canvas, start, radius, color, 10);
draw_solid_circle(G.viewport_canvas, end, radius, color, 10);
struct v2 a = xform_mul_v2(G.world_view, ent->res.a0);
struct v2 b = xform_mul_v2(G.world_view, ent->res.b0);
draw_solid_line(G.viewport_canvas, a, b, thickness, color_line);
draw_solid_circle(G.viewport_canvas, a, radius, color_a, 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 end = xform_mul_v2(G.world_view, ent->res.b1);
draw_solid_line(G.viewport_canvas, start, end, thickness, color);
draw_solid_circle(G.viewport_canvas, start, radius, color, 10);
draw_solid_circle(G.viewport_canvas, end, radius, color, 10);
struct v2 a = xform_mul_v2(G.world_view, ent->res.a1);
struct v2 b = xform_mul_v2(G.world_view, ent->res.b1);
draw_solid_line(G.viewport_canvas, a, b, thickness, color_line);
draw_solid_circle(G.viewport_canvas, a, radius, color_a, 10);
draw_solid_circle(G.viewport_canvas, b, radius, color_b, 10);
}
}
#endif