tile chunk testing

This commit is contained in:
jacob 2025-05-21 16:59:54 -05:00
parent fa4f750beb
commit 478f077030
12 changed files with 332 additions and 86 deletions

View File

@ -174,7 +174,7 @@ struct asset *font_load_asset(struct string path, f32 point_size, b32 help)
struct string key = string_format(scratch.arena, struct string key = string_format(scratch.arena,
LIT("%F%F_font"), LIT("%F%F_font"),
FMT_STR(path), FMT_STR(path),
FMT_FLOAT_P((f64)point_size, 3)); FMT_FLOAT_P((f64)point_size, 1));
u64 hash = asset_cache_hash(key); u64 hash = asset_cache_hash(key);
b32 is_first_touch; b32 is_first_touch;
struct asset *asset = asset_cache_touch(key, hash, &is_first_touch); struct asset *asset = asset_cache_touch(key, hash, &is_first_touch);

View File

@ -839,6 +839,21 @@ INLINE b32 v2i32_eq(struct v2i32 a, struct v2i32 b)
return a.x == b.x && a.y == b.y; return a.x == b.x && a.y == b.y;
} }
INLINE struct v2i32 v2i32_neg(struct v2i32 a)
{
return V2I32(-a.x, -a.y);
}
INLINE struct v2i32 v2i32_add(struct v2i32 a, struct v2i32 b)
{
return V2I32(a.x + b.x, a.y + b.y);
}
INLINE struct v2i32 v2i32_sub(struct v2i32 a, struct v2i32 b)
{
return V2I32(a.x - b.x, a.y - b.y);
}
/* ========================== * /* ========================== *
* Mat4x4 * Mat4x4
* ========================== */ * ========================== */

View File

