skip redundant manifold based on manifold iteration
This commit is contained in:
parent
5593db5202
commit
1f0c8964d0
16
src/common.h
16
src/common.h
@ -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
|
||||||
|
# define TYPEOF_DEFINED 1
|
||||||
# if LANGUAGE_CPP || (__STDC_VERSION__ < 202311L)
|
# 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
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|||||||
@ -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;
|
||||||
|
|
||||||
|
|||||||
73
src/game.c
73
src/game.c
@ -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) {
|
||||||
|
|||||||
10
src/gjk.c
10
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;
|
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;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user