prediction progress

This commit is contained in:
jacob 2025-02-25 08:05:58 -06:00
parent 4d7ab508fb
commit 7ab7af81a3
3 changed files with 187 additions and 193 deletions

View File

@ -18,6 +18,7 @@ enum sim_ent_prop {
SIM_ENT_PROP_SYNC_SRC, /* This entity should be networked to other clients */ SIM_ENT_PROP_SYNC_SRC, /* This entity should be networked to other clients */
SIM_ENT_PROP_SYNC_DST, /* This entity is not locally created, and should sync with incoming net src ents */ SIM_ENT_PROP_SYNC_DST, /* This entity is not locally created, and should sync with incoming net src ents */
SIM_ENT_PROP_SYNC_PREDICT,
SIM_ENT_PROP_CLIENT, SIM_ENT_PROP_CLIENT,
SIM_ENT_PROP_LOCAL_CLIENT, SIM_ENT_PROP_LOCAL_CLIENT,
@ -377,7 +378,14 @@ INLINE b32 sim_ent_is_valid_and_active(struct sim_ent *ent)
INLINE b32 sim_ent_should_simulate(struct sim_ent *ent) INLINE b32 sim_ent_should_simulate(struct sim_ent *ent)
{ {
return !sim_ent_has_prop(ent, SIM_ENT_PROP_SYNC_DST); b32 res = false;
if (sim_ent_is_valid_and_active(ent)) {
res = true;
if (sim_ent_has_prop(ent, SIM_ENT_PROP_SYNC_DST) && !sim_ent_has_prop(ent, SIM_ENT_PROP_SYNC_PREDICT)) {
res = false;
}
}
return res;
} }
/* ========================== * /* ========================== *

View File

@ -181,9 +181,10 @@ INTERNAL struct sim_ent *spawn_test_player(struct sim_snapshot *world)
//e->control_torque = 5000; //e->control_torque = 5000;
e->control_torque = F32_INFINITY; e->control_torque = F32_INFINITY;
sim_ent_enable_prop(e, SIM_ENT_PROP_PHYSICAL_DYNAMIC); sim_ent_enable_prop(e, SIM_ENT_PROP_PHYSICAL_DYNAMIC);
sim_ent_enable_prop(e, SIM_ENT_PROP_SYNC_PREDICT);
player_ent = e; player_ent = e;
} }
@ -253,7 +254,7 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, collision_data_array, st
struct sim_ent *e0 = sim_ent_from_id(world, data->e0); 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 *e1 = sim_ent_from_id(world, data->e1);
if (sim_ent_is_valid_and_active(e0) && sim_ent_is_valid_and_active(e1)) { if (sim_ent_should_simulate(e0) && sim_ent_should_simulate(e1)) {
/* Bullet hit entity */ /* Bullet hit entity */
if (sim_ent_has_prop(e0, SIM_ENT_PROP_BULLET) || sim_ent_has_prop(e1, SIM_ENT_PROP_BULLET)) { if (sim_ent_has_prop(e0, SIM_ENT_PROP_BULLET) || sim_ent_has_prop(e1, SIM_ENT_PROP_BULLET)) {
struct v2 normal = data->normal; /* Impact normal */ struct v2 normal = data->normal; /* Impact normal */
@ -283,7 +284,7 @@ INTERNAL PHYS_COLLISION_CALLBACK_FUNC_DEF(on_collision, collision_data_array, st
/* Update tracer */ /* Update tracer */
struct sim_ent *tracer = sim_ent_from_id(world, bullet->bullet_tracer); struct sim_ent *tracer = sim_ent_from_id(world, bullet->bullet_tracer);
if (sim_ent_is_valid_and_active(tracer)) { if (sim_ent_should_simulate(tracer)) {
struct xform xf = sim_ent_get_xform(tracer); struct xform xf = sim_ent_get_xform(tracer);
xf.og = point; xf.og = point;
sim_ent_set_xform(tracer, xf); sim_ent_set_xform(tracer, xf);
@ -365,7 +366,7 @@ void sim_step(struct sim_step_ctx *ctx)
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
struct sim_ent *ent = &world->ents[ent_index]; struct sim_ent *ent = &world->ents[ent_index];
if (!ent->valid) continue; if (!ent->valid) continue;
if (!sim_ent_should_simulate(ent)) continue; if (sim_ent_has_prop(ent, SIM_ENT_PROP_SYNC_DST) && !sim_ent_has_prop(ent, SIM_ENT_PROP_SYNC_PREDICT)) continue;
if (!sim_ent_has_prop(ent, SIM_ENT_PROP_ACTIVE)) { if (!sim_ent_has_prop(ent, SIM_ENT_PROP_ACTIVE)) {
u64 atick = ent->activation_tick; u64 atick = ent->activation_tick;
@ -381,7 +382,6 @@ void sim_step(struct sim_step_ctx *ctx)
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
struct sim_ent *ent = &world->ents[ent_index]; struct sim_ent *ent = &world->ents[ent_index];
if (!sim_ent_is_valid_and_active(ent)) continue;
if (!sim_ent_should_simulate(ent)) continue; if (!sim_ent_should_simulate(ent)) continue;
if (sim_ent_has_prop(ent, SIM_ENT_PROP_TRIGGER_NEXT_TICK)) { if (sim_ent_has_prop(ent, SIM_ENT_PROP_TRIGGER_NEXT_TICK)) {
@ -398,11 +398,11 @@ void sim_step(struct sim_step_ctx *ctx)
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
struct sim_ent *cmd_ent = &world->ents[ent_index]; struct sim_ent *cmd_ent = &world->ents[ent_index];
if (!sim_ent_is_valid_and_active(cmd_ent)) continue; if (!sim_ent_should_simulate(cmd_ent)) continue;
if (sim_ent_has_prop(cmd_ent, SIM_ENT_PROP_CMD_CONTROL)) { if (sim_ent_has_prop(cmd_ent, SIM_ENT_PROP_CMD_CONTROL)) {
struct sim_ent *client_ent = sim_ent_from_id(world, cmd_ent->cmd_client); struct sim_ent *client_ent = sim_ent_from_id(world, cmd_ent->cmd_client);
if (sim_ent_is_valid_and_active(client_ent)) { if (sim_ent_should_simulate(client_ent)) {
if (!ctx->is_master && !sim_ent_id_eq(client_ent->id, world->local_client_ent)) { if (!ctx->is_master && !sim_ent_id_eq(client_ent->id, world->local_client_ent)) {
/* We are not the master and the command is not our own, skip processing */ /* We are not the master and the command is not our own, skip processing */
continue; continue;
@ -471,7 +471,7 @@ void sim_step(struct sim_step_ctx *ctx)
if (ctx->is_master) { if (ctx->is_master) {
for (u64 i = 0; i < world->num_ents_reserved; ++i) { for (u64 i = 0; i < world->num_ents_reserved; ++i) {
struct sim_ent *ent = &world->ents[i]; struct sim_ent *ent = &world->ents[i];
if (!sim_ent_is_valid_and_active(ent)) continue; if (!sim_ent_should_simulate(ent)) continue;
if (sim_ent_has_prop(ent, SIM_ENT_PROP_CLIENT)) { if (sim_ent_has_prop(ent, SIM_ENT_PROP_CLIENT)) {
/* FIXME: Ents never released when client disconnects */ /* FIXME: Ents never released when client disconnects */
struct sim_ent *control_ent = sim_ent_from_id(world, ent->client_control_ent); struct sim_ent *control_ent = sim_ent_from_id(world, ent->client_control_ent);
@ -496,7 +496,6 @@ void sim_step(struct sim_step_ctx *ctx)
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
struct sim_ent *ent = &world->ents[ent_index]; struct sim_ent *ent = &world->ents[ent_index];
if (!sim_ent_is_valid_and_active(ent)) continue;
if (!sim_ent_should_simulate(ent)) continue; if (!sim_ent_should_simulate(ent)) continue;
if (sim_ent_has_prop(ent, SIM_ENT_PROP_CONTROLLED)) { if (sim_ent_has_prop(ent, SIM_ENT_PROP_CONTROLLED)) {
@ -519,7 +518,6 @@ void sim_step(struct sim_step_ctx *ctx)
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
struct sim_ent *ent = &world->ents[ent_index]; struct sim_ent *ent = &world->ents[ent_index];
if (!sim_ent_is_valid_and_active(ent)) continue;
if (!sim_ent_should_simulate(ent)) continue; if (!sim_ent_should_simulate(ent)) continue;
if (sprite_tag_is_nil(ent->sprite)) continue; if (sprite_tag_is_nil(ent->sprite)) continue;
@ -620,7 +618,6 @@ void sim_step(struct sim_step_ctx *ctx)
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
struct sim_ent *ent = &world->ents[ent_index]; struct sim_ent *ent = &world->ents[ent_index];
if (!sim_ent_is_valid_and_active(ent)) continue;
if (!sim_ent_should_simulate(ent)) continue; if (!sim_ent_should_simulate(ent)) continue;
if (!sim_ent_has_prop(ent, SIM_ENT_PROP_ATTACHED)) continue; if (!sim_ent_has_prop(ent, SIM_ENT_PROP_ATTACHED)) continue;
@ -697,12 +694,11 @@ void sim_step(struct sim_step_ctx *ctx)
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
struct sim_ent *ent = &world->ents[ent_index]; struct sim_ent *ent = &world->ents[ent_index];
if (!sim_ent_is_valid_and_active(ent)) continue;
if (!sim_ent_should_simulate(ent)) continue; if (!sim_ent_should_simulate(ent)) continue;
if (sim_ent_has_prop(ent, SIM_ENT_PROP_TRIGGERING_EQUIPPED)) { if (sim_ent_has_prop(ent, SIM_ENT_PROP_TRIGGERING_EQUIPPED)) {
struct sim_ent *eq = sim_ent_from_id(world, ent->equipped); struct sim_ent *eq = sim_ent_from_id(world, ent->equipped);
if (sim_ent_is_valid_and_active(eq)) { if (sim_ent_should_simulate(eq)) {
sim_ent_enable_prop(eq, SIM_ENT_PROP_TRIGGERED_THIS_TICK); sim_ent_enable_prop(eq, SIM_ENT_PROP_TRIGGERED_THIS_TICK);
} }
} }
@ -714,7 +710,6 @@ void sim_step(struct sim_step_ctx *ctx)
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
struct sim_ent *ent = &world->ents[ent_index]; struct sim_ent *ent = &world->ents[ent_index];
if (!sim_ent_is_valid_and_active(ent)) continue;
if (!sim_ent_should_simulate(ent)) continue; if (!sim_ent_should_simulate(ent)) continue;
if (!sim_ent_has_prop(ent, SIM_ENT_PROP_TRIGGERED_THIS_TICK)) continue; if (!sim_ent_has_prop(ent, SIM_ENT_PROP_TRIGGERED_THIS_TICK)) continue;
if ((world->sim_time_ns - ent->last_triggered_ns < NS_FROM_SECONDS(ent->trigger_delay)) && ent->last_triggered_ns != 0) continue; if ((world->sim_time_ns - ent->last_triggered_ns < NS_FROM_SECONDS(ent->trigger_delay)) && ent->last_triggered_ns != 0) continue;
@ -774,18 +769,17 @@ void sim_step(struct sim_step_ctx *ctx)
} }
/* ========================== * /* ========================== *
* Create motor joints from control move * Create & update motor joints from control move
* ========================== */ * ========================== */
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
struct sim_ent *ent = &world->ents[ent_index]; struct sim_ent *ent = &world->ents[ent_index];
if (!sim_ent_is_valid_and_active(ent)) continue;
if (!sim_ent_should_simulate(ent)) continue; if (!sim_ent_should_simulate(ent)) continue;
if (sim_ent_has_prop(ent, SIM_ENT_PROP_CONTROLLED)) { if (sim_ent_has_prop(ent, SIM_ENT_PROP_CONTROLLED)) {
struct sim_ent *joint_ent = sim_ent_from_id(world, ent->move_joint); struct sim_ent *joint_ent = sim_ent_from_id(world, ent->move_joint);
if (!sim_ent_is_valid_and_active(joint_ent)) { if (ctx->is_master && !sim_ent_is_valid_and_active(joint_ent)) {
joint_ent = sim_ent_alloc_local(root); joint_ent = sim_ent_alloc_sync_src(root);
joint_ent->mass_unscaled = F32_INFINITY; joint_ent->mass_unscaled = F32_INFINITY;
joint_ent->inertia_unscaled = F32_INFINITY; joint_ent->inertia_unscaled = F32_INFINITY;
sim_ent_enable_prop(joint_ent, SIM_ENT_PROP_MOTOR_JOINT); sim_ent_enable_prop(joint_ent, SIM_ENT_PROP_MOTOR_JOINT);
@ -799,21 +793,26 @@ void sim_step(struct sim_step_ctx *ctx)
def.max_force = ent->control_force; def.max_force = ent->control_force;
def.max_torque = 0; def.max_torque = 0;
joint_ent->motor_joint_data = phys_motor_joint_from_def(def); joint_ent->motor_joint_data = phys_motor_joint_from_def(def);
if (sim_ent_has_prop(ent, SIM_ENT_PROP_SYNC_PREDICT)) {
sim_ent_enable_prop(joint_ent, SIM_ENT_PROP_SYNC_PREDICT);
}
} }
sim_ent_set_xform(joint_ent, XFORM_IDENT); /* Reset joint ent position */ if (sim_ent_should_simulate(joint_ent)) {
sim_ent_set_linear_velocity(joint_ent, v2_mul(v2_clamp_len(ent->control.move, 1), ent->control_force_max_speed)); sim_ent_set_xform(joint_ent, XFORM_IDENT); /* Reset joint ent position */
sim_ent_set_linear_velocity(joint_ent, v2_mul(v2_clamp_len(ent->control.move, 1), ent->control_force_max_speed));
}
} }
} }
/* ========================== * /* ========================== *
* Create motor joints from control focus (aim) * Create & update motor joints from control focus (aim)
* ========================== */ * ========================== */
#if SIM_PLAYER_AIM #if SIM_PLAYER_AIM
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
struct sim_ent *ent = &world->ents[ent_index]; struct sim_ent *ent = &world->ents[ent_index];
if (!sim_ent_is_valid_and_active(ent)) continue;
if (!sim_ent_should_simulate(ent)) continue; if (!sim_ent_should_simulate(ent)) continue;
if (sim_ent_has_prop(ent, SIM_ENT_PROP_CONTROLLED)) { if (sim_ent_has_prop(ent, SIM_ENT_PROP_CONTROLLED)) {
@ -822,8 +821,8 @@ void sim_step(struct sim_step_ctx *ctx)
/* Retrieve / create aim joint */ /* Retrieve / create aim joint */
struct sim_ent *joint_ent = sim_ent_from_id(world, ent->aim_joint); struct sim_ent *joint_ent = sim_ent_from_id(world, ent->aim_joint);
if (!sim_ent_is_valid_and_active(joint_ent)) { if (ctx->is_master && !sim_ent_is_valid_and_active(joint_ent)) {
joint_ent = sim_ent_alloc_local(root); joint_ent = sim_ent_alloc_sync_src(root);
joint_ent->mass_unscaled = F32_INFINITY; joint_ent->mass_unscaled = F32_INFINITY;
joint_ent->inertia_unscaled = F32_INFINITY; joint_ent->inertia_unscaled = F32_INFINITY;
sim_ent_enable_prop(joint_ent, SIM_ENT_PROP_PHYSICAL_KINEMATIC); /* Since we'll be setting velocity manually */ sim_ent_enable_prop(joint_ent, SIM_ENT_PROP_PHYSICAL_KINEMATIC); /* Since we'll be setting velocity manually */
@ -837,66 +836,73 @@ void sim_step(struct sim_step_ctx *ctx)
def.max_force = 0; def.max_force = 0;
def.max_torque = ent->control_torque; def.max_torque = ent->control_torque;
joint_ent->motor_joint_data = phys_motor_joint_from_def(def); joint_ent->motor_joint_data = phys_motor_joint_from_def(def);
if (sim_ent_has_prop(ent, SIM_ENT_PROP_SYNC_PREDICT)) {
sim_ent_enable_prop(joint_ent, SIM_ENT_PROP_SYNC_PREDICT);
}
} }
/* Set correction rate dynamically since motor velocity is only set for one frame */ if (sim_ent_should_simulate(joint_ent)) {
joint_ent->motor_joint_data.correction_rate = 10 * sim_dt; /* Set correction rate dynamically since motor velocity is only set for one frame */
joint_ent->motor_joint_data.correction_rate = 10 * sim_dt;
/* Solve for final angle using law of sines */ /* Solve for final angle using law of sines */
f32 new_angle; f32 new_angle;
{
struct v2 ent_pos = xf.og;
struct v2 focus_pos = v2_add(ent_pos, ent->control.focus);
struct v2 sprite_hold_pos;
struct v2 sprite_hold_dir;
{ {
struct sprite_sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, ent->sprite); struct v2 ent_pos = xf.og;
struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, LIT("attach.wep"), ent->animation_frame); struct v2 focus_pos = v2_add(ent_pos, ent->control.focus);
sprite_hold_pos = slice.center;
sprite_hold_dir = slice.dir; struct v2 sprite_hold_pos;
struct v2 sprite_hold_dir;
{
struct sprite_sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, ent->sprite);
struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, LIT("attach.wep"), ent->animation_frame);
sprite_hold_pos = slice.center;
sprite_hold_dir = slice.dir;
}
struct v2 hold_dir = xform_basis_mul_v2(sprite_xf, sprite_hold_dir);
struct v2 hold_pos = xform_mul_v2(sprite_xf, sprite_hold_pos);
if (v2_eq(hold_pos, ent_pos)) {
/* If hold pos is same as origin (E.G if pivot is being used as hold pos), then move hold pos forward a tad to avoid issue */
sprite_hold_pos = v2_add(sprite_hold_pos, V2(0, -1));
hold_pos = xform_mul_v2(sprite_xf, sprite_hold_pos);
}
f32 forward_hold_angle_offset;
{
struct xform xf_unrotated = xform_basis_with_rotation_world(xf, 0);
struct v2 hold_pos_unrotated = xform_mul_v2(xf_unrotated, xform_mul_v2(ent->sprite_local_xform, sprite_hold_pos));
forward_hold_angle_offset = v2_angle_from_dirs(V2(0, -1), v2_sub(hold_pos_unrotated, xf_unrotated.og));
}
struct v2 hold_ent_dir = v2_sub(ent_pos, hold_pos);
struct v2 focus_ent_dir = v2_sub(ent_pos, focus_pos);
f32 hold_ent_len = v2_len(hold_ent_dir);
f32 focus_ent_len = v2_len(focus_ent_dir);
f32 final_hold_angle_btw_ent_and_focus = v2_angle_from_dirs(hold_ent_dir, hold_dir);
f32 final_focus_angle_btw_ent_and_hold = math_asin((math_sin(final_hold_angle_btw_ent_and_focus) * hold_ent_len) / focus_ent_len);
f32 final_ent_angle_btw_focus_and_hold = PI - (final_focus_angle_btw_ent_and_hold + final_hold_angle_btw_ent_and_focus);
new_angle = math_unwind_angle(v2_angle_from_dirs(V2(0, -1), v2_sub(focus_pos, ent_pos)) + final_ent_angle_btw_focus_and_hold - forward_hold_angle_offset);
} }
struct v2 hold_dir = xform_basis_mul_v2(sprite_xf, sprite_hold_dir); f32 new_vel = 0;
struct v2 hold_pos = xform_mul_v2(sprite_xf, sprite_hold_pos); if (!F32_IS_NAN(new_angle)) {
if (v2_eq(hold_pos, ent_pos)) { const f32 angle_error_allowed = 0.001f;
/* If hold pos is same as origin (E.G if pivot is being used as hold pos), then move hold pos forward a tad to avoid issue */ struct xform joint_xf = sim_ent_get_xform(joint_ent);
sprite_hold_pos = v2_add(sprite_hold_pos, V2(0, -1)); f32 diff = math_unwind_angle(new_angle - xform_get_rotation(joint_xf));
hold_pos = xform_mul_v2(sprite_xf, sprite_hold_pos); if (math_fabs(diff) > angle_error_allowed) {
/* Instantly snap joint ent to new angle */
new_vel = diff / sim_dt;
}
} }
sim_ent_set_angular_velocity(joint_ent, new_vel);
f32 forward_hold_angle_offset;
{
struct xform xf_unrotated = xform_basis_with_rotation_world(xf, 0);
struct v2 hold_pos_unrotated = xform_mul_v2(xf_unrotated, xform_mul_v2(ent->sprite_local_xform, sprite_hold_pos));
forward_hold_angle_offset = v2_angle_from_dirs(V2(0, -1), v2_sub(hold_pos_unrotated, xf_unrotated.og));
}
struct v2 hold_ent_dir = v2_sub(ent_pos, hold_pos);
struct v2 focus_ent_dir = v2_sub(ent_pos, focus_pos);
f32 hold_ent_len = v2_len(hold_ent_dir);
f32 focus_ent_len = v2_len(focus_ent_dir);
f32 final_hold_angle_btw_ent_and_focus = v2_angle_from_dirs(hold_ent_dir, hold_dir);
f32 final_focus_angle_btw_ent_and_hold = math_asin((math_sin(final_hold_angle_btw_ent_and_focus) * hold_ent_len) / focus_ent_len);
f32 final_ent_angle_btw_focus_and_hold = PI - (final_focus_angle_btw_ent_and_hold + final_hold_angle_btw_ent_and_focus);
new_angle = math_unwind_angle(v2_angle_from_dirs(V2(0, -1), v2_sub(focus_pos, ent_pos)) + final_ent_angle_btw_focus_and_hold - forward_hold_angle_offset);
} }
f32 new_vel = 0;
if (!F32_IS_NAN(new_angle)) {
const f32 angle_error_allowed = 0.001f;
struct xform joint_xf = sim_ent_get_xform(joint_ent);
f32 diff = math_unwind_angle(new_angle - xform_get_rotation(joint_xf));
if (math_fabs(diff) > angle_error_allowed) {
/* Instantly snap joint ent to new angle */
new_vel = diff / sim_dt;
}
}
sim_ent_set_angular_velocity(joint_ent, new_vel);
} }
} }
#endif #endif
@ -907,7 +913,6 @@ void sim_step(struct sim_step_ctx *ctx)
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
struct sim_ent *ent = &world->ents[ent_index]; struct sim_ent *ent = &world->ents[ent_index];
if (!sim_ent_is_valid_and_active(ent)) continue;
if (!sim_ent_should_simulate(ent)) continue; if (!sim_ent_should_simulate(ent)) continue;
if (!sim_ent_has_prop(ent, SIM_ENT_PROP_PHYSICAL_DYNAMIC)) continue; if (!sim_ent_has_prop(ent, SIM_ENT_PROP_PHYSICAL_DYNAMIC)) continue;
@ -920,12 +925,16 @@ void sim_step(struct sim_step_ctx *ctx)
def.max_force = ent->linear_ground_friction; def.max_force = ent->linear_ground_friction;
def.max_torque = ent->angular_ground_friction; def.max_torque = ent->angular_ground_friction;
if (joint_ent->motor_joint_data.max_force != def.max_force || joint_ent->motor_joint_data.max_torque != def.max_torque) { if (joint_ent->motor_joint_data.max_force != def.max_force || joint_ent->motor_joint_data.max_torque != def.max_torque) {
if (!sim_ent_is_valid_and_active(joint_ent)) { if (ctx->is_master && !sim_ent_is_valid_and_active(joint_ent)) {
joint_ent = sim_ent_alloc_local(root); joint_ent = sim_ent_alloc_sync_src(root);
sim_ent_enable_prop(joint_ent, SIM_ENT_PROP_MOTOR_JOINT); sim_ent_enable_prop(joint_ent, SIM_ENT_PROP_MOTOR_JOINT);
sim_ent_enable_prop(joint_ent, SIM_ENT_PROP_ACTIVE); sim_ent_enable_prop(joint_ent, SIM_ENT_PROP_ACTIVE);
joint_ent->motor_joint_data = phys_motor_joint_from_def(def); joint_ent->motor_joint_data = phys_motor_joint_from_def(def);
ent->ground_friction_joint = joint_ent->id; ent->ground_friction_joint = joint_ent->id;
if (sim_ent_has_prop(ent, SIM_ENT_PROP_SYNC_PREDICT)) {
sim_ent_enable_prop(ent, SIM_ENT_PROP_SYNC_PREDICT);
}
} }
} }
} }
@ -934,50 +943,51 @@ void sim_step(struct sim_step_ctx *ctx)
* Create mouse joints from client debug drag * Create mouse joints from client debug drag
* ========================== */ * ========================== */
for (u64 i = 0; i < world->num_ents_reserved; ++i) { if (ctx->is_master) {
struct sim_ent *client_ent = &world->ents[i]; for (u64 i = 0; i < world->num_ents_reserved; ++i) {
if (!sim_ent_is_valid_and_active(client_ent)) continue; struct sim_ent *client_ent = &world->ents[i];
if (!sim_ent_should_simulate(client_ent)) continue; if (!sim_ent_should_simulate(client_ent)) continue;
if (!sim_ent_has_prop(client_ent, SIM_ENT_PROP_CLIENT)) continue; if (!sim_ent_has_prop(client_ent, SIM_ENT_PROP_CLIENT)) continue;
struct v2 cursor = client_ent->client_cursor_pos; struct v2 cursor = client_ent->client_cursor_pos;
b32 start_dragging = client_ent->client_dbg_drag_start; b32 start_dragging = client_ent->client_dbg_drag_start;
b32 stop_dragging = client_ent->client_dbg_drag_stop; b32 stop_dragging = client_ent->client_dbg_drag_stop;
struct sim_ent *joint_ent = sim_ent_from_id(world, client_ent->client_dbg_drag_joint_ent); struct sim_ent *joint_ent = sim_ent_from_id(world, client_ent->client_dbg_drag_joint_ent);
struct sim_ent *target_ent = sim_ent_from_id(world, joint_ent->mouse_joint_data.target); struct sim_ent *target_ent = sim_ent_from_id(world, joint_ent->mouse_joint_data.target);
if (stop_dragging) { if (stop_dragging) {
target_ent = sim_ent_nil(); target_ent = sim_ent_nil();
} else if (start_dragging) { } else if (start_dragging) {
target_ent = sim_ent_from_id(world, client_ent->client_hovered_ent); target_ent = sim_ent_from_id(world, client_ent->client_hovered_ent);
}
if (sim_ent_is_valid_and_active(target_ent)) {
if (!sim_ent_is_valid_and_active(joint_ent)) {
/* FIXME: Joint ent may never release */
joint_ent = sim_ent_alloc_local(root);
joint_ent->mass_unscaled = F32_INFINITY;
joint_ent->inertia_unscaled = F32_INFINITY;
client_ent->client_dbg_drag_joint_ent = joint_ent->id;
sim_ent_enable_prop(joint_ent, SIM_ENT_PROP_MOUSE_JOINT);
sim_ent_enable_prop(joint_ent, SIM_ENT_PROP_ACTIVE);
} }
struct xform xf = sim_ent_get_xform(target_ent);
f32 mass = target_ent->mass_unscaled * math_fabs(xform_get_determinant(xf));
struct phys_mouse_joint_def def = ZI; if (sim_ent_should_simulate(target_ent)) {
def.target = target_ent->id; if (!sim_ent_is_valid_and_active(joint_ent)) {
if (sim_ent_id_eq(joint_ent->mouse_joint_data.target, target_ent->id)) { /* FIXME: Joint ent may never release */
def.point_local_start = joint_ent->mouse_joint_data.point_local_start; joint_ent = sim_ent_alloc_sync_src(root);
} else { joint_ent->mass_unscaled = F32_INFINITY;
def.point_local_start = xform_invert_mul_v2(xf, cursor); joint_ent->inertia_unscaled = F32_INFINITY;
client_ent->client_dbg_drag_joint_ent = joint_ent->id;
sim_ent_enable_prop(joint_ent, SIM_ENT_PROP_MOUSE_JOINT);
sim_ent_enable_prop(joint_ent, SIM_ENT_PROP_ACTIVE);
}
struct xform xf = sim_ent_get_xform(target_ent);
f32 mass = target_ent->mass_unscaled * math_fabs(xform_get_determinant(xf));
struct phys_mouse_joint_def def = ZI;
def.target = target_ent->id;
if (sim_ent_id_eq(joint_ent->mouse_joint_data.target, target_ent->id)) {
def.point_local_start = joint_ent->mouse_joint_data.point_local_start;
} else {
def.point_local_start = xform_invert_mul_v2(xf, cursor);
}
def.point_local_end = xform_invert_mul_v2(xf, cursor);
def.max_force = mass * 1000;
joint_ent->mouse_joint_data = phys_mouse_joint_from_def(def);
} else if (sim_ent_is_valid_and_active(joint_ent)) {
joint_ent->mouse_joint_data.target = target_ent->id;
} }
def.point_local_end = xform_invert_mul_v2(xf, cursor);
def.max_force = mass * 1000;
joint_ent->mouse_joint_data = phys_mouse_joint_from_def(def);
} else if (sim_ent_is_valid_and_active(joint_ent)) {
joint_ent->mouse_joint_data.target = target_ent->id;
} }
} }
@ -985,7 +995,7 @@ void sim_step(struct sim_step_ctx *ctx)
* Physics step * Physics step
* ========================== */ * ========================== */
if (ctx->is_master) { {
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 = on_collision; phys.pre_solve_callback = on_collision;
@ -998,7 +1008,6 @@ void sim_step(struct sim_step_ctx *ctx)
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
struct sim_ent *ent = &world->ents[ent_index]; struct sim_ent *ent = &world->ents[ent_index];
if (!sim_ent_is_valid_and_active(ent)) continue;
if (!sim_ent_should_simulate(ent)) continue; if (!sim_ent_should_simulate(ent)) continue;
if (!sim_ent_has_prop(ent, SIM_ENT_PROP_TRACER)) continue; if (!sim_ent_has_prop(ent, SIM_ENT_PROP_TRACER)) continue;
@ -1023,7 +1032,6 @@ void sim_step(struct sim_step_ctx *ctx)
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
struct sim_ent *ent = &world->ents[ent_index]; struct sim_ent *ent = &world->ents[ent_index];
if (!sim_ent_is_valid_and_active(ent)) continue;
if (!sim_ent_should_simulate(ent)) continue; if (!sim_ent_should_simulate(ent)) continue;
if (!sim_ent_has_prop(ent, SIM_ENT_PROP_BULLET)) continue; if (!sim_ent_has_prop(ent, SIM_ENT_PROP_BULLET)) continue;
@ -1052,7 +1060,7 @@ void sim_step(struct sim_step_ctx *ctx)
/* Initialize tracer */ /* Initialize tracer */
struct sim_ent *tracer = sim_ent_from_id(world, ent->bullet_tracer); struct sim_ent *tracer = sim_ent_from_id(world, ent->bullet_tracer);
if (sim_ent_is_valid_and_active(tracer)) { if (sim_ent_should_simulate(tracer)) {
sim_ent_set_xform(tracer, xf); sim_ent_set_xform(tracer, xf);
sim_ent_enable_prop(tracer, SIM_ENT_PROP_PHYSICAL_KINEMATIC); sim_ent_enable_prop(tracer, SIM_ENT_PROP_PHYSICAL_KINEMATIC);
sim_ent_set_linear_velocity(tracer, ent->linear_velocity); sim_ent_set_linear_velocity(tracer, ent->linear_velocity);
@ -1079,7 +1087,6 @@ void sim_step(struct sim_step_ctx *ctx)
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
struct sim_ent *ent = &world->ents[ent_index]; struct sim_ent *ent = &world->ents[ent_index];
if (!sim_ent_is_valid_and_active(ent)) continue;
if (!sim_ent_should_simulate(ent)) continue; if (!sim_ent_should_simulate(ent)) continue;
if (!sim_ent_has_prop(ent, SIM_ENT_PROP_CAMERA)) continue; if (!sim_ent_has_prop(ent, SIM_ENT_PROP_CAMERA)) continue;
@ -1121,7 +1128,7 @@ void sim_step(struct sim_step_ctx *ctx)
ent->shake = 0; ent->shake = 0;
for (u64 quake_ent_index = 0; quake_ent_index < world->num_ents_reserved; ++quake_ent_index) { for (u64 quake_ent_index = 0; quake_ent_index < world->num_ents_reserved; ++quake_ent_index) {
struct sim_ent *quake = &world->ents[quake_ent_index]; struct sim_ent *quake = &world->ents[quake_ent_index];
if (!sim_ent_is_valid_and_active(quake)) continue; if (!sim_ent_should_simulate(quake)) continue;
if (!sim_ent_has_prop(quake, SIM_ENT_PROP_QUAKE)) continue; if (!sim_ent_has_prop(quake, SIM_ENT_PROP_QUAKE)) continue;
ent->shake += quake->quake_intensity; ent->shake += quake->quake_intensity;
} }
@ -1136,7 +1143,6 @@ void sim_step(struct sim_step_ctx *ctx)
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
struct sim_ent *ent = &world->ents[ent_index]; struct sim_ent *ent = &world->ents[ent_index];
if (!sim_ent_is_valid_and_active(ent)) continue;
if (!sim_ent_should_simulate(ent)) continue; if (!sim_ent_should_simulate(ent)) continue;
if (!sim_ent_has_prop(ent, SIM_ENT_PROP_QUAKE)) continue; if (!sim_ent_has_prop(ent, SIM_ENT_PROP_QUAKE)) continue;
@ -1164,7 +1170,7 @@ void sim_step(struct sim_step_ctx *ctx)
i32 parent_layer = parent->final_layer; i32 parent_layer = parent->final_layer;
for (struct sim_ent *child = sim_ent_from_id(world, parent->first); child->valid; child = sim_ent_from_id(world, child->next)) { for (struct sim_ent *child = sim_ent_from_id(world, parent->first); child->valid; child = sim_ent_from_id(world, child->next)) {
if (sim_ent_is_valid_and_active(child) && sim_ent_should_simulate(child)) { if (sim_ent_should_simulate(child)) {
child->final_layer = parent_layer + child->layer; child->final_layer = parent_layer + child->layer;
*arena_push(temp.arena, struct sim_ent *) = child; *arena_push(temp.arena, struct sim_ent *) = child;
++stack_count; ++stack_count;

View File

@ -363,7 +363,7 @@ INTERNAL struct string get_ent_debug_text(struct arena *arena, struct sim_ent *e
res.len += string_copy(arena, LIT(" local")).len; res.len += string_copy(arena, LIT(" local")).len;
} }
res.len += string_copy(arena, LIT("\n")).len; res.len += string_copy(arena, LIT("\n\n")).len;
} }
{ {
@ -391,6 +391,17 @@ INTERNAL struct string get_ent_debug_text(struct arena *arena, struct sim_ent *e
res.len += string_format(arena, LIT("next: [%F]\n"), FMT_UID(ent->next.uid)).len; res.len += string_format(arena, LIT("next: [%F]\n"), FMT_UID(ent->next.uid)).len;
} }
res.len += string_copy(arena, LIT("\n")).len;
/* Pos */
struct xform xf = sim_ent_get_xform(ent);
struct v2 linear_velocity = ent->linear_velocity;
f32 angular_velocity = ent->angular_velocity;
res.len += string_format(arena, LIT("pos: (%F, %F)\n"), FMT_FLOAT_P(xf.og.x, 3), FMT_FLOAT_P(xf.og.y, 3)).len;
res.len += string_format(arena, LIT("linear velocity: (%F, %F)\n"), FMT_FLOAT_P(linear_velocity.x, 3), FMT_FLOAT_P(linear_velocity.y, 3)).len;
res.len += string_format(arena, LIT("angular velocity: %F\n"), FMT_FLOAT_P(angular_velocity, 3)).len;
/* Children */
if (!sim_ent_id_eq(ent->first, SIM_ENT_NIL_ID) || !sim_ent_id_eq(ent->last, SIM_ENT_NIL_ID)) { if (!sim_ent_id_eq(ent->first, SIM_ENT_NIL_ID) || !sim_ent_id_eq(ent->last, SIM_ENT_NIL_ID)) {
struct sim_ent *child = sim_ent_from_id(ss, ent->first); struct sim_ent *child = sim_ent_from_id(ss, ent->first);
if (!sim_ent_id_eq(ent->first, ent->last) || !child->valid) { if (!sim_ent_id_eq(ent->first, ent->last) || !child->valid) {
@ -398,7 +409,8 @@ INTERNAL struct string get_ent_debug_text(struct arena *arena, struct sim_ent *e
res.len += string_format(arena, LIT("last child: [%F]\n"), FMT_UID(ent->last.uid)).len; res.len += string_format(arena, LIT("last child: [%F]\n"), FMT_UID(ent->last.uid)).len;
} }
while (child->valid) { while (child->valid) {
res.len += string_copy(arena, LIT("\nCHILD\n")).len; res.len += string_copy(arena, LIT("\n---------------------------------\n")).len;
res.len += string_copy(arena, LIT("CHILD\n")).len;
struct string child_text = get_ent_debug_text(scratch.arena, child); struct string child_text = get_ent_debug_text(scratch.arena, child);
res.len += string_indent(arena, child_text, 4).len; res.len += string_indent(arena, child_text, 4).len;
child = sim_ent_from_id(ss, child->next); child = sim_ent_from_id(ss, child->next);
@ -2052,6 +2064,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
if (!control_cmd_ent->valid) { if (!control_cmd_ent->valid) {
control_cmd_ent = sim_ent_alloc_sync_src(user_input_root); control_cmd_ent = sim_ent_alloc_sync_src(user_input_root);
sim_ent_enable_prop(control_cmd_ent, SIM_ENT_PROP_CMD_CONTROL); sim_ent_enable_prop(control_cmd_ent, SIM_ENT_PROP_CMD_CONTROL);
sim_ent_enable_prop(control_cmd_ent, SIM_ENT_PROP_SYNC_PREDICT);
sim_ent_activate(control_cmd_ent, user_input_ss->tick); sim_ent_activate(control_cmd_ent, user_input_ss->tick);
} }
/* Update local control cmd ent */ /* Update local control cmd ent */
@ -2082,9 +2095,12 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
client_ent = sim_ent_alloc_sync_src(local_root); client_ent = sim_ent_alloc_sync_src(local_root);
client_ent->client_handle = client->handle; client_ent->client_handle = client->handle;
sim_ent_enable_prop(client_ent, SIM_ENT_PROP_CLIENT); sim_ent_enable_prop(client_ent, SIM_ENT_PROP_CLIENT);
sim_ent_enable_prop(client_ent, SIM_ENT_PROP_SYNC_PREDICT);
sim_ent_enable_prop(client_ent, SIM_ENT_PROP_ACTIVE); sim_ent_enable_prop(client_ent, SIM_ENT_PROP_ACTIVE);
client->ent_id = client_ent->id; client->ent_id = client_ent->id;
if (client == user_input_client) { if (client == user_input_client) {
user_input_client->ent_id = client_ent->id;
local_client->ent_id = client_ent->id;
local_ss->local_client_ent = client_ent->id; local_ss->local_client_ent = client_ent->id;
} }
} }
@ -2097,6 +2113,8 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
if (client_ss->valid) { if (client_ss->valid) {
sim_snapshot_sync(local_ss, client_ss); sim_snapshot_sync(local_ss, client_ss);
if (!is_master && client == master_client) { if (!is_master && client == master_client) {
user_input_client->ent_id = client_ss->local_client_ent;
local_client->ent_id = client_ss->local_client_ent;
local_ss->local_client_ent = client_ss->local_client_ent; local_ss->local_client_ent = client_ss->local_client_ent;
} }
} }
@ -2105,23 +2123,13 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
} }
} }
if (is_master) { /* Point cmds to correct client ents */
/* Point incoming client cmds to correct client ents */ for (u64 i = 0; i < local_ss->num_ents_reserved; ++i) {
for (u64 i = 0; i < local_ss->num_ents_reserved; ++i) { struct sim_ent *ent = &local_ss->ents[i];
struct sim_ent *ent = &local_ss->ents[i]; if (ent->valid && sim_ent_has_prop(ent, SIM_ENT_PROP_CMD_CONTROL) && sim_ent_has_prop(ent, SIM_ENT_PROP_SYNC_DST)) {
if (ent->valid && sim_ent_has_prop(ent, SIM_ENT_PROP_SYNC_DST)) { struct sim_client *src_client = sim_client_from_handle(store, ent->sync_src_client);
struct sim_client *src_client = sim_client_from_handle(store, ent->sync_src_client); struct sim_ent *client_ent = sim_ent_from_id(local_ss, src_client->ent_id);
struct sim_ent *client_ent = sim_ent_from_id(local_ss, src_client->ent_id); ent->cmd_client = client_ent->id;
ent->cmd_client = client_ent->id;
}
}
} else {
/* Mark all local commands as networked */
for (u64 i = 0; i < local_ss->num_ents_reserved; ++i) {
struct sim_ent *ent = &local_ss->ents[i];
if (ent->valid && sim_ent_has_prop(ent, SIM_ENT_PROP_CMD_CONTROL) && sim_ent_has_prop(ent, SIM_ENT_PROP_SYNC_DST)) {
sim_ent_enable_prop(ent, SIM_ENT_PROP_SYNC_SRC);
}
} }
} }
@ -2164,46 +2172,13 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
} }
} }
#if 0
#if 0
u64 oldest_client_ack = 0;
for (u64 i = 0; i < store->num_clients_reserved; ++i) {
struct sim_client *client = &store->clients[i];
enum sim_client_kind kind = client->kind;
if (client->valid && kind != SIM_CLIENT_KIND_LOCAL_SIM) {
u64 ack = client->ack;
u64 double_ack = client->double_ack;
if (double_ack > 1) {
sim_snapshot_release_ticks_in_range(client, 0, double_ack - 1);
}
if (ack < oldest_client_ack || oldest_client_ack == 0) {
oldest_client_ack = ack;
}
}
}
if (oldest_client_ack > 1) {
sim_snapshot_release_ticks_in_range(local_client, 0, oldest_client_ack - 1);
}
#else
for (u64 i = 0; i < store->num_clients_reserved; ++i) {
struct sim_client *client = &store->clients[i];
if (client->valid) {
if (client->is_remote) {
u64 double_ack = client->double_ack;
if (double_ack > 1) {
sim_snapshot_release_ticks_in_range(client, 0, double_ack - 1);
}
} else {
u64 keep_ticks_count = 500;
if (step_tick > keep_ticks_count) {
u64 keep_tick = client->last_tick - keep_ticks_count;
sim_snapshot_release_ticks_in_range(client, 0, keep_tick);
}
}
}
}
#endif
#endif
/* Step */ /* Step */
{ {
@ -2220,6 +2195,21 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
/* Signal any locally created CMDs as sync sources */
for (u64 i = 0; i < local_ss->num_ents_reserved; ++i) {
struct sim_ent *ent = &local_ss->ents[i];
if (sim_ent_is_valid_and_active(ent) && sim_ent_has_prop(ent, SIM_ENT_PROP_CMD_CONTROL)) {
if (!sim_ent_id_eq(ent->cmd_client, SIM_ENT_NIL_ID) && sim_ent_id_eq(ent->cmd_client, local_ss->local_client_ent)) {
sim_ent_enable_prop(ent, SIM_ENT_PROP_SYNC_SRC);
}
}
}
@ -2229,15 +2219,6 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
/* Construct publishable snapshot */ /* Construct publishable snapshot */
#if 0
{
if (is_master) {
//struct sim_snapshot *prev_pub_ss = sim_snapshot_from_tick(publish_client, publish_client->last_tick);
struct sim_snapshot *pub_ss = sim_snapshot_alloc(publish_client, local_ss, local_ss->tick);
(UNUSED)pub_ss;
}
}
#else
{ {
struct sim_snapshot *pub_ss; struct sim_snapshot *pub_ss;
if (is_master) { if (is_master) {
@ -2247,7 +2228,6 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
} }
sim_snapshot_sync(pub_ss, local_ss); sim_snapshot_sync(pub_ss, local_ss);
} }
#endif