@ -2,7 +2,6 @@
#define RENDERER_H #define RENDERER_H
struct sys_window; struct sys_window;
struct sprite_scope;
#define RENDERER_TEXTURE_MAX_WIDTH 16384 #define RENDERER_TEXTURE_MAX_WIDTH 16384
#define RENDERER_TEXTURE_MAX_HEIGHT 16384 #define RENDERER_TEXTURE_MAX_HEIGHT 16384
@ -81,7 +80,7 @@ struct renderer_texture renderer_texture_alloc(enum renderer_texture_format form
void renderer_texture_release(struct renderer_texture t); void renderer_texture_release(struct renderer_texture t);
void renderer_texture_clear(struct renderer_texture target_texture, u32 clear_color); void renderer_texture_clear(struct renderer_texture target_texture, u32 clear_color);
void renderer_texture_render(struct renderer_texture texture, struct renderer_cmd_buffer *cmdbuff, struct xform view, struct rect viewport, struct sprite_scope *sprite_scope); void renderer_texture_render(struct renderer_texture texture, struct renderer_cmd_buffer *cmdbuff, struct xform view, struct rect viewport);
struct v2i32 renderer_texture_get_size(struct renderer_texture texture); struct v2i32 renderer_texture_get_size(struct renderer_texture texture);
/* ========================== * /* ========================== *

View File

@ -638,10 +638,12 @@ struct renderer_startup_receipt renderer_startup(struct sys_window *window)
* Another option is to store a separate device on each cmdbuff? * Another option is to store a separate device on each cmdbuff?
* *
* I'm thinking we may also just need to lock texture modification access while presenting */ * I'm thinking we may also just need to lock texture modification access while presenting */
INTERNAL void dx11_render(ID3D11RenderTargetView *target, struct renderer_cmd_buffer *cmdbuff, struct xform view, struct rect viewport, struct sprite_scope *sprite_scope) INTERNAL void dx11_render(ID3D11RenderTargetView *target, struct renderer_cmd_buffer *cmdbuff, struct xform view, struct rect viewport)
{ {
__prof; __prof;
__profscope_d3d11(G.profiling_ctx, Render); __profscope_d3d11(G.profiling_ctx, Render);
struct sprite_scope *sprite_scope = sprite_scope_begin();
ID3D11DeviceContext_OMSetRenderTargets(G.devcon, 1, &target, NULL); ID3D11DeviceContext_OMSetRenderTargets(G.devcon, 1, &target, NULL);
D3D11_VIEWPORT d3d11_viewport = ZI; D3D11_VIEWPORT d3d11_viewport = ZI;
@ -754,6 +756,8 @@ INTERNAL void dx11_render(ID3D11RenderTargetView *target, struct renderer_cmd_bu
} break; } break;
} }
} }
sprite_scope_end(sprite_scope);
} }
/* ========================== * /* ========================== *
@ -900,7 +904,7 @@ void renderer_texture_clear(struct renderer_texture target_texture, u32 clear_co
} }
} }
void renderer_texture_render(struct renderer_texture texture, struct renderer_cmd_buffer *cmdbuff, struct xform view, struct rect viewport, struct sprite_scope *sprite_scope) void renderer_texture_render(struct renderer_texture texture, struct renderer_cmd_buffer *cmdbuff, struct xform view, struct rect viewport)
{ {
__prof; __prof;
@ -909,7 +913,7 @@ void renderer_texture_render(struct renderer_texture texture, struct renderer_cm
ID3D11RenderTargetView *target_view = NULL; ID3D11RenderTargetView *target_view = NULL;
ID3D11Device_CreateRenderTargetView(G.dev, (ID3D11Resource *)t->texture, NULL, &target_view); ID3D11Device_CreateRenderTargetView(G.dev, (ID3D11Resource *)t->texture, NULL, &target_view);
if (target_view) { if (target_view) {
dx11_render(target_view, cmdbuff, view, viewport, sprite_scope); dx11_render(target_view, cmdbuff, view, viewport);
} }
if (target_view) { if (target_view) {

View File

@ -543,6 +543,82 @@ struct sim_snapshot *sim_snapshot_from_closest_tick_gte(struct sim_client *clien
return ss; return ss;
} }
/* ========================== *
* Tile
* ========================== */
struct v2i32 sim_world_tile_index_from_pos(struct v2 pos)
{
struct v2i32 res = V2I32(pos.x * SIM_TILES_PER_UNIT_SQRT, pos.y * SIM_TILES_PER_UNIT_SQRT);
res.x -= pos.x < 0;
res.y -= pos.y < 0;
return res;
}
struct v2 sim_pos_from_world_tile_index(struct v2i32 world_tile_index)
{
struct v2 res = ZI;
f32 tile_size = 1.f / SIM_TILES_PER_UNIT_SQRT;
res.x = (f32)world_tile_index.x * tile_size;
res.y = (f32)world_tile_index.y * tile_size;
if (world_tile_index.x < 0) {
res.x += tile_size;
}
if (world_tile_index.y < 0) {
res.y += tile_size;
}
return res;
}
struct v2i32 sim_local_tile_index_from_world_tile_index(struct v2i32 world_tile_index)
{
struct v2i32 res = ZI;
res.x = world_tile_index.x % SIM_TILES_PER_CHUNK_SQRT;
res.y = world_tile_index.y % SIM_TILES_PER_CHUNK_SQRT;
if (world_tile_index.x < 0) {
res.x = SIM_TILES_PER_CHUNK_SQRT + res.x - 1;
}
if (world_tile_index.y < 0) {
res.y = SIM_TILES_PER_CHUNK_SQRT + res.y - 1;
}
return res;
}
struct v2i32 sim_world_tile_index_from_local_tile_index(struct v2i32 tile_chunk_index, struct v2i32 local_tile_index)
{
struct v2i32 res = ZI;
res.x = (tile_chunk_index.x * SIM_TILES_PER_CHUNK_SQRT) + local_tile_index.x;
res.y = (tile_chunk_index.y * SIM_TILES_PER_CHUNK_SQRT) + local_tile_index.y;
return res;
}
struct v2i32 sim_tile_chunk_index_from_world_tile_index(struct v2i32 world_tile_index)
{
struct v2i32 res = ZI;
res.x = world_tile_index.x / SIM_TILES_PER_CHUNK_SQRT;
res.y = world_tile_index.y / SIM_TILES_PER_CHUNK_SQRT;
res.x -= world_tile_index.x < 0;
res.y -= world_tile_index.y < 0;
return res;
}
void sim_snapshot_set_tile(struct sim_snapshot *ss, struct v2i32 world_tile_index, enum sim_tile_kind tile_kind)
{
struct v2i32 chunk_index = sim_tile_chunk_index_from_world_tile_index(world_tile_index);
struct sim_ent_id chunk_id = sim_ent_tile_chunk_id_from_tile_chunk_index(chunk_index);
struct sim_ent *chunk_ent = sim_ent_from_id(ss, chunk_id);
if (!chunk_ent->valid) {
struct sim_ent *root = sim_ent_from_id(ss, SIM_ENT_ROOT_ID);
chunk_ent = sim_ent_alloc_sync_src_with_id(root, chunk_id);
sim_ent_enable_prop(chunk_ent, SEPROP_TILE_CHUNK);
chunk_ent->tile_chunk_index = chunk_index;
}
struct v2i32 local_index = sim_local_tile_index_from_world_tile_index(world_tile_index);
chunk_ent->tile_chunk_tiles[local_index.x + (local_index.y * SIM_TILES_PER_CHUNK_SQRT)] = tile_kind;
}
/* ========================== * /* ========================== *
* Snapshot lerp * Snapshot lerp
* ========================== */ * ========================== */

View File

