From 1f0c8964d0b44b7a6a67f9385756f99f49ab7f40 Mon Sep 17 00:00:00 2001 From: jacob Date: Thu, 19 Sep 2024 12:50:26 -0500 Subject: [PATCH] skip redundant manifold based on manifold iteration --- src/common.h | 26 +++++-------------- src/entity.h | 1 + src/game.c | 73 ++++++++++++++++++++++++++++------------------------ src/gjk.c | 10 ++++--- 4 files changed, 54 insertions(+), 56 deletions(-) diff --git a/src/common.h b/src/common.h index c408a77a..653f5274 100644 --- a/src/common.h +++ b/src/common.h @@ -205,18 +205,18 @@ void __asan_unpoison_memory_region(void const volatile *add, size_t); # define READONLY __declspec(allocate(".rdata")) # endif #elif PLATFORM_MAC -#define READONLY __attribute((section("__TEXT,__const"))) +# define READONLY __attribute((section("__TEXT,__const"))) #else -#define READONLY __attribute((section(".rodata"))) +# define READONLY __attribute((section(".rodata"))) #endif /* Markup */ #define UNUSED void #if COMPILER_CLANG -#define FALLTHROUGH __attribute((fallthrough)) +# define FALLTHROUGH __attribute((fallthrough)) #else -#define FALLTHROUGH +# define FALLTHROUGH #endif /* Sizes */ @@ -226,15 +226,14 @@ void __asan_unpoison_memory_region(void const volatile *add, size_t); #define TERABYTE(n) (n*GIGABYTE(1024ULL)) /* typeof */ - #if COMPILER_MSVC /* Typeof not supported in MSVC */ -# define typeof(type) ASSERT(false) # define TYPEOF_DEFINED 0 +# define typeof(type) ASSERT(false) #else -# if LANGUAGE_CPP || (__STDC_VERSION__ < 202311L) +# define TYPEOF_DEFINED 1 +# if LANGUAGE_CPP || (__STDC_VERSION__ < 202311L) # define typeof(type) __typeof__(type) -# define TYPEOF_DEFINED 1 # endif #endif @@ -307,17 +306,6 @@ void __asan_unpoison_memory_region(void const volatile *add, size_t); #define STRINGIZE2(x) #x #define STRINGIZE(x) STRINGIZE2(x) - -#if 0 -/* ========================== * - * Bit utils - * ========================== */ - -#define bit_set(i, mask) (i |= mask) -#define bit_clear(i, mask) (i &= ~mask) -#define bit_flip(i, mask) (i ^= mask) -#endif - /* ========================== * * Primitive types * ========================== */ diff --git a/src/entity.h b/src/entity.h index 1ebbd1b1..6ba99a6a 100644 --- a/src/entity.h +++ b/src/entity.h @@ -132,6 +132,7 @@ struct entity { struct entity_handle manifold_e0; struct entity_handle manifold_e1; struct v2 manifold_normal; /* Normal vector of collision from e0 -> e1 */ + u64 last_manifold_iteration; struct contact contacts[2]; u32 num_contacts; diff --git a/src/game.c b/src/game.c index 238c741c..d9e496e1 100644 --- a/src/game.c +++ b/src/game.c @@ -246,6 +246,10 @@ INTERNAL void spawn_test_entities(void) INTERNAL void create_contact_manifolds(void) { + /* TODO: Remove this */ + static u64 manifold_iteration = 0; + ++manifold_iteration; + struct entity_store *store = G.tick.entity_store; struct sprite_scope *sprite_frame_scope = G.sprite_frame_scope; struct entity *root = G.root; @@ -253,8 +257,8 @@ INTERNAL void create_contact_manifolds(void) struct entity *e0 = &store->entities[e0_index]; if (!(e0->valid && entity_has_prop(e0, ENTITY_PROP_ACTIVE))) continue; if (!entity_has_prop(e0, ENTITY_PROP_PHYSICAL)) continue; - if (!entity_has_prop(e0, ENTITY_PROP_PLAYER_CONTROLLED) && !entity_has_prop(e0, ENTITY_PROP_BULLET)) continue; + /* Calculate entity 0 shape */ struct xform e0_xf = entity_get_xform(e0); struct quad e0_quad; struct v2_array e0_poly; @@ -274,8 +278,41 @@ INTERNAL void create_contact_manifolds(void) if (e1 == e0) continue; if (!(e1->valid && entity_has_prop(e1, ENTITY_PROP_ACTIVE))) continue; if (!entity_has_prop(e1, ENTITY_PROP_PHYSICAL)) continue; - if (entity_has_prop(e1, ENTITY_PROP_PLAYER_CONTROLLED)) continue; + /* TODO: Remove this */ + static struct arena dict_arena = ZI; + static struct fixed_dict dict = ZI; + if (dict.buckets_count == 0) { + dict_arena = arena_alloc(GIGABYTE(64)); + dict = fixed_dict_init(&dict_arena, 4096); + } + + /* Retrieve manifold */ + u64 manifold_hash; + struct string manifold_key; + { + struct entity_handle h0 = e0->handle; + struct entity_handle h1 = e1->handle; + if (h0.idx > h1.idx) { + h0 = e1->handle; + h1 = e0->handle; + } + manifold_hash = hash_fnv64(HASH_FNV64_BASIS, BUFFER_FROM_STRUCT(&h0)); + manifold_hash = hash_fnv64(manifold_hash, BUFFER_FROM_STRUCT(&h1)); + manifold_key = STRING_FROM_BUFFER(BUFFER_FROM_STRUCT(&manifold_hash)); + } + struct entity *manifold = fixed_dict_get(&dict, manifold_key); + + /* Ensure manifold hasn't already been computed this iteration */ + if (manifold) { + if (manifold->last_manifold_iteration == manifold_iteration) { + /* Already iterated this manifold from The other entity's perspective, skip */ + continue; + } + manifold->last_manifold_iteration = manifold_iteration; + } + + /* Calculate entity 1 shape */ struct xform e1_xf = entity_get_xform(e1); struct quad e1_quad; struct v2_array e1_poly; @@ -290,29 +327,6 @@ INTERNAL void create_contact_manifolds(void) }; } - - /* TODO: Remove this */ - static struct arena dict_arena = ZI; - static struct fixed_dict dict = ZI; - if (dict.buckets_count == 0) { - dict_arena = arena_alloc(GIGABYTE(64)); - dict = fixed_dict_init(&dict_arena, 4096); - } - - u64 manifold_hash; - struct string manifold_key; - { - manifold_hash = hash_fnv64(HASH_FNV64_BASIS, BUFFER_FROM_STRUCT(&e0->handle)); - /* FIXME: Contact should be same regardless of entity order */ - manifold_hash = hash_fnv64(manifold_hash, BUFFER_FROM_STRUCT(&e1->handle)); - manifold_key = STRING_FROM_BUFFER(BUFFER_FROM_STRUCT(&manifold_hash)); - } - - struct entity *manifold = fixed_dict_get(&dict, manifold_key); - - - - #if 1 const f32 remove_contact_threshold_global_dist_sq = 0.005f * 0.005f; const f32 insert_contact_threshold_global_dist_sq = 0.005f * 0.005f; @@ -321,8 +335,6 @@ INTERNAL void create_contact_manifolds(void) const f32 insert_contact_threshold_global_dist_sq = 0; #endif - - struct gjk_contact_points_result res = gjk_contact_points(e0_poly, e1_poly); if (res.num_pairs > 0) { if (!manifold) { @@ -337,19 +349,12 @@ INTERNAL void create_contact_manifolds(void) } - - /* TODO: Remove this (debugging) */ manifold->prototype = res.prototype; manifold->simplex = res.simplex; - - - - - /* Update contact depths, and remove contacts that are no longer penetrating or have drifted too far from original position */ struct v2 old_normal = manifold->manifold_normal; for (i32 j = 0; j < (i32)manifold->num_contacts; ++j) { diff --git a/src/gjk.c b/src/gjk.c index 12afd5f5..a0b5dc99 100644 --- a/src/gjk.c +++ b/src/gjk.c @@ -34,6 +34,8 @@ b32 gjk_boolean(struct v2_array shape0, struct v2_array shape1) { struct { struct v2 a, b, c; } s = ZI; + /* FIXME: Infinite loop when shapes exactly overlap same space */ + /* First point is support point in shape's general directions to eachother */ s.a = menkowski_point(shape0, shape1, v2_sub(shape1.points[0], shape0.points[0])); @@ -187,6 +189,8 @@ struct gjk_contact_points_result gjk_contact_points(struct v2_array shape0, stru * ========================== */ { + /* FIXME: Collision is false when 2 shapes exactly overlap */ + /* First point is support point in shape's general directions to eachother */ s.a = menkowski_point_extended(shape0, shape1, v2_sub(shape1.points[0], shape0.points[0])); s.len = 1; @@ -194,7 +198,7 @@ struct gjk_contact_points_result gjk_contact_points(struct v2_array shape0, stru /* Second point is support point towards origin */ dir = v2_neg(s.a.p); m = menkowski_point_extended(shape0, shape1, dir); - if (v2_dot(dir, m.p) >= 0) { + if (v2_dot(dir, m.p) > 0) { s.b = s.a; s.a = m; s.len = 2; @@ -217,13 +221,13 @@ struct gjk_contact_points_result gjk_contact_points(struct v2_array shape0, stru struct v2 a_to_origin = v2_neg(s.a.p); dir = v2_perp_towards_dir(vab, v2_neg(vac)); /* Normal of ab pointing away from c */ - if (v2_dot(dir, a_to_origin) >= 0) { + if (v2_dot(dir, a_to_origin) > 0) { /* Point is in region ab, remove c from simplex */ s.len = 2; } else { /* Point is not in region ab */ dir = v2_perp_towards_dir(vac, v2_neg(vab)); /* Normal of ac pointing away from b */ - if (v2_dot(dir, a_to_origin) >= 0) { + if (v2_dot(dir, a_to_origin) > 0) { /* Point is in region ac, remove b from simplex */ s.b = s.c; s.len = 2;