From e601e5e85d5ba2b4536c52bbddd390f07f7e0bd6 Mon Sep 17 00:00:00 2001 From: Katajisto Date: Fri, 18 Sep 2026 23:28:43 +0300 Subject: [PATCH] clean up world loading logic and add chunk occupancy masks --- src/assets/asset_manager.jai | 31 ++----- src/pseudophysics/core.jai | 1 + src/pseudophysics/worldphysics.jai | 15 ++++ src/world.jai | 131 +++++------------------------ 4 files changed, 48 insertions(+), 130 deletions(-) create mode 100644 src/pseudophysics/worldphysics.jai diff --git a/src/assets/asset_manager.jai b/src/assets/asset_manager.jai index ed156e6..f7e8bb6 100644 --- a/src/assets/asset_manager.jai +++ b/src/assets/asset_manager.jai @@ -168,28 +168,15 @@ process_completed_fetch :: (req: *Fetch_Request, data: []u8) { array_add(*g_asset_manager.loadedPacks, pack); case .WORLD; - is_json := data.count > 0 && data[0] == #char "{"; - if is_json { - json_copy := NewArray(data.count, u8, false); - memcpy(json_copy.data, data.data, data.count); - chunks_req: Fetch_Request; - chunks_req.type = .WORLD_CHUNKS; - chunks_req.priority = req.priority; - chunks_req.world_name = req.world_name; - chunks_req.path = sprint("%/worlds/%/chunks.bin", GAME_RESOURCES_DIR, req.world_name); - chunks_req.world_json_data = json_copy; - array_add(*g_asset_manager.queue, chunks_req); - } else { - world, ok := load_world_from_data(data); - if ok { - set_loaded_world(world); - rdm_loader_enqueue_world(*get_current_world().world); - shgrid_loader_enqueue_world(*get_current_world().world); - log_info("Loaded world (legacy): %", req.world_name); - } else { - log_error("Failed to parse world '%'", req.world_name); - } - } + json_copy := NewArray(data.count, u8, false); + memcpy(json_copy.data, data.data, data.count); + chunks_req: Fetch_Request; + chunks_req.type = .WORLD_CHUNKS; + chunks_req.priority = req.priority; + chunks_req.world_name = req.world_name; + chunks_req.path = sprint("%/worlds/%/chunks.bin", GAME_RESOURCES_DIR, req.world_name); + chunks_req.world_json_data = json_copy; + array_add(*g_asset_manager.queue, chunks_req); case .WORLD_CHUNKS; json_data := req.world_json_data; diff --git a/src/pseudophysics/core.jai b/src/pseudophysics/core.jai index cadd0b1..f15b8ef 100644 --- a/src/pseudophysics/core.jai +++ b/src/pseudophysics/core.jai @@ -1 +1,2 @@ #load "colliders.jai"; +#load "worldphysics.jai"; diff --git a/src/pseudophysics/worldphysics.jai b/src/pseudophysics/worldphysics.jai new file mode 100644 index 0000000..65171df --- /dev/null +++ b/src/pseudophysics/worldphysics.jai @@ -0,0 +1,15 @@ +is_trile_collision :: (fx: float, fy: float, fz: float) -> bool { + x := cast(s32)fx; + y := cast(s32)fy; + z := cast(s32)fz; + world := get_current_world(); + key := world_to_chunk_coord(x, y, z); + chunk := table_find_pointer(*world.world.chunks, key); + if !chunk then return false; + + lx, ly, lz := world_to_local(x, y, z); + + print("% % %\n", lx, ly, lz); + + return chunk.occupancy_mask[lx][ly][lz]; +} diff --git a/src/world.jai b/src/world.jai index bdb0507..825cb6c 100644 --- a/src/world.jai +++ b/src/world.jai @@ -59,6 +59,8 @@ Chunk :: struct { coord: Chunk_Key; groups: [..]Chunk_Trile_Group; + occupancy_mask : [32][32][32]bool; + sh_probe_grid: sg_image; // 192x4096 RGBA16F 2D texture (2 probes/trile/axis) sh_valid: bool; sh_dirty: bool; @@ -97,6 +99,26 @@ World :: struct { rdm_lookup : [..]Rdm_Atlas_Entry; // populated by bake (Step 5) and by loader (Step 6) } +calculate_and_set_chunk_occupancy_mask :: (chunk: *Chunk) { + print("Calculating occupancy mask for chunk %\n", chunk.coord); + // Clear it first: + for i: 0..15 { + for j: 0..15 { + for k: 0..15 { + chunk.occupancy_mask[i][j][k] = false; + } + } + } + + for group: chunk.groups { + // @ToDo: Handle non-colliding triles by getting the + // trile data here and continuing if it's non-colliding. + for instance : group.instances { + chunk.occupancy_mask[instance.x][instance.y][instance.z] = true; + } + } +} + rdm_get_atlas_rect :: (world: *World, x: s32, y: s32, z: s32) -> (Vector4, bool) { for world.rdm_lookup { if it.x == x && it.y == y && it.z == z then return it.atlas_rect, true; @@ -776,6 +798,7 @@ load_world_from_json :: (json_str: string, chunk_bin: []u8) -> (World, bool) { group.average_pos = gavg; array_add(*chunk.groups, group); } + calculate_and_set_chunk_occupancy_mask(*chunk); table_set(*world.chunks, chunk.coord, chunk); } @@ -813,114 +836,6 @@ load_world_from_json :: (json_str: string, chunk_bin: []u8) -> (World, bool) { return world, true; } -load_world_from_data :: (data: []u8) -> (World, bool) { - world: World; - cursor: s64 = 0; - - if data.count < size_of(u32) + size_of(u16) { - log_error("World file too small"); - return world, false; - } - - // Header - magic := read_value(data, *cursor, u32); - if magic != WORLD_MAGIC { - log_error("Invalid world file magic"); - return world, false; - } - - version := read_value(data, *cursor, u16); - if version != 1 && version != 2 && version != 3 { - log_error("Unsupported world version: %", version); - return world, false; - } - - name_len := cast(s64) read_value(data, *cursor, u16); - world.name = read_string(data, *cursor, name_len); - - // World config - conf_bin := read_value(data, *cursor, World_Config_Binary); - world.conf = world_config_from_binary(*conf_bin); - - num_chunks := read_value(data, *cursor, u32); - - // Read chunk table - Chunk_Table_Entry :: struct { - coord: Chunk_Key; - offset: u32; - size: u32; - } - - chunk_table: [..]Chunk_Table_Entry; - chunk_table.allocator = temp; - for i: 0..cast(s64)num_chunks-1 { - entry: Chunk_Table_Entry; - entry.coord.x = read_value(data, *cursor, s32); - entry.coord.y = read_value(data, *cursor, s32); - entry.coord.z = read_value(data, *cursor, s32); - entry.offset = read_value(data, *cursor, u32); - entry.size = read_value(data, *cursor, u32); - array_add(*chunk_table, entry); - } - - // Read chunk data - for entry: chunk_table { - chunk_cursor: s64 = cast(s64) entry.offset; - chunk: Chunk; - chunk.coord = entry.coord; - - num_types := read_value(data, *chunk_cursor, u16); - for t: 0..cast(s64)num_types-1 { - group: Chunk_Trile_Group; - gname_len := cast(s64) read_value(data, *chunk_cursor, u16); - group.trile_name = read_string(data, *chunk_cursor, gname_len); - count := cast(s64) read_value(data, *chunk_cursor, u16); - for i: 0..count-1 { - inst := read_value(data, *chunk_cursor, Trile_Instance); - array_add(*group.instances, inst); - } - - array_add(*chunk.groups, group); - } - table_set(*world.chunks, chunk.coord, chunk); - } - - if chunk_table.count > 0 { - last := chunk_table[chunk_table.count - 1]; - cursor = cast(s64)(last.offset + last.size); - } - - if version >= 2 && cursor < data.count { - num_emitters := cast(s64) read_value(data, *cursor, u16); - for i: 0..num_emitters-1 { - inst: Particle_Emitter_Instance; - name_len := cast(s64) read_value(data, *cursor, u16); - inst.definition_name = read_string(data, *cursor, name_len); - inst.position.x = read_value(data, *cursor, float); - inst.position.y = read_value(data, *cursor, float); - inst.position.z = read_value(data, *cursor, float); - inst.active = true; - array_add(*world.emitter_instances, inst); - } - } - - if version >= 3 && cursor < data.count { - num_notes := cast(s64) read_value(data, *cursor, u16); - for i: 0..num_notes-1 { - note: Editor_Note; - text_len := cast(s64) read_value(data, *cursor, u16); - note.text = read_string(data, *cursor, text_len); - note.position.x = read_value(data, *cursor, s32); - note.position.y = read_value(data, *cursor, s32); - note.position.z = read_value(data, *cursor, s32); - array_add(*world.notes, note); - } - } - - return world, true; -} - - World_Config :: struct { // All of the @Notes are for the autoedit functionality. skyBase : Vector3 = .{0.38, 0.81, 0.95}; @Color