accumulate impulses

This commit is contained in:
jacob 2024-09-19 12:11:00 -05:00
parent 7b37f78b1e
commit eed68f04cd
6 changed files with 56 additions and 69 deletions

View File

@ -245,7 +245,7 @@ INTERNAL void inflate(u8 *dest, u8 *encoded)
struct temp_arena scratch = scratch_begin_no_conflict(); struct temp_arena scratch = scratch_begin_no_conflict();
__prof; __prof;
struct bitbuf bb = { encoded }; struct bitbuf bb = { .data = encoded };
/* ZLIB header */ /* ZLIB header */
u32 cm = consume_bits(&bb, 4); u32 cm = consume_bits(&bb, 4);

View File

@ -71,6 +71,8 @@ struct contact {
struct v2 p1_initial_world; struct v2 p1_initial_world;
f32 depth; /* How far is p0 from p1 along normal */ f32 depth; /* How far is p0 from p1 along normal */
f32 accumulated_impulse; /* Accumulated impulse along normal */
f32 delta_impulse; /* Change in impulse along normal */
b32 persisted; b32 persisted;
}; };

View File

@ -129,10 +129,10 @@ INTERNAL void spawn_test_entities(void)
//struct v2 pos = V2(0.374142020941, -0.246118023992); /* Touching glitch spot */ //struct v2 pos = V2(0.374142020941, -0.246118023992); /* Touching glitch spot */
//struct v2 size = V2(1, 1); //struct v2 size = V2(1, 1);
struct v2 size = V2(0.5, 0.5); struct v2 size = V2(0.5, 0.5);
f32 r = PI / 4; //f32 r = PI / 4;
//f32 r = PI / 3; //f32 r = PI / 3;
//f32 r = PI / 2; //f32 r = PI / 2;
//f32 r = 0; f32 r = 0;
f32 skew = 0; f32 skew = 0;
struct entity *e = entity_alloc(root); struct entity *e = entity_alloc(root);
@ -155,8 +155,8 @@ INTERNAL void spawn_test_entities(void)
entity_enable_prop(e, ENTITY_PROP_PHYSICAL); entity_enable_prop(e, ENTITY_PROP_PHYSICAL);
e->mass_unscaled = 100; e->mass_unscaled = 100;
//e->inertia_unscaled = 1; e->inertia_unscaled = 1;
e->inertia_unscaled = F32_INFINITY; //e->inertia_unscaled = F32_INFINITY;
e->linear_ground_friction = 1000; e->linear_ground_friction = 1000;
e->angular_ground_friction = 100; e->angular_ground_friction = 100;
@ -182,7 +182,7 @@ INTERNAL void spawn_test_entities(void)
e->attach_slice = STR("attach.wep"); e->attach_slice = STR("attach.wep");
entity_enable_prop(e, ENTITY_PROP_WEAPON); entity_enable_prop(e, ENTITY_PROP_WEAPON);
e->trigger_delay = 1.0 / 10.0; e->trigger_delay = 1.0f / 10.0f;
player_ent->equipped = e->handle; player_ent->equipped = e->handle;
} }
@ -299,10 +299,11 @@ INTERNAL void create_contact_manifolds(void)
dict = fixed_dict_init(&dict_arena, 4096); dict = fixed_dict_init(&dict_arena, 4096);
} }
u64 manifold_hash;
struct string manifold_key; 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 */ /* FIXME: Contact should be same regardless of entity order */
u64 manifold_hash = hash_fnv64(HASH_FNV64_BASIS, BUFFER_FROM_STRUCT(&e0->handle));
manifold_hash = hash_fnv64(manifold_hash, BUFFER_FROM_STRUCT(&e1->handle)); manifold_hash = hash_fnv64(manifold_hash, BUFFER_FROM_STRUCT(&e1->handle));
manifold_key = STRING_FROM_BUFFER(BUFFER_FROM_STRUCT(&manifold_hash)); manifold_key = STRING_FROM_BUFFER(BUFFER_FROM_STRUCT(&manifold_hash));
} }
@ -313,8 +314,8 @@ INTERNAL void create_contact_manifolds(void)
#if 1 #if 1
const f32 remove_contact_threshold_global_dist_sq = 0.005 * 0.005; const f32 remove_contact_threshold_global_dist_sq = 0.005f * 0.005f;
const f32 insert_contact_threshold_global_dist_sq = 0.005 * 0.005; const f32 insert_contact_threshold_global_dist_sq = 0.005f * 0.005f;
#else #else
const f32 remove_contact_threshold_global_dist_sq = 0; const f32 remove_contact_threshold_global_dist_sq = 0;
const f32 insert_contact_threshold_global_dist_sq = 0; const f32 insert_contact_threshold_global_dist_sq = 0;
@ -518,7 +519,6 @@ INTERNAL void create_contact_manifolds(void)
INTERNAL void solve_collisions(f32 dt, b32 apply_bias) INTERNAL void solve_collisions(f32 dt, b32 apply_bias)
{ {
struct entity_store *store = G.tick.entity_store; struct entity_store *store = G.tick.entity_store;
for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) { for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) {
struct entity *manifold = &store->entities[entity_index]; struct entity *manifold = &store->entities[entity_index];
if (!(manifold->valid && entity_has_prop(manifold, ENTITY_PROP_ACTIVE))) continue; if (!(manifold->valid && entity_has_prop(manifold, ENTITY_PROP_ACTIVE))) continue;
@ -527,13 +527,15 @@ INTERNAL void solve_collisions(f32 dt, b32 apply_bias)
struct entity *e0 = entity_from_handle(store, manifold->manifold_e0); struct entity *e0 = entity_from_handle(store, manifold->manifold_e0);
struct entity *e1 = entity_from_handle(store, manifold->manifold_e1); struct entity *e1 = entity_from_handle(store, manifold->manifold_e1);
u32 num_contacts = manifold->num_contacts;
f32 inv_num_contacts = 1.f / num_contacts;
if (num_contacts > 0 && e0->valid && e1->valid) {
/* TODO: Remove this (testing) */
if (!e0->test_collided) {
e0->test_collided = true;
}
if (manifold->num_contacts > 0 && e0->valid && e1->valid) {
struct xform e0_xf = entity_get_xform(e0); struct xform e0_xf = entity_get_xform(e0);
struct xform e1_xf = entity_get_xform(e1); struct xform e1_xf = entity_get_xform(e1);
@ -549,13 +551,14 @@ INTERNAL void solve_collisions(f32 dt, b32 apply_bias)
f32 inv_i1 = 1.f / i1; f32 inv_i1 = 1.f / i1;
struct v2 e0_accumulated_linear_impulse = { 0 }; struct queued_impulse {
f32 e0_accumulated_angular_impulse = 0; struct v2 p0, p1;
struct v2 e1_accumulated_linear_impulse = { 0 }; f32 impulse;
f32 e1_accumulated_angular_impulse = 0; };
struct queued_impulse queued_impulses[ARRAY_COUNT(manifold->contacts)];
struct v2 normal = manifold->manifold_normal; struct v2 normal = manifold->manifold_normal;
for (u32 contact_index = 0; contact_index < manifold->num_contacts; ++contact_index) { for (u32 contact_index = 0; contact_index < num_contacts; ++contact_index) {
struct contact *contact = &manifold->contacts[contact_index]; struct contact *contact = &manifold->contacts[contact_index];
struct v2 p0 = xform_mul_v2(e0_xf, contact->p0_local); struct v2 p0 = xform_mul_v2(e0_xf, contact->p0_local);
@ -563,14 +566,14 @@ INTERNAL void solve_collisions(f32 dt, b32 apply_bias)
f32 bias = 0; f32 bias = 0;
if (apply_bias) { if (apply_bias) {
//f32 bias_factor = 0.2; //f32 bias_factor = 0.2f;
f32 bias_factor = 0.1; f32 bias_factor = 0.1f;
f32 bias_slop = 0.0005; //f32 bias_slop = 0.0005f;
//f32 bias_slop = 0.001; f32 bias_slop = 0.001f;
//f32 bias_slop = 0.00; //f32 bias_slop = 0.00f;
bias = (bias_factor / dt) * max((contact->depth - bias_slop), 0); bias = (bias_factor / dt) * max_f32((contact->depth - bias_slop), 0);
} }
@ -593,44 +596,24 @@ INTERNAL void solve_collisions(f32 dt, b32 apply_bias)
/* (to be applied along n) */ /* (to be applied along n) */
f32 j = (vn + bias) / k; f32 j = (vn + bias) / k;
//j = max_f32(j, 0); j *= inv_num_contacts; /* TODO: Is this the correct place to do this? */
struct v2 imp = v2_mul(normal, j); f32 old_impulse = contact->accumulated_impulse;
contact->accumulated_impulse = max_f32(contact->accumulated_impulse + j, 0);
if (!e0->test_collided) { queued_impulses[contact_index] = (struct queued_impulse) {
e0->test_collided = true; .p0 = p0,
.p1 = p1,
.impulse = contact->accumulated_impulse - old_impulse
};
} }
e0_accumulated_linear_impulse = v2_add(e0_accumulated_linear_impulse, imp); for (u32 i = 0; i < num_contacts; ++i) {
e1_accumulated_linear_impulse = v2_add(e1_accumulated_linear_impulse, v2_neg(imp)); struct queued_impulse qi = queued_impulses[i];
struct v2 impulse = v2_mul(normal, qi.impulse);
e0_accumulated_angular_impulse += v2_wedge(vcp0, imp); entity_apply_linear_impulse(e0, impulse, qi.p0);
e1_accumulated_angular_impulse += v2_wedge(vcp1, v2_neg(imp)); entity_apply_linear_impulse(e1, v2_neg(impulse), qi.p1);
//entity_apply_linear_impulse(e0, imp, p0);
//entity_apply_linear_impulse(e1, v2_neg(imp), p1);
} }
//entity_apply_linear_impulse(e0, imp, p0);
//entity_apply_linear_impulse(e1, v2_neg(imp), p1);
/* TODO: Remove this (testing) */
#if 1
/* Divide impulses by number of contact points. */
{
f32 inv_num_contacts = 1.f / manifold->num_contacts;
e0_accumulated_linear_impulse = v2_mul(e0_accumulated_linear_impulse, inv_num_contacts);
e1_accumulated_linear_impulse = v2_mul(e1_accumulated_linear_impulse, inv_num_contacts);
e0_accumulated_angular_impulse *= inv_num_contacts;
e1_accumulated_angular_impulse *= inv_num_contacts;
}
#endif
entity_apply_linear_impulse_to_center(e0, e0_accumulated_linear_impulse);
entity_apply_angular_impulse(e0, e0_accumulated_angular_impulse);
entity_apply_linear_impulse_to_center(e1, e1_accumulated_linear_impulse);
entity_apply_angular_impulse(e1, e1_accumulated_angular_impulse);
} else { } else {
entity_enable_prop(manifold, ENTITY_PROP_RELEASE); entity_enable_prop(manifold, ENTITY_PROP_RELEASE);
} }
@ -1036,10 +1019,10 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
bullet->bullet_src = ent->handle; bullet->bullet_src = ent->handle;
bullet->bullet_src_pos = rel_pos; bullet->bullet_src_pos = rel_pos;
bullet->bullet_src_dir = rel_dir; bullet->bullet_src_dir = rel_dir;
bullet->bullet_impulse = 0.25; bullet->bullet_impulse = 0.25f;
//bullet->bullet_impulse = 1; //bullet->bullet_impulse = 1.f;
bullet->mass_unscaled = 0.04; bullet->mass_unscaled = 0.04f;
bullet->inertia_unscaled = 0.00001; bullet->inertia_unscaled = 0.00001f;
entity_enable_prop(bullet, ENTITY_PROP_BULLET); entity_enable_prop(bullet, ENTITY_PROP_BULLET);
} }
@ -1197,7 +1180,7 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
} }
if (!F32_IS_NAN(final_xf_angle)) { if (!F32_IS_NAN(final_xf_angle)) {
const f32 angle_error_allowed = 0.001; const f32 angle_error_allowed = 0.001f;
f32 cur_angle = v2_angle(xf.bx); f32 cur_angle = v2_angle(xf.bx);
f32 diff = final_xf_angle - cur_angle; f32 diff = final_xf_angle - cur_angle;
if (math_fabs(diff) > angle_error_allowed) { if (math_fabs(diff) > angle_error_allowed) {

View File

@ -159,12 +159,12 @@ struct v2_array cloud(struct arena *arena, struct v2_array poly0, struct v2_arra
* `colliding` & `has_2nd_pair` become "num_pairs", where 0 = no collision. */ * `colliding` & `has_2nd_pair` become "num_pairs", where 0 = no collision. */
struct gjk_contact_points_result gjk_contact_points(struct v2_array shape0, struct v2_array shape1) struct gjk_contact_points_result gjk_contact_points(struct v2_array shape0, struct v2_array shape1)
{ {
struct temp_arena scratch = scratch_begin_no_conflict(); struct temp_arena scratch = scratch_begin_no_conflict(); /* TODO: Only begin scratch for EPA */
struct gjk_contact_points_result res = { 0 }; struct gjk_contact_points_result res = { 0 };
/* TODO: Verify epsilon */ /* TODO: Verify epsilon */
/* FIXME: Infinite loop when epsilon too low and shapes is too far from 0 (precision issue) */ /* FIXME: Infinite loop when epsilon too low and shapes is too far from 0 (precision issue) */
const f32 epsilon = 0.0000100; const f32 epsilon = 0.0000100f;
struct gjk_simplex s = { 0 }; struct gjk_simplex s = { 0 };
b32 colliding = false; b32 colliding = false;
struct gjk_menkowski_point *proto = NULL; struct gjk_menkowski_point *proto = NULL;

View File

@ -869,7 +869,7 @@ INTERNAL void win32_update_window_from_system(struct win32_window *window)
/* TODO: Error if we can't get monitor info */ /* TODO: Error if we can't get monitor info */
/* Screen dimensions */ /* Screen dimensions */
MONITORINFO monitor_info = {sizeof(monitor_info)}; MONITORINFO monitor_info = { .cbSize = sizeof(monitor_info) };
GetMonitorInfo(MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY), &monitor_info); GetMonitorInfo(MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY), &monitor_info);
RECT monitor_rect = monitor_info.rcMonitor; RECT monitor_rect = monitor_info.rcMonitor;
window->monitor_width = monitor_rect.right - monitor_rect.left; window->monitor_width = monitor_rect.right - monitor_rect.left;
@ -877,7 +877,7 @@ INTERNAL void win32_update_window_from_system(struct win32_window *window)
/* Minimized / maximized */ /* Minimized / maximized */
if (window->flags & SYS_WINDOW_FLAG_SHOWING) { if (window->flags & SYS_WINDOW_FLAG_SHOWING) {
WINDOWPLACEMENT placement = {sizeof(placement)}; WINDOWPLACEMENT placement = { .length = sizeof(placement) };
GetWindowPlacement(hwnd, &placement); GetWindowPlacement(hwnd, &placement);
if (placement.showCmd == SW_SHOWMINIMIZED) { if (placement.showCmd == SW_SHOWMINIMIZED) {
window->settings.flags |= SYS_WINDOW_SETTINGS_FLAG_MINIMIZED; window->settings.flags |= SYS_WINDOW_SETTINGS_FLAG_MINIMIZED;

View File

@ -202,6 +202,8 @@ struct ttf_decode_result ttf_decode(struct arena *arena, struct buffer encoded,
/* Compute glyph metrics */ /* Compute glyph metrics */
DWRITE_GLYPH_METRICS glyph_metrics = { 0 }; DWRITE_GLYPH_METRICS glyph_metrics = { 0 };
error = font_face->GetDesignGlyphMetrics(&i, 1, &glyph_metrics, false); error = font_face->GetDesignGlyphMetrics(&i, 1, &glyph_metrics, false);
f32 off_x = (f32)bounding_box.left - raster_target_x; f32 off_x = (f32)bounding_box.left - raster_target_x;