diff --git a/src/collider.c b/src/collider.c index a9163f9b..b4084828 100644 --- a/src/collider.c +++ b/src/collider.c @@ -106,6 +106,16 @@ struct aabb collider_aabb_from_collider(struct collider_shape *shape, struct xfo return res; } +struct aabb collider_aabb_from_combined_aabb(struct aabb b0, struct aabb b1) +{ + struct aabb res; + res.p0.x = min_f32(min_f32(b0.p0.x, b0.p1.x), min_f32(b1.p0.x, b1.p1.x)); + res.p0.y = min_f32(min_f32(b0.p0.y, b0.p1.y), min_f32(b1.p0.y, b1.p1.y)); + res.p1.x = max_f32(max_f32(b0.p0.x, b0.p1.x), max_f32(b1.p0.x, b1.p1.x)); + res.p1.y = max_f32(max_f32(b0.p0.y, b0.p1.y), max_f32(b1.p0.y, b1.p1.y)); + return res; +} + b32 collider_test_aabb(struct aabb box0, struct aabb box1) { b32 res = (box0.p0.x >= box1.p0.x && box0.p0.x <= box1.p1.x && box0.p0.y >= box1.p0.y && box0.p0.y <= box1.p1.y) || /* Test box0 top left inside box1 */ diff --git a/src/collider.h b/src/collider.h index 6d277932..c6a45619 100644 --- a/src/collider.h +++ b/src/collider.h @@ -62,6 +62,8 @@ struct collider_support_point collider_get_support_point(struct collider_shape * struct aabb collider_aabb_from_collider(struct collider_shape *shape, struct xform xf); +struct aabb collider_aabb_from_combined_aabb(struct aabb b0, struct aabb b1); + b32 collider_test_aabb(struct aabb box0, struct aabb box1); 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/phys.c b/src/phys.c index 4bda5d4c..04a7208d 100644 --- a/src/phys.c +++ b/src/phys.c @@ -1062,33 +1062,34 @@ f32 phys_determine_earliest_toi_for_bullets(struct phys_ctx *ctx, f32 step_dt, f { __prof; struct entity_store *store = ctx->store; + struct space *space = ctx->space; f32 smallest_t = 1; for (u64 e0_index = 0; e0_index < store->reserved; ++e0_index) { struct entity *e0 = &store->entities[e0_index]; if (!entity_is_valid_and_active(e0)) continue; if (!(entity_has_prop(e0, ENTITY_PROP_PHYSICAL_DYNAMIC) || entity_has_prop(e0, ENTITY_PROP_PHYSICAL_KINEMATIC))) continue; + if (!entity_has_prop(e0, ENTITY_PROP_BULLET)) continue; if (e0->local_collider.count <= 0) continue; - b32 e0_is_bullet = entity_has_prop(e0, ENTITY_PROP_BULLET); - struct collider_shape e0_collider = e0->local_collider; struct xform e0_xf_t0 = entity_get_xform(e0); struct xform e0_xf_t1 = get_derived_xform(e0, step_dt); - /* Start e1 index at e0 index + 1 to prevent redundant checks */ - for (u64 e1_index = e0_index + 1; e1_index < store->reserved; ++e1_index) { - struct entity *e1 = &store->entities[e1_index]; + /* TODO: Use swept aabb rather than combined aabb. This should prevent spikes from bullets returning false positive TOIs with irrelevant entities. */ + struct aabb aabb_t0 = collider_aabb_from_collider(&e0_collider, e0_xf_t0); + struct aabb aabb_t1 = collider_aabb_from_collider(&e0_collider, e0_xf_t1); + struct aabb combined_aabb = collider_aabb_from_combined_aabb(aabb_t0, aabb_t1); + + struct space_iter iter = space_iter_begin_aabb(space, combined_aabb); + struct space_client *client; + while ((client = space_iter_next(&iter))) { + struct entity *e1 = entity_from_handle(store, client->ent); if (e1 == e0) continue; if (!entity_is_valid_and_active(e1)) continue; if (!(entity_has_prop(e1, ENTITY_PROP_PHYSICAL_DYNAMIC) || entity_has_prop(e1, ENTITY_PROP_PHYSICAL_KINEMATIC))) continue; if (e1->local_collider.count <= 0) continue; - b32 e1_is_bullet = entity_has_prop(e1, ENTITY_PROP_BULLET); - - /* Skip check if neither e0 or e1 are bullets */ - if (!e0_is_bullet && !e1_is_bullet) continue; - struct collider_shape e1_collider = e1->local_collider; struct xform e1_xf_t0 = entity_get_xform(e1); struct xform e1_xf_t1 = get_derived_xform(e1, step_dt); @@ -1098,6 +1099,7 @@ f32 phys_determine_earliest_toi_for_bullets(struct phys_ctx *ctx, f32 step_dt, f smallest_t = t; } } + space_iter_end(&iter); } return smallest_t;