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();
|
||||
|
||||
__prof;
|
||||
struct bitbuf bb = { encoded };
|
||||
struct bitbuf bb = { .data = encoded };
|
||||
|
||||
/* ZLIB header */
|
||||
u32 cm = consume_bits(&bb, 4);
|
||||
|
||||
@ -70,7 +70,9 @@ struct contact {
|
||||
struct v2 p1_local;
|
||||
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;
|
||||
};
|
||||
|
||||
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 size = V2(1, 1);
|
||||
struct v2 size = V2(0.5, 0.5);
|
||||
f32 r = PI / 4;
|
||||
//f32 r = PI / 4;
|
||||
//f32 r = PI / 3;
|
||||
//f32 r = PI / 2;
|
||||
//f32 r = 0;
|
||||
f32 r = 0;
|
||||
f32 skew = 0;
|
||||
|
||||
struct entity *e = entity_alloc(root);
|
||||
@ -155,8 +155,8 @@ INTERNAL void spawn_test_entities(void)
|
||||
|
||||
entity_enable_prop(e, ENTITY_PROP_PHYSICAL);
|
||||
e->mass_unscaled = 100;
|
||||
//e->inertia_unscaled = 1;
|
||||
e->inertia_unscaled = F32_INFINITY;
|
||||
e->inertia_unscaled = 1;
|
||||
//e->inertia_unscaled = F32_INFINITY;
|
||||
e->linear_ground_friction = 1000;
|
||||
e->angular_ground_friction = 100;
|
||||
|
||||
@ -182,7 +182,7 @@ INTERNAL void spawn_test_entities(void)
|
||||
e->attach_slice = STR("attach.wep");
|
||||
|
||||
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;
|
||||
}
|
||||
@ -299,10 +299,11 @@ INTERNAL void create_contact_manifolds(void)
|
||||
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 */
|
||||
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_key = STRING_FROM_BUFFER(BUFFER_FROM_STRUCT(&manifold_hash));
|
||||
}
|
||||
@ -313,8 +314,8 @@ INTERNAL void create_contact_manifolds(void)
|
||||
|
||||
|
||||
#if 1
|
||||
const f32 remove_contact_threshold_global_dist_sq = 0.005 * 0.005;
|
||||
const f32 insert_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.005f * 0.005f;
|
||||
#else
|
||||
const f32 remove_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)
|
||||
{
|
||||
struct entity_store *store = G.tick.entity_store;
|
||||
|
||||
for (u64 entity_index = 0; entity_index < store->reserved; ++entity_index) {
|
||||
struct entity *manifold = &store->entities[entity_index];
|
||||
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 *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 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;
|
||||
|
||||
|
||||
struct v2 e0_accumulated_linear_impulse = { 0 };
|
||||
f32 e0_accumulated_angular_impulse = 0;
|
||||
struct v2 e1_accumulated_linear_impulse = { 0 };
|
||||
f32 e1_accumulated_angular_impulse = 0;
|
||||
struct queued_impulse {
|
||||
struct v2 p0, p1;
|
||||
f32 impulse;
|
||||
};
|
||||
struct queued_impulse queued_impulses[ARRAY_COUNT(manifold->contacts)];
|
||||
|
||||
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 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;
|
||||
if (apply_bias) {
|
||||
//f32 bias_factor = 0.2;
|
||||
f32 bias_factor = 0.1;
|
||||
//f32 bias_factor = 0.2f;
|
||||
f32 bias_factor = 0.1f;
|
||||
|
||||
f32 bias_slop = 0.0005;
|
||||
//f32 bias_slop = 0.001;
|
||||
//f32 bias_slop = 0.00;
|
||||
//f32 bias_slop = 0.0005f;
|
||||
f32 bias_slop = 0.001f;
|
||||
//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) */
|
||||
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) {
|
||||
e0->test_collided = true;
|
||||
}
|
||||
|
||||
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);
|
||||
queued_impulses[contact_index] = (struct queued_impulse) {
|
||||
.p0 = p0,
|
||||
.p1 = p1,
|
||||
.impulse = contact->accumulated_impulse - old_impulse
|
||||
};
|
||||
}
|
||||
|
||||
//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;
|
||||
for (u32 i = 0; i < num_contacts; ++i) {
|
||||
struct queued_impulse qi = queued_impulses[i];
|
||||
struct v2 impulse = v2_mul(normal, qi.impulse);
|
||||
entity_apply_linear_impulse(e0, impulse, qi.p0);
|
||||
entity_apply_linear_impulse(e1, v2_neg(impulse), qi.p1);
|
||||
}
|
||||
#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 {
|
||||
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_pos = rel_pos;
|
||||
bullet->bullet_src_dir = rel_dir;
|
||||
bullet->bullet_impulse = 0.25;
|
||||
//bullet->bullet_impulse = 1;
|
||||
bullet->mass_unscaled = 0.04;
|
||||
bullet->inertia_unscaled = 0.00001;
|
||||
bullet->bullet_impulse = 0.25f;
|
||||
//bullet->bullet_impulse = 1.f;
|
||||
bullet->mass_unscaled = 0.04f;
|
||||
bullet->inertia_unscaled = 0.00001f;
|
||||
|
||||
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)) {
|
||||
const f32 angle_error_allowed = 0.001;
|
||||
const f32 angle_error_allowed = 0.001f;
|
||||
f32 cur_angle = v2_angle(xf.bx);
|
||||
f32 diff = final_xf_angle - cur_angle;
|
||||
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. */
|
||||
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 };
|
||||
|
||||
/* TODO: Verify epsilon */
|
||||
/* 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 };
|
||||
b32 colliding = false;
|
||||
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 */
|
||||
/* Screen dimensions */
|
||||
MONITORINFO monitor_info = {sizeof(monitor_info)};
|
||||
MONITORINFO monitor_info = { .cbSize = sizeof(monitor_info) };
|
||||
GetMonitorInfo(MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY), &monitor_info);
|
||||
RECT monitor_rect = monitor_info.rcMonitor;
|
||||
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 */
|
||||
if (window->flags & SYS_WINDOW_FLAG_SHOWING) {
|
||||
WINDOWPLACEMENT placement = {sizeof(placement)};
|
||||
WINDOWPLACEMENT placement = { .length = sizeof(placement) };
|
||||
GetWindowPlacement(hwnd, &placement);
|
||||
if (placement.showCmd == SW_SHOWMINIMIZED) {
|
||||
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 */
|
||||
DWRITE_GLYPH_METRICS glyph_metrics = { 0 };
|
||||
|
||||
|
||||
error = font_face->GetDesignGlyphMetrics(&i, 1, &glyph_metrics, false);
|
||||
|
||||
f32 off_x = (f32)bounding_box.left - raster_target_x;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user