fix clip winding swap

This commit is contained in:
jacob 2024-10-30 13:58:11 -05:00
parent c8b48b9537
commit c071e17305
4 changed files with 72 additions and 37 deletions

View File

@ -425,7 +425,14 @@ struct collider_collision_points_result collider_collision_points(struct collide
f32 vap_wedge = v2_wedge(vap, normal); f32 vap_wedge = v2_wedge(vap, normal);
f32 vpb_wedge = v2_wedge(vpb, normal); f32 vpb_wedge = v2_wedge(vpb, normal);
if (vap_wedge * v2_winding(vap, vpb) < (vpb_wedge + wedge_epsilon)) { if (count0 > 2 && v2_winding(vap, vpb) > 0) {
/* Winding is reversed, swap */
f32 t = vap_wedge;
vap_wedge = vpb_wedge;
vpb_wedge = t;
}
if (vap_wedge > (vpb_wedge + wedge_epsilon)) {
id_a0 = a_i; id_a0 = a_i;
id_b0 = p_i; id_b0 = p_i;
a0 = a; a0 = a;
@ -453,7 +460,14 @@ struct collider_collision_points_result collider_collision_points(struct collide
f32 vap_wedge = v2_wedge(vap, normal); f32 vap_wedge = v2_wedge(vap, normal);
f32 vpb_wedge = v2_wedge(vpb, normal); f32 vpb_wedge = v2_wedge(vpb, normal);
if (vap_wedge * -v2_winding(vap, vpb) < (vpb_wedge + wedge_epsilon)) { if (count1 > 2 && v2_winding(vap, vpb) < 0) {
/* Winding is reversed, swap */
f32 t = vap_wedge;
vap_wedge = vpb_wedge;
vpb_wedge = t;
}
if (vap_wedge > (vpb_wedge + wedge_epsilon)) {
id_a1 = a_i; id_a1 = a_i;
id_b1 = p_i; id_b1 = p_i;
a1 = a; a1 = a;

View File

@ -41,11 +41,13 @@
#define GAME_PHYSICS_ENABLE_COLLISION 1 #define GAME_PHYSICS_ENABLE_COLLISION 1
#define GAME_SPAWN_LOTS 0 #define GAME_SPAWN_LOTS 0
#define GAME_SPAWN_TESTENT 0 #define GAME_SPAWN_TESTENT 0
#define GAME_SPAWN_BOX 1 #define GAME_SPAWN_BOX 0
#define GAME_PLAYER_AIM 1 #define GAME_PLAYER_AIM 1
#define GAME_MAX_LINEAR_VELOCITY 100 //#define GAME_MAX_LINEAR_VELOCITY 500
#define GAME_MAX_ANGULAR_VELOCITY (TAU * 20) //#define GAME_MAX_ANGULAR_VELOCITY (TAU * 20)
#define GAME_MAX_LINEAR_VELOCITY F32_INFINITY
#define GAME_MAX_ANGULAR_VELOCITY F32_INFINITY
/* How many ticks back in time should the user blend between? /* How many ticks back in time should the user blend between?
* <Delay ms> = <USER_INTERP_OFFSET_TICK_RATIO> * <Game tick rate> * <Delay ms> = <USER_INTERP_OFFSET_TICK_RATIO> * <Game tick rate>

View File

@ -177,10 +177,21 @@ INTERNAL void spawn_test_entities(f32 offset)
f32 r = 0; f32 r = 0;
if (!G.extra_spawn) { if (!G.extra_spawn) {
entity_enable_prop(e, ENTITY_PROP_PLAYER_CONTROLLED);
entity_enable_prop(e, ENTITY_PROP_TEST);
e->sprite = sprite_tag_from_path(STR("res/graphics/tim.ase")); e->sprite = sprite_tag_from_path(STR("res/graphics/tim.ase"));
e->mass_unscaled = 10;
e->inertia_unscaled = 5;
} else { } else {
entity_enable_prop(e, ENTITY_PROP_TEST);
e->sprite = sprite_tag_from_path(STR("res/graphics/tim.ase"));
e->mass_unscaled = 10;
e->inertia_unscaled = 5;
#if 0
e->sprite = sprite_tag_from_path(STR("res/graphics/box.ase")); e->sprite = sprite_tag_from_path(STR("res/graphics/box.ase"));
//size = V2(0.5, 0.5); e->mass_unscaled = 100;
e->inertia_unscaled = 100;
#endif
} }
//e->sprite = sprite_tag_from_path(STR("res/graphics/box_rounded.ase")); //e->sprite = sprite_tag_from_path(STR("res/graphics/box_rounded.ase"));
@ -194,32 +205,21 @@ INTERNAL void spawn_test_entities(f32 offset)
entity_set_xform(e, xf); entity_set_xform(e, xf);
if (!G.extra_spawn) {
entity_enable_prop(e, ENTITY_PROP_PLAYER_CONTROLLED);
}
e->linear_ground_friction = 150;
e->angular_ground_friction = 100;
e->linear_ground_friction = 250;
e->angular_ground_friction = 200;
//e->control_force = 500; //e->control_force = 500;
e->control_force = 500; e->control_force = 500;
//e->control_force_max_speed = 4; //e->control_force_max_speed = 4;
e->control_torque = 500; e->control_torque = 1000;
e->control_force_max_speed = 4; e->control_force_max_speed = 4;
entity_enable_prop(e, ENTITY_PROP_PHYSICAL); entity_enable_prop(e, ENTITY_PROP_PHYSICAL);
e->mass_unscaled = 10;
e->inertia_unscaled = 10;
entity_enable_prop(e, ENTITY_PROP_TEST);
player_ent = e; player_ent = e;
#if 1
#if 0
{ {
struct entity *joint_ent = entity_alloc(root); struct entity *joint_ent = entity_alloc(root);
entity_enable_prop(joint_ent, ENTITY_PROP_PHYSICAL); entity_enable_prop(joint_ent, ENTITY_PROP_PHYSICAL);
@ -1203,12 +1203,31 @@ INTERNAL void solve_mouse_joints(f32 dt)
f32 mass_scale = softness.mass_scale; f32 mass_scale = softness.mass_scale;
f32 impulse_scale = softness.impulse_scale; f32 impulse_scale = softness.impulse_scale;
#if 0
struct v2 vel = v2_add(v, v2_perp_mul(vcp, w)); struct v2 vel = v2_add(v, v2_perp_mul(vcp, w));
struct v2 b = v2_mul(xform_basis_mul_v2(joint->linear_mass_xf, v2_add(vel, bias)), mass_scale); struct v2 b = v2_mul(xform_basis_mul_v2(xform_invert(joint->linear_mass_xf), v2_add(vel, bias)), mass_scale);
struct v2 old_impulse = joint->linear_impulse; struct v2 old_impulse = joint->linear_impulse;
struct v2 impulse = v2_sub(v2_mul(old_impulse, -impulse_scale), b); struct v2 impulse = v2_sub(v2_mul(old_impulse, -impulse_scale), b);
joint->linear_impulse = v2_clamp_len(v2_add(joint->linear_impulse, impulse), max_impulse); joint->linear_impulse = v2_clamp_len(v2_add(joint->linear_impulse, impulse), max_impulse);
impulse = v2_sub(joint->linear_impulse, old_impulse); impulse = v2_sub(joint->linear_impulse, old_impulse);
#else
struct v2 vel = v2_add(v, v2_perp_mul(vcp, w));
struct v2 b = xform_basis_mul_v2(joint->linear_mass_xf, v2_add(vel, bias));
struct v2 impulse;
impulse.x = -mass_scale * b.x - impulse_scale * joint->linear_impulse.x;
impulse.y = -mass_scale * b.y - impulse_scale * joint->linear_impulse.y;
struct v2 old_impulse = joint->linear_impulse;
joint->linear_impulse.x += impulse.x;
joint->linear_impulse.y += impulse.y;
joint->linear_impulse = v2_clamp_len(joint->linear_impulse, max_impulse);
impulse.x = joint->linear_impulse.x - old_impulse.x;
impulse.y = joint->linear_impulse.y - old_impulse.y;
#endif
v = v2_add(v, v2_mul(impulse, inv_m)); v = v2_add(v, v2_mul(impulse, inv_m));
w += v2_wedge(vcp, impulse) * inv_i; w += v2_wedge(vcp, impulse) * inv_i;
@ -1513,20 +1532,20 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, STR("shape"), ent->animation_frame); struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, STR("shape"), ent->animation_frame);
ent->local_collider = collider_from_quad(xform_mul_quad(cxf, quad_from_rect(slice.rect))); ent->local_collider = collider_from_quad(xform_mul_quad(cxf, quad_from_rect(slice.rect)));
#if 0 #if 1
if (entity_has_prop(ent, ENTITY_PROP_TEST)) { if (entity_has_prop(ent, ENTITY_PROP_TEST)) {
//if ((true)) { //if ((true)) {
#if 1 #if 0
ent->local_collider.points[0] = V2(0, 0); ent->local_collider.points[0] = V2(0, 0);
ent->local_collider.count = 1; ent->local_collider.count = 1;
ent->local_collider.radius = 0.5; ent->local_collider.radius = 0.5;
#elif 0 #elif 1
ent->local_collider.points[0] = V2(0, 0.5); ent->local_collider.points[0] = v2_with_len(V2(0.08, 0.17), 0.15);
ent->local_collider.points[1] = V2(0, -0.5); ent->local_collider.points[1] = v2_with_len(V2(-0.07, -0.2), 0.15);
ent->local_collider.count = 2; ent->local_collider.count = 2;
ent->local_collider.radius = 0.25; ent->local_collider.radius = 0.075;
#elif 0 #elif 1
#if 1 #if 0
/* "Bad" winding order */ /* "Bad" winding order */
ent->local_collider.points[0] = V2(-0.5, 0.5); ent->local_collider.points[0] = V2(-0.5, 0.5);
ent->local_collider.points[1] = V2(0.5, 0.5); ent->local_collider.points[1] = V2(0.5, 0.5);

View File

@ -87,7 +87,7 @@ GLOBAL READONLY enum user_bind_kind g_binds[SYS_BTN_COUNT] = {
/* Testing */ /* Testing */
[SYS_BTN_M1] = USER_BIND_KIND_DEBUG_DRAG, [SYS_BTN_M2] = USER_BIND_KIND_DEBUG_DRAG,
[SYS_BTN_C] = USER_BIND_KIND_DEBUG_CLEAR, [SYS_BTN_C] = USER_BIND_KIND_DEBUG_CLEAR,
[SYS_BTN_V] = USER_BIND_KIND_DEBUG_SPAWN, [SYS_BTN_V] = USER_BIND_KIND_DEBUG_SPAWN,
[SYS_BTN_N] = USER_BIND_KIND_DEBUG_STEP, [SYS_BTN_N] = USER_BIND_KIND_DEBUG_STEP,
@ -1098,7 +1098,7 @@ INTERNAL void user_update(void)
/* Draw menkowski */ /* Draw menkowski */
{ {
u32 color = ent->res.solved ? RGBA_32_F(0, 0, 0.25, 1) : RGBA_32_F(0, 0.25, 0.25, 1); u32 color = data->res.solved ? RGBA_32_F(0, 0, 0.25, 1) : RGBA_32_F(0, 0.25, 0.25, 1);
f32 thickness = 2; f32 thickness = 2;
u32 detail = 512; u32 detail = 512;
(UNUSED)thickness; (UNUSED)thickness;
@ -1131,7 +1131,7 @@ INTERNAL void user_update(void)
f32 arrow_thickness = 2; f32 arrow_thickness = 2;
f32 arrow_height = 5; f32 arrow_height = 5;
struct v2 start = xform_mul_v2(G.world_view, V2(0, 0)); struct v2 start = xform_mul_v2(G.world_view, V2(0, 0));
struct v2 end = xform_mul_v2(G.world_view, v2_mul(v2_norm(ent->manifold_normal), len)); struct v2 end = xform_mul_v2(G.world_view, v2_mul(v2_norm(data->normal), len));
draw_solid_arrow_line(G.viewport_canvas, start, end, arrow_thickness, arrow_height, color); draw_solid_arrow_line(G.viewport_canvas, start, end, arrow_thickness, arrow_height, color);
} }
@ -1141,8 +1141,8 @@ INTERNAL void user_update(void)
u32 color = RGBA_32_F(1, 1, 1, 0.25); u32 color = RGBA_32_F(1, 1, 1, 0.25);
struct v2_array m = { struct v2_array m = {
.points = ent->res.prototype.points, .points = data->res.prototype.points,
.count = ent->res.prototype.len .count = data->res.prototype.len
}; };
for (u64 i = 0; i < m.count; ++i) m.points[i] = xform_mul_v2(G.world_view, m.points[i]); for (u64 i = 0; i < m.count; ++i) m.points[i] = xform_mul_v2(G.world_view, m.points[i]);
draw_solid_poly_line(G.viewport_canvas, m, true, thickness, color); draw_solid_poly_line(G.viewport_canvas, m, true, thickness, color);
@ -1157,7 +1157,7 @@ INTERNAL void user_update(void)
u32 color_second = RGBA_32_F(0, 1, 0, 0.75); u32 color_second = RGBA_32_F(0, 1, 0, 0.75);
u32 color_third = RGBA_32_F(0, 0, 1, 0.75); u32 color_third = RGBA_32_F(0, 0, 1, 0.75);
struct collider_simplex simplex = ent->res.simplex; struct collider_simplex simplex = data->res.simplex;
struct v2 simplex_points[] = { simplex.a, simplex.b, simplex.c }; struct v2 simplex_points[] = { simplex.a, simplex.b, simplex.c };
for (u64 i = 0; i < ARRAY_COUNT(simplex_points); ++i) simplex_points[i] = xform_mul_v2(G.world_view, simplex_points[i]); for (u64 i = 0; i < ARRAY_COUNT(simplex_points); ++i) simplex_points[i] = xform_mul_v2(G.world_view, simplex_points[i]);
struct v2_array simplex_array = { .count = simplex.len, .points = simplex_points }; struct v2_array simplex_array = { .count = simplex.len, .points = simplex_points };
@ -1417,7 +1417,7 @@ INTERNAL void user_update(void)
/* Queue physics drag cmd */ /* Queue physics drag cmd */
i32 drag_presses = G.bind_states[USER_BIND_KIND_DEBUG_DRAG].num_presses - G.bind_states[USER_BIND_KIND_DEBUG_DRAG].num_releases; i32 drag_presses = G.bind_states[USER_BIND_KIND_DEBUG_DRAG].num_presses - G.bind_states[USER_BIND_KIND_DEBUG_DRAG].num_releases;
if (G.debug_camera && drag_presses) { if (drag_presses) {
queue_game_cmd(scratch.arena, &cmd_list, (struct game_cmd) { queue_game_cmd(scratch.arena, &cmd_list, (struct game_cmd) {
.kind = GAME_CMD_KIND_DRAG_OBJECT, .kind = GAME_CMD_KIND_DRAG_OBJECT,
.state = drag_presses > 0 ? GAME_CMD_STATE_START : GAME_CMD_STATE_STOP .state = drag_presses > 0 ? GAME_CMD_STATE_START : GAME_CMD_STATE_STOP