unevenly-scaled shape collisions working
This commit is contained in:
parent
daf1a862f5
commit
31082916ad
@ -24,6 +24,7 @@ INTERNAL void _dbgbreakable(void)
|
||||
|
||||
struct v2 collider_support_point(struct collider_shape *a, struct xform xf, struct v2 dir)
|
||||
{
|
||||
#if 0
|
||||
struct v2 *points = a->points;
|
||||
u32 count = a->count;
|
||||
f32 radius = a->radius;
|
||||
@ -46,6 +47,62 @@ struct v2 collider_support_point(struct collider_shape *a, struct xform xf, stru
|
||||
}
|
||||
|
||||
return furthest;
|
||||
#elif 0
|
||||
struct v2 *points = a->points;
|
||||
u32 count = a->count;
|
||||
f32 radius = a->radius;
|
||||
|
||||
/* TODO: Could probably binary search for largest dot since shape is convex */
|
||||
struct xform inv = xform_invert(xf);
|
||||
dir = xform_basis_mul_v2(inv, dir);
|
||||
|
||||
struct v2 furthest = ZI;
|
||||
f32 furthest_dot = -F32_INFINITY;
|
||||
for (u32 i = 0; i < count; ++i) {
|
||||
struct v2 p = points[i];
|
||||
f32 dot = v2_dot(dir, p);
|
||||
if (dot > furthest_dot) {
|
||||
furthest = p;
|
||||
furthest_dot = dot;
|
||||
}
|
||||
}
|
||||
|
||||
if (radius > 0.0) {
|
||||
dir = v2_with_len(dir, radius);
|
||||
furthest = v2_add(furthest, dir);
|
||||
}
|
||||
|
||||
furthest = xform_mul_v2(xf, furthest);
|
||||
|
||||
return furthest;
|
||||
#else
|
||||
struct v2 *points = a->points;
|
||||
u32 count = a->count;
|
||||
f32 radius = a->radius;
|
||||
|
||||
dir = v2_rotated(dir, -xform_get_rotation(xf));
|
||||
dir = v2_mul_v2(dir, xform_get_scale(xf));
|
||||
|
||||
struct v2 furthest = ZI;
|
||||
f32 furthest_dot = -F32_INFINITY;
|
||||
for (u32 i = 0; i < count; ++i) {
|
||||
struct v2 p = points[i];
|
||||
f32 dot = v2_dot(dir, p);
|
||||
if (dot > furthest_dot) {
|
||||
furthest = p;
|
||||
furthest_dot = dot;
|
||||
}
|
||||
}
|
||||
|
||||
if (radius > 0.0) {
|
||||
dir = v2_with_len(dir, radius);
|
||||
furthest = v2_add(furthest, dir);
|
||||
}
|
||||
|
||||
furthest = xform_mul_v2(xf, furthest);
|
||||
|
||||
return furthest;
|
||||
#endif
|
||||
}
|
||||
|
||||
INTERNAL u32 collider_support_point_index(struct collider_shape *a, struct xform xf, struct v2 dir)
|
||||
@ -487,7 +544,7 @@ struct collider_collision_points_result collider_collision_points(struct collide
|
||||
}
|
||||
}
|
||||
|
||||
#if 1
|
||||
#if 0
|
||||
if (radius0 > 0.0) {
|
||||
struct v2 scale = xform_get_scale(xf0);
|
||||
struct v2 normal_radius = v2_mul_v2(v2_mul(normal, radius0), scale);
|
||||
@ -501,6 +558,24 @@ struct collider_collision_points_result collider_collision_points(struct collide
|
||||
a1 = v2_sub(a1, normal_radius);
|
||||
b1 = v2_sub(b1, normal_radius);
|
||||
}
|
||||
#else
|
||||
if (radius0 > 0.0) {
|
||||
struct v2 radius_dir = v2_rotated(normal, -xform_get_rotation(xf0));
|
||||
radius_dir = v2_mul_v2(radius_dir, xform_get_scale(xf0));
|
||||
radius_dir = v2_with_len(radius_dir, radius0);
|
||||
radius_dir = xform_basis_mul_v2(xf0, radius_dir);
|
||||
a0 = v2_add(a0, radius_dir);
|
||||
b0 = v2_add(b0, radius_dir);
|
||||
}
|
||||
|
||||
if (radius1 > 0.0) {
|
||||
struct v2 radius_dir = v2_rotated(normal, -xform_get_rotation(xf1));
|
||||
radius_dir = v2_mul_v2(radius_dir, xform_get_scale(xf1));
|
||||
radius_dir = v2_with_len(radius_dir, radius1);
|
||||
radius_dir = xform_basis_mul_v2(xf1, radius_dir);
|
||||
a1 = v2_sub(a1, radius_dir);
|
||||
b1 = v2_sub(b1, radius_dir);
|
||||
}
|
||||
#endif
|
||||
|
||||
f32 a0t = 0;
|
||||
@ -571,10 +646,17 @@ struct collider_collision_points_result collider_collision_points(struct collide
|
||||
point->point = contact_b;
|
||||
}
|
||||
|
||||
#if 0
|
||||
res.a0 = a0_clipped;
|
||||
res.a1 = a1_clipped;
|
||||
res.b0 = b0_clipped;
|
||||
res.b1 = b1_clipped;
|
||||
#else
|
||||
res.a0 = a0;
|
||||
res.a1 = a1;
|
||||
res.b0 = b0;
|
||||
res.b1 = b1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -38,7 +38,7 @@
|
||||
#define GAME_PHYSICS_ENABLE_RELAXATION 1
|
||||
#define GAME_PHYSICS_ENABLE_GROUND_FRICTION 0
|
||||
|
||||
#define GAME_SPAWN_LOTS 0
|
||||
#define GAME_SPAWN_LOTS 1
|
||||
|
||||
#define GAME_MAX_LINEAR_VELOCITY 100
|
||||
#define GAME_MAX_ANGULAR_VELOCITY ((2 * PI) * 20)
|
||||
|
||||
@ -283,8 +283,16 @@ void draw_solid_collider_line(struct renderer_canvas *canvas, struct xform draw_
|
||||
points[i] = p;
|
||||
}
|
||||
|
||||
#if 1
|
||||
struct v2_array poly = { .points = points, .count = detail };
|
||||
draw_solid_poly_line(canvas, poly, true, thickness, color);
|
||||
#else
|
||||
for (u64 i = 0; i < detail; ++i) {
|
||||
struct v2 point = points[i];
|
||||
(UNUSED)thickness;
|
||||
draw_solid_circle(canvas, point, 3, color, 10);
|
||||
}
|
||||
#endif
|
||||
|
||||
scratch_end(scratch);
|
||||
}
|
||||
|
||||
43
src/game.c
43
src/game.c
@ -134,7 +134,7 @@ INTERNAL void spawn_test_entities(f32 offset)
|
||||
//struct v2 pos = V2(0.25, -10);
|
||||
//struct v2 pos = V2(0.25, -7);
|
||||
//struct v2 pos = V2(0.25, -5.27);
|
||||
struct v2 pos = V2(0.25, -1);
|
||||
struct v2 pos = V2(0.5, -1);
|
||||
//struct v2 pos = V2(1.1230469346046448864129274625156, -1); /* Touching right side of box */
|
||||
//struct v2 pos = V2(1.1230469346046448864129274625156 - 0.0001, -1); /* Touching right side of box */
|
||||
//struct v2 pos = V2(0.374142020941, -0.246118023992); /* Touching glitch spot */
|
||||
@ -143,14 +143,16 @@ INTERNAL void spawn_test_entities(f32 offset)
|
||||
pos = v2_add(pos, V2(0, offset_all));
|
||||
|
||||
//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(1.0, 0.5);
|
||||
//f32 r = PI;
|
||||
//f32 r = PI / 4;
|
||||
f32 r = PI / 4;
|
||||
//f32 r = PI / 3;
|
||||
//f32 r = 0.05;
|
||||
//f32 r = PI / 2;
|
||||
f32 r = 0;
|
||||
//f32 r = 0;
|
||||
//f32 skew = PI / 4;
|
||||
//f32 skew = 0.9f;
|
||||
f32 skew = 0;
|
||||
|
||||
struct entity *e = entity_alloc(root);
|
||||
@ -166,9 +168,12 @@ INTERNAL void spawn_test_entities(f32 offset)
|
||||
e->sprite_span_name = STR("idle.two_handed");
|
||||
|
||||
entity_enable_prop(e, ENTITY_PROP_PLAYER_CONTROLLED);
|
||||
#if GAME_PHYSICS_ENABLE_GROUND_FRICTION
|
||||
//e->control_force = 4500;
|
||||
//e->control_force = 1200;
|
||||
e->control_force = 1200;
|
||||
#else
|
||||
e->control_force = 250;
|
||||
#endif
|
||||
e->control_torque = 10;
|
||||
e->control.focus = V2(0, -1);
|
||||
|
||||
@ -189,8 +194,7 @@ INTERNAL void spawn_test_entities(f32 offset)
|
||||
//struct v2 pos = V2(0.25, -10);
|
||||
//struct v2 pos = V2(0.25, -7);
|
||||
//struct v2 pos = V2(0.25, -5.27);
|
||||
//struct v2 pos = V2(0.85, -2);
|
||||
struct v2 pos = V2(0.25, -1);
|
||||
struct v2 pos = V2(0.5, -1);
|
||||
//struct v2 pos = V2(1.1230469346046448864129274625156, -1); /* Touching right side of box */
|
||||
//struct v2 pos = V2(1.1230469346046448864129274625156 - 0.0001, -1); /* Touching right side of box */
|
||||
//struct v2 pos = V2(0.374142020941, -0.246118023992); /* Touching glitch spot */
|
||||
@ -199,13 +203,14 @@ INTERNAL void spawn_test_entities(f32 offset)
|
||||
pos = v2_add(pos, V2(0, offset_all));
|
||||
|
||||
//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(1.0, 0.5);
|
||||
//f32 r = PI;
|
||||
//f32 r = PI / 4;
|
||||
f32 r = PI / 4;
|
||||
//f32 r = PI / 3;
|
||||
//f32 r = 0.05;
|
||||
//f32 r = PI / 2;
|
||||
f32 r = 0;
|
||||
//f32 r = 0;
|
||||
//f32 skew = PI / 4;
|
||||
f32 skew = 0;
|
||||
|
||||
@ -268,8 +273,11 @@ INTERNAL void spawn_test_entities(f32 offset)
|
||||
//struct v2 pos = V2(0.5, 29);
|
||||
//struct v2 pos = V2(0.5, 24);
|
||||
//struct v2 pos = V2(1, -1);
|
||||
//struct v2 size = V2(1, 1);
|
||||
#if !GAME_SPAWN_LOTS
|
||||
struct v2 size = V2(1, 1);
|
||||
#else
|
||||
struct v2 size = V2(500, 1);
|
||||
#endif
|
||||
//f32 rot = PI / 4;
|
||||
f32 rot = 0;
|
||||
struct entity *e = entity_alloc(root);
|
||||
@ -832,12 +840,21 @@ INTERNAL void integrate_positions_from_velocities(f32 dt)
|
||||
ent->linear_velocity = v2_clamp_len(ent->linear_velocity, GAME_MAX_LINEAR_VELOCITY);
|
||||
ent->angular_velocity = clamp_f32(ent->angular_velocity, -GAME_MAX_ANGULAR_VELOCITY, GAME_MAX_ANGULAR_VELOCITY);
|
||||
|
||||
#if 0
|
||||
struct xform xf = entity_get_xform(ent);
|
||||
struct v2 tick_linear_velocity = v2_mul(ent->linear_velocity, dt);
|
||||
f32 tick_angular_velocity = ent->angular_velocity * dt;
|
||||
xf.og = v2_add(xf.og, tick_linear_velocity);
|
||||
xf = xform_rotated(xf, tick_angular_velocity);
|
||||
entity_set_xform(ent, xf);
|
||||
#else
|
||||
struct xform xf = entity_get_xform(ent);
|
||||
struct v2 tick_linear_velocity = v2_mul(ent->linear_velocity, dt);
|
||||
f32 tick_angular_velocity = ent->angular_velocity * dt;
|
||||
xf.og = v2_add(xf.og, tick_linear_velocity);
|
||||
xf = xform_rotated_to(xf, xform_get_rotation(xf) + tick_angular_velocity);
|
||||
entity_set_xform(ent, xf);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@ -1056,7 +1073,7 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
||||
ent->local_collider.points[1] = V2(0, -0.5);
|
||||
ent->local_collider.count = 2;
|
||||
ent->local_collider.radius = 0.25;
|
||||
#elif 1
|
||||
#elif 0
|
||||
#if 1
|
||||
/* "Bad" winding order */
|
||||
ent->local_collider.points[0] = V2(-0.5, 0.5);
|
||||
@ -1071,7 +1088,7 @@ INTERNAL void game_update(struct game_cmd_array game_cmds)
|
||||
ent->local_collider.radius = 0.25;
|
||||
//ent->local_collider.radius = math_fabs(math_sin(G.tick.time) / 3);
|
||||
#else
|
||||
ent->local_collider.radius = 0.25;
|
||||
ent->local_collider.radius = 0.5;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
27
src/user.c
27
src/user.c
@ -998,17 +998,34 @@ INTERNAL void user_update(void)
|
||||
struct collider_shape collider = ent->local_collider;
|
||||
u32 color = ent->colliding > 0 ? RGBA_32_F(1, 1, 1, 0.5) : RGBA_32_F(1, 1, 0, 0.25);
|
||||
f32 thickness = 2;
|
||||
//u32 detail = 32;
|
||||
u32 detail = 512;
|
||||
draw_solid_collider_line(G.viewport_canvas, G.world_view, collider, xf, thickness, color, detail);
|
||||
{
|
||||
/* Draw collider using support points */
|
||||
u32 detail = 512;
|
||||
draw_solid_collider_line(G.viewport_canvas, G.world_view, collider, xf, thickness, color, detail);
|
||||
}
|
||||
{
|
||||
/* Draw collider shape points */
|
||||
for (u32 i = 0; i < collider.count; ++i) {
|
||||
struct v2 p = xform_mul_v2(xform_mul(G.world_view, xf), collider.points[i]);
|
||||
draw_solid_circle(G.viewport_canvas, p, 3, COLOR_BLUE, 10);
|
||||
}
|
||||
}
|
||||
if (collider.count == 1 && collider.radius > 0) {
|
||||
/* Draw upwards line for circle */
|
||||
struct v2 start = xf.og;
|
||||
struct v2 end = collider_support_point(&collider, xf, v2_neg(xf.by));
|
||||
struct v2 end = collider_support_point(&collider, xf, xf.by);
|
||||
start = xform_mul_v2(G.world_view, start);
|
||||
end = xform_mul_v2(G.world_view, end);
|
||||
draw_solid_line(G.viewport_canvas, start, end, thickness, color);
|
||||
}
|
||||
#if 0
|
||||
/* Draw support point at focus dir */
|
||||
{
|
||||
struct v2 p = collider_support_point(&collider, xf, ent->control.focus);
|
||||
p = xform_mul_v2(G.world_view, p);
|
||||
draw_solid_circle(G.viewport_canvas, p, 3, COLOR_RED, 10);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Draw collision */
|
||||
@ -1144,7 +1161,7 @@ INTERNAL void user_update(void)
|
||||
struct v2 end = xform_mul_v2(G.world_view, v2_add(point, v2_mul(v2_norm(ent->manifold_normal), len)));
|
||||
draw_solid_arrow_line(G.viewport_canvas, start, end, arrow_thickness, arrow_height, color);
|
||||
}
|
||||
#if 1
|
||||
#if 0
|
||||
/* Draw contact info */
|
||||
{
|
||||
struct font *disp_font = font_load_async(STR("res/fonts/fixedsys.ttf"), 12.0f);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user