run collision callbacks twice. process explosion blast collision in collision callback
This commit is contained in:
parent
855fa051d0
commit
6ac44c3de9
22
src/log.c
22
src/log.c
@ -139,15 +139,16 @@ void _log(i32 level, struct string msg)
|
||||
#if LOG_INCLUDE_SOURCE_LOCATION
|
||||
struct string msg_formatted = string_format(
|
||||
scratch.arena,
|
||||
LIT("%F:%F:%F |Thread %F| [%F] <%F:%F> %F"),
|
||||
LIT("[%F:%F:%F.%F] |%F| [%F] <%F:%F> %F"),
|
||||
|
||||
/* Time */
|
||||
FMT_UINT(lt.hour),
|
||||
FMT_UINT(lt.minute),
|
||||
FMT_UINT(lt.second),
|
||||
FMT_UINT_Z(lt.hour, 2),
|
||||
FMT_UINT_Z(lt.minute, 2),
|
||||
FMT_UINT_Z(lt.second, 2),
|
||||
FMT_UINT_Z(lt.milliseconds, 3),
|
||||
|
||||
/* TID */
|
||||
FMT_UINT(tid),
|
||||
FMT_UINT_Z(tid, 5),
|
||||
|
||||
/* Level */
|
||||
FMT_STR(shorthand),
|
||||
@ -162,15 +163,16 @@ void _log(i32 level, struct string msg)
|
||||
#else
|
||||
struct string msg_formatted = string_format(
|
||||
scratch.arena,
|
||||
LIT("%F:%F:%F |Thread %F| [%F] %F"),
|
||||
LIT("[%F:%F:%F.%F] |%F| [%F] %F"),
|
||||
|
||||
/* Time */
|
||||
FMT_UINT(lt.hour),
|
||||
FMT_UINT(lt.minute),
|
||||
FMT_UINT(lt.second),
|
||||
FMT_UINT_Z(lt.hour, 2),
|
||||
FMT_UINT_Z(lt.minute, 2),
|
||||
FMT_UINT_Z(lt.second, 2),
|
||||
FMT_UINT_Z(lt.milliseconds, 3),
|
||||
|
||||
/* TID */
|
||||
FMT_UINT(tid),
|
||||
FMT_UINT_Z(tid, 5),
|
||||
|
||||
/* Level */
|
||||
FMT_STR(shorthand),
|
||||
|
||||
40
src/phys.c
40
src/phys.c
@ -55,7 +55,7 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a
|
||||
for (u64 check0_index = 0; check0_index < ss->num_ents_reserved; ++check0_index) {
|
||||
struct sim_ent *check0 = &ss->ents[check0_index];
|
||||
if (!sim_ent_is_valid_and_active(check0)) continue;
|
||||
if (!(sim_ent_has_prop(check0, SEPROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(check0, SEPROP_PHYSICAL_KINEMATIC))) continue;
|
||||
if (!(sim_ent_has_prop(check0, SEPROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(check0, SEPROP_PHYSICAL_KINEMATIC) || sim_ent_has_prop(check0, SEPROP_SENSOR))) continue;
|
||||
if (check0->local_collider.count <= 0) continue;
|
||||
|
||||
struct xform check0_xf = sim_ent_get_xform(check0);
|
||||
@ -68,7 +68,7 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a
|
||||
struct sim_ent *check1 = sim_ent_from_id(ss, space_entry->ent);
|
||||
if (check1 == check0) continue;
|
||||
if (!sim_ent_is_valid_and_active(check1)) continue;
|
||||
if (!(sim_ent_has_prop(check1, SEPROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(check1, SEPROP_PHYSICAL_KINEMATIC))) continue;
|
||||
if (!(sim_ent_has_prop(check1, SEPROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(check1, SEPROP_PHYSICAL_KINEMATIC) || sim_ent_has_prop(check1, SEPROP_SENSOR))) continue;
|
||||
if (check1->local_collider.count <= 0) continue;
|
||||
|
||||
/* Deterministic order based on entity id */
|
||||
@ -323,11 +323,11 @@ void phys_prepare_contacts(struct phys_step_ctx *ctx, u64 phys_iteration)
|
||||
constraint->inv_i0 = inv_i0;
|
||||
constraint->inv_i1 = inv_i1;
|
||||
|
||||
if (sim_ent_has_prop(e0, SEPROP_PHYSICAL_KINEMATIC)) {
|
||||
if (!sim_ent_has_prop(e0, SEPROP_PHYSICAL_DYNAMIC)) {
|
||||
constraint->inv_m0 = 0;
|
||||
constraint->inv_i0 = 0;
|
||||
}
|
||||
if (sim_ent_has_prop(e1, SEPROP_PHYSICAL_KINEMATIC)) {
|
||||
if (!sim_ent_has_prop(e1, SEPROP_PHYSICAL_DYNAMIC)) {
|
||||
constraint->inv_m1 = 0;
|
||||
constraint->inv_i1 = 0;
|
||||
}
|
||||
@ -381,8 +381,8 @@ void phys_prepare_contacts(struct phys_step_ctx *ctx, u64 phys_iteration)
|
||||
|
||||
|
||||
if (!sim_ent_should_simulate(e0) || !sim_ent_should_simulate(e1)
|
||||
|| !(sim_ent_has_prop(e0, SEPROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(e0, SEPROP_PHYSICAL_KINEMATIC))
|
||||
|| !(sim_ent_has_prop(e1, SEPROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(e1, SEPROP_PHYSICAL_KINEMATIC))) {
|
||||
|| !(sim_ent_has_prop(e0, SEPROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(e0, SEPROP_PHYSICAL_KINEMATIC) || !sim_ent_has_prop(e0, SEPROP_SENSOR))
|
||||
|| !(sim_ent_has_prop(e1, SEPROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(e1, SEPROP_PHYSICAL_KINEMATIC) || !sim_ent_has_prop(e1, SEPROP_SENSOR))) {
|
||||
/* Mark dbg ent for removal */
|
||||
sim_ent_disable_prop(dbg_ent, SEPROP_ACTIVE);
|
||||
sim_ent_enable_prop(dbg_ent, SEPROP_RELEASE);
|
||||
@ -1002,7 +1002,7 @@ f32 phys_determine_earliest_toi_for_bullets(struct phys_step_ctx *ctx, f32 step_
|
||||
for (u64 e0_index = 0; e0_index < ss->num_ents_reserved; ++e0_index) {
|
||||
struct sim_ent *e0 = &ss->ents[e0_index];
|
||||
if (!sim_ent_should_simulate(e0)) continue;
|
||||
if (!(sim_ent_has_prop(e0, SEPROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(e0, SEPROP_PHYSICAL_KINEMATIC))) continue;
|
||||
if (!(sim_ent_has_prop(e0, SEPROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(e0, SEPROP_PHYSICAL_KINEMATIC) || sim_ent_has_prop(e0, SEPROP_SENSOR))) continue;
|
||||
if (!sim_ent_has_prop(e0, SEPROP_BULLET)) continue;
|
||||
if (e0->local_collider.count <= 0) continue;
|
||||
|
||||
@ -1021,7 +1021,7 @@ f32 phys_determine_earliest_toi_for_bullets(struct phys_step_ctx *ctx, f32 step_
|
||||
struct sim_ent *e1 = sim_ent_from_id(ss, entry->ent);
|
||||
if (e1 == e0) continue;
|
||||
if (!sim_ent_should_simulate(e1)) continue;
|
||||
if (!(sim_ent_has_prop(e1, SEPROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(e1, SEPROP_PHYSICAL_KINEMATIC))) continue;
|
||||
if (!(sim_ent_has_prop(e1, SEPROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(e1, SEPROP_PHYSICAL_KINEMATIC) || sim_ent_has_prop(e1, SEPROP_SENSOR))) continue;
|
||||
if (e1->local_collider.count <= 0) continue;
|
||||
|
||||
struct collider_shape e1_collider = e1->local_collider;
|
||||
@ -1068,6 +1068,26 @@ void phys_update_aabbs(struct phys_step_ctx *ctx)
|
||||
* Step
|
||||
* ========================== */
|
||||
|
||||
INTERNAL void run_collision_callbacks(struct phys_step_ctx *ctx, phys_collision_callback_func *callback, struct phys_collision_data_array collision_data)
|
||||
{
|
||||
struct sim_step_ctx *sim_step_ctx = ctx->sim_step_ctx;
|
||||
for (u64 i = 0; i < collision_data.count; ++i) {
|
||||
/* Collision data from e0's perspective */
|
||||
struct phys_collision_data *data = &collision_data.a[i];
|
||||
|
||||
/* Collision data from e1's perspective */
|
||||
struct phys_collision_data data_inverted = *data;
|
||||
data_inverted.e0 = data->e1;
|
||||
data_inverted.e1 = data->e0;
|
||||
data_inverted.normal = v2_neg(data->normal);
|
||||
data_inverted.vrel = v2_neg(data->vrel);
|
||||
|
||||
/* Run callback twice for both e0 & e1 */
|
||||
callback(data, sim_step_ctx);
|
||||
callback(&data_inverted, sim_step_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
/* Returns phys iteration to be fed into next step. Supplied iteration must be > 0. */
|
||||
void phys_step(struct phys_step_ctx *ctx, f32 timestep)
|
||||
{
|
||||
@ -1107,7 +1127,7 @@ void phys_step(struct phys_step_ctx *ctx, f32 timestep)
|
||||
|
||||
if (ctx->pre_solve_callback) {
|
||||
__profscope(pre_solve_callback);
|
||||
ctx->pre_solve_callback(collision_data, ctx->sim_step_ctx);
|
||||
run_collision_callbacks(ctx, ctx->pre_solve_callback, collision_data);
|
||||
}
|
||||
|
||||
f32 substep_dt = step_dt / SIM_PHYSICS_SUBSTEPS;
|
||||
@ -1141,7 +1161,7 @@ void phys_step(struct phys_step_ctx *ctx, f32 timestep)
|
||||
|
||||
if (ctx->post_solve_callback) {
|
||||
__profscope(post_solve_callback);
|
||||
ctx->post_solve_callback(collision_data, ctx->sim_step_ctx);
|
||||
run_collision_callbacks(ctx, ctx->post_solve_callback, collision_data);
|
||||
}
|
||||
|
||||
scratch_end(scratch);
|
||||
|
||||
@ -10,6 +10,7 @@ struct sim_step_ctx;
|
||||
|
||||
struct phys_contact_constraint;
|
||||
struct phys_collision_data {
|
||||
/* NOTE: e0 & e1 can be opposite of e0 & e1 contained in constraint when passed to collision callbacks */
|
||||
struct phys_contact_constraint *constraint;
|
||||
struct sim_ent_id e0;
|
||||
struct sim_ent_id e1;
|
||||
@ -25,7 +26,7 @@ struct phys_collision_data_array {
|
||||
};
|
||||
|
||||
struct phys_collision_data;
|
||||
#define PHYS_COLLISION_CALLBACK_FUNC_DEF(name, arg_collision_data, arg_sim_step_ctx) void name(struct phys_collision_data_array arg_collision_data, struct sim_step_ctx *arg_sim_step_ctx)
|
||||
#define PHYS_COLLISION_CALLBACK_FUNC_DEF(name, arg_collision_data, arg_sim_step_ctx) void name(struct phys_collision_data *arg_collision_data, struct sim_step_ctx *arg_sim_step_ctx)
|
||||
typedef PHYS_COLLISION_CALLBACK_FUNC_DEF(phys_collision_callback_func, collision_data, ctx);
|
||||
|
||||
/* Structure containing data used for a single physics step */
|
||||
|
||||
@ -291,9 +291,16 @@ INTERNAL struct string shader_alloc(struct arena *arena, struct dx11_shader *sha
|
||||
} else {
|
||||
error_str = LIT("Unknown error");
|
||||
if (error_blob) {
|
||||
u64 error_cstr_len = ID3D10Blob_GetBufferSize(error_blob);
|
||||
char *error_cstr = (char *)ID3D10Blob_GetBufferPointer(error_blob);
|
||||
error_str = string_copy(arena, string_from_cstr(error_cstr, error_cstr_len));
|
||||
u64 error_blob_cstr_len = ID3D10Blob_GetBufferSize(error_blob);
|
||||
char *error_blob_cstr = (char *)ID3D10Blob_GetBufferPointer(error_blob);
|
||||
struct string error_blob_str = string_copy(arena, string_from_cstr(error_blob_cstr, error_blob_cstr_len));
|
||||
if (string_ends_with(error_blob_str, LIT("\n"))) {
|
||||
/* Remove trailing newline */
|
||||
error_blob_str.len -= 1;
|
||||
}
|
||||
if (error_blob_str.len > 0) {
|
||||
error_str = error_blob_str;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -346,7 +353,7 @@ INTERNAL void reload_shader(struct dx11_shader *old_shader, struct dx11_shader_d
|
||||
*old_shader = new_shader;
|
||||
} else {
|
||||
error_msg = string_format(scratch.arena,
|
||||
LIT("Failed to compile shader \"%F\":\n\n%F"),
|
||||
LIT("Failed to compile shader \"%F\":\n%F"),
|
||||
FMT_STR(name),
|
||||
FMT_STR(comp_error));
|
||||
shader_release(&new_shader);
|
||||
|
||||
@ -48,7 +48,6 @@ enum sim_ent_prop {
|
||||
SEPROP_TRIGGER_NEXT_TICK,
|
||||
|
||||
SEPROP_EXPLOSION,
|
||||
SEPROP_EXPLOSION_STARTED,
|
||||
|
||||
SEPROP_BULLET,
|
||||
SEPROP_TRACER,
|
||||
@ -303,6 +302,7 @@ struct sim_ent {
|
||||
/* Explosion */
|
||||
|
||||
f32 explosion_radius;
|
||||
u64 explosion_tick;
|
||||
|
||||
/* ====================================================================== */
|
||||
/* Tracer */
|
||||
|
||||
150
src/sim_step.c
150
src/sim_step.c
@ -49,7 +49,7 @@ void sim_accel_reset(struct sim_snapshot *ss, struct sim_accel *accel)
|
||||
* Test
|
||||
* ========================== */
|
||||
|
||||
/* TODO: Remove this */
|
||||
/* TODO: Remove this */
|
||||
|
||||
INTERNAL struct sim_ent *spawn_test_employee(struct sim_step_ctx *ctx)
|
||||
{
|
||||
@ -153,6 +153,23 @@ INTERNAL struct sim_ent *spawn_test_camera(struct sim_snapshot *world, struct si
|
||||
return camera_ent;
|
||||
}
|
||||
|
||||
INTERNAL struct sim_ent *spawn_test_explosion(struct sim_snapshot *world, struct v2 point, f32 radius)
|
||||
{
|
||||
struct sim_ent *root = sim_ent_from_id(world, SIM_ENT_ROOT_ID);
|
||||
|
||||
struct sim_ent *ent = sim_ent_alloc_sync_src(root);
|
||||
sim_ent_set_xform(ent, XFORM_POS(point));
|
||||
|
||||
sim_ent_enable_prop(ent, SEPROP_EXPLOSION);
|
||||
ent->explosion_radius = radius;
|
||||
|
||||
sim_ent_enable_prop(ent, SEPROP_SENSOR);
|
||||
ent->local_collider.count = 1;
|
||||
ent->local_collider.radius = radius;
|
||||
|
||||
return ent;
|
||||
}
|
||||
|
||||
INTERNAL void spawn_test_entities(struct sim_step_ctx *ctx, struct v2 offset)
|
||||
{
|
||||
struct sim_snapshot *world = ctx->world;
|
||||
@ -257,30 +274,25 @@ INTERNAL void test_clear_level(struct sim_step_ctx *ctx)
|
||||
* Respond to physics collisions
|
||||
* ========================== */
|
||||
|
||||
INTERNAL void on_collision(struct sim_ent *e0, struct sim_ent *e1, struct phys_collision_data *data, struct sim_step_ctx *step_ctx)
|
||||
INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, data, step_ctx)
|
||||
{
|
||||
|
||||
struct sim_snapshot *world = step_ctx->world;
|
||||
struct sim_ent *e0 = sim_ent_from_id(world, data->e0);
|
||||
struct sim_ent *e1 = sim_ent_from_id(world, data->e1);
|
||||
struct sim_ent *root = sim_ent_from_id(world, SIM_ENT_ROOT_ID);
|
||||
struct phys_contact_constraint *constraint = data->constraint;
|
||||
|
||||
if (sim_ent_should_simulate(e0) && sim_ent_should_simulate(e1)) {
|
||||
|
||||
/* Bullet impact */
|
||||
if (sim_ent_has_prop(e0, SEPROP_BULLET)) {
|
||||
struct v2 normal = data->normal; /* Impact normal */
|
||||
struct v2 vrel = v2_neg(data->vrel); /* Impact velocity */
|
||||
struct v2 vrel = data->vrel; /* Impact velocity */
|
||||
|
||||
struct sim_ent *bullet = e0;
|
||||
struct sim_ent *target = e1;
|
||||
struct sim_ent *src = sim_ent_from_id(world, bullet->bullet_src);
|
||||
|
||||
if (bullet->bullet_has_hit || sim_ent_id_eq(src->top, target->top)) {
|
||||
/* Ignore collision if bullet already spent or if weapon and
|
||||
* target share same top level parent */
|
||||
/* NOTE: Since bullet is most likely just a sensor skip_solve is probably already true */
|
||||
constraint->skip_solve = true;
|
||||
} else {
|
||||
/* Process collision if bullet already spent or * target share same top level parent */
|
||||
if (!bullet->bullet_has_hit && !sim_ent_id_eq(src->top, target->top)) {
|
||||
struct v2 point = data->point;
|
||||
|
||||
/* Update tracer */
|
||||
@ -323,12 +335,7 @@ INTERNAL void on_collision(struct sim_ent *e0, struct sim_ent *e1, struct phys_c
|
||||
|
||||
/* Create explosion */
|
||||
if (bullet->bullet_impact_explosion_radius > 0) {
|
||||
struct sim_ent *exp = sim_ent_alloc_sync_src(root);
|
||||
sim_ent_set_xform(exp, XFORM_POS(point));
|
||||
|
||||
sim_ent_enable_prop(exp, SEPROP_SENSOR);
|
||||
sim_ent_enable_prop(exp, SEPROP_EXPLOSION);
|
||||
exp->explosion_radius = bullet->bullet_impact_explosion_radius;
|
||||
spawn_test_explosion(world, point, bullet->bullet_impact_explosion_radius);
|
||||
}
|
||||
|
||||
/* Update bullet */
|
||||
@ -336,20 +343,39 @@ INTERNAL void on_collision(struct sim_ent *e0, struct sim_ent *e1, struct phys_c
|
||||
sim_ent_enable_prop(bullet, SEPROP_RELEASE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(pre_solve_callback, collision_data_array, step_ctx)
|
||||
{
|
||||
struct sim_snapshot *world = step_ctx->world;
|
||||
for (u64 i = 0; i < collision_data_array.count; ++i) {
|
||||
struct phys_collision_data *data = &collision_data_array.a[i];
|
||||
struct sim_ent *e0 = sim_ent_from_id(world, data->e0);
|
||||
struct sim_ent *e1 = sim_ent_from_id(world, data->e1);
|
||||
if (sim_ent_is_valid_and_active(e0) && sim_ent_is_valid_and_active(e1)) {
|
||||
on_collision(e0, e1, data, step_ctx);
|
||||
if (sim_ent_is_valid_and_active(e1) && sim_ent_is_valid_and_active(e0)) {
|
||||
on_collision(e1, e0, data, step_ctx);
|
||||
/* Explosion blast collision */
|
||||
if (sim_ent_has_prop(e0, SEPROP_EXPLOSION) && (e0->explosion_tick == world->tick || e0->explosion_tick == 0)) {
|
||||
struct sim_ent *exp = e0;
|
||||
struct sim_ent *victim = e1;
|
||||
|
||||
exp->explosion_tick = world->tick;
|
||||
sim_ent_disable_prop(exp, SEPROP_SENSOR);
|
||||
|
||||
struct xform xf = sim_ent_get_xform(exp);
|
||||
|
||||
f32 radius = exp->explosion_radius;
|
||||
|
||||
struct collider_shape origin_collider = ZI;
|
||||
origin_collider.count = 1;
|
||||
|
||||
struct xform victim_xf = sim_ent_get_xform(victim);
|
||||
struct collider_closest_points_result closest_points = collider_closest_points(&origin_collider, &victim->local_collider, xf, victim_xf);
|
||||
struct v2 dir = v2_sub(closest_points.p1, closest_points.p0);
|
||||
f32 distance = v2_len(dir);
|
||||
if (closest_points.colliding) {
|
||||
dir = v2_neg(dir);
|
||||
distance = 0;
|
||||
} else {
|
||||
distance = v2_len(dir);
|
||||
}
|
||||
/* TODO: Blast obstruction */
|
||||
if (distance <= radius) {
|
||||
/* TODO: Exponential decay */
|
||||
f32 strength = 100;
|
||||
f32 ratio = (radius - distance) / radius;
|
||||
struct v2 impulse = v2_with_len(dir, strength * ratio);
|
||||
sim_ent_apply_linear_impulse(victim, impulse, closest_points.p1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -584,11 +610,7 @@ void sim_step(struct sim_step_ctx *ctx)
|
||||
if (flags & SIM_CONTROL_FLAG_EXPLODE_TEST) {
|
||||
if (!(old_control.flags & SIM_CONTROL_FLAG_EXPLODE_TEST)) {
|
||||
logf_info("Explosion (test)");
|
||||
struct sim_ent *exp = sim_ent_alloc_sync_src(root);
|
||||
sim_ent_set_xform(exp, XFORM_POS(player->player_cursor_pos));
|
||||
|
||||
sim_ent_enable_prop(exp, SEPROP_EXPLOSION);
|
||||
exp->explosion_radius = 50;
|
||||
spawn_test_explosion(world, player->player_cursor_pos, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1228,64 +1250,10 @@ void sim_step(struct sim_step_ctx *ctx)
|
||||
{
|
||||
struct phys_step_ctx phys = ZI;
|
||||
phys.sim_step_ctx = ctx;
|
||||
phys.pre_solve_callback = pre_solve_callback;
|
||||
phys.pre_solve_callback = on_collision;
|
||||
phys_step(&phys, sim_dt);
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Update explosions
|
||||
* ========================== */
|
||||
|
||||
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
|
||||
struct sim_ent *ent = &world->ents[ent_index];
|
||||
if (!sim_ent_should_simulate(ent)) continue;
|
||||
|
||||
if (sim_ent_has_prop(ent, SEPROP_EXPLOSION)) {
|
||||
struct xform xf = sim_ent_get_xform(ent);
|
||||
if (!sim_ent_has_prop(ent, SEPROP_EXPLOSION_STARTED)) {
|
||||
f32 radius = ent->explosion_radius;
|
||||
sim_ent_enable_prop(ent, SEPROP_EXPLOSION_STARTED);
|
||||
|
||||
struct collider_shape origin_collider = ZI;
|
||||
origin_collider.count = 1;
|
||||
|
||||
struct aabb aabb = ZI;
|
||||
{
|
||||
struct collider_shape radius_collider = ZI;
|
||||
radius_collider.radius = radius;
|
||||
radius_collider.count = 1;
|
||||
ent->local_collider = radius_collider;
|
||||
aabb = collider_aabb_from_collider(&radius_collider, xf);
|
||||
}
|
||||
|
||||
/* Find ents in blast range */
|
||||
struct space_iter iter = space_iter_begin_aabb(ctx->accel->space, aabb);
|
||||
struct space_entry *space_entry;
|
||||
while ((space_entry = space_iter_next(&iter))) {
|
||||
struct sim_ent *victim = sim_ent_from_id(world, space_entry->ent);
|
||||
if (sim_ent_should_simulate(victim) && sim_ent_has_prop(victim, SEPROP_PHYSICAL_DYNAMIC) && !sim_ent_id_eq(ent->id, victim->id)) {
|
||||
struct xform victim_xf = sim_ent_get_xform(victim);
|
||||
struct collider_closest_points_result closest_points = collider_closest_points(&origin_collider, &victim->local_collider, xf, victim_xf);
|
||||
struct v2 dir = v2_sub(closest_points.p1, closest_points.p0);
|
||||
f32 distance = v2_len(dir);
|
||||
/* TODO: Blast obstruction */
|
||||
if (distance <= radius) {
|
||||
/* TODO: Exponential decay */
|
||||
//f32 ratio = (radius - distance) / radius;
|
||||
//f32 strength = 100;
|
||||
//struct v2 impulse = v2_with_len(dir, strength * ratio);
|
||||
struct v2 impulse = V2(-100, 0);
|
||||
|
||||
//sim_ent_apply_linear_impulse(victim, impulse, closest_points.p1);
|
||||
sim_ent_apply_linear_impulse_to_center(victim, impulse);
|
||||
}
|
||||
}
|
||||
}
|
||||
space_iter_end(iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ========================== *
|
||||
* Update tracers
|
||||
* ========================== */
|
||||
|
||||
Loading…
Reference in New Issue
Block a user