@ -167,8 +167,11 @@ enum sim_cmd_kind {
enum sim_tile_kind { enum sim_tile_kind {
SIM_TILE_KIND_NONE, SIM_TILE_KIND_NONE,
SIM_TILE_KIND_TEST SIM_TILE_KIND_WALL,
NUM_SIM_TILE_KINDS
}; };
CT_ASSERT(NUM_SIM_TILE_KINDS < 256); /* Tile kind must fit in 8 bits */
struct sim_ent_bin; struct sim_ent_bin;
@ -228,6 +231,14 @@ struct sim_snapshot *sim_snapshot_from_tick(struct sim_client *client, u64 tick)
struct sim_snapshot *sim_snapshot_from_closest_tick_lte(struct sim_client *client, u64 tick); struct sim_snapshot *sim_snapshot_from_closest_tick_lte(struct sim_client *client, u64 tick);
struct sim_snapshot *sim_snapshot_from_closest_tick_gte(struct sim_client *client, u64 tick); struct sim_snapshot *sim_snapshot_from_closest_tick_gte(struct sim_client *client, u64 tick);
/* Tile */
struct v2i32 sim_world_tile_index_from_pos(struct v2 pos);
struct v2 sim_pos_from_world_tile_index(struct v2i32 world_tile_index);
struct v2i32 sim_local_tile_index_from_world_tile_index(struct v2i32 world_tile_index);
struct v2i32 sim_world_tile_index_from_local_tile_index(struct v2i32 tile_chunk_index, struct v2i32 local_tile_index);
struct v2i32 sim_tile_chunk_index_from_world_tile_index(struct v2i32 world_tile_index);
void sim_snapshot_set_tile(struct sim_snapshot *ss, struct v2i32 world_tile_index, enum sim_tile_kind tile_kind);
/* Lerp */ /* Lerp */
struct sim_snapshot *sim_snapshot_alloc_from_lerp(struct sim_client *client, struct sim_snapshot *ss0, struct sim_snapshot *ss1, f64 blend); struct sim_snapshot *sim_snapshot_alloc_from_lerp(struct sim_client *client, struct sim_snapshot *ss0, struct sim_snapshot *ss1, f64 blend);

View File

@ -296,12 +296,11 @@ struct sim_ent_id sim_ent_collision_debug_id_from_ids(struct sim_ent_id player_i
} }
/* Returns the deterministic id of the tile chunk that should be produced at chunk pos */ /* Returns the deterministic id of the tile chunk that should be produced at chunk pos */
struct sim_ent_id sim_ent_chunk_id_from_chunk_pos(struct sim_ent_id player_id, struct v2i32 chunk_pos) struct sim_ent_id sim_ent_tile_chunk_id_from_tile_chunk_index(struct v2i32 chunk_index)
{ {
struct sim_ent_id res = ZI; struct sim_ent_id res = ZI;
res.uid = SIM_ENT_TILE_CHUNK_BASIS_UID; res.uid = SIM_ENT_TILE_CHUNK_BASIS_UID;
res.uid = uid_combine(res.uid, player_id.uid); res.uid = uid_combine(res.uid, UID(rand_u64_from_seed(chunk_index.x), rand_u64_from_seed(chunk_index.y)));
res.uid = uid_combine(res.uid, UID(rand_u64_from_seed(chunk_pos.x), rand_u64_from_seed(chunk_pos.y)));
return res; return res;
} }
@ -564,20 +563,21 @@ void sim_ent_apply_torque(struct sim_ent *ent, f32 torque)
} }
/* ========================== * /* ========================== *
* Tile chunk * Tile
* ========================== */ * ========================== */
struct string sim_ent_get_tile_chunk_data(struct sim_ent *ent) struct sim_ent *sim_tile_chunk_from_world_tile_index(struct sim_snapshot *ss, struct v2i32 world_tile_index)
{ {
(UNUSED)ent; struct v2i32 chunk_index = sim_tile_chunk_index_from_world_tile_index(world_tile_index);
struct string res = ZI; struct sim_ent_id chunk_id = sim_ent_tile_chunk_id_from_tile_chunk_index(chunk_index);
return res; struct sim_ent *chunk_ent = sim_ent_from_id(ss, chunk_id);
return chunk_ent;
} }
void sim_ent_set_tile_chunk_data(struct sim_ent *ent, struct string data) enum sim_tile_kind sim_get_chunk_tile(struct sim_ent *chunk_ent, struct v2i32 local_tile_index)
{ {
(UNUSED)ent; enum sim_tile_kind res = chunk_ent->tile_chunk_tiles[local_tile_index.x + (local_tile_index.y * SIM_TILES_PER_CHUNK_SQRT)];
(UNUSED)data; return res;
} }
/* ========================== * /* ========================== *

View File

@ -25,6 +25,7 @@ enum sim_ent_prop {
SEPROP_CMD, SEPROP_CMD,
SEPROP_TILE_CHUNK, SEPROP_TILE_CHUNK,
SEPROP_WALL,
/* Physics collision */ /* Physics collision */
SEPROP_SENSOR, /* This entity's collisions generate contacts */ SEPROP_SENSOR, /* This entity's collisions generate contacts */
@ -158,6 +159,17 @@ struct sim_ent {
struct sim_ent_id chat_player; struct sim_ent_id chat_player;
//struct string chat_msg; //struct string chat_msg;
/* ====================================================================== */
/* Tile */
/* SEPROP_TILE_CHUNK */
/* FIXME: Move out of here */
u8 tile_chunk_tiles[SIM_TILES_PER_CHUNK_SQRT * SIM_TILES_PER_CHUNK_SQRT];
struct v2i32 tile_chunk_index;
/* ====================================================================== */ /* ====================================================================== */
/* Client */ /* Client */
@ -505,7 +517,7 @@ struct sim_ent *sim_ent_from_id(struct sim_snapshot *ss, struct sim_ent_id id);
struct sim_ent_id sim_ent_random_id(void); struct sim_ent_id sim_ent_random_id(void);
struct sim_ent_id sim_ent_contact_constraint_id_from_contacting_ids(struct sim_ent_id player_id, struct sim_ent_id id0, struct sim_ent_id id1); struct sim_ent_id sim_ent_contact_constraint_id_from_contacting_ids(struct sim_ent_id player_id, struct sim_ent_id id0, struct sim_ent_id id1);
struct sim_ent_id sim_ent_collision_debug_id_from_ids(struct sim_ent_id player_id, struct sim_ent_id id0, struct sim_ent_id id1); struct sim_ent_id sim_ent_collision_debug_id_from_ids(struct sim_ent_id player_id, struct sim_ent_id id0, struct sim_ent_id id1);
struct sim_ent_id sim_ent_chunk_id_from_chunk_pos(struct sim_ent_id player_id, struct v2i32 chunk_pos); struct sim_ent_id sim_ent_tile_chunk_id_from_tile_chunk_index(struct v2i32 chunk_start);
/* Query */ /* Query */
struct sim_ent *sim_ent_find_first_match_one(struct sim_snapshot *ss, enum sim_ent_prop prop); struct sim_ent *sim_ent_find_first_match_one(struct sim_snapshot *ss, enum sim_ent_prop prop);
@ -530,9 +542,9 @@ void sim_ent_apply_force_to_center(struct sim_ent *ent, struct v2 force);
void sim_ent_apply_angular_impulse(struct sim_ent *ent, f32 impulse); void sim_ent_apply_angular_impulse(struct sim_ent *ent, f32 impulse);
void sim_ent_apply_torque(struct sim_ent *ent, f32 torque); void sim_ent_apply_torque(struct sim_ent *ent, f32 torque);
/* Tile chunk */ /* Tile */
struct string sim_ent_get_tile_chunk_data(struct sim_ent *ent); struct sim_ent *sim_tile_chunk_from_world_tile_index(struct sim_snapshot *ss, struct v2i32 world_tile_index);
void sim_ent_set_tile_chunk_data(struct sim_ent *ent, struct string data); enum sim_tile_kind sim_get_chunk_tile(struct sim_ent *chunk_ent, struct v2i32 local_tile_index);
/* Lerp */ /* Lerp */
void sim_ent_lerp(struct sim_ent *e, struct sim_ent *e0, struct sim_ent *e1, f64 blend); void sim_ent_lerp(struct sim_ent *e, struct sim_ent *e0, struct sim_ent *e1, f64 blend);

View File

@ -327,15 +327,16 @@ INTERNAL void test_spawn_entities3(struct sim_ent *parent, struct v2 pos)
} }
} }
INTERNAL void test_spawn_tile(struct sim_ent *parent, struct v2 cursor_pos) INTERNAL void test_spawn_tile(struct sim_snapshot *world, struct v2 world_pos)
{ {
#if 0
struct sim_ent *e = sim_ent_alloc_sync_src(parent); struct sim_ent *e = sim_ent_alloc_sync_src(parent);
i32 sign_x = (cursor_pos.x >= 0) - (cursor_pos.x < 0); i32 sign_x = (world_pos.x >= 0) - (world_pos.x < 0);
i32 sign_y = (cursor_pos.y >= 0) - (cursor_pos.y < 0); i32 sign_y = (world_pos.y >= 0) - (world_pos.y < 0);
struct v2i32 tile_index = V2I32(cursor_pos.x * SIM_TILES_PER_UNIT_SQRT, cursor_pos.y * SIM_TILES_PER_UNIT_SQRT); struct v2i32 tile_index = V2I32(world_pos.x * SIM_TILES_PER_UNIT_SQRT, world_pos.y * SIM_TILES_PER_UNIT_SQRT);
cursor_pos.x -= sign_x < 0; world_pos.x -= sign_x < 0;
cursor_pos.y -= sign_y < 0; world_pos.y -= sign_y < 0;
struct v2 tile_size = V2(1.f / SIM_TILES_PER_UNIT_SQRT, 1.f / SIM_TILES_PER_UNIT_SQRT); struct v2 tile_size = V2(1.f / SIM_TILES_PER_UNIT_SQRT, 1.f / SIM_TILES_PER_UNIT_SQRT);
@ -359,6 +360,10 @@ INTERNAL void test_spawn_tile(struct sim_ent *parent, struct v2 cursor_pos)
sim_ent_enable_prop(e, SEPROP_SOLID); sim_ent_enable_prop(e, SEPROP_SOLID);
struct quad collider_quad = quad_from_rect(RECT(-tile_size.x / 2, -tile_size.y / 2, tile_size.y, tile_size.y)); struct quad collider_quad = quad_from_rect(RECT(-tile_size.x / 2, -tile_size.y / 2, tile_size.y, tile_size.y));
e->local_collider = collider_from_quad(collider_quad); e->local_collider = collider_from_quad(collider_quad);
#else
struct v2i32 tile_index = sim_world_tile_index_from_pos(world_pos);
sim_snapshot_set_tile(world, tile_index, SIM_TILE_KIND_WALL);
#endif
} }
@ -369,19 +374,22 @@ INTERNAL void test_spawn_tile(struct sim_ent *parent, struct v2 cursor_pos)
INTERNAL SORT_COMPARE_FUNC_DEF(tile_chunk_sort, arg_a, arg_b, udata)
{
(UNUSED)udata;
struct sim_ent *a = (struct sim_ent *)arg_a;
struct sim_ent *b = (struct sim_ent *)arg_b;
struct v2i32 index_a = a->tile_chunk_index;
struct v2i32 index_b = b->tile_chunk_index;
i32 res = 0;
res = 2 * ((index_a.y > index_b.y) - (index_a.y < index_b.y)) + ((index_a.x > index_b.x) - (index_a.x < index_b.x));
/* TODO: Move this */ return res;
enum tile_kind { }
TILE_KIND_NONE,
TILE_KIND_WALL
};
INTERNAL void test_generate_walls(struct sim_ent *parent) INTERNAL void test_generate_walls(struct sim_ent *parent)
{ {
#if 0 #if 1
struct temp_arena scratch = scratch_begin_no_conflict(); struct temp_arena scratch = scratch_begin_no_conflict();
struct sim_snapshot *world = parent->ss; struct sim_snapshot *world = parent->ss;
@ -395,33 +403,103 @@ INTERNAL void test_generate_walls(struct sim_ent *parent)
} }
/* Sort tile chunks */ /* Sort tile chunks */
struct sim_ent **tile_chunks = arena_dry_push(scratch.arena, struct sim_ent *);
u64 tile_chunks_count = 0;
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
struct sim_ent *ent = &world->ents[ent_index]; struct sim_ent *ent = &world->ents[ent_index];
if (!ent->valid) continue; if (!ent->valid) continue;
if (sim_ent_has_prop(ent, SEPROP_TILE_CHUNK)) { if (sim_ent_has_prop(ent, SEPROP_TILE_CHUNK)) {
*arena_push_no_zero(scratch.arena, struct sim_ent *) = ent;
++tile_chunks_count;
} }
} }
merge_sort(tile_chunks, tile_chunks_count, sizeof(*tile_chunks), tile_chunk_sort, NULL);
/* Generate horizontal walls */ struct wall_node {
struct v2i32 start;
struct v2i32 end;
struct wall_node *next;
};
struct wall_node *first_wall = NULL;
/* Generate horizontal wall nodes */
for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) { for (u64 ent_index = 0; ent_index < world->num_ents_reserved; ++ent_index) {
struct sim_ent *ent = &world->ents[ent_index]; struct sim_ent *chunk = &world->ents[ent_index];
if (!ent->valid) continue; if (!chunk->valid) continue;
if (sim_ent_has_prop(ent, SEPROP_TILE_CHUNK)) { if (sim_ent_has_prop(chunk, SEPROP_TILE_CHUNK)) {
//struct v2i32 chunk_start = ent->tile_chunk_start; struct v2i32 chunk_index = chunk->tile_chunk_index;
//struct v2i32 chunk_end = v2_add(chunk_start, V2(SIM_TILES_PER_CHUNK_SQRT, SIM_TILES_PER_CHUNK_SQRT)); struct sim_ent *top_chunk = sim_tile_chunk_from_world_tile_index(world, V2I32(chunk_index.x, chunk_index.y - 1));
//struct sim_ent *left_chunk = sim_chunk_from_index(world, v2i32(chunk_start.x - 1, chunk_start.y)); struct sim_ent *bottom_chunk = sim_tile_chunk_from_world_tile_index(world, V2I32(chunk_index.x, chunk_index.y + 1));
//struct sim_ent *right_chunk = sim_chunk_from_index(world, v2i32(chunk_end.x, chunk_start.y)); /* If there's no chunk below this one, then do an extra iteration (since walls are created at the top of each tile) */
//struct sim_ent *top_chunk = sim_chunk_from_index(world, v2i32(chunk_start.x, chunk_start.y - 1); i32 y_iterations = SIM_TILES_PER_CHUNK_SQRT + !bottom_chunk->valid;
//struct sim_ent *bottom_chunk = sim_chunk_from_index(world, v2i32(chunk_start.x, chunk_start.y)); i32 x_iterations = SIM_TILES_PER_CHUNK_SQRT + 1;
for (i64 tile_y = 0; tile_y < SIM_TILES_PER_CHUNK_SQRT; ++tile_y) { for (i32 tile_y = 0; tile_y < y_iterations; ++tile_y) {
i64 tile_x = 0; i32 wall_start = -1;
while (true) { i32 wall_end = -1;
for (i32 tile_x = 0; tile_x < x_iterations; ++tile_x) {
enum sim_tile_kind tile = SIM_TILE_KIND_NONE;
enum sim_tile_kind top_tile = SIM_TILE_KIND_NONE;
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));
}
if (tile == SIM_TILE_KIND_NONE && tile_x < SIM_TILES_PER_CHUNK_SQRT) {
if (tile_y == 0) {
if (top_chunk->valid) {
top_tile = sim_get_chunk_tile(top_chunk, V2I32(tile_x, SIM_TILES_PER_CHUNK_SQRT - 1));
}
} else {
top_tile = sim_get_chunk_tile(chunk, V2I32(tile_x, tile_y - 1));
}
}
if (top_tile == SIM_TILE_KIND_WALL && tile != SIM_TILE_KIND_WALL) {
if (wall_start < 0) {
/* Start wall */
wall_start = tile_x;
}
/* Extend wall */
wall_end = tile_x + 1;
} 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 end = sim_world_tile_index_from_local_tile_index(chunk_index, V2I32(wall_end, tile_y));
struct wall_node *node = arena_push(scratch.arena, struct wall_node);
node->start = start;
node->end = end;
node->next = first_wall;
first_wall = node;
wall_start = -1;
wall_end = -1;
}
} }
} }
} }
} }
/* Create wall entities */
for (struct wall_node *node = first_wall; node; node = node->next) {
struct sim_ent *wall_ent = sim_ent_alloc_sync_src(parent);
sim_ent_enable_prop(wall_ent, SEPROP_WALL);
#if 0
struct v2i32 node_start = node->start;
struct v2i32 node_end = node->end;
struct v2 start = V2(node_start.x / SIM_TILES_PER_UNIT_SQRT, node_start.y / SIM_TILES_PER_UNIT_SQRT);
struct v2 end = V2(node_end.x / SIM_TILES_PER_UNIT_SQRT, node_end.y / SIM_TILES_PER_UNIT_SQRT);
#endif
struct v2 start = sim_pos_from_world_tile_index(node->start);
struct v2 end = sim_pos_from_world_tile_index(node->end);
struct xform xf = XFORM_POS(start);
sim_ent_set_xform(wall_ent, xf);
sim_ent_enable_prop(wall_ent, SEPROP_SOLID);
wall_ent->local_collider.count = 2;
wall_ent->local_collider.points[1] = v2_sub(end, start);
}
scratch_end(scratch); scratch_end(scratch);
#else #else
(UNUSED)parent; (UNUSED)parent;
@ -840,7 +918,7 @@ void sim_step(struct sim_step_ctx *ctx)
sim_ent_set_tile_chunk_data(chunk_ent, new_data); sim_ent_set_tile_chunk_data(chunk_ent, new_data);
} }
#else #else
test_spawn_tile(root, player->player_cursor_pos); test_spawn_tile(world, player->player_cursor_pos);
#endif #endif
} }
} }

