diff --git a/src/collider.c b/src/collider.c index 607c8d7e..3b3a47d4 100644 --- a/src/collider.c +++ b/src/collider.c @@ -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) { diff --git a/src/entity.h b/src/entity.h index 9ab2ac57..eb800244 100644 --- a/src/entity.h +++ b/src/entity.h @@ -81,6 +81,9 @@ struct contact { f32 inv_i1; b32 persisted; + + /* Debugging */ + struct v2 dbg_pt; }; diff --git a/src/game.c b/src/game.c index 62c33f65..647b1092 100644 --- a/src/game.c +++ b/src/game.c @@ -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,23 +673,22 @@ INTERNAL void solve_collisions(f32 dt, b32 apply_bias) f32 mass_scale = 1.0f; f32 impulse_scale = 0.0f; - if (apply_bias) { - if (separation > 0.0f) { - velocity_bias = separation / dt; - } else { - /* Soft constraint */ + /* Only apply speculative if applying bias */ + if (separation > 0.0f) { + velocity_bias = separation / dt; + } else if (apply_bias) { + /* 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)); @@ -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; diff --git a/src/user.c b/src/user.c index 2128c89d..21828750 100644 --- a/src/user.c +++ b/src/user.c @@ -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