Files
wschod/game/src/chunk/manager.c
T
2025-06-03 10:51:21 +02:00

143 lines
3.4 KiB
C

#include "manager.h"
/* TODO: perhaps render the chunks in a circle, not a square, around
the player? */
ChunkManager chunk_manager;
guint
cm_ivec2_hash (gconstpointer key)
{
const ivec2 *v = key;
return g_int_hash(&(*v)[0]) ^ g_int_hash(&(*v)[1]);
}
gboolean
cm_ivec2_equal (gconstpointer a, gconstpointer b)
{
const ivec2 *av = a;
const ivec2 *bv = b;
return (*av)[0] == (*bv)[0] && (*av)[1] == (*bv)[1];
}
ivec2 *
cm_make_key(int x, int z)
{
ivec2 *key = malloc(sizeof(ivec2));
(*key)[0] = x;
(*key)[1] = z;
return key;
}
void
cm_world_to_chunk (float x, float z, int *ox, int *oz)
{
*ox = floor (x / (float) CHUNK_DIM);
*oz = floor (z / (float) CHUNK_DIM);
}
void
ChunkManager_init ()
{
chunk_manager.chunks = g_hash_table_new_full (cm_ivec2_hash, cm_ivec2_equal, free, (GDestroyNotify) Chunk_free);
chunk_manager.chunk_meshes = g_hash_table_new_full (cm_ivec2_hash, cm_ivec2_equal, free, (GDestroyNotify) Chunk_free);
}
void
ChunkManager_update (vec3 camera_position)
{
int cx, cz;
cm_world_to_chunk (camera_position[0], camera_position[2], &cx, &cz);
for (int z = cz - RENDER_DISTANCE - 1; z <= cz + RENDER_DISTANCE + 1; ++z)
{
for (int x = cx - RENDER_DISTANCE - 1; x <= cx + RENDER_DISTANCE + 1; ++x)
{
if (ChunkManager_get_Chunk_at (x, z) == NULL)
{
ChunkManager_generate_Chunk_at (x, z);
}
}
}
for (int z = cz - RENDER_DISTANCE; z <= cz + RENDER_DISTANCE; ++z)
{
for (int x = cx - RENDER_DISTANCE; x <= cx + RENDER_DISTANCE; ++x)
{
if (ChunkManager_get_ChunkMesh_at (x, z) == NULL)
{
ChunkManager_generate_ChunkMesh_at (x, z);
}
}
}
}
void
ChunkManager_render (vec3 camera_position, int program)
{
int cx = 0, cz = 0;
cm_world_to_chunk (camera_position[0], camera_position[2], &cx, &cz);
for (int z = cz - RENDER_DISTANCE; z <= cz + RENDER_DISTANCE; ++z)
{
for (int x = cx - RENDER_DISTANCE; x <= cx + RENDER_DISTANCE; ++x)
{
ChunkMesh *mesh = ChunkManager_get_ChunkMesh_at (x, z);
if (mesh != NULL)
{
program_set_vec3 (program, "chunk_position", x * CHUNK_DIM, 0.0, z * CHUNK_DIM);
ChunkMesh_render (mesh);
}
}
}
}
Chunk *
ChunkManager_get_Chunk_at (int x, int z)
{
return (Chunk *) g_hash_table_lookup (chunk_manager.chunks, (ivec2) { x, z });
}
void
ChunkManager_set_Chunk_at (int x, int z, Chunk *chunk)
{
g_hash_table_insert (chunk_manager.chunks, cm_make_key (x, z), chunk);
}
void
ChunkManager_generate_Chunk_at (int x, int z)
{
Chunk *chunk = Chunk_new ();
Chunk_random (chunk, x * CHUNK_DIM, z * CHUNK_DIM);
ChunkManager_set_Chunk_at (x, z, chunk);
}
void
ChunkManager_get_Chunk_neighbors_at (int x, int z, Chunk **nr, Chunk **nd, Chunk **nc)
{
*nr = ChunkManager_get_Chunk_at (x + 1, z);
*nd = ChunkManager_get_Chunk_at (x, z + 1);
*nc = ChunkManager_get_Chunk_at (x + 1, z + 1);
}
ChunkMesh *
ChunkManager_get_ChunkMesh_at (int x, int z)
{
return (ChunkMesh *) g_hash_table_lookup (chunk_manager.chunk_meshes, (ivec2) { x, z });
}
void
ChunkManager_set_ChunkMesh_at (int x, int z, ChunkMesh *mesh)
{
g_hash_table_insert (chunk_manager.chunk_meshes, cm_make_key (x, z), mesh);
}
void
ChunkManager_generate_ChunkMesh_at (int x, int z)
{
Chunk *nr, *nd, *nc;
ChunkManager_get_Chunk_neighbors_at (x, z, &nr, &nd, &nc);
ChunkManager_set_ChunkMesh_at
(x, z, ChunkMesh_build (ChunkManager_get_Chunk_at (x, z), nr, nd, nc));
}