more popping work
This commit is contained in:
parent
73b7fef768
commit
8f1422a882
150
src/collider.c
150
src/collider.c
@ -100,7 +100,8 @@ struct collider_collision_points_result collider_collision_points(struct collide
|
|||||||
const f32 tolerance = 0.005f;
|
const f32 tolerance = 0.005f;
|
||||||
|
|
||||||
/* NOTE: Should always be less than tolerance, since colliding=true if origin is within this distance. */
|
/* NOTE: Should always be less than tolerance, since colliding=true if origin is within this distance. */
|
||||||
const f32 min_unique_pt_dist_sq = 0.0001f * 0.0001f;
|
//const f32 min_unique_pt_dist_sq = 0.0001f * 0.0001f;
|
||||||
|
const f32 min_unique_pt_dist_sq = 0.001f * 0.001f;
|
||||||
|
|
||||||
/* To prevent extremely large prototypes when origin is in exact center of rounded feature */
|
/* To prevent extremely large prototypes when origin is in exact center of rounded feature */
|
||||||
const u32 max_epa_iterations = 64;
|
const u32 max_epa_iterations = 64;
|
||||||
@ -155,16 +156,10 @@ struct collider_collision_points_result collider_collision_points(struct collide
|
|||||||
s.a = m;
|
s.a = m;
|
||||||
s.len = 2;
|
s.len = 2;
|
||||||
|
|
||||||
if (math_fabs(v2_wedge(v2_sub(s.b, s.a), v2_neg(s.a))) <= min_unique_pt_dist_sq) {
|
|
||||||
/* Third point is support point in direction of line normal towards origin */
|
|
||||||
dir = v2_perp(v2_sub(s.b, s.a));
|
|
||||||
} else {
|
|
||||||
/* Third point is support point in direction of line normal towards origin */
|
/* Third point is support point in direction of line normal towards origin */
|
||||||
dir = v2_perp_towards_dir(v2_sub(s.b, s.a), v2_neg(s.a));
|
dir = v2_perp_towards_dir(v2_sub(s.b, s.a), v2_neg(s.a));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
{
|
||||||
DBGSTEP;
|
DBGSTEP;
|
||||||
m = menkowski_point(shape0, shape1, xf0, xf1, dir);
|
m = menkowski_point(shape0, shape1, xf0, xf1, dir);
|
||||||
@ -178,6 +173,7 @@ struct collider_collision_points_result collider_collision_points(struct collide
|
|||||||
) ||
|
) ||
|
||||||
math_fabs(v2_wedge(v2_sub(s.b, s.a), v2_sub(m, s.a))) < min_unique_pt_dist_sq)
|
math_fabs(v2_wedge(v2_sub(s.b, s.a), v2_sub(m, s.a))) < min_unique_pt_dist_sq)
|
||||||
{
|
{
|
||||||
|
colliding = false;
|
||||||
simplex_is_closest_edge = true;
|
simplex_is_closest_edge = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -186,15 +182,13 @@ struct collider_collision_points_result collider_collision_points(struct collide
|
|||||||
s.a = m;
|
s.a = m;
|
||||||
s.len = 3;
|
s.len = 3;
|
||||||
|
|
||||||
#if 1
|
if ((math_fabs(v2_wedge(v2_sub(s.b, s.a), v2_neg(s.a))) <= min_unique_pt_dist_sq) ||
|
||||||
if (colliding ||
|
(math_fabs(v2_wedge(v2_sub(s.c, s.b), v2_neg(s.b))) <= min_unique_pt_dist_sq) ||
|
||||||
math_fabs(v2_wedge(v2_sub(s.c, s.a), v2_neg(s.a))) <= min_unique_pt_dist_sq ||
|
(math_fabs(v2_wedge(v2_sub(s.c, s.a), v2_neg(s.a))) <= min_unique_pt_dist_sq)) {
|
||||||
math_fabs(v2_wedge(v2_sub(s.c, s.b), v2_neg(s.b))) <= min_unique_pt_dist_sq) {
|
|
||||||
/* Simplex lies on origin */
|
/* Simplex lies on origin */
|
||||||
colliding = true;
|
colliding = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Determine region of the simplex in which the origin lies */
|
/* Determine region of the simplex in which the origin lies */
|
||||||
@ -269,11 +263,6 @@ struct collider_collision_points_result collider_collision_points(struct collide
|
|||||||
* Epa (to find collision normal from inside shape)
|
* Epa (to find collision normal from inside shape)
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
//const f32 epa_normal_epsilon_sq = 0;
|
|
||||||
//const f32 epa_normal_epsilon_sq = 0.01f * 0.01f;
|
|
||||||
//const f32 epa_normal_epsilon_sq = 0.001f * 0.001f;
|
|
||||||
const f32 epa_normal_epsilon_sq = F32_INFINITY;
|
|
||||||
|
|
||||||
proto = arena_dry_push(scratch.arena, struct v2);
|
proto = arena_dry_push(scratch.arena, struct v2);
|
||||||
proto_count = 0;
|
proto_count = 0;
|
||||||
{
|
{
|
||||||
@ -290,96 +279,86 @@ struct collider_collision_points_result collider_collision_points(struct collide
|
|||||||
u32 epa_iterations = 0;
|
u32 epa_iterations = 0;
|
||||||
while (colliding) {
|
while (colliding) {
|
||||||
++epa_iterations;
|
++epa_iterations;
|
||||||
f32 pen_len_sq = F32_INFINITY;
|
|
||||||
|
|
||||||
/* Find dir from origin to closest edge */
|
/* Find dir from origin to closest edge */
|
||||||
/* FIXME: Winding order of ps & pe index */
|
/* FIXME: Winding order of ps & pe index */
|
||||||
u32 pen_ps_index = 0;
|
f32 closest_len_sq = F32_INFINITY;
|
||||||
u32 pen_pe_index = 0;
|
struct v2 closest_a = ZI;
|
||||||
struct v2 pen = ZI;
|
struct v2 closest_b = ZI;
|
||||||
|
u32 closest_b_index = 0;
|
||||||
for (u32 i = 0; i < proto_count; ++i) {
|
for (u32 i = 0; i < proto_count; ++i) {
|
||||||
u32 ps_index = i;
|
u32 a_index = i;
|
||||||
u32 pe_index = (i < proto_count - 1) ? (i + 1) : 0;
|
u32 b_index = (i < proto_count - 1) ? (i + 1) : 0;
|
||||||
struct v2 ps = proto[ps_index];
|
struct v2 a = proto[a_index];
|
||||||
struct v2 pe = proto[pe_index];
|
struct v2 b = proto[b_index];
|
||||||
|
|
||||||
struct v2 vse = v2_sub(pe, ps);
|
struct v2 vab = v2_sub(b, a);
|
||||||
struct v2 vso = v2_neg(ps);
|
struct v2 vao = v2_neg(a);
|
||||||
|
|
||||||
struct v2 vsd = v2_mul(vse, clamp_f32(v2_dot(vso, vse) / v2_len_sq(vse), 0, 1));
|
f32 proj_ratio = clamp_f32(v2_dot(vao, vab) / v2_len_sq(vab), 0, 1);
|
||||||
//struct v2 vsd = v2_mul(vse, v2_dot(vso, vse) / v2_len_sq(vse));
|
struct v2 proj = v2_add(a, v2_mul(vab, proj_ratio));
|
||||||
struct v2 pd = v2_add(ps, vsd);
|
|
||||||
|
|
||||||
f32 pd_len_sq = v2_len_sq(pd);
|
f32 proj_len_sq = v2_len_sq(proj);
|
||||||
if (pd_len_sq < pen_len_sq - min_unique_pt_dist_sq) {
|
if (proj_len_sq < closest_len_sq - min_unique_pt_dist_sq) {
|
||||||
pen_ps_index = ps_index;
|
closest_a = a;
|
||||||
pen_pe_index = pe_index;
|
closest_b = b;
|
||||||
pen_len_sq = pd_len_sq;
|
closest_b_index = b_index;
|
||||||
pen = pd;
|
closest_len_sq = proj_len_sq;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
struct v2 vab = v2_sub(closest_b, closest_a);
|
||||||
/* TODO: Remove this (debugging) */
|
|
||||||
s.a = proto[pen_ps_index];
|
|
||||||
s.b = proto[pen_pe_index];
|
|
||||||
s.len = 2;
|
|
||||||
|
|
||||||
/* Find new point in dir */
|
/* Find new point in dir */
|
||||||
DBGSTEP;
|
|
||||||
{
|
|
||||||
/* TODO: If winding order is guaranteed then this can become v2_perp_left/right? */
|
|
||||||
struct v2 a = proto[pen_ps_index];
|
|
||||||
struct v2 b = proto[pen_pe_index];
|
|
||||||
struct v2 vab = v2_sub(b, a);
|
|
||||||
#if 0
|
|
||||||
if (pen_len_sq < epa_normal_epsilon_sq) {
|
|
||||||
/* Next point is in direction of line normal pointing outwards from simplex */
|
|
||||||
struct v2 n = proto[(pen_pe_index < proto_count - 1) ? (pen_pe_index + 1) : 0]; /* Next point along prototype after edge */
|
|
||||||
dir = v2_perp_towards_dir(vab, v2_sub(a, n));
|
|
||||||
} else {
|
|
||||||
dir = v2_perp_towards_dir(vab, a);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
dir = v2_mul(v2_perp(vab), winding);
|
dir = v2_mul(v2_perp(vab), winding);
|
||||||
#endif
|
|
||||||
}
|
|
||||||
m = menkowski_point(shape0, shape1, xf0, xf1, dir);
|
m = menkowski_point(shape0, shape1, xf0, xf1, dir);
|
||||||
|
|
||||||
/* Check unique */
|
/* TODO: Remove this (debugging) */
|
||||||
/* TODO: Better */
|
|
||||||
{
|
{
|
||||||
b32 unique = true;
|
|
||||||
for (u32 i = 0; i < proto_count; ++i) {
|
|
||||||
struct v2 edge_start = proto[i];
|
|
||||||
struct v2 edge_end = i < proto_count - 1 ? proto[i + 1] : proto[0];
|
|
||||||
struct v2 vsm = v2_sub(m, edge_start);
|
|
||||||
if (v2_len_sq(vsm) < min_unique_pt_dist_sq ||
|
|
||||||
math_fabs(v2_wedge(v2_sub(edge_end, edge_start), vsm)) < min_unique_pt_dist_sq) {
|
|
||||||
unique = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!unique || epa_iterations >= max_epa_iterations) {
|
|
||||||
res.path = 1;
|
|
||||||
if (pen_len_sq < epa_normal_epsilon_sq) {
|
|
||||||
normal = v2_norm(dir);
|
normal = v2_norm(dir);
|
||||||
} else {
|
s.a = closest_a;
|
||||||
normal = v2_norm(pen);
|
s.b = closest_b;
|
||||||
|
s.len = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Check validity of new point */
|
||||||
|
DBGSTEP;
|
||||||
|
{
|
||||||
|
b32 valid = true;
|
||||||
|
|
||||||
|
{
|
||||||
|
const f32 validity_epsilon = min_unique_pt_dist_sq; /* Arbitrary */
|
||||||
|
//const f32 validity_epsilon = 0.000000001f; /* Arbitrary */
|
||||||
|
|
||||||
|
struct v2 vam = v2_sub(m, closest_a);
|
||||||
|
struct v2 vbm = v2_sub(closest_b, closest_a);
|
||||||
|
|
||||||
|
f32 dot = v2_dot(vab, vam) / v2_len_sq(vab);
|
||||||
|
|
||||||
|
if (dot >= -validity_epsilon && dot <= 1 - validity_epsilon && (v2_wedge(vab, vam) * -winding) >= -validity_epsilon) {
|
||||||
|
/* New point is not between edge */
|
||||||
|
valid = false;
|
||||||
|
} else if (v2_len_sq(vam) < min_unique_pt_dist_sq || v2_len_sq(vbm) < min_unique_pt_dist_sq) {
|
||||||
|
/* New point is too close to existing */
|
||||||
|
valid = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!valid || epa_iterations >= max_epa_iterations) {
|
||||||
|
res.path = 1;
|
||||||
|
normal = v2_norm(dir);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Insert point into prototype */
|
/* Insert point into prototype */
|
||||||
/* FIXME: Preserve winding order */
|
|
||||||
arena_push(scratch.arena, struct collider_menkowski_point);
|
arena_push(scratch.arena, struct collider_menkowski_point);
|
||||||
++proto_count;
|
++proto_count;
|
||||||
for (u32 i = proto_count - 1; i > pen_pe_index; --i) {
|
for (u32 i = proto_count - 1; i > closest_b_index; --i) {
|
||||||
u32 shift_from = (i > 0) ? i - 1 : proto_count - 1;
|
u32 shift_from = (i > 0) ? i - 1 : proto_count - 1;
|
||||||
u32 shift_to = i;
|
u32 shift_to = i;
|
||||||
proto[shift_to] = proto[shift_from];
|
proto[shift_to] = proto[shift_from];
|
||||||
}
|
}
|
||||||
proto[pen_pe_index] = m;
|
proto[closest_b_index] = m;
|
||||||
}
|
}
|
||||||
} else if (simplex_is_closest_edge) {
|
} else if (simplex_is_closest_edge) {
|
||||||
if (s.len == 1) {
|
if (s.len == 1) {
|
||||||
@ -724,24 +703,11 @@ struct collider_collision_points_result collider_collision_points(struct collide
|
|||||||
|
|
||||||
res.solved = true;
|
res.solved = true;
|
||||||
abort:
|
abort:
|
||||||
if (proto_count > 0) {
|
|
||||||
u32 len = min_u32(proto_count, ARRAY_COUNT(res.prototype.points));
|
u32 len = min_u32(proto_count, ARRAY_COUNT(res.prototype.points));
|
||||||
for (u32 i = 0; i < len; ++i) {
|
for (u32 i = 0; i < len; ++i) {
|
||||||
res.prototype.points[i] = proto[i];
|
res.prototype.points[i] = proto[i];
|
||||||
}
|
}
|
||||||
res.prototype.len = len;
|
res.prototype.len = len;
|
||||||
} else {
|
|
||||||
if (s.len >= 1) {
|
|
||||||
res.prototype.points[0] = s.a;
|
|
||||||
if (s.len >= 2) {
|
|
||||||
res.prototype.points[1] = s.b;
|
|
||||||
if (s.len >= 3) {
|
|
||||||
res.prototype.points[2] = s.c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
res.prototype.len = s.len;
|
|
||||||
}
|
|
||||||
res.normal = normal;
|
res.normal = normal;
|
||||||
res.points[0] = points[0];
|
res.points[0] = points[0];
|
||||||
res.points[1] = points[1];
|
res.points[1] = points[1];
|
||||||
|
|||||||
18
src/game.c
18
src/game.c
@ -136,10 +136,13 @@ INTERNAL void spawn_test_entities(f32 offset)
|
|||||||
|
|
||||||
struct entity *e = entity_alloc(root);
|
struct entity *e = entity_alloc(root);
|
||||||
|
|
||||||
|
#if 1
|
||||||
//struct v2 pos = V2(0.25, -10);
|
//struct v2 pos = V2(0.25, -10);
|
||||||
//struct v2 pos = V2(0.25, -7);
|
//struct v2 pos = V2(0.25, -7);
|
||||||
//struct v2 pos = V2(0.25, -5.27);
|
//struct v2 pos = V2(0.25, -5.27);
|
||||||
struct v2 pos = V2(0.5, -2);
|
//struct v2 pos = V2(0.5, -1.5);
|
||||||
|
struct v2 pos = V2(1, -1);
|
||||||
|
//struct v2 pos = V2(0.300121694803, -1.322724342346);
|
||||||
//struct v2 pos = V2(1.0295, -1);
|
//struct v2 pos = V2(1.0295, -1);
|
||||||
|
|
||||||
pos = v2_add(pos, V2(0, offset));
|
pos = v2_add(pos, V2(0, offset));
|
||||||
@ -147,7 +150,7 @@ INTERNAL void spawn_test_entities(f32 offset)
|
|||||||
|
|
||||||
//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);
|
||||||
//struct v2 size = V2(3.0, 0.5);
|
//struct v2 size = V2(0.5, 0.25);
|
||||||
//struct v2 size = V2(1.0, 1.0);
|
//struct v2 size = V2(1.0, 1.0);
|
||||||
//struct v2 size = V2(1.5, 1.5);
|
//struct v2 size = V2(1.5, 1.5);
|
||||||
//f32 r = PI;
|
//f32 r = PI;
|
||||||
@ -159,6 +162,9 @@ INTERNAL void spawn_test_entities(f32 offset)
|
|||||||
f32 r = 0;
|
f32 r = 0;
|
||||||
|
|
||||||
struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size);
|
struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size);
|
||||||
|
#else
|
||||||
|
struct xform xf = { .bx = {0.0382978655, -0.498547733}, .by = {0.498547733, 0.0382978655}, .og = {2.01672602, -1.06180537}, };
|
||||||
|
#endif
|
||||||
|
|
||||||
entity_set_xform(e, xf);
|
entity_set_xform(e, xf);
|
||||||
|
|
||||||
@ -196,6 +202,7 @@ INTERNAL void spawn_test_entities(f32 offset)
|
|||||||
{
|
{
|
||||||
struct entity *e = entity_alloc(root);
|
struct entity *e = entity_alloc(root);
|
||||||
|
|
||||||
|
#if 0
|
||||||
//struct v2 pos = V2(0.25, -10);
|
//struct v2 pos = V2(0.25, -10);
|
||||||
//struct v2 pos = V2(0.25, -7);
|
//struct v2 pos = V2(0.25, -7);
|
||||||
//struct v2 pos = V2(0.25, -5.27);
|
//struct v2 pos = V2(0.25, -5.27);
|
||||||
@ -215,6 +222,9 @@ INTERNAL void spawn_test_entities(f32 offset)
|
|||||||
f32 r = 0;
|
f32 r = 0;
|
||||||
|
|
||||||
struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size);
|
struct xform xf = XFORM_TRS(.t = pos, .r = r, .s = size);
|
||||||
|
#else
|
||||||
|
struct xform xf = { .bx = {-0.108915359, -0.488007843}, .by = {0.488007843, -0.108915359}, .og = {1.62569654, -0.750172377}, };
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
entity_set_xform(e, xf);
|
entity_set_xform(e, xf);
|
||||||
@ -1082,11 +1092,11 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
|||||||
#if 1
|
#if 1
|
||||||
if (entity_has_prop(ent, ENTITY_PROP_TEST)) {
|
if (entity_has_prop(ent, ENTITY_PROP_TEST)) {
|
||||||
//if ((true)) {
|
//if ((true)) {
|
||||||
#if 0
|
#if 1
|
||||||
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 1
|
#elif 0
|
||||||
ent->local_collider.points[0] = V2(0, 0.5);
|
ent->local_collider.points[0] = V2(0, 0.5);
|
||||||
ent->local_collider.points[1] = V2(0, -0.5);
|
ent->local_collider.points[1] = V2(0, -0.5);
|
||||||
ent->local_collider.count = 2;
|
ent->local_collider.count = 2;
|
||||||
|
|||||||
@ -1051,7 +1051,7 @@ INTERNAL void user_update(void)
|
|||||||
#if 0
|
#if 0
|
||||||
b32 should_draw = false;
|
b32 should_draw = false;
|
||||||
for (u32 i = 0; i < ent->num_contacts; ++i) {
|
for (u32 i = 0; i < ent->num_contacts; ++i) {
|
||||||
if (ent->contacts[i].starting_separation < -0.5) {
|
if (ent->contacts[i].starting_separation < -0.1) {
|
||||||
should_draw = true;
|
should_draw = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1136,6 +1136,7 @@ INTERNAL void user_update(void)
|
|||||||
};
|
};
|
||||||
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);
|
||||||
|
for (u64 i = 0; i < m.count; ++i) draw_solid_circle(G.viewport_canvas, m.points[i], 10, color, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Draw simplex */
|
/* Draw simplex */
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user