View File

@ -39,7 +39,7 @@ b32 string_ends_with(struct string str, struct string substring);
* Format * Format
* ========================== */ * ========================== */
#define DEFAULT_FMT_PRECISION 6 #define DEFAULT_FMT_PRECISION 3
enum fmt_type { enum fmt_type {
FMT_TYPE_NONE, FMT_TYPE_NONE,

View File

@ -408,9 +408,9 @@ INTERNAL struct string get_ent_debug_text(struct arena *arena, struct sim_ent *e
struct xform xf = sim_ent_get_xform(ent); struct xform xf = sim_ent_get_xform(ent);
struct v2 linear_velocity = ent->linear_velocity; struct v2 linear_velocity = ent->linear_velocity;
f32 angular_velocity = ent->angular_velocity; f32 angular_velocity = ent->angular_velocity;
res.len += string_format(arena, LIT("pos: (%F, %F)\n"), FMT_FLOAT_P(xf.og.x, 3), FMT_FLOAT_P(xf.og.y, 3)).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_P(linear_velocity.x, 3), FMT_FLOAT_P(linear_velocity.y, 3)).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_P(angular_velocity, 3)).len; res.len += string_format(arena, LIT("angular velocity: %F\n"), FMT_FLOAT(angular_velocity)).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)) {
@ -1103,6 +1103,30 @@ INTERNAL void user_update(void)
} }
} }
/* Draw tiles */
/* TODO: Something better */
if (sim_ent_has_prop(ent, SEPROP_TILE_CHUNK)) {
struct v2i32 chunk_index = ent->tile_chunk_index;
struct sprite_tag tile_sprite = sprite_tag_from_path(LIT("res/graphics/tile.ase"));
f32 tile_size = 1.f / SIM_TILES_PER_UNIT_SQRT;
for (i32 tile_y = 0; tile_y < SIM_TILES_PER_CHUNK_SQRT; ++tile_y) {
for (i32 tile_x = 0; tile_x < SIM_TILES_PER_CHUNK_SQRT; ++tile_x) {
struct v2i32 local_tile_index = V2I32(tile_x, tile_y);
enum sim_tile_kind tile = ent->tile_chunk_tiles[local_tile_index.x + (local_tile_index.y * SIM_TILES_PER_CHUNK_SQRT)];
//if (tile > -1) {
if (tile == SIM_TILE_KIND_WALL) {
struct v2i32 world_tile_index = sim_world_tile_index_from_local_tile_index(chunk_index, local_tile_index);
struct v2 pos = sim_pos_from_world_tile_index(world_tile_index);
struct quad quad = quad_from_rect(RECT(pos.x, pos.y, tile_size, tile_size));
struct draw_texture_params params = DRAW_TEXTURE_PARAMS(.sprite = tile_sprite);
draw_quad_texture(G.world_cmd_buffer, params, quad);
}
}
}
}
/* Debug draw entity info */ /* Debug draw entity info */
if (G.debug_draw && !skip_debug_draw) { if (G.debug_draw && !skip_debug_draw) {
struct temp_arena temp = arena_temp_begin(scratch.arena); struct temp_arena temp = arena_temp_begin(scratch.arena);
@ -1298,8 +1322,8 @@ INTERNAL void user_update(void)
FMT_UINT(e0->handle.idx), FMT_UINT(e0->handle.idx),
FMT_UINT(e1->handle.idx), FMT_UINT(e1->handle.idx),
FMT_HEX(point.id), FMT_HEX(point.id),
FMT_FLOAT_P(point.normal_impulse, 3), FMT_FLOAT(point.normal_impulse),
FMT_FLOAT_P(point.tangent_impulse, 3), FMT_FLOAT(point.tangent_impulse),
FMT_FLOAT_P(point.starting_separation, 6), FMT_FLOAT_P(point.starting_separation, 6),
FMT_FLOAT_P(data->normal.x, 6), FMT_FLOAT_P(data->normal.y, 6), FMT_FLOAT_P(data->normal.x, 6), FMT_FLOAT_P(data->normal.y, 6),
FMT_UINT(data->num_points)); FMT_UINT(data->num_points));
@ -1768,26 +1792,26 @@ INTERNAL void user_update(void)
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("blended world tick: %F"), FMT_UINT(G.ss_blended->tick))); draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("blended world tick: %F"), FMT_UINT(G.ss_blended->tick)));
pos.y += spacing; pos.y += spacing;
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("blended world time: %F"), FMT_FLOAT_P(SECONDS_FROM_NS(G.ss_blended->sim_time_ns), 3))); draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("blended world time: %F"), FMT_FLOAT(SECONDS_FROM_NS(G.ss_blended->sim_time_ns))));
pos.y += spacing; pos.y += spacing;
pos.y += spacing; pos.y += spacing;
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("average local sim publish dt: %F"), FMT_FLOAT_P(SECONDS_FROM_NS(G.average_local_to_user_snapshot_publish_dt_ns), 3))); draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("average local sim publish dt: %F"), FMT_FLOAT(SECONDS_FROM_NS(G.average_local_to_user_snapshot_publish_dt_ns))));
pos.y += spacing; pos.y += spacing;
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("local sim last known tick: %F"), FMT_UINT(G.local_sim_last_known_tick))); draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("local sim last known tick: %F"), FMT_UINT(G.local_sim_last_known_tick)));
pos.y += spacing; pos.y += spacing;
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("local sim last known time: %F"), FMT_FLOAT_P(SECONDS_FROM_NS(G.local_sim_last_known_time_ns), 3))); draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("local sim last known time: %F"), FMT_FLOAT(SECONDS_FROM_NS(G.local_sim_last_known_time_ns))));
pos.y += spacing; pos.y += spacing;
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("local sim predicted time: %F"), FMT_FLOAT_P(SECONDS_FROM_NS(G.local_sim_predicted_time_ns), 3))); draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("local sim predicted time: %F"), FMT_FLOAT(SECONDS_FROM_NS(G.local_sim_predicted_time_ns))));
pos.y += spacing; pos.y += spacing;
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("render time target: %F"), FMT_FLOAT_P(SECONDS_FROM_NS(G.render_time_target_ns), 3))); draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("render time target: %F"), FMT_FLOAT(SECONDS_FROM_NS(G.render_time_target_ns))));
pos.y += spacing; pos.y += spacing;
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("render time: %F"), FMT_FLOAT_P(SECONDS_FROM_NS(G.render_time_ns), 3))); draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("render time: %F"), FMT_FLOAT(SECONDS_FROM_NS(G.render_time_ns))));
pos.y += spacing; pos.y += spacing;
pos.y += spacing; pos.y += spacing;
@ -1795,23 +1819,40 @@ INTERNAL void user_update(void)
pos.y += spacing; pos.y += spacing;
pos.y += spacing; pos.y += spacing;
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("Network read: %F mbit/s"), FMT_FLOAT_P((f64)G.net_bytes_read.last_second * 8 / 1000 / 1000, 3))); struct v2 world_cursor = G.world_cursor;
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("cursor world: %F, %F"), FMT_FLOAT(world_cursor.x), FMT_FLOAT(world_cursor.y)));
pos.y += spacing; pos.y += spacing;
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("Network write: %F mbit/s"), FMT_FLOAT_P((f64)G.net_bytes_sent.last_second * 8 / 1000 / 1000, 3))); struct v2i32 world_tile_cursor = sim_world_tile_index_from_pos(world_cursor);
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("cursor world tile: %F, %F"), FMT_SINT(world_tile_cursor.x), FMT_SINT(world_tile_cursor.y)));
pos.y += spacing; pos.y += spacing;
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("Ping (real): %F ms"), FMT_FLOAT_P(SECONDS_FROM_NS(local_player->player_last_rtt_ns) * 1000, 3))); struct v2i32 local_tile_cursor = sim_local_tile_index_from_world_tile_index(world_tile_cursor);
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("cursor local tile: %F, %F"), FMT_SINT(local_tile_cursor.x), FMT_SINT(local_tile_cursor.y)));
pos.y += spacing; pos.y += spacing;
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("Ping (average): %F ms"), FMT_FLOAT_P(local_player->player_average_rtt_seconds * 1000, 3))); struct v2i32 tile_chunk_cursor = sim_tile_chunk_index_from_world_tile_index(world_tile_cursor);
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("cursor tile chunk: %F, %F"), FMT_SINT(tile_chunk_cursor.x), FMT_SINT(tile_chunk_cursor.y)));
pos.y += spacing; pos.y += spacing;
pos.y += spacing; pos.y += spacing;
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("Memory usage: %F MiB"), FMT_FLOAT_P((f64)gstat_get(GSTAT_MEMORY_COMMITTED) / 1024 / 1024, 3))); draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("Network read: %F mbit/s"), FMT_FLOAT((f64)G.net_bytes_read.last_second * 8 / 1000 / 1000)));
pos.y += spacing; pos.y += spacing;
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("Virtual memory usage: %F TiB"), FMT_FLOAT_P((f64)gstat_get(GSTAT_MEMORY_RESERVED) / 1024 / 1024 / 1024 / 1024, 3))); draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("Network write: %F mbit/s"), FMT_FLOAT((f64)G.net_bytes_sent.last_second * 8 / 1000 / 1000)));
pos.y += spacing;
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("Ping (real): %F ms"), FMT_FLOAT(SECONDS_FROM_NS(local_player->player_last_rtt_ns) * 1000)));
pos.y += spacing;
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("Ping (average): %F ms"), FMT_FLOAT(local_player->player_average_rtt_seconds * 1000)));
pos.y += spacing;
pos.y += spacing;
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("Memory usage: %F MiB"), FMT_FLOAT((f64)gstat_get(GSTAT_MEMORY_COMMITTED) / 1024 / 1024)));
pos.y += spacing;
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("Virtual memory usage: %F TiB"), FMT_FLOAT((f64)gstat_get(GSTAT_MEMORY_RESERVED) / 1024 / 1024 / 1024 / 1024)));
pos.y += spacing; pos.y += spacing;
draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("Arenas allocated: %F"), FMT_UINT(gstat_get(GSTAT_NUM_ARENAS)))); draw_text(G.ui_cmd_buffer, font, pos, string_format(temp.arena, LIT("Arenas allocated: %F"), FMT_UINT(gstat_get(GSTAT_NUM_ARENAS))));
@ -1956,16 +1997,16 @@ INTERNAL void user_update(void)
renderer_texture_clear(G.backbuffer_texture, RGBA_F(0, 0, 0, 1)); renderer_texture_clear(G.backbuffer_texture, RGBA_F(0, 0, 0, 1));
/* Render to world texture */ /* Render to world texture */
renderer_texture_render(G.world_texture, G.world_cmd_buffer, G.world_to_ui_xf, ui_viewport, sprite_frame_scope); renderer_texture_render(G.world_texture, G.world_cmd_buffer, G.world_to_ui_xf, ui_viewport);
/* Render to UI texture */ /* Render to UI texture */
renderer_texture_render(G.ui_texture, G.ui_cmd_buffer, XFORM_IDENT, ui_viewport, sprite_frame_scope); renderer_texture_render(G.ui_texture, G.ui_cmd_buffer, XFORM_IDENT, ui_viewport);
/* Render to final texture */ /* Render to final texture */
renderer_texture_render(G.final_texture, G.final_cmd_buffer, XFORM_IDENT, ui_viewport, sprite_frame_scope); renderer_texture_render(G.final_texture, G.final_cmd_buffer, XFORM_IDENT, ui_viewport);
/* Render to backbuffer */ /* Render to backbuffer */
renderer_texture_render(G.backbuffer_texture, G.backbuffer_cmd_buffer, XFORM_IDENT, backbuffer_viewport, sprite_frame_scope); renderer_texture_render(G.backbuffer_texture, G.backbuffer_cmd_buffer, XFORM_IDENT, backbuffer_viewport);
} }
/* Present */ /* Present */

