determine contacts from uid combination

This commit is contained in:
jacob 2025-02-23 02:50:37 -06:00
parent 9723530ad9
commit ca731215ee
11 changed files with 89 additions and 121 deletions

View File

@ -4,6 +4,7 @@
#include "math.h"
#include "scratch.h"
#include "space.h"
#include "uid.h"
GLOBAL struct {
/* Constants */
@ -46,10 +47,6 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a
res.a = arena_dry_push(arena, struct phys_collision_data);
struct sim_snapshot *ss = ctx->sim_step_ctx->world;
struct space *space = ctx->sim_step_ctx->accel->space;
struct sim_lookup *contact_lookup = &ctx->sim_step_ctx->accel->contact_lookup;
#if COLLIDER_DEBUG
struct sim_lookup *debug_lookup = ctx->collision_debug_lookup;
#endif
struct sim_ent *root = sim_ent_from_handle(ss, SIM_ENT_ROOT_HANDLE);
u64 tick = ss->tick;
@ -96,23 +93,15 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a
e1_collider = check0_collider;
}
struct sim_lookup_key key = sim_lookup_key_from_two_handles(e0->handle, e1->handle);
struct sim_lookup_entry *constraint_entry = sim_lookup_get(contact_lookup, key);
struct uid constraint_uid = uid_combine(uid_combine(SIM_ENT_BASIS_UID_CONTACT, e0->uid), e1->uid);
struct sim_ent *constraint_ent = sim_ent_from_uid(ss, constraint_uid);
struct sim_ent *constraint_ent = sim_ent_nil();
if (constraint_entry) {
constraint_ent = sim_ent_from_handle(ss, constraint_entry->ent);
if (sim_ent_is_valid_and_active(constraint_ent)) {
if (constraint_ent->contact_constraint_data.last_phys_iteration >= phys_iteration) {
/* Already processed constraint this iteration */
continue;
} else {
constraint_ent->contact_constraint_data.last_phys_iteration = phys_iteration;
}
if (constraint_ent->valid) {
if (constraint_ent->contact_constraint_data.last_phys_iteration >= phys_iteration) {
/* Already processed constraint this iteration */
continue;
} else {
/* Constraint ent no longer valid, delete constraint_entry*/
sim_lookup_remove(contact_lookup, constraint_entry);
constraint_entry= NULL;
constraint_ent->contact_constraint_data.last_phys_iteration = phys_iteration;
}
}
@ -125,10 +114,10 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a
struct phys_contact_constraint *constraint = NULL;
if (collider_res.num_points > 0) {
if (!sim_ent_is_valid_and_active(constraint_ent)) {
if (!constraint_ent->valid) {
/* Create constraint */
{
constraint_ent = sim_ent_alloc_local(root);
constraint_ent = sim_ent_alloc_local_with_uid(root, constraint_uid);
constraint_ent->contact_constraint_data.e1 = e1->handle;
constraint_ent->contact_constraint_data.e0 = e0->handle;
constraint_ent->contact_constraint_data.skip_solve = sim_ent_has_prop(e0, SIM_ENT_PROP_SENSOR) || sim_ent_has_prop(e1, SIM_ENT_PROP_SENSOR)
@ -138,8 +127,6 @@ struct phys_collision_data_array phys_create_and_update_contacts(struct arena *a
/* TODO: Should we recalculate normal as more contact points are added? */
sim_ent_enable_prop(constraint_ent, SIM_ENT_PROP_CONTACT_CONSTRAINT);
sim_ent_activate(constraint_ent, tick);
ASSERT(!constraint_entry); /* Existing entry should never be present here */
sim_lookup_set(contact_lookup, key, constraint_ent->handle);
}
/* Push collision data */
@ -284,7 +271,6 @@ void phys_prepare_contacts(struct phys_step_ctx *ctx, u64 phys_iteration)
{
__prof;
struct sim_snapshot *ss = ctx->sim_step_ctx->world;
struct sim_lookup *contact_lookup = &ctx->sim_step_ctx->accel->contact_lookup;
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];
@ -364,14 +350,6 @@ void phys_prepare_contacts(struct phys_step_ctx *ctx, u64 phys_iteration)
constraint_ent->contact_constraint_data.num_points = 0;
sim_ent_disable_prop(constraint_ent, SIM_ENT_PROP_ACTIVE);
sim_ent_enable_prop(constraint_ent, SIM_ENT_PROP_RELEASE);
/* Remove from lookup */
struct sim_lookup_key key = sim_lookup_key_from_two_handles(constraint->e0, constraint->e1);
struct sim_lookup_entry *entry = sim_lookup_get(contact_lookup, key);
if (entry) {
sim_lookup_remove(contact_lookup, entry);
} else {
ASSERT(false); /* This should always exist */
}
}
}

View File

@ -78,13 +78,6 @@ u128 rng_rand_u128(void)
return v;
}
struct uid rng_rand_uid(void)
{
u128 v = 0;
sys_rand(STRING_FROM_STRUCT(&v));
return (struct uid) { .v = v };
}
f32 rng_rand_f32(f32 range_start, f32 range_end)
{
return ((f32)rng_rand_u32() / (f32)U32_MAX) * (range_end - range_start) + range_start;

View File

@ -11,7 +11,6 @@ struct rng_startup_receipt rng_startup(struct resource_startup_receipt *resource
u32 rng_rand_u32(void);
u64 rng_rand_u64(void);
u128 rng_rand_u128(void);
struct uid rng_rand_uid(void);
f32 rng_rand_f32(f32 range_start, f32 range_end);
f64 rng_rand_f64(f64 range_start, f64 range_end);

View File

@ -3,6 +3,9 @@
#define SIM_CLIENT_NIL_HANDLE ((struct sim_client_handle) { .gen = 0, .idx = 0 })
/* UID magic number bases (to be used in conjunction with random UIDs in deterministic UID combinations) */
#define SIM_ENT_BASIS_UID_CONTACT (UID(0x6a2a5d2dbecf534f, 0x0a8ca7c372a015af))
/* Absolute layers */
#define SIM_LAYER_FLOOR_DECALS (-300)
#define SIM_LAYER_BULLETS (-200)

View File

@ -2,7 +2,7 @@
#include "sim.h"
#include "math.h"
#include "bitbuff.h"
#include "rng.h"
#include "uid.h"
/* ========================== *
* Ent allocation
@ -40,7 +40,19 @@ struct sim_ent *sim_ent_alloc_local(struct sim_ent *parent)
struct sim_ent *e = sim_ent_alloc_raw(ss);
sim_ent_link_parent(e, parent);
sim_ent_set_uid(e, rng_rand_uid());
sim_ent_set_uid(e, uid_rand());
return e;
}
struct sim_ent *sim_ent_alloc_local_with_uid(struct sim_ent *parent, struct uid uid)
{
ASSERT(parent->valid);
struct sim_snapshot *ss = parent->ss;
struct sim_ent *e = sim_ent_alloc_raw(ss);
sim_ent_link_parent(e, parent);
sim_ent_set_uid(e, uid);
return e;
}
@ -52,7 +64,7 @@ struct sim_ent *sim_ent_alloc_sync_src(struct sim_ent *parent)
struct sim_ent *e = sim_ent_alloc_raw(ss);
sim_ent_link_parent(e, parent);
sim_ent_set_uid(e, rng_rand_uid());
sim_ent_set_uid(e, uid_rand());
sim_ent_enable_prop(e, SIM_ENT_PROP_SYNC_SRC);
e->sync_src_client = ss->client->handle;
@ -105,6 +117,17 @@ void sim_ent_release(struct sim_ent *ent)
sim_ent_release_raw(ent);
}
/* ========================== *
* Activate
* ========================== */
void sim_ent_activate(struct sim_ent *ent, u64 current_tick)
{
sim_ent_enable_prop(ent, SIM_ENT_PROP_ACTIVE);
ent->activation_tick = current_tick;
++ent->continuity_gen;
}
/* ========================== *
* Uid
* ========================== */
@ -115,18 +138,13 @@ INLINE u64 hash_from_uid(struct uid uid)
return uid.lo;
}
struct uid sim_ent_get_uid(struct sim_ent *ent)
{
return ent->_uid;
}
void sim_ent_set_uid(struct sim_ent *ent, struct uid uid)
{
struct sim_snapshot *ss = ent->ss;
struct sim_ent_bucket *buckets = ss->uid_buckets;
u64 num_uid_buckets = ss->num_uid_buckets;
struct uid old_uid = ent->_uid;
struct uid old_uid = ent->uid;
/* Release old from lookup */
if (!uid_eq(old_uid, UID0)) {
@ -137,7 +155,7 @@ void sim_ent_set_uid(struct sim_ent *ent, struct uid uid)
struct sim_ent *e = sim_ent_from_handle(ss, bucket->first);
while (e->valid) {
next = sim_ent_from_handle(ss, e->next_in_uid_bucket);
if (uid_eq(e->_uid, old_uid)) {
if (uid_eq(e->uid, old_uid)) {
break;
}
prev = e;
@ -171,7 +189,7 @@ void sim_ent_set_uid(struct sim_ent *ent, struct uid uid)
bucket->last = ent->handle;
}
ent->_uid = uid;
ent->uid = uid;
}
struct sim_ent *sim_ent_from_uid(struct sim_snapshot *ss, struct uid uid)
@ -182,7 +200,7 @@ struct sim_ent *sim_ent_from_uid(struct sim_snapshot *ss, struct uid uid)
u64 hash = hash_from_uid(uid);
struct sim_ent_bucket *bucket = &ss->uid_buckets[hash % num_buckets];
for (struct sim_ent *e = sim_ent_from_handle(ss, bucket->first); e->valid; e = sim_ent_from_handle(ss, e->next_in_uid_bucket)) {
if (uid_eq(e->_uid, uid)) {
if (uid_eq(e->uid, uid)) {
res = e;
break;
}
@ -303,17 +321,6 @@ void sim_ent_unlink_from_parent(struct sim_ent *ent)
ent->next = sim_ent_nil()->handle;
}
/* ========================== *
* Activate
* ========================== */
void sim_ent_activate(struct sim_ent *ent, u64 current_tick)
{
sim_ent_enable_prop(ent, SIM_ENT_PROP_ACTIVE);
ent->activation_tick = current_tick;
++ent->continuity_gen;
}
/* ========================== *
* Ent xform
* ========================== */
@ -530,7 +537,7 @@ void sim_ent_decode(struct bitbuff_reader *br, struct sim_ent *e)
{
struct sim_snapshot *ss = e->ss;
struct uid old_uid = sim_ent_get_uid(e);
struct uid old_uid = e->uid;
u64 pos = 0;
while (pos < sizeof(*e)) {
@ -543,8 +550,8 @@ void sim_ent_decode(struct bitbuff_reader *br, struct sim_ent *e)
pos += 8;
}
struct uid new_uid = sim_ent_get_uid(e);
e->_uid = old_uid;
struct uid new_uid = e->uid;
e->uid = old_uid;
if (!uid_eq(old_uid, new_uid)) {
sim_ent_set_uid(e, new_uid);
}

View File

@ -67,11 +67,7 @@ struct sim_ent {
b32 valid; /* Is this ent allocated in memory that can be written to (can always be read) */
struct sim_ent_handle handle;
/* The unique ID of the entity determined at allocation time.
* Mainly used for networking.
* Use uid getter to access. */
struct uid _uid;
struct uid uid;
u64 props[(SIM_ENT_PROP_COUNT + 63) / 64];
u64 continuity_gen;
@ -398,15 +394,18 @@ INLINE b32 sim_ent_is_valid_and_active(struct sim_ent *ent)
/* Alloc */
struct sim_ent *sim_ent_alloc_raw(struct sim_snapshot *ss);
struct sim_ent *sim_ent_alloc_local(struct sim_ent *parent);
struct sim_ent *sim_ent_alloc_local_with_uid(struct sim_ent *parent, struct uid uid);
struct sim_ent *sim_ent_alloc_sync_src(struct sim_ent *parent);
struct sim_ent *sim_ent_alloc_sync_dst(struct sim_ent *parent, struct sim_client_handle client_handle, struct uid uid);
void sim_ent_release_raw(struct sim_ent *ent);
void sim_ent_release(struct sim_ent *ent);
/* Activate */
void sim_ent_activate(struct sim_ent *ent, u64 current_tick);
/* Uid */
struct uid sim_ent_get_uid(struct sim_ent *ent);
void sim_ent_set_uid(struct sim_ent *ent, struct uid uid);
struct sim_ent *sim_ent_from_uid(struct sim_snapshot *ss, struct uid uid);
@ -419,9 +418,6 @@ struct sim_ent *sim_ent_find_first_match_all(struct sim_snapshot *ss, struct sim
void sim_ent_link_parent(struct sim_ent *parent, struct sim_ent *child);
void sim_ent_unlink_from_parent(struct sim_ent *ent);
/* Activate */
void sim_ent_activate(struct sim_ent *ent, u64 current_tick);
/* Xform */
struct xform sim_ent_get_xform(struct sim_ent *ent);
struct xform sim_ent_get_local_xform(struct sim_ent *ent);

View File

@ -124,16 +124,6 @@ void sim_lookup_remove(struct sim_lookup *l, struct sim_lookup_entry *entry)
l->first_free_entry = entry;
}
struct sim_lookup_key sim_lookup_key_from_two_handles(struct sim_ent_handle h0, struct sim_ent_handle h1)
{
struct sim_lookup_key key = ZI;
struct string b0 = STRING_FROM_STRUCT(&h0);
struct string b1 = STRING_FROM_STRUCT(&h1);
key.hash = hash_fnv64(HASH_FNV64_BASIS, b0);
key.hash = hash_fnv64(key.hash, b1);
return key;
}
/* ========================== *
* Sim accel
* ========================== */
@ -142,19 +132,11 @@ struct sim_accel sim_accel_alloc(void)
{
struct sim_accel accel = ZI;
accel.space = space_alloc(1, 256);
accel.contact_lookup = sim_lookup_alloc(4096);
#if COLLIDER_DEBUG
accel.collision_debug_lookup = sim_lookup_alloc(4096);
#endif
return accel;
}
void sim_accel_release(struct sim_accel *accel)
{
#if COLLIDER_DEBUG
sim_lookup_release(&accel->collision_debug_lookup);
#endif
sim_lookup_release(&accel->contact_lookup);
space_release(accel->space);
}
@ -163,7 +145,6 @@ void sim_accel_rebuild(struct sim_snapshot *ss, struct sim_accel *accel)
/* FIXME: Rebuild collision debug lookup */
space_reset(accel->space);
sim_lookup_reset(&accel->contact_lookup);
/* Reset ent space handles */
for (u64 sim_ent_index = 0; sim_ent_index < ss->num_ents_reserved; ++sim_ent_index) {
@ -174,17 +155,6 @@ void sim_accel_rebuild(struct sim_snapshot *ss, struct sim_accel *accel)
}
/* NOTE: Not rebuilding space since it'll happen during phys step */
/* Rebuild lookup tables */
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];
if (sim_ent_is_valid_and_active(ent)) {
if (sim_ent_has_prop(ent, SIM_ENT_PROP_CONTACT_CONSTRAINT)) {
struct sim_lookup_key contact_lookup_key = sim_lookup_key_from_two_handles(ent->contact_constraint_data.e0, ent->contact_constraint_data.e1);
sim_lookup_set(&accel->contact_lookup, contact_lookup_key, ent->handle);
}
}
}
}
/* ========================== *

View File

@ -44,9 +44,6 @@ struct sim_lookup_entry *sim_lookup_get(struct sim_lookup *l, struct sim_lookup_
void sim_lookup_set(struct sim_lookup *l, struct sim_lookup_key key, struct sim_ent_handle handle);
void sim_lookup_remove(struct sim_lookup *l, struct sim_lookup_entry *entry);
struct sim_lookup_key sim_lookup_key_from_two_handles(struct sim_ent_handle h0, struct sim_ent_handle h1);
/* ========================== *
* Sim accel
* ========================== */
@ -56,10 +53,6 @@ struct sim_lookup_key sim_lookup_key_from_two_handles(struct sim_ent_handle h0,
struct sim_accel {
struct space *space;
struct sim_lookup contact_lookup;
#if COLLIDER_DEBUG
struct sim_lookup collision_debug_lookup;
#endif
};
struct sim_accel sim_accel_alloc(void);

20
src/uid.c Normal file
View File

@ -0,0 +1,20 @@
#include "uid.h"
#include "sys.h"
#include "util.h"
/* Returns a uid generated from the system's random number generator */
struct uid uid_rand(void)
{
u128 v = 0;
sys_rand(STRING_FROM_STRUCT(&v));
return (struct uid) { .v = v };
}
/* Returns the deterministic outcome of two uids formed into a new uid */
struct uid uid_combine(struct uid a, struct uid b)
{
struct uid res;
res.v = hash_fnv128(HASH_FNV128_BASIS, STRING_FROM_STRUCT(&a));
res.v = hash_fnv128(res.v, STRING_FROM_STRUCT(&b));
return res;
}

7
src/uid.h Normal file
View File

@ -0,0 +1,7 @@
#ifndef UID_H
#define UID_H
struct uid uid_rand(void);
struct uid uid_combine(struct uid a, struct uid b);
#endif

View File

@ -351,7 +351,7 @@ INTERNAL struct string get_ent_debug_text(struct arena *arena, struct sim_ent *e
res.len += string_format(arena, LIT("<%F>"), FMT_HANDLE(ent->handle)).len;
/* TODO: String fmt function */
struct uid uid = sim_ent_get_uid(ent);
struct uid uid = ent->uid;
res.len += string_copy(arena, LIT(" [")).len;
res.len += string_from_uint(arena, (U128_HI(uid.v) >> 36) & 0xFFFFFFF, 16, 7).len;
res.len += string_copy(arena, LIT("]\n")).len;
@ -1531,7 +1531,7 @@ INTERNAL void user_update(void)
u32 old_flags = G.user_sim_cmd_control.flags;
G.user_sim_cmd_control = control;
G.user_sim_cmd_control.flags |= old_flags;
G.user_sim_cmd_hovered_ent_uid = sim_ent_get_uid(hovered_ent);
G.user_sim_cmd_hovered_ent_uid = hovered_ent->uid;
sys_mutex_unlock(&lock);
}
}
@ -1844,7 +1844,7 @@ INTERNAL struct sim_ent_handle _translate(struct sim_snapshot *local_ss, struct
struct sim_ent_handle local_handle = SIM_ENT_NIL_HANDLE;
struct sim_ent *remote_ent = sim_ent_from_handle(remote_ss, remote_ent_handle);
if (remote_ent->valid) {
struct uid uid = sim_ent_get_uid(remote_ent);
struct uid uid = remote_ent->uid;
struct sim_ent *local_ent = sim_ent_from_uid(local_ss, uid);
local_handle = local_ent->handle;
}
@ -1860,6 +1860,9 @@ INTERNAL void sim_ent_sync_tree(struct sim_ent *local, struct sim_ent *remote)
struct sim_ent old = *local;
MEMCPY_STRUCT(local, remote);
/* Why would 2 ents w/ different uids ever be synced? */
ASSERT(uid_eq(local->uid, old.uid));
sim_ent_disable_prop(local, SIM_ENT_PROP_SYNC_SRC);
sim_ent_enable_prop(local, SIM_ENT_PROP_SYNC_DST);
@ -1867,7 +1870,7 @@ INTERNAL void sim_ent_sync_tree(struct sim_ent *local, struct sim_ent *remote)
local->ss = old.ss;
local->handle = old.handle;
local->sync_src_client = remote_client_handle;
local->_uid = old._uid;
local->uid = old.uid;
local->parent = old.parent;
local->prev = old.prev;
local->next = old.next;
@ -1903,7 +1906,7 @@ INTERNAL void sim_ent_alloc_any_new_sync_dsts(struct sim_ent *local_parent, stru
struct sim_snapshot *remote_ss = remote->ss;
struct sim_client_handle remote_client_handle = remote_ss->client->handle;
struct uid uid = sim_ent_get_uid(remote);
struct uid uid = remote->uid;
struct sim_ent *local_ent = sim_ent_from_uid(local_ss, uid);
if (!local_ent->valid) {
local_ent = sim_ent_alloc_sync_dst(local_parent, remote_client_handle, uid);
@ -1932,8 +1935,7 @@ INTERNAL void sim_snapshot_sync(struct sim_snapshot *local_ss, struct sim_snapsh
for (u64 i = 0; i < local_ss->num_ents_reserved; ++i) {
struct sim_ent *local_ent = &local_ss->ents[i];
if (local_ent->valid && sim_ent_has_prop(local_ent, SIM_ENT_PROP_SYNC_DST) && sim_client_handle_eq(local_ent->sync_src_client, remote_client_handle)) {
struct uid uid = sim_ent_get_uid(local_ent);
struct sim_ent *remote_ent = sim_ent_from_uid(remote_ss, uid);
struct sim_ent *remote_ent = sim_ent_from_uid(remote_ss, local_ent->uid);
if (remote_ent->valid) {
/* Copy all ent data from remote */
sim_ent_sync_tree(local_ent, remote_ent);
@ -2209,9 +2211,9 @@ INTERNAL SYS_THREAD_ENTRY_POINT_FUNC_DEF(user_local_sim_thread_entry_point, arg)
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_ACTIVE);
client->ent_uid = sim_ent_get_uid(client_ent);
client->ent_uid = client_ent->uid;
if (client == user_input_client) {
local_ss->local_client_ent_uid = sim_ent_get_uid(client_ent);
local_ss->local_client_ent_uid = client_ent->uid;
}
}
}