#pragma once #include #include #include "types.h" #include "gl.h" #define LOG(level, ...) \ do { \ printf("%s", level); \ printf(__VA_ARGS__); \ printf("\n"); \ } while (0) #define INFO(...) LOG("INFO ", __VA_ARGS__) #define WARN(...) LOG("WARN ", __VA_ARGS__) #define ERROR(...) LOG("ERROR ", __VA_ARGS__) #define DEBUG(...) LOG("DEBUG ", __VA_ARGS__) #define VOXEL_OK 0 #define VOXEL_ERROR 1 #define VOXEL_TRUE 0 #define VOXEL_FALSE 1 #define VOXEL_RESULT int typedef enum : char { POS_X = 0, NEG_X = 1, POS_Y = 2, NEG_Y = 3, POS_Z = 4, NEG_Z = 5, } Face; typedef enum : char { AIR = 0, A, B, C, D } Block; #define CHUNK_SIZE 16 #define CHUNK_BLOCKS CHUNK_SIZE * CHUNK_SIZE * CHUNK_SIZE #define LOCAL_POS(n) (((n) % CHUNK_SIZE + CHUNK_SIZE) % CHUNK_SIZE) #define LOCAL_VEC(gx, gy, gz) { LOCAL_POS(gx), LOCAL_POS(gy), LOCAL_POS(gz) } #define LOCAL_VEC_V(vec) LOCAL_VEC((int)(vec)[0], (int)(vec)[1], (int)(vec)[2]) #define CHUNK_POS(n) (((n) - LOCAL_POS(n)) / CHUNK_SIZE) #define CHUNK_VEC(gx, gy, gz) { CHUNK_POS(gx), CHUNK_POS(gy), CHUNK_POS(gz) } #define CHUNK_VEC_V(vec) CHUNK_VEC((int)(vec)[0], (int)(vec)[1], (int)(vec)[2]) typedef enum chunk_state { CHUNK_NEW = 0, CHUNK_GENERATING, CHUNK_GENERATED, CHUNK_MESHING, CHUNK_MESHED, } ChunkState; typedef struct chunk { ivec3 pos; Block *blocks; _Atomic ChunkState state; /* cached mesh */ _Atomic bool has_mesh; Uniform mesh; } Chunk; void chunk_init(Chunk *chunk, i32 cx, i32 cy, i32 cz); void chunk_free(Chunk *chunk); void chunk_generate(Chunk *chunk, i32 seed); Block chunk_at(Chunk *chunk, i32 lx, i32 ly, i32 lz); typedef vec4 Plane; typedef struct frustum { Plane left; Plane right; Plane bottom; Plane top; Plane near; Plane far; } Frustum; typedef struct aabb { vec3 min; vec3 max; } AABB; bool aabb_in_plane(AABB *aabb, Plane plane); bool aabb_in_frustum(AABB *aabb, Frustum *frustum); AABB chunk_aabb(Chunk *chunk); typedef struct camera { vec3 position; vec3 rotation; int fov; float near; float far; float look_speed; float move_speed; Frustum frustum; } Camera; void camera_init(Camera *camera); void camera_proj(Camera *camera, mat4 proj); void camera_view(Camera *camera, mat4 view); void camera_proj_view(Camera *camera, mat4 proj_view); void camera_update(Camera *camera); Frustum camera_frustum(Camera *camera); typedef struct renderer { Mesh quad; Shader shader; Uniform matrices; Frustum frustum; } Renderer; VOXEL_RESULT renderer_init(Renderer *renderer); void renderer_start(Renderer *renderer, Camera *camera); void renderer_draw(Renderer *renderer, Chunk *chunk); void renderer_stop(Renderer *renderer); void renderer_free(Renderer *renderer); #define RENDER_DISTANCE 10 typedef struct rc_chunk { Chunk chunk; _Atomic u32 rc; } RcChunk; void rcchunk_drop(RcChunk *chunk); typedef i32 seed_t; typedef struct world { seed_t seed; bool loaded; ivec3 center; RcChunk **chunks; mtx_t lock; } World; void world_init(World *world, seed_t seed); void world_lock(World *world); void world_unlock(World *world); void world_free(World *world); void world_update(World *world, Camera *camera); void world_render(World *world, Renderer *renderer); RcChunk *world_get_chunk(World *world, i32 cx, i32 cy, i32 cz); bool world_is_generated(World *world, i32 cx, i32 cy, i32 cz); Block world_get_block(World *world, i32 gx, i32 gy, i32 gz); void chunk_mesh(Chunk *chunk, World *world);