accumulate impulses
This commit is contained in:
parent
7b37f78b1e
commit
eed68f04cd
@ -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);
|
||||||
|
|||||||
@ -70,7 +70,9 @@ struct contact {
|
|||||||
struct v2 p1_local;
|
struct v2 p1_local;
|
||||||
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;
|
||||||
};
|
};
|
||||||
|
|||||||
109
src/game.c
109
src/game.c
@ -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);
|
};
|
||||||
e1_accumulated_linear_impulse = v2_add(e1_accumulated_linear_impulse, v2_neg(imp));
|
|
||||||
|
|
||||||
e0_accumulated_angular_impulse += v2_wedge(vcp0, imp);
|
|
||||||
e1_accumulated_angular_impulse += v2_wedge(vcp1, v2_neg(imp));
|
|
||||||
|
|
||||||
//entity_apply_linear_impulse(e0, imp, p0);
|
|
||||||
//entity_apply_linear_impulse(e1, v2_neg(imp), p1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//entity_apply_linear_impulse(e0, imp, p0);
|
for (u32 i = 0; i < num_contacts; ++i) {
|
||||||
//entity_apply_linear_impulse(e1, v2_neg(imp), p1);
|
struct queued_impulse qi = queued_impulses[i];
|
||||||
|
struct v2 impulse = v2_mul(normal, qi.impulse);
|
||||||
|
entity_apply_linear_impulse(e0, impulse, qi.p0);
|
||||||
/* TODO: Remove this (testing) */
|
entity_apply_linear_impulse(e1, v2_neg(impulse), qi.p1);
|
||||||
#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) {
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user