View File

@ -108,25 +108,26 @@ INLINE void merge_sort(void *items, u64 item_count, u64 item_size, sort_compare_
struct dict_entry { struct dict_entry {
u64 hash; u64 hash;
u64 value; u64 value;
struct dict_entry *next_in_bin;
struct dict_entry *next; struct dict_entry *next;
}; };
struct dict_bin { struct dict_bin {
struct dict_entry *entry_head; struct dict_entry *first;
}; };
struct dict { struct dict {
u64 bins_count; u64 bins_count;
struct dict_bin *bins; struct dict_bin *bins;
struct dict_entry *first;
}; };
INLINE struct dict dict_init(struct arena *arena, u64 bins_count) INLINE struct dict dict_init(struct arena *arena, u64 bins_count)
{ {
__prof; __prof;
struct dict dict = ZI; struct dict dict = ZI;
bins_count = max_u64(bins_count, 1); /* Ensure at least 1 bin */ dict.bins_count = max_u64(bins_count, 1); /* Ensure at least 1 bin */
dict.bins_count = bins_count; dict.bins = arena_push_array(arena, struct dict_bin, dict.bins_count);
dict.bins = arena_push_array(arena, struct dict_bin, bins_count);
return dict; return dict;
} }
@ -136,13 +137,13 @@ INLINE void dict_set(struct arena *arena, struct dict *dict, u64 hash, u64 value
struct dict_bin *bin = &dict->bins[hash % dict->bins_count]; struct dict_bin *bin = &dict->bins[hash % dict->bins_count];
struct dict_entry *entry = bin->entry_head; struct dict_entry *entry = bin->first;
while (entry) { while (entry) {
if (hash == entry->hash) { if (hash == entry->hash) {
/* Existing match found */ /* Existing match found */
break; break;
} }
entry = entry->next; entry = entry->next_in_bin;
} }
/* No match found, create new entry */ /* No match found, create new entry */
@ -150,28 +151,37 @@ INLINE void dict_set(struct arena *arena, struct dict *dict, u64 hash, u64 value
entry = arena_push(arena, struct dict_entry); entry = arena_push(arena, struct dict_entry);
entry->value = value; entry->value = value;
entry->hash = hash; entry->hash = hash;
entry->next = bin->entry_head; entry->next_in_bin = bin->first;
bin->entry_head = entry; entry->next = dict->first;
dict->first = entry;
bin->first = entry;
} }
entry->value = value; entry->value = value;
} }
INLINE u64 dict_get(const struct dict *dict, u64 hash) INLINE struct dict_entry *dict_get_entry(const struct dict *dict, u64 hash)
{ {
__prof; __prof;
u64 result = 0; struct dict_entry *result = NULL;
struct dict_bin *bin = &dict->bins[hash % dict->bins_count]; struct dict_bin *bin = &dict->bins[hash % dict->bins_count];
for (struct dict_entry *entry = bin->entry_head; entry; entry = entry->next) { for (struct dict_entry *entry = bin->first; entry; entry = entry->next_in_bin) {
if (hash == entry->hash) { if (hash == entry->hash) {
/* Match found */ /* Match found */
result = entry->value; result = entry;
break; break;
} }
} }
return result; return result;
} }
INLINE u64 dict_get(const struct dict *dict, u64 hash)
{
__prof;
struct dict_entry *entry = dict_get_entry(dict, hash);
return entry ? entry->value : 0;
}
/* ========================== * /* ========================== *
* Sync flag * Sync flag
* ========================== */ * ========================== */