skip redundant manifold based on manifold iteration

This commit is contained in:
jacob 2024-09-19 12:50:26 -05:00
parent 5593db5202
commit 1f0c8964d0
4 changed files with 54 additions and 56 deletions

View File

@ -205,18 +205,18 @@ void __asan_unpoison_memory_region(void const volatile *add, size_t);
# define READONLY __declspec(allocate(".rdata")) # define READONLY __declspec(allocate(".rdata"))
# endif # endif
#elif PLATFORM_MAC #elif PLATFORM_MAC
#define READONLY __attribute((section("__TEXT,__const"))) # define READONLY __attribute((section("__TEXT,__const")))
#else #else
#define READONLY __attribute((section(".rodata"))) # define READONLY __attribute((section(".rodata")))
#endif #endif
/* Markup */ /* Markup */
#define UNUSED void #define UNUSED void
#if COMPILER_CLANG #if COMPILER_CLANG
#define FALLTHROUGH __attribute((fallthrough)) # define FALLTHROUGH __attribute((fallthrough))
#else #else
#define FALLTHROUGH # define FALLTHROUGH
#endif #endif
/* Sizes */ /* Sizes */
@ -226,15 +226,14 @@ void __asan_unpoison_memory_region(void const volatile *add, size_t);
#define TERABYTE(n) (n*GIGABYTE(1024ULL)) #define TERABYTE(n) (n*GIGABYTE(1024ULL))
/* typeof */ /* typeof */
#if COMPILER_MSVC #if COMPILER_MSVC
/* Typeof not supported in MSVC */ /* Typeof not supported in MSVC */
# define typeof(type) ASSERT(false)
# define TYPEOF_DEFINED 0 # define TYPEOF_DEFINED 0
# define typeof(type) ASSERT(false)
#else #else
# if LANGUAGE_CPP || (__STDC_VERSION__ < 202311L) # define TYPEOF_DEFINED 1
# if LANGUAGE_CPP || (__STDC_VERSION__ < 202311L)
# define typeof(type) __typeof__(type) # define typeof(type) __typeof__(type)
# define TYPEOF_DEFINED 1
# endif # endif
#endif #endif
@ -307,17 +306,6 @@ void __asan_unpoison_memory_region(void const volatile *add, size_t);
#define STRINGIZE2(x) #x #define STRINGIZE2(x) #x
#define STRINGIZE(x) STRINGIZE2(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 * Primitive types
* ========================== */ * ========================== */

View File

@ -132,6 +132,7 @@ struct entity {
struct entity_handle manifold_e0; struct entity_handle manifold_e0;
struct entity_handle manifold_e1; struct entity_handle manifold_e1;
struct v2 manifold_normal; /* Normal vector of collision from e0 -> e1 */ struct v2 manifold_normal; /* Normal vector of collision from e0 -> e1 */
u64 last_manifold_iteration;
struct contact contacts[2]; struct contact contacts[2];
u32 num_contacts; u32 num_contacts;

View File

@ -246,6 +246,10 @@ INTERNAL void spawn_test_entities(void)
INTERNAL void create_contact_manifolds(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 entity_store *store = G.tick.entity_store;
struct sprite_scope *sprite_frame_scope = G.sprite_frame_scope; struct sprite_scope *sprite_frame_scope = G.sprite_frame_scope;
struct entity *root = G.root; struct entity *root = G.root;
@ -253,8 +257,8 @@ INTERNAL void create_contact_manifolds(void)
struct entity *e0 = &store->entities[e0_index]; struct entity *e0 = &store->entities[e0_index];
if (!(e0->valid && entity_has_prop(e0, ENTITY_PROP_ACTIVE))) continue; 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_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 xform e0_xf = entity_get_xform(e0);
struct quad e0_quad; struct quad e0_quad;
struct v2_array e0_poly; struct v2_array e0_poly;
@ -274,8 +278,41 @@ INTERNAL void create_contact_manifolds(void)
if (e1 == e0) continue; if (e1 == e0) continue;
if (!(e1->valid && entity_has_prop(e1, ENTITY_PROP_ACTIVE))) 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_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 xform e1_xf = entity_get_xform(e1);
struct quad e1_quad; struct quad e1_quad;
struct v2_array e1_poly; 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 #if 1
const f32 remove_contact_threshold_global_dist_sq = 0.005f * 0.005f; const f32 remove_contact_threshold_global_dist_sq = 0.005f * 0.005f;
const f32 insert_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; const f32 insert_contact_threshold_global_dist_sq = 0;
#endif #endif
struct gjk_contact_points_result res = gjk_contact_points(e0_poly, e1_poly); struct gjk_contact_points_result res = gjk_contact_points(e0_poly, e1_poly);
if (res.num_pairs > 0) { if (res.num_pairs > 0) {
if (!manifold) { if (!manifold) {
@ -337,19 +349,12 @@ INTERNAL void create_contact_manifolds(void)
} }
/* TODO: Remove this (debugging) */ /* TODO: Remove this (debugging) */
manifold->prototype = res.prototype; manifold->prototype = res.prototype;
manifold->simplex = res.simplex; manifold->simplex = res.simplex;
/* Update contact depths, and remove contacts that are no longer penetrating or have drifted too far from original position */ /* 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; struct v2 old_normal = manifold->manifold_normal;
for (i32 j = 0; j < (i32)manifold->num_contacts; ++j) { for (i32 j = 0; j < (i32)manifold->num_contacts; ++j) {

View File

@ -34,6 +34,8 @@ b32 gjk_boolean(struct v2_array shape0, struct v2_array shape1)
{ {
struct { struct v2 a, b, c; } s = ZI; 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 */ /* 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])); 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 */ /* 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.a = menkowski_point_extended(shape0, shape1, v2_sub(shape1.points[0], shape0.points[0]));
s.len = 1; 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 */ /* Second point is support point towards origin */
dir = v2_neg(s.a.p); dir = v2_neg(s.a.p);
m = menkowski_point_extended(shape0, shape1, dir); 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.b = s.a;
s.a = m; s.a = m;
s.len = 2; 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); 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 */ 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 */ /* Point is in region ab, remove c from simplex */
s.len = 2; s.len = 2;
} else { } else {
/* Point is not in region ab */ /* Point is not in region ab */
dir = v2_perp_towards_dir(vac, v2_neg(vab)); /* Normal of ac pointing away from b */ 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 */ /* Point is in region ac, remove b from simplex */
s.b = s.c; s.b = s.c;
s.len = 2; s.len = 2;