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"))
# 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
# 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
* ========================== */

View File

@ -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;

View File

@ -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) {

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;
/* 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;