prediction progress

This commit is contained in:
jacob 2025-02-25 14:02:59 -06:00
parent a6d103f391
commit 2769e98450
9 changed files with 69 additions and 51 deletions

View File

@ -173,6 +173,8 @@ struct buddy_block *buddy_alloc(struct buddy_ctx *ctx, u64 size)
/* TODO: Minimum block size */ /* TODO: Minimum block size */
/* TODO: Faster MSB calculation */
u64 desired_block_size = 1; u64 desired_block_size = 1;
u64 desired_level_tier = 0; u64 desired_level_tier = 0;
while (desired_block_size < size && desired_level_tier < 64) { while (desired_block_size < size && desired_level_tier < 64) {

View File

@ -16,7 +16,7 @@ struct buddy_block {
struct buddy_level { struct buddy_level {
struct buddy_ctx *ctx; struct buddy_ctx *ctx;
b32 backed; /* Is this level backed by memory in the ctx arena */ b32 backed; /* Signals whether this level is backed by memory in the ctx arena */
u32 tier; u32 tier;
u64 size; u64 size;
struct buddy_block *first_unused_block; struct buddy_block *first_unused_block;

View File

@ -661,7 +661,7 @@ void host_update(struct host *host)
struct sock_address address = packet->address; struct sock_address address = packet->address;
struct bitbuff bb = bitbuff_from_string(packet->data); struct bitbuff bb = bitbuff_from_string(packet->data);
struct bitbuff_reader br = br_from_bitbuff(&bb); struct bitbuff_reader br = br_from_bitbuff(&bb);
u32 magic = br_read_ubits(&br, 32); u32 magic = br_read_ubits(&br, 32); /* TODO: implicitly encode magic into crc32 */
if (magic == PACKET_MAGIC) { if (magic == PACKET_MAGIC) {
/* TODO: Combine kind byte with flags byte */ /* TODO: Combine kind byte with flags byte */
struct host_channel *channel = host_channel_from_address(host, address); struct host_channel *channel = host_channel_from_address(host, address);
@ -864,7 +864,7 @@ void host_update(struct host *host)
struct host_snd_packet *packet = host_channel_snd_packet_alloc(channel, false); struct host_snd_packet *packet = host_channel_snd_packet_alloc(channel, false);
struct bitbuff bb = bitbuff_from_string(STRING_FROM_ARRAY(packet->data)); struct bitbuff bb = bitbuff_from_string(STRING_FROM_ARRAY(packet->data));
struct bitbuff_writer bw = bw_from_bitbuff(&bb); struct bitbuff_writer bw = bw_from_bitbuff(&bb);
bw_write_ubits(&bw, PACKET_MAGIC, 32); bw_write_ubits(&bw, PACKET_MAGIC, 32); /* TODO: implicitly encode magic into crc32 */
bw_write_ibits(&bw, HOST_PACKET_KIND_TRY_CONNECT, 8); bw_write_ibits(&bw, HOST_PACKET_KIND_TRY_CONNECT, 8);
bw_write_ubits(&bw, packet_flags, 8); bw_write_ubits(&bw, packet_flags, 8);
bw_write_uv(&bw, channel->our_acked_seq); bw_write_uv(&bw, channel->our_acked_seq);
@ -877,7 +877,7 @@ void host_update(struct host *host)
struct host_snd_packet *packet = host_channel_snd_packet_alloc(channel, false); struct host_snd_packet *packet = host_channel_snd_packet_alloc(channel, false);
struct bitbuff bb = bitbuff_from_string(STRING_FROM_ARRAY(packet->data)); struct bitbuff bb = bitbuff_from_string(STRING_FROM_ARRAY(packet->data));
struct bitbuff_writer bw = bw_from_bitbuff(&bb); struct bitbuff_writer bw = bw_from_bitbuff(&bb);
bw_write_ubits(&bw, PACKET_MAGIC, 32); bw_write_ubits(&bw, PACKET_MAGIC, 32); /* TODO: implicitly encode magic into crc32 */
bw_write_ibits(&bw, HOST_PACKET_KIND_CONNECT_SUCCESS, 8); bw_write_ibits(&bw, HOST_PACKET_KIND_CONNECT_SUCCESS, 8);
bw_write_ubits(&bw, packet_flags, 8); bw_write_ubits(&bw, packet_flags, 8);
bw_write_uv(&bw, channel->our_acked_seq); bw_write_uv(&bw, channel->our_acked_seq);
@ -890,7 +890,7 @@ void host_update(struct host *host)
struct host_snd_packet *packet = host_channel_snd_packet_alloc(channel, false); struct host_snd_packet *packet = host_channel_snd_packet_alloc(channel, false);
struct bitbuff bb = bitbuff_from_string(STRING_FROM_ARRAY(packet->data)); struct bitbuff bb = bitbuff_from_string(STRING_FROM_ARRAY(packet->data));
struct bitbuff_writer bw = bw_from_bitbuff(&bb); struct bitbuff_writer bw = bw_from_bitbuff(&bb);
bw_write_ubits(&bw, PACKET_MAGIC, 32); bw_write_ubits(&bw, PACKET_MAGIC, 32); /* TODO: implicitly encode magic into crc32 */
bw_write_ibits(&bw, HOST_PACKET_KIND_DISCONNECT, 8); bw_write_ibits(&bw, HOST_PACKET_KIND_DISCONNECT, 8);
bw_write_ubits(&bw, packet_flags, 8); bw_write_ubits(&bw, packet_flags, 8);
bw_write_uv(&bw, channel->our_acked_seq); bw_write_uv(&bw, channel->our_acked_seq);
@ -922,7 +922,7 @@ void host_update(struct host *host)
struct host_snd_packet *packet = host_channel_snd_packet_alloc(channel, is_reliable); struct host_snd_packet *packet = host_channel_snd_packet_alloc(channel, is_reliable);
struct bitbuff bb = bitbuff_from_string(STRING_FROM_ARRAY(packet->data)); struct bitbuff bb = bitbuff_from_string(STRING_FROM_ARRAY(packet->data));
struct bitbuff_writer bw = bw_from_bitbuff(&bb); struct bitbuff_writer bw = bw_from_bitbuff(&bb);
bw_write_ubits(&bw, PACKET_MAGIC, 32); bw_write_ubits(&bw, PACKET_MAGIC, 32); /* TODO: implicitly encode magic into crc32 */
bw_write_ibits(&bw, HOST_PACKET_KIND_MSG_CHUNK, 8); bw_write_ibits(&bw, HOST_PACKET_KIND_MSG_CHUNK, 8);
bw_write_ubits(&bw, packet_flags, 8); bw_write_ubits(&bw, packet_flags, 8);
bw_write_uv(&bw, channel->our_acked_seq); bw_write_uv(&bw, channel->our_acked_seq);

View File

@ -53,7 +53,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_should_simulate(check0)) continue;
if (!(sim_ent_has_prop(check0, SIM_ENT_PROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(check0, SIM_ENT_PROP_PHYSICAL_KINEMATIC))) continue; if (!(sim_ent_has_prop(check0, SIM_ENT_PROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(check0, SIM_ENT_PROP_PHYSICAL_KINEMATIC))) continue;
if (check0->local_collider.count <= 0) continue; if (check0->local_collider.count <= 0) continue;
@ -66,7 +66,7 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a
while ((space_entry = space_iter_next(&iter))) { while ((space_entry = space_iter_next(&iter))) {
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_should_simulate(check1)) continue;
if (!(sim_ent_has_prop(check1, SIM_ENT_PROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(check1, SIM_ENT_PROP_PHYSICAL_KINEMATIC))) continue; if (!(sim_ent_has_prop(check1, SIM_ENT_PROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(check1, SIM_ENT_PROP_PHYSICAL_KINEMATIC))) continue;
if (check1->local_collider.count <= 0) continue; if (check1->local_collider.count <= 0) continue;
@ -274,7 +274,7 @@ void phys_prepare_contacts(struct phys_step_ctx *ctx, u64 phys_iteration)
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
struct sim_ent *constraint_ent = &ss->ents[sim_ent_index]; struct sim_ent *constraint_ent = &ss->ents[sim_ent_index];
if (!sim_ent_is_valid_and_active(constraint_ent)) continue; if (!sim_ent_should_simulate(constraint_ent)) continue;
if (!sim_ent_has_prop(constraint_ent, SIM_ENT_PROP_CONTACT_CONSTRAINT)) continue; if (!sim_ent_has_prop(constraint_ent, SIM_ENT_PROP_CONTACT_CONSTRAINT)) continue;
struct phys_contact_constraint *constraint = &constraint_ent->contact_constraint_data; struct phys_contact_constraint *constraint = &constraint_ent->contact_constraint_data;
@ -282,7 +282,7 @@ void phys_prepare_contacts(struct phys_step_ctx *ctx, u64 phys_iteration)
u32 num_points = constraint->num_points; u32 num_points = constraint->num_points;
struct sim_ent *e0 = sim_ent_from_id(ss, constraint->e0); struct sim_ent *e0 = sim_ent_from_id(ss, constraint->e0);
struct sim_ent *e1 = sim_ent_from_id(ss, constraint->e1); struct sim_ent *e1 = sim_ent_from_id(ss, constraint->e1);
if (constraint->last_phys_iteration >= phys_iteration && num_points > 0 && sim_ent_is_valid_and_active(e0) && sim_ent_is_valid_and_active(e1)) { if (constraint->last_phys_iteration >= phys_iteration && num_points > 0 && sim_ent_should_simulate(e0) && sim_ent_should_simulate(e1)) {
struct v2 normal = constraint->normal; struct v2 normal = constraint->normal;
struct v2 tangent = v2_perp(normal); struct v2 tangent = v2_perp(normal);
@ -392,7 +392,7 @@ void phys_warm_start_contacts(struct phys_step_ctx *ctx)
struct sim_snapshot *ss = ctx->sim_step_ctx->world; struct sim_snapshot *ss = ctx->sim_step_ctx->world;
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
struct sim_ent *constraint_ent = &ss->ents[sim_ent_index]; struct sim_ent *constraint_ent = &ss->ents[sim_ent_index];
if (!sim_ent_is_valid_and_active(constraint_ent)) continue; if (!sim_ent_should_simulate(constraint_ent)) continue;
if (!sim_ent_has_prop(constraint_ent, SIM_ENT_PROP_CONTACT_CONSTRAINT)) continue; if (!sim_ent_has_prop(constraint_ent, SIM_ENT_PROP_CONTACT_CONSTRAINT)) continue;
struct phys_contact_constraint *constraint = &constraint_ent->contact_constraint_data; struct phys_contact_constraint *constraint = &constraint_ent->contact_constraint_data;
@ -401,7 +401,7 @@ void phys_warm_start_contacts(struct phys_step_ctx *ctx)
struct sim_ent *e0 = sim_ent_from_id(ss, constraint->e0); struct sim_ent *e0 = sim_ent_from_id(ss, constraint->e0);
struct sim_ent *e1 = sim_ent_from_id(ss, constraint->e1); struct sim_ent *e1 = sim_ent_from_id(ss, constraint->e1);
if (num_points > 0 && sim_ent_is_valid_and_active(e0) && sim_ent_is_valid_and_active(e1) && !constraint->skip_solve) { if (num_points > 0 && sim_ent_should_simulate(e0) && sim_ent_should_simulate(e1) && !constraint->skip_solve) {
struct xform e0_xf = sim_ent_get_xform(e0); struct xform e0_xf = sim_ent_get_xform(e0);
struct xform e1_xf = sim_ent_get_xform(e1); struct xform e1_xf = sim_ent_get_xform(e1);
@ -447,7 +447,7 @@ void phys_solve_contacts(struct phys_step_ctx *ctx, f32 dt, b32 apply_bias)
struct sim_snapshot *ss = ctx->sim_step_ctx->world; struct sim_snapshot *ss = ctx->sim_step_ctx->world;
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
struct sim_ent *constraint_ent = &ss->ents[sim_ent_index]; struct sim_ent *constraint_ent = &ss->ents[sim_ent_index];
if (!sim_ent_is_valid_and_active(constraint_ent)) continue; if (!sim_ent_should_simulate(constraint_ent)) continue;
if (!sim_ent_has_prop(constraint_ent, SIM_ENT_PROP_CONTACT_CONSTRAINT)) continue; if (!sim_ent_has_prop(constraint_ent, SIM_ENT_PROP_CONTACT_CONSTRAINT)) continue;
struct phys_contact_constraint *constraint = &constraint_ent->contact_constraint_data; struct phys_contact_constraint *constraint = &constraint_ent->contact_constraint_data;
@ -461,7 +461,7 @@ void phys_solve_contacts(struct phys_step_ctx *ctx, f32 dt, b32 apply_bias)
f32 w1 = e1->angular_velocity; f32 w1 = e1->angular_velocity;
u32 num_points = constraint->num_points; u32 num_points = constraint->num_points;
if (num_points > 0 && sim_ent_is_valid_and_active(e0) && sim_ent_is_valid_and_active(e1) && !constraint->skip_solve) { if (num_points > 0 && sim_ent_should_simulate(e0) && sim_ent_should_simulate(e1) && !constraint->skip_solve) {
struct xform e0_xf = sim_ent_get_xform(e0); struct xform e0_xf = sim_ent_get_xform(e0);
struct xform e1_xf = sim_ent_get_xform(e1); struct xform e1_xf = sim_ent_get_xform(e1);
@ -578,7 +578,7 @@ void phys_prepare_motor_joints(struct phys_step_ctx *ctx)
struct sim_snapshot *ss = ctx->sim_step_ctx->world; struct sim_snapshot *ss = ctx->sim_step_ctx->world;
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
struct sim_ent *joint_ent = &ss->ents[sim_ent_index]; struct sim_ent *joint_ent = &ss->ents[sim_ent_index];
if (!sim_ent_is_valid_and_active(joint_ent)) continue; if (!sim_ent_should_simulate(joint_ent)) continue;
if (!sim_ent_has_prop(joint_ent, SIM_ENT_PROP_MOTOR_JOINT)) continue; if (!sim_ent_has_prop(joint_ent, SIM_ENT_PROP_MOTOR_JOINT)) continue;
struct phys_motor_joint *joint = &joint_ent->motor_joint_data; struct phys_motor_joint *joint = &joint_ent->motor_joint_data;
@ -586,7 +586,7 @@ void phys_prepare_motor_joints(struct phys_step_ctx *ctx)
struct sim_ent *e0 = sim_ent_from_id(ss, joint->e0); struct sim_ent *e0 = sim_ent_from_id(ss, joint->e0);
struct sim_ent *e1 = sim_ent_from_id(ss, joint->e1); struct sim_ent *e1 = sim_ent_from_id(ss, joint->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)) {
struct xform e0_xf = sim_ent_get_xform(e0); struct xform e0_xf = sim_ent_get_xform(e0);
struct xform e1_xf = sim_ent_get_xform(e1); struct xform e1_xf = sim_ent_get_xform(e1);
@ -642,7 +642,7 @@ void phys_warm_start_motor_joints(struct phys_step_ctx *ctx)
struct sim_snapshot *ss = ctx->sim_step_ctx->world; struct sim_snapshot *ss = ctx->sim_step_ctx->world;
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
struct sim_ent *joint_ent = &ss->ents[sim_ent_index]; struct sim_ent *joint_ent = &ss->ents[sim_ent_index];
if (!sim_ent_is_valid_and_active(joint_ent)) continue; if (!sim_ent_should_simulate(joint_ent)) continue;
if (!sim_ent_has_prop(joint_ent, SIM_ENT_PROP_MOTOR_JOINT)) continue; if (!sim_ent_has_prop(joint_ent, SIM_ENT_PROP_MOTOR_JOINT)) continue;
struct phys_motor_joint *joint = &joint_ent->motor_joint_data; struct phys_motor_joint *joint = &joint_ent->motor_joint_data;
@ -674,7 +674,7 @@ void phys_solve_motor_joints(struct phys_step_ctx *ctx, f32 dt)
struct sim_snapshot *ss = ctx->sim_step_ctx->world; struct sim_snapshot *ss = ctx->sim_step_ctx->world;
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
struct sim_ent *joint_ent = &ss->ents[sim_ent_index]; struct sim_ent *joint_ent = &ss->ents[sim_ent_index];
if (!sim_ent_is_valid_and_active(joint_ent)) continue; if (!sim_ent_should_simulate(joint_ent)) continue;
if (!sim_ent_has_prop(joint_ent, SIM_ENT_PROP_MOTOR_JOINT)) continue; if (!sim_ent_has_prop(joint_ent, SIM_ENT_PROP_MOTOR_JOINT)) continue;
struct phys_motor_joint *joint = &joint_ent->motor_joint_data; struct phys_motor_joint *joint = &joint_ent->motor_joint_data;
@ -767,12 +767,12 @@ void phys_prepare_mouse_joints(struct phys_step_ctx *ctx)
struct sim_snapshot *ss = ctx->sim_step_ctx->world; struct sim_snapshot *ss = ctx->sim_step_ctx->world;
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
struct sim_ent *joint_ent = &ss->ents[sim_ent_index]; struct sim_ent *joint_ent = &ss->ents[sim_ent_index];
if (!sim_ent_is_valid_and_active(joint_ent)) continue; if (!sim_ent_should_simulate(joint_ent)) continue;
if (!sim_ent_has_prop(joint_ent, SIM_ENT_PROP_MOUSE_JOINT)) continue; if (!sim_ent_has_prop(joint_ent, SIM_ENT_PROP_MOUSE_JOINT)) continue;
struct phys_mouse_joint *joint = &joint_ent->mouse_joint_data; struct phys_mouse_joint *joint = &joint_ent->mouse_joint_data;
struct sim_ent *ent = sim_ent_from_id(ss, joint->target); struct sim_ent *ent = sim_ent_from_id(ss, joint->target);
if (sim_ent_is_valid_and_active(ent)) { if (sim_ent_should_simulate(ent)) {
struct xform xf = sim_ent_get_xform(ent); struct xform xf = sim_ent_get_xform(ent);
/* TODO: Cache this */ /* TODO: Cache this */
@ -814,12 +814,12 @@ void phys_warm_start_mouse_joints(struct phys_step_ctx *ctx)
struct sim_snapshot *ss = ctx->sim_step_ctx->world; struct sim_snapshot *ss = ctx->sim_step_ctx->world;
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
struct sim_ent *joint_ent = &ss->ents[sim_ent_index]; struct sim_ent *joint_ent = &ss->ents[sim_ent_index];
if (!sim_ent_is_valid_and_active(joint_ent)) continue; if (!sim_ent_should_simulate(joint_ent)) continue;
if (!sim_ent_has_prop(joint_ent, SIM_ENT_PROP_MOUSE_JOINT)) continue; if (!sim_ent_has_prop(joint_ent, SIM_ENT_PROP_MOUSE_JOINT)) continue;
struct phys_mouse_joint *joint = &joint_ent->mouse_joint_data; struct phys_mouse_joint *joint = &joint_ent->mouse_joint_data;
struct sim_ent *ent = sim_ent_from_id(ss, joint->target); struct sim_ent *ent = sim_ent_from_id(ss, joint->target);
if (sim_ent_is_valid_and_active(ent)) { if (sim_ent_should_simulate(ent)) {
f32 inv_m = joint->inv_m; f32 inv_m = joint->inv_m;
f32 inv_i = joint->inv_i; f32 inv_i = joint->inv_i;
struct xform xf = sim_ent_get_xform(ent); struct xform xf = sim_ent_get_xform(ent);
@ -836,12 +836,12 @@ void phys_solve_mouse_joints(struct phys_step_ctx *ctx, f32 dt)
struct sim_snapshot *ss = ctx->sim_step_ctx->world; struct sim_snapshot *ss = ctx->sim_step_ctx->world;
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
struct sim_ent *joint_ent = &ss->ents[sim_ent_index]; struct sim_ent *joint_ent = &ss->ents[sim_ent_index];
if (!sim_ent_is_valid_and_active(joint_ent)) continue; if (!sim_ent_should_simulate(joint_ent)) continue;
if (!sim_ent_has_prop(joint_ent, SIM_ENT_PROP_MOUSE_JOINT)) continue; if (!sim_ent_has_prop(joint_ent, SIM_ENT_PROP_MOUSE_JOINT)) continue;
struct phys_mouse_joint *joint = &joint_ent->mouse_joint_data; struct phys_mouse_joint *joint = &joint_ent->mouse_joint_data;
struct sim_ent *ent = sim_ent_from_id(ss, joint->target); struct sim_ent *ent = sim_ent_from_id(ss, joint->target);
if (sim_ent_is_valid_and_active(ent)) { if (sim_ent_should_simulate(ent)) {
struct v2 v = ent->linear_velocity; struct v2 v = ent->linear_velocity;
f32 w = ent->angular_velocity; f32 w = ent->angular_velocity;
@ -923,7 +923,7 @@ void phys_integrate_forces(struct phys_step_ctx *ctx, f32 dt)
struct sim_snapshot *ss = ctx->sim_step_ctx->world; struct sim_snapshot *ss = ctx->sim_step_ctx->world;
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
struct sim_ent *ent = &ss->ents[sim_ent_index]; struct sim_ent *ent = &ss->ents[sim_ent_index];
if (!sim_ent_is_valid_and_active(ent)) continue; if (!sim_ent_should_simulate(ent)) continue;
b32 is_dynamic = sim_ent_has_prop(ent, SIM_ENT_PROP_PHYSICAL_DYNAMIC); b32 is_dynamic = sim_ent_has_prop(ent, SIM_ENT_PROP_PHYSICAL_DYNAMIC);
b32 is_kinematic = sim_ent_has_prop(ent, SIM_ENT_PROP_PHYSICAL_KINEMATIC); b32 is_kinematic = sim_ent_has_prop(ent, SIM_ENT_PROP_PHYSICAL_KINEMATIC);
@ -965,7 +965,7 @@ void phys_integrate_velocities(struct phys_step_ctx *ctx, f32 dt)
struct sim_snapshot *ss = ctx->sim_step_ctx->world; struct sim_snapshot *ss = ctx->sim_step_ctx->world;
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) { for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
struct sim_ent *ent = &ss->ents[sim_ent_index]; struct sim_ent *ent = &ss->ents[sim_ent_index];
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_PHYSICAL_DYNAMIC) && !sim_ent_has_prop(ent, SIM_ENT_PROP_PHYSICAL_KINEMATIC)) continue; if (!sim_ent_has_prop(ent, SIM_ENT_PROP_PHYSICAL_DYNAMIC) && !sim_ent_has_prop(ent, SIM_ENT_PROP_PHYSICAL_KINEMATIC)) continue;
struct xform xf = get_derived_xform(ent, dt); struct xform xf = get_derived_xform(ent, dt);
@ -986,7 +986,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_is_valid_and_active(e0)) continue; if (!sim_ent_should_simulate(e0)) continue;
if (!(sim_ent_has_prop(e0, SIM_ENT_PROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(e0, SIM_ENT_PROP_PHYSICAL_KINEMATIC))) continue; if (!(sim_ent_has_prop(e0, SIM_ENT_PROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(e0, SIM_ENT_PROP_PHYSICAL_KINEMATIC))) continue;
if (!sim_ent_has_prop(e0, SIM_ENT_PROP_BULLET)) continue; if (!sim_ent_has_prop(e0, SIM_ENT_PROP_BULLET)) continue;
if (e0->local_collider.count <= 0) continue; if (e0->local_collider.count <= 0) continue;
@ -1005,7 +1005,7 @@ f32 phys_determine_earliest_toi_for_bullets(struct phys_step_ctx *ctx, f32 step_
while ((entry = space_iter_next(&iter))) { while ((entry = space_iter_next(&iter))) {
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_is_valid_and_active(e1)) continue; if (!sim_ent_should_simulate(e1)) continue;
if (!(sim_ent_has_prop(e1, SIM_ENT_PROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(e1, SIM_ENT_PROP_PHYSICAL_KINEMATIC))) continue; if (!(sim_ent_has_prop(e1, SIM_ENT_PROP_PHYSICAL_DYNAMIC) || sim_ent_has_prop(e1, SIM_ENT_PROP_PHYSICAL_KINEMATIC))) continue;
if (e1->local_collider.count <= 0) continue; if (e1->local_collider.count <= 0) continue;

View File

@ -10,17 +10,26 @@
* *
* Client store -> clients -> snapshots -> ents * Client store -> clients -> snapshots -> ents
* *
* A client store holds clients, which can be retrieved by client handle or by a host channel id (if one is set). * A client store holds clients, which can be retrieved by client handle or by a host channel id (if one is assigned).
* *
* A client holds snapshots, which can be retrieved by tick (64 bit unsigned int). * A client holds snapshots, which can be retrieved by tick number.
* - The snapshots stored in clients & the contents of those snapshots are determined from data transmitted by the client. * - The snapshots stored in clients & the contents of those snapshots are determined from data transmitted by the client.
* - Different kinds of clients will transmit different subsets of snapshot data (e.g. a master client will transmit most/all ent state, while slave clients may just transmit 1 or more cmds) * - Different kinds of clients will transmit different subsets of snapshot data (e.g. a master client will transmit most ent state, while slave clients may just transmit 1 or more command ents)
* - A client will never hold more than one snapshot for the same tick (e.g. a client will never have 2 snapshots at tick 5) * - A client will never hold more than one snapshot for the same tick (e.g. a client will never have 2 snapshots at tick 5)
* *
* A snapshot holds the ent tree for a particular tick, in which ents can be retrieved by ent handle. * A snapshot holds the ent tree for a particular tick, in which ents can be retrieved by ent id.
* - A tick is the quantized time step that all clients implicitly conform to. * - A tick is the quantized time step that all clients implicitly conform to.
* *
* An ent is the smallest unit of simulation state. * An ent is the smallest unit of simulation state.
* - It is assigned a 128 bit unique identifer generated at allocation time.
* - This id is used to refer to other ents in the tree and to sync ents accross clients.
* - This id is usually random, but can be deterministic under certain conditions.
* - For example, instead of storing a contact constraint lookup table, contact constraints are
* retrieved by searching for the ent with the id resulting from combining the ent ids of the
* two contacting entities (plus a unique 'basis' ent id used for all contact constraints).
* - The ent also implicitly has a 32 bit index, which is just its offset from the start of the entity array in the local snapshot.
* - Since index is based on offset which remains stable regardless of snapshot memory location, it
* is used when working in contexts where id is irrelevant.
*/ */
#define CLIENT_LOOKUP_BINS 127 #define CLIENT_LOOKUP_BINS 127
@ -590,7 +599,7 @@ struct sim_snapshot *sim_snapshot_alloc_from_lerp(struct sim_client *client, str
* ========================== */ * ========================== */
/* Syncs entity data between snapshots */ /* Syncs entity data between snapshots */
void sim_snapshot_sync(struct sim_snapshot *local_ss, struct sim_snapshot *remote_ss) void sim_snapshot_sync_ents(struct sim_snapshot *local_ss, struct sim_snapshot *remote_ss)
{ {
__prof; __prof;

View File

@ -208,7 +208,7 @@ struct sim_snapshot *sim_snapshot_from_closest_tick_gte(struct sim_client *clien
struct sim_snapshot *sim_snapshot_alloc_from_lerp(struct sim_client *client, struct sim_snapshot *ss0, struct sim_snapshot *ss1, f64 blend); struct sim_snapshot *sim_snapshot_alloc_from_lerp(struct sim_client *client, struct sim_snapshot *ss0, struct sim_snapshot *ss1, f64 blend);
/* Sync */ /* Sync */
void sim_snapshot_sync(struct sim_snapshot *local_ss, struct sim_snapshot *remote_ss); void sim_snapshot_sync_ents(struct sim_snapshot *local_ss, struct sim_snapshot *remote_ss);
/* Encode / decode */ /* Encode / decode */
void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_client *receiver, struct sim_snapshot *ss0, struct sim_snapshot *ss1); void sim_snapshot_encode(struct bitbuff_writer *bw, struct sim_client *receiver, struct sim_snapshot *ss0, struct sim_snapshot *ss1);

View File

@ -151,7 +151,7 @@ void sim_ent_release_all_with_prop(struct sim_snapshot *ss, enum sim_ent_prop pr
* child entities will be released along with parent anyway) */ * child entities will be released along with parent anyway) */
for (u64 i = 0; i < ents_to_release_count; ++i) { for (u64 i = 0; i < ents_to_release_count; ++i) {
struct sim_ent *ent = ents_to_release[i]; struct sim_ent *ent = ents_to_release[i];
if (ent->is_top && !ent->is_root && ent->valid) { if (ent->valid && !ent->is_root && !sim_ent_has_prop(ent, SIM_ENT_PROP_CMD_CONTROL) && !sim_ent_has_prop(ent, SIM_ENT_PROP_CLIENT)) {
sim_ent_release(ent); sim_ent_release(ent);
} }
} }

View File

@ -342,6 +342,7 @@ void sim_step(struct sim_step_ctx *ctx)
struct sim_client *user_input_client = ctx->user_input_client; struct sim_client *user_input_client = ctx->user_input_client;
struct sim_client *publish_client = ctx->publish_client; struct sim_client *publish_client = ctx->publish_client;
struct sim_client *master_client = ctx->master_client; struct sim_client *master_client = ctx->master_client;
(UNUSED)master_client;
i64 sim_dt_ns = ctx->sim_dt_ns; i64 sim_dt_ns = ctx->sim_dt_ns;
@ -361,6 +362,10 @@ void sim_step(struct sim_step_ctx *ctx)
* Sync remote ents * Sync remote ents
* ========================== */ * ========================== */
if (user_input_client->valid) {
user_input_client->ent_id = world->local_client_ent;
}
{ {
for (u64 client_index = 0; client_index < client_store->num_clients_reserved; ++client_index) { for (u64 client_index = 0; client_index < client_store->num_clients_reserved; ++client_index) {
struct sim_client *client = &client_store->clients[client_index]; struct sim_client *client = &client_store->clients[client_index];
@ -385,15 +390,9 @@ void sim_step(struct sim_step_ctx *ctx)
} }
/* Sync ents from client */ /* Sync ents from client */
{
struct sim_snapshot *src_ss = sim_snapshot_from_tick(client, world->tick); struct sim_snapshot *src_ss = sim_snapshot_from_tick(client, world->tick);
if (src_ss->valid) { if (src_ss->valid) {
sim_snapshot_sync(world, src_ss); sim_snapshot_sync_ents(world, src_ss);
if (client == master_client) {
world_client->ent_id = src_ss->local_client_ent;
world->local_client_ent = src_ss->local_client_ent;
}
}
} }
} }
} }
@ -1264,8 +1263,13 @@ void sim_step(struct sim_step_ctx *ctx)
if (!pub_world->valid) { if (!pub_world->valid) {
struct sim_snapshot *prev_pub_world = sim_snapshot_from_tick(publish_client, publish_client->last_tick); struct sim_snapshot *prev_pub_world = sim_snapshot_from_tick(publish_client, publish_client->last_tick);
pub_world = sim_snapshot_alloc(publish_client, prev_pub_world, world->tick); pub_world = sim_snapshot_alloc(publish_client, prev_pub_world, world->tick);
/* Sync */
sim_snapshot_sync_ents(pub_world, world);
pub_world->sim_dt_ns = world->sim_dt_ns;
pub_world->sim_time_ns = world->sim_time_ns;
pub_world->continuity_gen = world->continuity_gen;
pub_world->phys_iteration = world->phys_iteration;
pub_world->local_client_ent = world->local_client_ent; pub_world->local_client_ent = world->local_client_ent;
sim_snapshot_sync(pub_world, world);
} }
} }

View File

@ -1982,7 +1982,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
struct sim_snapshot *base_ss = sim_snapshot_from_tick(client, base_tick); struct sim_snapshot *base_ss = sim_snapshot_from_tick(client, base_tick);
if (base_ss->tick == base_tick) { if (base_ss->tick == base_tick) {
if (is_master) { if (is_master) {
/* Decode incoming slave client snapshots */ /* Queue incoming slave client snapshot for decoding */
b32 should_decode = tick == client->highest_received_tick + 1 || client->highest_received_tick == 0; b32 should_decode = tick == client->highest_received_tick + 1 || client->highest_received_tick == 0;
if (should_decode) { if (should_decode) {
struct sim_ss_decode_node *node = arena_push_zero(scratch.arena, struct sim_ss_decode_node); struct sim_ss_decode_node *node = arena_push_zero(scratch.arena, struct sim_ss_decode_node);
@ -2000,8 +2000,8 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
client->highest_received_tick = tick; client->highest_received_tick = tick;
} }
} }
} else { } else if (client == master_client) {
/* Decode incoming master client snapshots (only the newest one) */ /* Decode incoming master client snapshots for decoding (only the newest one) */
b32 should_decode = tick > client->highest_received_tick; b32 should_decode = tick > client->highest_received_tick;
if (should_decode) { if (should_decode) {
struct sim_ss_decode_node *node = queue.first ? queue.first : arena_push_zero(scratch.arena, struct sim_ss_decode_node); struct sim_ss_decode_node *node = queue.first ? queue.first : arena_push_zero(scratch.arena, struct sim_ss_decode_node);
@ -2044,9 +2044,12 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
/* Alloc & decode snapshot */ /* Alloc & decode snapshot */
struct sim_snapshot *ss = sim_snapshot_alloc(client, base_ss, tick); struct sim_snapshot *ss = sim_snapshot_alloc(client, base_ss, tick);
sim_snapshot_decode(&br, ss); sim_snapshot_decode(&br, ss);
/* Assume all incoming ents want to be sync srcs */
for (u64 i = 0; i < ss->num_ents_reserved; ++i) { for (u64 i = 0; i < ss->num_ents_reserved; ++i) {
struct sim_ent *ent = &ss->ents[i]; struct sim_ent *ent = &ss->ents[i];
if (ent->valid && sim_ent_has_prop(ent, SIM_ENT_PROP_SYNC_DST)) { if (ent->valid && sim_ent_has_prop(ent, SIM_ENT_PROP_SYNC_DST)) {
sim_ent_disable_prop(ent, SIM_ENT_PROP_SYNC_DST); sim_ent_disable_prop(ent, SIM_ENT_PROP_SYNC_DST);
sim_ent_enable_prop(ent, SIM_ENT_PROP_SYNC_SRC); sim_ent_enable_prop(ent, SIM_ENT_PROP_SYNC_SRC);
} }
@ -2070,7 +2073,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
/* Create user input */ /* Create user input */
{ {
struct sim_snapshot *prev_user_input_ss = sim_snapshot_from_tick(user_input_client, user_input_client->last_tick); struct sim_snapshot *prev_user_input_ss = sim_snapshot_from_tick(user_input_client, user_input_client->last_tick);
struct sim_snapshot *user_input_ss = sim_snapshot_alloc(user_input_client, prev_user_input_ss, local_client->last_tick + ahead + 1); struct sim_snapshot *user_input_ss = sim_snapshot_alloc(user_input_client, prev_user_input_ss, local_client->last_tick + 1);
struct sim_ent *user_input_root = sim_ent_from_id(user_input_ss, SIM_ENT_ROOT_ID); struct sim_ent *user_input_root = sim_ent_from_id(user_input_ss, SIM_ENT_ROOT_ID);
/* Find / create local control cmd ent */ /* Find / create local control cmd ent */
struct sim_ent *control_cmd_ent = sim_ent_find_first_match_one(user_input_ss, SIM_ENT_PROP_CMD_CONTROL); struct sim_ent *control_cmd_ent = sim_ent_find_first_match_one(user_input_ss, SIM_ENT_PROP_CMD_CONTROL);
@ -2138,7 +2141,7 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
} }
/* Release unneeded user input snapshots */ /* Release unneeded user input snapshots */
sim_snapshot_release_ticks_in_range(user_input_client, 0, local_client->last_tick - 1); sim_snapshot_release_ticks_in_range(user_input_client, 0, local_client->first_tick - 1);