diff --git a/src/collider.c b/src/collider.c index 8cc19f8b..f48c1294 100644 --- a/src/collider.c +++ b/src/collider.c @@ -4,10 +4,12 @@ #include "scratch.h" /* How close can non-overlapping shapes be before collision is considered */ -#define COLLISION_TOLERANCE 0.005f +//#define COLLISION_TOLERANCE 0.005f +#define COLLISION_TOLERANCE 0.0005f /* NOTE: Should always be less than tolerance, since colliding = true if origin is within this distance. */ -#define MIN_UNIQUE_PT_DIST_SQ (0.001f * 0.001f) +//#define MIN_UNIQUE_PT_DIST_SQ (0.001f * 0.001f) +#define MIN_UNIQUE_PT_DIST_SQ (0.0001f * 0.0001f) /* To prevent extremely large prototypes when origin is in exact center of rounded feature */ #define MAX_EPA_ITERATIONS 64 @@ -366,7 +368,7 @@ INTERNAL struct epa_result epa_get_normal_from_gjk(struct collider_shape *shape0 { /* NOTE: Changing this value affects how stable normals are for circular colliders */ //const f32 validity_epsilon = min_unique_pt_dist_sq; /* Arbitrary */ - const f32 validity_epsilon = 0.0000000001f; /* Arbitrary */ + const f32 validity_epsilon = 0.00000000001f; /* Arbitrary */ struct v2 vam = v2_sub(m.p, closest_a.p); struct v2 vbm = v2_sub(closest_b.p, closest_a.p); @@ -511,7 +513,8 @@ struct collider_collision_points_result collider_collision_points(struct collide DBGSTEP; { - const f32 wedge_epsilon = 0.05f; + const f32 wedge_epsilon = 0.001f; + //const f32 wedge_epsilon = 0.05f; //const f32 wedge_epsilon = 0.1f; /* shape0 a -> b winding = clockwise */ @@ -655,8 +658,13 @@ struct collider_collision_points_result collider_collision_points(struct collide f32 vab0_wedge_normal = v2_wedge(vab0, normal); f32 vab1_wedge_normal = v2_wedge(vab1, normal); +#if 0 b32 collapse0 = math_fabs(vab0_wedge_normal) < wedge_epsilon; b32 collapse1 = math_fabs(vab1_wedge_normal) < wedge_epsilon; +#else + b32 collapse0 = false; + b32 collapse1 = false; +#endif if (collapse0) { if (v2_dot(b0, normal) >= v2_dot(a0, normal)) { @@ -741,17 +749,15 @@ struct collider_collision_points_result collider_collision_points(struct collide point->point = contact_b; } -#if 1 - res.a0 = a0_clipped; - res.a1 = a1_clipped; - res.b0 = b0_clipped; - res.b1 = b1_clipped; -#else + /* TODO: Remove this */ + res.a0_clipped = a0_clipped; + res.a1_clipped = a1_clipped; + res.b0_clipped = b0_clipped; + res.b1_clipped = b1_clipped; res.a0 = a0; res.a1 = a1; res.b0 = b0; res.b1 = b1; -#endif } } diff --git a/src/collider.h b/src/collider.h index e4e79682..e8e172cc 100644 --- a/src/collider.h +++ b/src/collider.h @@ -37,7 +37,10 @@ struct collider_collision_points_result { b32 solved; struct collider_menkowski_simplex simplex; struct collider_prototype prototype; - struct v2 a0, b0, a1, b1; /* Clipping faces */ + + /* Clipping faces */ + struct v2 a0, b0, a1, b1; + struct v2 a0_clipped, b0_clipped, a1_clipped, b1_clipped; }; struct collider_closest_points_result { diff --git a/src/config.h b/src/config.h index c659ccbb..6e3342bd 100644 --- a/src/config.h +++ b/src/config.h @@ -37,8 +37,7 @@ #define GAME_PHYSICS_ENABLE_RELAXATION 1 #define GAME_PHYSICS_ENABLE_TOI 1 -#define USER_DRAW_MENKOWSKI 0 -#define GAME_PHYSICS_ENABLE_COLLISION 1 +#define GAME_PHYSICS_ENABLE_COLLISION 0 #define GAME_SPAWN_TESTENT 0 #define GAME_PLAYER_AIM 1 @@ -55,7 +54,8 @@ #define USER_INTERP_ENABLED 1 #define COLLIDER_DEBUG RTC -#define COLLIDER_DEBUG_DETAILED 0 +#define COLLIDER_DEBUG_DETAILED 1 +#define COLLIDER_DEBUG_DETAILED_DRAW_MENKOWSKI 1 /* ========================== * * Settings diff --git a/src/game.c b/src/game.c index c5d292f8..5be21bea 100644 --- a/src/game.c +++ b/src/game.c @@ -192,11 +192,15 @@ INTERNAL void spawn_test_entities(void) #endif } + e->local_collider.points[0] = v2_with_len(V2(0.08f, 0.17f), 0.15f); + e->local_collider.points[1] = v2_with_len(V2(-0.07f, -0.2f), 0.15f); + e->local_collider.count = 2; + e->local_collider.radius = 0.075f; + //e->sprite = sprite_tag_from_path(STR("res/graphics/box_rounded.ase")); //e->sprite_span_name = STR("idle.unarmed"); //e->sprite_span_name = STR("idle.one_handed"); e->sprite_span_name = STR("idle.two_handed"); - e->sprite_collider_slice = STR("shape"); struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size); //xf.bx.y = -1.f; @@ -218,6 +222,7 @@ INTERNAL void spawn_test_entities(void) } /* Enemy */ +#if 0 { struct entity *e = entity_alloc(root); @@ -236,11 +241,13 @@ INTERNAL void spawn_test_entities(void) e->linear_ground_friction = 250; e->angular_ground_friction = 200; } +#endif /* Box */ -#if 0 +#if 1 { +#if 0 struct entity *e = entity_alloc(root); struct v2 pos = V2(1, -0.5); @@ -257,6 +264,23 @@ INTERNAL void spawn_test_entities(void) e->inertia_unscaled = 10; e->linear_ground_friction = 250; e->angular_ground_friction = 5; +#else + struct entity *e = entity_alloc(root); + + struct v2 pos = V2(1, -0.5); + f32 r = PI / 4; + struct v2 size = V2(0.5, 0.25); + struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size); + entity_set_xform(e, xf); + + e->sprite = sprite_tag_from_path(STR("res/graphics/bullet.ase")); + e->sprite_collider_slice = STR("shape"); + + entity_enable_prop(e, ENTITY_PROP_PHYSICAL_DYNAMIC); + e->mass_unscaled = 0.5; + e->inertia_unscaled = 1000; + e->linear_ground_friction = 0.001; +#endif } #endif @@ -615,7 +639,7 @@ INTERNAL void game_update(struct game_cmd_array game_cmds) struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, ent->sprite_collider_slice, ent->animation_frame); ent->local_collider = collider_from_quad(xform_mul_quad(cxf, quad_from_rect(slice.rect))); -#if 1 +#if 0 if (entity_has_prop(ent, ENTITY_PROP_TEST)) { //if ((true)) { #if 0 @@ -839,9 +863,14 @@ INTERNAL void game_update(struct game_cmd_array game_cmds) bullet->mass_unscaled = 0.04f; bullet->inertia_unscaled = 0.00001f; +#if 0 /* Point collider */ bullet->local_collider.points[0] = V2(0, 0); bullet->local_collider.count = 1; +#else + bullet->sprite = sprite_tag_from_path(STR("res/graphics/bullet.ase")); + bullet->sprite_collider_slice = STR("shape"); +#endif entity_enable_prop(bullet, ENTITY_PROP_BULLET); entity_enable_prop(bullet, ENTITY_PROP_SENSOR); diff --git a/src/phys.c b/src/phys.c index 4aab9dc1..0331f0bd 100644 --- a/src/phys.c +++ b/src/phys.c @@ -245,15 +245,6 @@ struct phys_collision_data_array phys_create_contacts(struct arena *arena, struc struct phys_collision_debug *dbg = &dbg_ent->collision_debug_data; - if (dbg->res.num_points == 0) { - if (collider_res.num_points > 0) { - ++e0->colliding; - ++e1->colliding; - } - } else if (collider_res.num_points == 0) { - --e0->colliding; - --e1->colliding; - } dbg->e0 = e0->handle; dbg->e1 = e1->handle; dbg->res = collider_res; diff --git a/src/user.c b/src/user.c index 1b829b1f..d82273fc 100644 --- a/src/user.c +++ b/src/user.c @@ -877,7 +877,7 @@ INTERNAL void user_update(void) b32 skip_debug_draw = !G.debug_camera && ent == active_camera; b32 skip_debug_draw_transform = entity_has_prop(ent, ENTITY_PROP_CAMERA); - //b32 skip_debug_draw_transform = true; + skip_debug_draw_transform = true; struct xform sprite_xform = xf; @@ -1007,7 +1007,7 @@ INTERNAL void user_update(void) /* Draw collider */ if (entity_has_prop(ent, ENTITY_PROP_PHYSICAL_DYNAMIC)) { struct collider_shape collider = ent->local_collider; - u32 color = RGBA_32_F(1, 0, 1, 0.25); + u32 color = RGBA_32_F(1, 1, 0, 0.25); f32 thickness = 2; { /* Draw collider using support points */ @@ -1141,15 +1141,24 @@ INTERNAL void user_update(void) { f32 thickness = 2; f32 radius = 4; - 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); + u32 color_line = RGBA_32_F(1, 0, 1, 0.25); + u32 color_a = RGBA_32_F(1, 0, 0, 0.25); + u32 color_b = RGBA_32_F(0, 1, 0, 0.25); + u32 color_line_clipped = RGBA_32_F(1, 0, 1, 1); + u32 color_a_clipped = RGBA_32_F(1, 0, 0, 1); + u32 color_b_clipped = RGBA_32_F(0, 1, 0, 1); { struct v2 a = xform_mul_v2(G.world_view, collider_res.a0); struct v2 b = xform_mul_v2(G.world_view, collider_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 a_clipped = xform_mul_v2(G.world_view, collider_res.a0_clipped); + struct v2 b_clipped = xform_mul_v2(G.world_view, collider_res.b0_clipped); + draw_solid_line(G.viewport_canvas, a_clipped, b_clipped, thickness, color_line_clipped); + draw_solid_circle(G.viewport_canvas, a_clipped, radius, color_a_clipped, 10); + draw_solid_circle(G.viewport_canvas, b_clipped, radius, color_b_clipped, 10); } { struct v2 a = xform_mul_v2(G.world_view, collider_res.a1); @@ -1157,10 +1166,16 @@ INTERNAL void user_update(void) 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 a_clipped = xform_mul_v2(G.world_view, collider_res.a1_clipped); + struct v2 b_clipped = xform_mul_v2(G.world_view, collider_res.b1_clipped); + draw_solid_line(G.viewport_canvas, a_clipped, b_clipped, thickness, color_line_clipped); + draw_solid_circle(G.viewport_canvas, a_clipped, radius, color_a_clipped, 10); + draw_solid_circle(G.viewport_canvas, b_clipped, radius, color_b_clipped, 10); } } -#if USER_DRAW_MENKOWSKI +#if COLLIDER_DEBUG_DETAILED_DRAW_MENKOWSKI struct xform e0_xf = data->xf0; struct xform e1_xf = data->xf1; @@ -1263,7 +1278,7 @@ INTERNAL void user_update(void) u32 color_second = RGBA_32_F(0, 1, 0, 0.75); u32 color_third = RGBA_32_F(0, 0, 1, 0.75); - struct collider_simplex simplex = collider_res.simplex; + struct collider_menkowski_simplex simplex = collider_res.simplex; struct v2 simplex_points[] = { simplex.a.p, simplex.b.p, simplex.c.p }; for (u64 i = 0; i < ARRAY_COUNT(simplex_points); ++i) simplex_points[i] = xform_mul_v2(G.world_view, simplex_points[i]); struct v2_array simplex_array = { .count = simplex.len, .points = simplex_points }; @@ -1407,7 +1422,8 @@ INTERNAL void user_update(void) /* Queue player fire cmd */ i32 fire_presses = G.bind_states[USER_BIND_KIND_FIRE].num_presses - G.bind_states[USER_BIND_KIND_FIRE].num_releases; - if (!G.debug_camera && fire_presses) { + //if (!G.debug_camera && fire_presses) { + if (fire_presses) { queue_game_cmd(scratch.arena, &cmd_list, (struct game_cmd) { .kind = GAME_CMD_KIND_PLAYER_FIRE, .state = fire_presses > 0 ? GAME_CMD_STATE_START : GAME_CMD_STATE_STOP