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
|
#if LOG_INCLUDE_SOURCE_LOCATION
|
||||||
struct string msg_formatted = string_format(
|
struct string msg_formatted = string_format(
|
||||||
scratch.arena,
|
scratch.arena,
|
||||||
LIT("%F:%F:%F |Thread %F| [%F] <%F:%F> %F"),
|
LIT("[%F:%F:%F.%F] |%F| [%F] <%F:%F> %F"),
|
||||||
|
|
||||||
/* Time */
|
/* Time */
|
||||||
FMT_UINT(lt.hour),
|
FMT_UINT_Z(lt.hour, 2),
|
||||||
FMT_UINT(lt.minute),
|
FMT_UINT_Z(lt.minute, 2),
|
||||||
FMT_UINT(lt.second),
|
FMT_UINT_Z(lt.second, 2),
|
||||||
|
FMT_UINT_Z(lt.milliseconds, 3),
|
||||||
|
|
||||||
/* TID */
|
/* TID */
|
||||||
FMT_UINT(tid),
|
FMT_UINT_Z(tid, 5),
|
||||||
|
|
||||||
/* Level */
|
/* Level */
|
||||||
FMT_STR(shorthand),
|
FMT_STR(shorthand),
|
||||||
@ -162,15 +163,16 @@ void _log(i32 level, struct string msg)
|
|||||||
#else
|
#else
|
||||||
struct string msg_formatted = string_format(
|
struct string msg_formatted = string_format(
|
||||||
scratch.arena,
|
scratch.arena,
|
||||||
LIT("%F:%F:%F |Thread %F| [%F] %F"),
|
LIT("[%F:%F:%F.%F] |%F| [%F] %F"),
|
||||||
|
|
||||||
/* Time */
|
/* Time */
|
||||||
FMT_UINT(lt.hour),
|
FMT_UINT_Z(lt.hour, 2),
|
||||||
FMT_UINT(lt.minute),
|
FMT_UINT_Z(lt.minute, 2),
|
||||||
FMT_UINT(lt.second),
|
FMT_UINT_Z(lt.second, 2),
|
||||||
|
FMT_UINT_Z(lt.milliseconds, 3),
|
||||||
|
|
||||||
/* TID */
|
/* TID */
|
||||||
FMT_UINT(tid),
|
FMT_UINT_Z(tid, 5),
|
||||||
|
|
||||||
/* Level */
|
/* Level */
|
||||||
FMT_STR(shorthand),
|
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) {
|
for (u64 check0_index = 0; check0_index < ss->num_ents_reserved; ++check0_index) {
|
||||||
struct sim_ent *check0 = &ss->ents[check0_index];
|
struct sim_ent *check0 = &ss->ents[check0_index];
|
||||||
if (!sim_ent_is_valid_and_active(check0)) continue;
|
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;
|
if (check0->local_collider.count <= 0) continue;
|
||||||
|
|
||||||
struct xform check0_xf = sim_ent_get_xform(check0);
|
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);
|
struct sim_ent *check1 = sim_ent_from_id(ss, space_entry->ent);
|
||||||
if (check1 == check0) continue;
|
if (check1 == check0) continue;
|
||||||
if (!sim_ent_is_valid_and_active(check1)) 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;
|
if (check1->local_collider.count <= 0) continue;
|
||||||
|
|
||||||
/* Deterministic order based on entity id */
|
/* 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_i0 = inv_i0;
|
||||||
constraint->inv_i1 = inv_i1;
|
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_m0 = 0;
|
||||||
constraint->inv_i0 = 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_m1 = 0;
|
||||||
constraint->inv_i1 = 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)
|
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(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_PHYSICAL_DYNAMIC) || sim_ent_has_prop(e1, SEPROP_PHYSICAL_KINEMATIC) || !sim_ent_has_prop(e1, SEPROP_SENSOR))) {
|
||||||
/* Mark dbg ent for removal */
|
/* Mark dbg ent for removal */
|
||||||
sim_ent_disable_prop(dbg_ent, SEPROP_ACTIVE);
|
sim_ent_disable_prop(dbg_ent, SEPROP_ACTIVE);
|
||||||
sim_ent_enable_prop(dbg_ent, SEPROP_RELEASE);
|
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) {
|
for (u64 e0_index = 0; e0_index < ss->num_ents_reserved; ++e0_index) {
|
||||||
struct sim_ent *e0 = &ss->ents[e0_index];
|
struct sim_ent *e0 = &ss->ents[e0_index];
|
||||||
if (!sim_ent_should_simulate(e0)) continue;
|
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 (!sim_ent_has_prop(e0, SEPROP_BULLET)) continue;
|
||||||
if (e0->local_collider.count <= 0) 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);
|
struct sim_ent *e1 = sim_ent_from_id(ss, entry->ent);
|
||||||
if (e1 == e0) continue;
|
if (e1 == e0) continue;
|
||||||
if (!sim_ent_should_simulate(e1)) 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;
|
if (e1->local_collider.count <= 0) continue;
|
||||||
|
|
||||||
struct collider_shape e1_collider = e1->local_collider;
|
struct collider_shape e1_collider = e1->local_collider;
|
||||||
@ -1068,6 +1068,26 @@ void phys_update_aabbs(struct phys_step_ctx *ctx)
|
|||||||
* Step
|
* 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. */
|
/* Returns phys iteration to be fed into next step. Supplied iteration must be > 0. */
|
||||||
void phys_step(struct phys_step_ctx *ctx, f32 timestep)
|
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) {
|
if (ctx->pre_solve_callback) {
|
||||||
__profscope(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;
|
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) {
|
if (ctx->post_solve_callback) {
|
||||||
__profscope(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);
|
scratch_end(scratch);
|
||||||
|
|||||||
@ -10,6 +10,7 @@ struct sim_step_ctx;
|
|||||||
|
|
||||||
struct phys_contact_constraint;
|
struct phys_contact_constraint;
|
||||||
struct phys_collision_data {
|
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 phys_contact_constraint *constraint;
|
||||||
struct sim_ent_id e0;
|
struct sim_ent_id e0;
|
||||||
struct sim_ent_id e1;
|
struct sim_ent_id e1;
|
||||||
@ -25,7 +26,7 @@ struct phys_collision_data_array {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct phys_collision_data;
|
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);
|
typedef PHYS_COLLISION_CALLBACK_FUNC_DEF(phys_collision_callback_func, collision_data, ctx);
|
||||||
|
|
||||||
/* Structure containing data used for a single physics step */
|
/* 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 {
|
} else {
|
||||||
error_str = LIT("Unknown error");
|
error_str = LIT("Unknown error");
|
||||||
if (error_blob) {
|
if (error_blob) {
|
||||||
u64 error_cstr_len = ID3D10Blob_GetBufferSize(error_blob);
|
u64 error_blob_cstr_len = ID3D10Blob_GetBufferSize(error_blob);
|
||||||
char *error_cstr = (char *)ID3D10Blob_GetBufferPointer(error_blob);
|
char *error_blob_cstr = (char *)ID3D10Blob_GetBufferPointer(error_blob);
|
||||||
error_str = string_copy(arena, string_from_cstr(error_cstr, error_cstr_len));
|
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;
|
*old_shader = new_shader;
|
||||||
} else {
|
} else {
|
||||||
error_msg = string_format(scratch.arena,
|
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(name),
|
||||||
FMT_STR(comp_error));
|
FMT_STR(comp_error));
|
||||||
shader_release(&new_shader);
|
shader_release(&new_shader);
|
||||||
|
|||||||
@ -48,7 +48,6 @@ enum sim_ent_prop {
|
|||||||
SEPROP_TRIGGER_NEXT_TICK,
|
SEPROP_TRIGGER_NEXT_TICK,
|
||||||
|
|
||||||
SEPROP_EXPLOSION,
|
SEPROP_EXPLOSION,
|
||||||
SEPROP_EXPLOSION_STARTED,
|
|
||||||
|
|
||||||
SEPROP_BULLET,
|
SEPROP_BULLET,
|
||||||
SEPROP_TRACER,
|
SEPROP_TRACER,
|
||||||
@ -303,6 +302,7 @@ struct sim_ent {
|
|||||||
/* Explosion */
|
/* Explosion */
|
||||||
|
|
||||||
f32 explosion_radius;
|
f32 explosion_radius;
|
||||||
|
u64 explosion_tick;
|
||||||
|
|
||||||
/* ====================================================================== */
|
/* ====================================================================== */
|
||||||
/* Tracer */
|
/* 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
|
* Test
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
/* TODO: Remove this */
|
/* TODO: Remove this */
|
||||||
|
|
||||||
INTERNAL struct sim_ent *spawn_test_employee(struct sim_step_ctx *ctx)
|
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;
|
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)
|
INTERNAL void spawn_test_entities(struct sim_step_ctx *ctx, struct v2 offset)
|
||||||
{
|
{
|
||||||
struct sim_snapshot *world = ctx->world;
|
struct sim_snapshot *world = ctx->world;
|
||||||
@ -257,30 +274,25 @@ INTERNAL void test_clear_level(struct sim_step_ctx *ctx)
|
|||||||
* Respond to physics collisions
|
* 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_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 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)) {
|
if (sim_ent_should_simulate(e0) && sim_ent_should_simulate(e1)) {
|
||||||
|
|
||||||
/* Bullet impact */
|
/* Bullet impact */
|
||||||
if (sim_ent_has_prop(e0, SEPROP_BULLET)) {
|
if (sim_ent_has_prop(e0, SEPROP_BULLET)) {
|
||||||
struct v2 normal = data->normal; /* Impact normal */
|
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 *bullet = e0;
|
||||||
struct sim_ent *target = e1;
|
struct sim_ent *target = e1;
|
||||||
struct sim_ent *src = sim_ent_from_id(world, bullet->bullet_src);
|
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)) {
|
/* Process collision if bullet already spent or * target share same top level parent */
|
||||||
/* Ignore collision if bullet already spent or if weapon and
|
if (!bullet->bullet_has_hit && !sim_ent_id_eq(src->top, target->top)) {
|
||||||
* 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 {
|
|
||||||
struct v2 point = data->point;
|
struct v2 point = data->point;
|
||||||
|
|
||||||
/* Update tracer */
|
/* Update tracer */
|
||||||
@ -323,12 +335,7 @@ INTERNAL void on_collision(struct sim_ent *e0, struct sim_ent *e1, struct phys_c
|
|||||||
|
|
||||||
/* Create explosion */
|
/* Create explosion */
|
||||||
if (bullet->bullet_impact_explosion_radius > 0) {
|
if (bullet->bullet_impact_explosion_radius > 0) {
|
||||||
struct sim_ent *exp = sim_ent_alloc_sync_src(root);
|
spawn_test_explosion(world, point, bullet->bullet_impact_explosion_radius);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update bullet */
|
/* 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);
|
sim_ent_enable_prop(bullet, SEPROP_RELEASE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(pre_solve_callback, collision_data_array, step_ctx)
|
/* Explosion blast collision */
|
||||||
{
|
if (sim_ent_has_prop(e0, SEPROP_EXPLOSION) && (e0->explosion_tick == world->tick || e0->explosion_tick == 0)) {
|
||||||
struct sim_snapshot *world = step_ctx->world;
|
struct sim_ent *exp = e0;
|
||||||
for (u64 i = 0; i < collision_data_array.count; ++i) {
|
struct sim_ent *victim = e1;
|
||||||
struct phys_collision_data *data = &collision_data_array.a[i];
|
|
||||||
struct sim_ent *e0 = sim_ent_from_id(world, data->e0);
|
exp->explosion_tick = world->tick;
|
||||||
struct sim_ent *e1 = sim_ent_from_id(world, data->e1);
|
sim_ent_disable_prop(exp, SEPROP_SENSOR);
|
||||||
if (sim_ent_is_valid_and_active(e0) && sim_ent_is_valid_and_active(e1)) {
|
|
||||||
on_collision(e0, e1, data, step_ctx);
|
struct xform xf = sim_ent_get_xform(exp);
|
||||||
if (sim_ent_is_valid_and_active(e1) && sim_ent_is_valid_and_active(e0)) {
|
|
||||||
on_collision(e1, e0, data, step_ctx);
|
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 (flags & SIM_CONTROL_FLAG_EXPLODE_TEST) {
|
||||||
if (!(old_control.flags & SIM_CONTROL_FLAG_EXPLODE_TEST)) {
|
if (!(old_control.flags & SIM_CONTROL_FLAG_EXPLODE_TEST)) {
|
||||||
logf_info("Explosion (test)");
|
logf_info("Explosion (test)");
|
||||||
struct sim_ent *exp = sim_ent_alloc_sync_src(root);
|
spawn_test_explosion(world, player->player_cursor_pos, 1);
|
||||||
sim_ent_set_xform(exp, XFORM_POS(player->player_cursor_pos));
|
|
||||||
|
|
||||||
sim_ent_enable_prop(exp, SEPROP_EXPLOSION);
|
|
||||||
exp->explosion_radius = 50;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1228,64 +1250,10 @@ void sim_step(struct sim_step_ctx *ctx)
|
|||||||
{
|
{
|
||||||
struct phys_step_ctx phys = ZI;
|
struct phys_step_ctx phys = ZI;
|
||||||
phys.sim_step_ctx = ctx;
|
phys.sim_step_ctx = ctx;
|
||||||
phys.pre_solve_callback = pre_solve_callback;
|
phys.pre_solve_callback = on_collision;
|
||||||
phys_step(&phys, sim_dt);
|
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
|
* Update tracers
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user