1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
#pragma once
#include <cglm/cglm.h>
#include <threads.h>
#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);
|