don't merge walls with different collision directions
This commit is contained in:
parent
6c884a2228
commit
b0ffb143f2
@ -98,8 +98,8 @@ void phys_create_and_update_contacts(struct phys_step_ctx *ctx, f32 elapsed_dt,
|
|||||||
b32 create_constraint = collider_res.num_points > 0;
|
b32 create_constraint = collider_res.num_points > 0;
|
||||||
if (create_constraint) {
|
if (create_constraint) {
|
||||||
struct v2 normal = collider_res.normal;
|
struct v2 normal = collider_res.normal;
|
||||||
struct v2 dir0 = e0->test_dir;
|
struct v2 dir0 = e0->collision_dir;
|
||||||
struct v2 dir1 = e1->test_dir;
|
struct v2 dir1 = e1->collision_dir;
|
||||||
f32 threshold = 0.5;
|
f32 threshold = 0.5;
|
||||||
if (create_constraint && !v2_is_zero(dir0)) {
|
if (create_constraint && !v2_is_zero(dir0)) {
|
||||||
create_constraint = v2_dot(dir0, normal) > threshold;
|
create_constraint = v2_dot(dir0, normal) > threshold;
|
||||||
|
|||||||
@ -41,6 +41,11 @@ u64 rand_u64_from_seed(u64 seed)
|
|||||||
return seed;
|
return seed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u64 rand_u64_from_seeds(u64 seed_a, u64 seed_b)
|
||||||
|
{
|
||||||
|
return rand_u64_from_seed((seed_a * 3) + seed_b);
|
||||||
|
}
|
||||||
|
|
||||||
f64 rand_f64_from_seed(u64 seed, f64 range_start, f64 range_end)
|
f64 rand_f64_from_seed(u64 seed, f64 range_start, f64 range_end)
|
||||||
{
|
{
|
||||||
return range_start + (range_end - range_start) * ((f64)(rand_u64_from_seed(seed) % F64_RAND_MAX) / (f64)F64_RAND_MAX);
|
return range_start + (range_end - range_start) * ((f64)(rand_u64_from_seed(seed) % F64_RAND_MAX) / (f64)F64_RAND_MAX);
|
||||||
|
|||||||
@ -11,6 +11,7 @@ u64 rand_u64_from_state(struct rand_state *state);
|
|||||||
f64 rand_f64_from_state(struct rand_state *state, f64 range_start, f64 range_end);
|
f64 rand_f64_from_state(struct rand_state *state, f64 range_start, f64 range_end);
|
||||||
|
|
||||||
u64 rand_u64_from_seed(u64 seed);
|
u64 rand_u64_from_seed(u64 seed);
|
||||||
|
u64 rand_u64_from_seeds(u64 seed_a, u64 seed_b);
|
||||||
f64 rand_f64_from_seed(u64 seed, f64 range_start, f64 range_end);
|
f64 rand_f64_from_seed(u64 seed, f64 range_start, f64 range_end);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -73,28 +73,6 @@ enum sim_ent_prop {
|
|||||||
struct sim_ent {
|
struct sim_ent {
|
||||||
struct sim_snapshot *ss;
|
struct sim_snapshot *ss;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
struct v2 test_dir;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ====================================================================== */
|
/* ====================================================================== */
|
||||||
/* Metadata */
|
/* Metadata */
|
||||||
|
|
||||||
@ -191,7 +169,6 @@ struct sim_ent {
|
|||||||
u8 tile_chunk_tiles[SIM_TILES_PER_CHUNK_SQRT * SIM_TILES_PER_CHUNK_SQRT];
|
u8 tile_chunk_tiles[SIM_TILES_PER_CHUNK_SQRT * SIM_TILES_PER_CHUNK_SQRT];
|
||||||
struct v2i32 tile_chunk_index;
|
struct v2i32 tile_chunk_index;
|
||||||
|
|
||||||
|
|
||||||
/* ====================================================================== */
|
/* ====================================================================== */
|
||||||
/* Client */
|
/* Client */
|
||||||
|
|
||||||
@ -219,6 +196,7 @@ struct sim_ent {
|
|||||||
/* ====================================================================== */
|
/* ====================================================================== */
|
||||||
/* Collider */
|
/* Collider */
|
||||||
|
|
||||||
|
struct v2 collision_dir; /* If set, then only collisions coming from this direction will generate contacts (used for walls to prevent ghost collisions) */
|
||||||
struct collider_shape local_collider;
|
struct collider_shape local_collider;
|
||||||
|
|
||||||
#if COLLIDER_DEBUG
|
#if COLLIDER_DEBUG
|
||||||
|
|||||||
111
src/sim_step.c
111
src/sim_step.c
@ -461,14 +461,13 @@ INTERNAL void test_generate_walls(struct sim_snapshot *world)
|
|||||||
for (i32 tile_y = 0; tile_y < y_iterations; ++tile_y) {
|
for (i32 tile_y = 0; tile_y < y_iterations; ++tile_y) {
|
||||||
i32 wall_start = -1;
|
i32 wall_start = -1;
|
||||||
i32 wall_end = -1;
|
i32 wall_end = -1;
|
||||||
i32 last_wall_dir = -1;
|
i32 wall_dir = -1;
|
||||||
for (i32 tile_x = 0; tile_x < x_iterations; ++tile_x) {
|
for (i32 tile_x = 0; tile_x < x_iterations; ++tile_x) {
|
||||||
i32 wall_dir = -1;
|
i32 desired_wall_dir = -1;
|
||||||
enum sim_tile_kind tile = SIM_TILE_KIND_NONE;
|
enum sim_tile_kind tile = SIM_TILE_KIND_NONE;
|
||||||
if (tile_x < SIM_TILES_PER_CHUNK_SQRT && tile_y < SIM_TILES_PER_CHUNK_SQRT) {
|
if (tile_x < SIM_TILES_PER_CHUNK_SQRT && tile_y < SIM_TILES_PER_CHUNK_SQRT) {
|
||||||
tile = sim_get_chunk_tile(chunk, V2I32(tile_x, tile_y));
|
tile = sim_get_chunk_tile(chunk, V2I32(tile_x, tile_y));
|
||||||
}
|
}
|
||||||
b32 should_have_top_wall = false;
|
|
||||||
if (tile_x < SIM_TILES_PER_CHUNK_SQRT) {
|
if (tile_x < SIM_TILES_PER_CHUNK_SQRT) {
|
||||||
enum sim_tile_kind top_tile = SIM_TILE_KIND_NONE;
|
enum sim_tile_kind top_tile = SIM_TILE_KIND_NONE;
|
||||||
if (tile_y == 0) {
|
if (tile_y == 0) {
|
||||||
@ -481,29 +480,25 @@ INTERNAL void test_generate_walls(struct sim_snapshot *world)
|
|||||||
}
|
}
|
||||||
if (tile == SIM_TILE_KIND_WALL) {
|
if (tile == SIM_TILE_KIND_WALL) {
|
||||||
/* Process wall tile */
|
/* Process wall tile */
|
||||||
should_have_top_wall = top_tile != SIM_TILE_KIND_WALL;
|
if (top_tile != SIM_TILE_KIND_WALL) {
|
||||||
wall_dir = 0;
|
desired_wall_dir = 0;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Process non-wall tile */
|
/* Process non-wall tile */
|
||||||
should_have_top_wall = top_tile == SIM_TILE_KIND_WALL;
|
if (top_tile == SIM_TILE_KIND_WALL) {
|
||||||
wall_dir = 2;
|
desired_wall_dir = 2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (should_have_top_wall) {
|
|
||||||
if (wall_start < 0) {
|
/* Stop wall */
|
||||||
/* Start wall */
|
if (wall_dir >= 0 && desired_wall_dir != wall_dir) {
|
||||||
wall_start = tile_x;
|
|
||||||
}
|
|
||||||
/* Extend wall */
|
|
||||||
wall_end = tile_x + 1;
|
|
||||||
last_wall_dir = wall_dir;
|
|
||||||
} else if (wall_end >= 0) {
|
|
||||||
/* Stop wall */
|
|
||||||
struct v2i32 start = sim_world_tile_index_from_local_tile_index(chunk_index, V2I32(wall_start, tile_y));
|
struct v2i32 start = sim_world_tile_index_from_local_tile_index(chunk_index, V2I32(wall_start, tile_y));
|
||||||
struct v2i32 end = sim_world_tile_index_from_local_tile_index(chunk_index, V2I32(wall_end, tile_y));
|
struct v2i32 end = sim_world_tile_index_from_local_tile_index(chunk_index, V2I32(wall_end, tile_y));
|
||||||
struct wall_node *node = NULL;
|
struct wall_node *node = NULL;
|
||||||
if (wall_start == 0) {
|
if (wall_start == 0) {
|
||||||
u64 start_hash = rand_u64_from_seed(*(u64 *)&start);
|
u64 start_hash = rand_u64_from_seed(*(u64 *)&start);
|
||||||
|
start_hash = rand_u64_from_seeds(start_hash, wall_dir);
|
||||||
struct dict_entry *entry = dict_get_entry(&horizontal_ends_dict, start_hash);
|
struct dict_entry *entry = dict_get_entry(&horizontal_ends_dict, start_hash);
|
||||||
if (entry) {
|
if (entry) {
|
||||||
/* Existing wall exists accross chunk boundary */
|
/* Existing wall exists accross chunk boundary */
|
||||||
@ -515,17 +510,29 @@ INTERNAL void test_generate_walls(struct sim_snapshot *world)
|
|||||||
node = arena_push(scratch.arena, struct wall_node);
|
node = arena_push(scratch.arena, struct wall_node);
|
||||||
node->start = start;
|
node->start = start;
|
||||||
node->next = first_wall;
|
node->next = first_wall;
|
||||||
node->wall_dir = last_wall_dir;
|
node->wall_dir = wall_dir;
|
||||||
first_wall = node;
|
first_wall = node;
|
||||||
}
|
}
|
||||||
node->end = end;
|
node->end = end;
|
||||||
if (wall_end == SIM_TILES_PER_CHUNK_SQRT) {
|
if (wall_end == SIM_TILES_PER_CHUNK_SQRT) {
|
||||||
u64 end_hash = rand_u64_from_seed(*(u64 *)&end);
|
u64 end_hash = rand_u64_from_seed(*(u64 *)&end);
|
||||||
|
end_hash = rand_u64_from_seeds(end_hash, wall_dir);
|
||||||
dict_set(scratch.arena, &horizontal_ends_dict, end_hash, node);
|
dict_set(scratch.arena, &horizontal_ends_dict, end_hash, node);
|
||||||
}
|
}
|
||||||
wall_start = -1;
|
wall_start = -1;
|
||||||
wall_end = -1;
|
wall_end = -1;
|
||||||
last_wall_dir = -1;
|
wall_dir = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Start / extend wall */
|
||||||
|
if (desired_wall_dir >= 0) {
|
||||||
|
if (wall_dir != desired_wall_dir) {
|
||||||
|
/* Start wall */
|
||||||
|
wall_start = tile_x;
|
||||||
|
}
|
||||||
|
/* Extend wall */
|
||||||
|
wall_end = tile_x + 1;
|
||||||
|
wall_dir = desired_wall_dir;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -543,15 +550,14 @@ INTERNAL void test_generate_walls(struct sim_snapshot *world)
|
|||||||
for (i32 tile_x = 0; tile_x < x_iterations; ++tile_x) {
|
for (i32 tile_x = 0; tile_x < x_iterations; ++tile_x) {
|
||||||
i32 wall_start = -1;
|
i32 wall_start = -1;
|
||||||
i32 wall_end = -1;
|
i32 wall_end = -1;
|
||||||
i32 last_wall_dir = -1;
|
i32 wall_dir = -1;
|
||||||
for (i32 tile_y = 0; tile_y < y_iterations; ++tile_y) {
|
for (i32 tile_y = 0; tile_y < y_iterations; ++tile_y) {
|
||||||
i32 wall_dir = -1;
|
i32 desired_wall_dir = -1;
|
||||||
enum sim_tile_kind tile = SIM_TILE_KIND_NONE;
|
enum sim_tile_kind tile = SIM_TILE_KIND_NONE;
|
||||||
if (tile_x < SIM_TILES_PER_CHUNK_SQRT && tile_y < SIM_TILES_PER_CHUNK_SQRT) {
|
if (tile_x < SIM_TILES_PER_CHUNK_SQRT && tile_y < SIM_TILES_PER_CHUNK_SQRT) {
|
||||||
tile = sim_get_chunk_tile(chunk, V2I32(tile_x, tile_y));
|
tile = sim_get_chunk_tile(chunk, V2I32(tile_x, tile_y));
|
||||||
}
|
}
|
||||||
|
|
||||||
b32 should_have_left_wall = false;
|
|
||||||
if (tile_y < SIM_TILES_PER_CHUNK_SQRT) {
|
if (tile_y < SIM_TILES_PER_CHUNK_SQRT) {
|
||||||
enum sim_tile_kind left_tile = SIM_TILE_KIND_NONE;
|
enum sim_tile_kind left_tile = SIM_TILE_KIND_NONE;
|
||||||
if (tile_x == 0) {
|
if (tile_x == 0) {
|
||||||
@ -564,29 +570,25 @@ INTERNAL void test_generate_walls(struct sim_snapshot *world)
|
|||||||
}
|
}
|
||||||
if (tile == SIM_TILE_KIND_WALL) {
|
if (tile == SIM_TILE_KIND_WALL) {
|
||||||
/* Process wall tile */
|
/* Process wall tile */
|
||||||
should_have_left_wall = left_tile != SIM_TILE_KIND_WALL;
|
if (left_tile != SIM_TILE_KIND_WALL) {
|
||||||
wall_dir = 3;
|
desired_wall_dir = 3;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Process non-wall tile */
|
/* Process non-wall tile */
|
||||||
should_have_left_wall = left_tile == SIM_TILE_KIND_WALL;
|
if (left_tile == SIM_TILE_KIND_WALL) {
|
||||||
wall_dir = 1;
|
desired_wall_dir = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (should_have_left_wall) {
|
|
||||||
if (wall_start < 0) {
|
/* Stop wall */
|
||||||
/* Start wall */
|
if (wall_dir >= 0 && desired_wall_dir != wall_dir) {
|
||||||
wall_start = tile_y;
|
|
||||||
}
|
|
||||||
/* Extend wall */
|
|
||||||
wall_end = tile_y + 1;
|
|
||||||
last_wall_dir = wall_dir;
|
|
||||||
} else if (wall_end >= 0) {
|
|
||||||
/* Stop wall */
|
|
||||||
struct v2i32 start = sim_world_tile_index_from_local_tile_index(chunk_index, V2I32(tile_x, wall_start));
|
struct v2i32 start = sim_world_tile_index_from_local_tile_index(chunk_index, V2I32(tile_x, wall_start));
|
||||||
struct v2i32 end = sim_world_tile_index_from_local_tile_index(chunk_index, V2I32(tile_x, wall_end));
|
struct v2i32 end = sim_world_tile_index_from_local_tile_index(chunk_index, V2I32(tile_x, wall_end));
|
||||||
struct wall_node *node = NULL;
|
struct wall_node *node = NULL;
|
||||||
if (wall_start == 0) {
|
if (wall_start == 0) {
|
||||||
u64 start_hash = rand_u64_from_seed(*(u64 *)&start);
|
u64 start_hash = rand_u64_from_seed(*(u64 *)&start);
|
||||||
|
start_hash = rand_u64_from_seeds(start_hash, wall_dir);
|
||||||
struct dict_entry *entry = dict_get_entry(&vertical_ends_dict, start_hash);
|
struct dict_entry *entry = dict_get_entry(&vertical_ends_dict, start_hash);
|
||||||
if (entry) {
|
if (entry) {
|
||||||
/* Existing wall exists accross chunk boundary */
|
/* Existing wall exists accross chunk boundary */
|
||||||
@ -598,17 +600,29 @@ INTERNAL void test_generate_walls(struct sim_snapshot *world)
|
|||||||
node = arena_push(scratch.arena, struct wall_node);
|
node = arena_push(scratch.arena, struct wall_node);
|
||||||
node->start = start;
|
node->start = start;
|
||||||
node->next = first_wall;
|
node->next = first_wall;
|
||||||
node->wall_dir = last_wall_dir;
|
node->wall_dir = wall_dir;
|
||||||
first_wall = node;
|
first_wall = node;
|
||||||
}
|
}
|
||||||
node->end = end;
|
node->end = end;
|
||||||
if (wall_end == SIM_TILES_PER_CHUNK_SQRT) {
|
if (wall_end == SIM_TILES_PER_CHUNK_SQRT) {
|
||||||
u64 end_hash = rand_u64_from_seed(*(u64 *)&end);
|
u64 end_hash = rand_u64_from_seed(*(u64 *)&end);
|
||||||
|
end_hash = rand_u64_from_seeds(end_hash, wall_dir);
|
||||||
dict_set(scratch.arena, &vertical_ends_dict, end_hash, node);
|
dict_set(scratch.arena, &vertical_ends_dict, end_hash, node);
|
||||||
}
|
}
|
||||||
wall_start = -1;
|
wall_start = -1;
|
||||||
wall_end = -1;
|
wall_end = -1;
|
||||||
last_wall_dir = -1;
|
wall_dir = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Start / extend wall */
|
||||||
|
if (desired_wall_dir >= 0) {
|
||||||
|
if (wall_dir != desired_wall_dir) {
|
||||||
|
/* Start wall */
|
||||||
|
wall_start = tile_y;
|
||||||
|
}
|
||||||
|
/* Extend wall */
|
||||||
|
wall_end = tile_y + 1;
|
||||||
|
wall_dir = desired_wall_dir;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -629,24 +643,9 @@ INTERNAL void test_generate_walls(struct sim_snapshot *world)
|
|||||||
wall_ent->local_collider.count = 2;
|
wall_ent->local_collider.count = 2;
|
||||||
wall_ent->local_collider.points[1] = v2_sub(end, start);
|
wall_ent->local_collider.points[1] = v2_sub(end, start);
|
||||||
|
|
||||||
switch (node->wall_dir) {
|
LOCAL_PERSIST struct v2 dirs[4] = { V2(0, -1), V2(1, 0), V2(0, 1), V2(-1, 0) };
|
||||||
case 0:
|
ASSERT(node->wall_dir >= 0 && (u32)node->wall_dir < ARRAY_COUNT(dirs));
|
||||||
{
|
wall_ent->collision_dir = dirs[node->wall_dir];
|
||||||
wall_ent->test_dir = V2(0, -1);
|
|
||||||
} break;
|
|
||||||
case 1:
|
|
||||||
{
|
|
||||||
wall_ent->test_dir = V2(1, 0);
|
|
||||||
} break;
|
|
||||||
case 2:
|
|
||||||
{
|
|
||||||
wall_ent->test_dir = V2(0, 1);
|
|
||||||
} break;
|
|
||||||
case 3:
|
|
||||||
{
|
|
||||||
wall_ent->test_dir = V2(-1, 0);
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
|
|
||||||
sim_ent_activate(wall_ent, world->tick);
|
sim_ent_activate(wall_ent, world->tick);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -410,10 +410,10 @@ INTERNAL struct string get_ent_debug_text(struct arena *arena, struct sim_ent *e
|
|||||||
f32 angular_velocity = ent->angular_velocity;
|
f32 angular_velocity = ent->angular_velocity;
|
||||||
res.len += string_format(arena, LIT("pos: (%F, %F)\n"), FMT_FLOAT(xf.og.x), FMT_FLOAT(xf.og.y)).len;
|
res.len += string_format(arena, LIT("pos: (%F, %F)\n"), FMT_FLOAT(xf.og.x), FMT_FLOAT(xf.og.y)).len;
|
||||||
res.len += string_format(arena, LIT("linear velocity: (%F, %F)\n"), FMT_FLOAT(linear_velocity.x), FMT_FLOAT(linear_velocity.y)).len;
|
res.len += string_format(arena, LIT("linear velocity: (%F, %F)\n"), FMT_FLOAT(linear_velocity.x), FMT_FLOAT(linear_velocity.y)).len;
|
||||||
res.len += string_format(arena, LIT("angular velocity: %F\n"), FMT_FLOAT(angular_velocity)).len;
|
res.len += string_format(arena, LIT("angular velocity: %F\n"), FMT_FLOAT(angular_velocity)).len;
|
||||||
|
|
||||||
/* Test */
|
/* Test */
|
||||||
res.len += string_format(arena, LIT("test_dir: (%F, %F)\n"), FMT_FLOAT(ent->test_dir.x), FMT_FLOAT(ent->test_dir.y)).len;
|
res.len += string_format(arena, LIT("collision dir: (%F, %F)\n"), FMT_FLOAT(ent->collision_dir.x), FMT_FLOAT(ent->collision_dir.y)).len;
|
||||||
|
|
||||||
/* Children */
|
/* Children */
|
||||||
if (!sim_ent_id_is_nil(ent->first) || !sim_ent_id_is_nil(ent->last)) {
|
if (!sim_ent_id_is_nil(ent->first) || !sim_ent_id_is_nil(ent->last)) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user