5 #include "server/terrain_gen.h"
6 #include "server/voxelctx.h"
8 static VoxelctxState *create_state(VoxelctxState *old)
10 VoxelctxState *state = malloc(sizeof *state);
19 state->scale[0] = 1.0f;
20 state->scale[1] = 1.0f;
21 state->scale[2] = 1.0f;
22 mat4x4_identity(state->mat);
32 Voxelctx *voxelctx_create(List *changed_chunks, TerrainGenStage tgs, v3s32 pos)
34 Voxelctx *ctx = malloc(sizeof(Voxelctx));
36 ctx->changed_chunks = changed_chunks;
39 list_ini(&ctx->statestack);
42 list_apd(&ctx->statestack, create_state(NULL));
47 void voxelctx_delete(Voxelctx *ctx)
49 list_clr(&ctx->statestack, &free, NULL, NULL);
53 static void move_value(f32 *x, f32 v, f32 range)
55 f32 dst = v >= 0 ? range : 0;
57 *x = f32_mix(*x, dst, v);
60 void voxelctx_hue(Voxelctx *ctx, f32 value)
62 VOXELCTXSTATE(ctx).h += value;
65 void voxelctx_sat(Voxelctx *ctx, f32 value)
67 move_value(&VOXELCTXSTATE(ctx).s, value, 1.0f);
70 void voxelctx_light(Voxelctx *ctx, f32 value)
72 move_value(&VOXELCTXSTATE(ctx).l, value, 1.0f);
75 void voxelctx_life(Voxelctx *ctx, s32 value)
77 VOXELCTXSTATE(ctx).life += value;
80 static void apply_translation(Voxelctx *ctx, v3f32 translate)
83 mat4x4_mul_vec4(translate_vec, VOXELCTXSTATE(ctx).mat, (vec4) {translate.x, translate.y, translate.z, 0.0f});
84 vec4_add(VOXELCTXSTATE(ctx).pos, VOXELCTXSTATE(ctx).pos, translate_vec);
87 void voxelctx_x(Voxelctx *ctx, f32 value)
89 apply_translation(ctx, (v3f32) {value, 0.0f, 0.0f});
92 void voxelctx_y(Voxelctx *ctx, f32 value)
94 apply_translation(ctx, (v3f32) {0.0f, value, 0.0f});
97 void voxelctx_z(Voxelctx *ctx, f32 value)
99 apply_translation(ctx, (v3f32) {0.0f, 0.0f, value});
102 void voxelctx_rx(Voxelctx *ctx, f32 value)
104 mat4x4_rotate_X(VOXELCTXSTATE(ctx).mat, VOXELCTXSTATE(ctx).mat, value * M_PI / 180.0f);
107 void voxelctx_ry(Voxelctx *ctx, f32 value)
109 mat4x4_rotate_Y(VOXELCTXSTATE(ctx).mat, VOXELCTXSTATE(ctx).mat, value * M_PI / 180.0f);
112 void voxelctx_rz(Voxelctx *ctx, f32 value)
114 mat4x4_rotate_Z(VOXELCTXSTATE(ctx).mat, VOXELCTXSTATE(ctx).mat, value * M_PI / 180.0f);
117 static void apply_scale(Voxelctx *ctx, v3f32 scale)
119 VOXELCTXSTATE(ctx).scale[0] *= scale.x;
120 VOXELCTXSTATE(ctx).scale[1] *= scale.y;
121 VOXELCTXSTATE(ctx).scale[2] *= scale.z;
123 mat4x4_scale_aniso(VOXELCTXSTATE(ctx).mat, VOXELCTXSTATE(ctx).mat, scale.x, scale.y, scale.z);
126 void voxelctx_sx(Voxelctx *ctx, f32 value)
128 apply_scale(ctx, (v3f32) {value, 1.0f, 1.0f});
131 void voxelctx_sy(Voxelctx *ctx, f32 value)
133 apply_scale(ctx, (v3f32) {1.0f, value, 1.0f});
136 void voxelctx_sz(Voxelctx *ctx, f32 value)
138 apply_scale(ctx, (v3f32) {1.0f, 1.0f, value});
141 void voxelctx_s(Voxelctx *ctx, f32 value)
143 apply_scale(ctx, (v3f32) {value, value, value});
146 void voxelctx_pop(Voxelctx *ctx)
148 free(ctx->statestack.fst->dat);
149 list_nrm(&ctx->statestack, &ctx->statestack.fst);
152 void voxelctx_push(Voxelctx *ctx)
154 list_ppd(&ctx->statestack, create_state(&VOXELCTXSTATE(ctx)));
157 bool voxelctx_is_alive(Voxelctx *ctx)
159 if (VOXELCTXSTATE(ctx).life > 0) {
160 VOXELCTXSTATE(ctx).life--;
161 if (VOXELCTXSTATE(ctx).life <= 0)
165 return VOXELCTXSTATE(ctx).scale[0] >= 1.0f && VOXELCTXSTATE(ctx).scale[1] >= 1.0f && VOXELCTXSTATE(ctx).scale[2] >= 1.0f;
168 void voxelctx_cube(Voxelctx *ctx, NodeType node, bool use_color)
170 if (!voxelctx_is_alive(ctx))
173 vec4 base_corners[8] = {
174 {0.0f, 0.0f, 0.0f, 0.0f},
175 {0.0f, 0.0f, 1.0f, 0.0f},
176 {0.0f, 1.0f, 0.0f, 0.0f},
177 {0.0f, 1.0f, 1.0f, 0.0f},
178 {1.0f, 0.0f, 0.0f, 0.0f},
179 {1.0f, 0.0f, 1.0f, 0.0f},
180 {1.0f, 1.0f, 0.0f, 0.0f},
181 {1.0f, 1.0f, 1.0f, 0.0f},
190 mat4x4_mul_vec4(center, VOXELCTXSTATE(ctx).mat, (vec4) {0.5f, 0.5f, 0.5f});
192 for (int i = 0; i < 8; i++) {
193 mat4x4_mul_vec4(corners[i], VOXELCTXSTATE(ctx).mat, base_corners[i]);
196 vec3_sub(from_center, corners[i], center);
198 s32 len = ceil(vec3_len(from_center));
204 for (s32 x = -max_len; x <= +max_len; x++)
205 for (s32 y = -max_len; y <= +max_len; y++)
206 for (s32 z = -max_len; z <= +max_len; z++) {
209 for (int i = 0; i < 3; i++) {
211 + f32_mix(corners[0][i], corners[4][i], (f32) x / (f32) max_len / 2.0f)
212 + f32_mix(corners[0][i], corners[2][i], (f32) y / (f32) max_len / 2.0f)
213 + f32_mix(corners[0][i], corners[1][i], (f32) z / (f32) max_len / 2.0f));
215 v[i] = floor(VOXELCTXSTATE(ctx).pos[i] + f + 0.5f);
218 Blob buffer = {0, NULL};
221 ColorData_write(&buffer, &(ColorData) {hsl_to_rgb((v3f32) {
222 VOXELCTXSTATE(ctx).h / 360.0,
223 VOXELCTXSTATE(ctx).s,
224 VOXELCTXSTATE(ctx).l,
227 server_terrain_gen_node(
228 v3s32_add(ctx->pos, (v3s32) {v[0], v[2], v[1]}),
229 terrain_node_create(node, buffer),
239 void voxelctx_cylinder(Voxelctx *ctx, NodeType node, bool use_color)
241 voxelctx_cube(ctx, node, use_color);
245 void voxelctx_cylinder(Voxelctx *ctx, Node node, bool use_color)
247 if (!voxelctx_is_alive(ctx))
252 f32 xf = VOXELCTXSTATE(ctx).scale[0] / 2.0f;
253 for (s32 x = round(-xf + 0.5f); x <= round(xf); x++) {
254 f32 yf = cos(x / VOXELCTXSTATE(ctx).scale[0] * M_PI) * VOXELCTXSTATE(ctx).scale[1] / 2.0f;
255 for (s32 y = round(-yf); y <= round(yf); y++) {
256 f32 zf = VOXELCTXSTATE(ctx).scale[2] / 2.0f;
257 for (s32 z = round(-zf + 0.5f); z <= round(zf); z++) {
258 mapgen_set_node((v3s32) {
259 ctx->pos.x + round(VOXELCTXSTATE(ctx).pos[0] + x),
260 ctx->pos.y + round(VOXELCTXSTATE(ctx).pos[2] + z),
261 ctx->pos.z + round(VOXELCTXSTATE(ctx).pos[1] + y),
262 }, CREATE_NODE, ctx->tgs, ctx->changed_chunks);
269 f32 voxelctx_random(Voxelctx *ctx, f32 base, f32 vary)
271 return base + noise3d(ctx->pos.x, ctx->pos.y, ctx->pos.z, ctx->random++, seed + SO_VOXELCTX) * vary;