]> git.lizzy.rs Git - dragonblocks_alpha.git/blob - src/server/voxelctx.c
6f5ee208b240d31acae08214e562eb5e708e77cb
[dragonblocks_alpha.git] / src / server / voxelctx.c
1 #include <stdlib.h>
2 #include <pthread.h>
3 #include "server/mapgen.h"
4 #include "server/voxelctx.h"
5 #include "perlin.h"
6 #include "util.h"
7
8 static VoxelctxState *create_state(VoxelctxState *old)
9 {
10         VoxelctxState *state = malloc(sizeof(VoxelctxState));
11
12         if (old) {
13                 *state = *old;
14         } else {
15                 state->pos[0] = 0.0f;
16                 state->pos[1] = 0.0f;
17                 state->pos[2] = 0.0f;
18                 state->pos[3] = 0.0f;
19                 state->scale[0] = 1.0f;
20                 state->scale[1] = 1.0f;
21                 state->scale[2] = 1.0f;
22                 mat4x4_identity(state->mat);
23                 state->h = 0.0f;
24                 state->s = 0.0f;
25                 state->l = 1.0f;
26                 state->life = 0;
27         }
28
29         return state;
30 }
31
32 Voxelctx *voxelctx_create(List *changed_blocks, MapgenStage mgs, v3s32 pos)
33 {
34         Voxelctx *ctx = malloc(sizeof(Voxelctx));
35
36         ctx->changed_blocks = changed_blocks;
37         ctx->mgs = mgs;
38         ctx->pos = pos;
39         ctx->statestack = list_create(NULL);
40         ctx->random = 0;
41
42         list_put(&ctx->statestack, create_state(NULL), NULL);
43
44         return ctx;
45 }
46
47 static void list_delete_state(void *key, unused void *value, unused void *arg)
48 {
49         free(key);
50 }
51
52 void voxelctx_delete(Voxelctx *ctx)
53 {
54         list_clear_func(&ctx->statestack, &list_delete_state, NULL);
55         free(ctx);
56 }
57
58 static void move_value(f32 *x, f32 v, f32 range)
59 {
60     f32 dst = v >= 0 ? range : 0;
61     v = fabs(v);
62     *x = f32_mix(*x, dst, v);
63 }
64
65 void voxelctx_hue(Voxelctx *ctx, f32 value)
66 {
67         VOXELCTXSTATE(ctx).h += value;
68 }
69
70 void voxelctx_sat(Voxelctx *ctx, f32 value)
71 {
72         move_value(&VOXELCTXSTATE(ctx).s, value, 1.0f);
73 }
74
75 void voxelctx_light(Voxelctx *ctx, f32 value)
76 {
77         move_value(&VOXELCTXSTATE(ctx).l, value, 1.0f);
78 }
79
80 void voxelctx_life(Voxelctx *ctx, s32 value)
81 {
82         VOXELCTXSTATE(ctx).life += value;
83 }
84
85 static void apply_translation(Voxelctx *ctx, v3f32 translate)
86 {
87         vec4 translate_vec;
88         mat4x4_mul_vec4(translate_vec, VOXELCTXSTATE(ctx).mat, (vec4) {translate.x, translate.y, translate.z, 0.0f});
89         vec4_add(VOXELCTXSTATE(ctx).pos, VOXELCTXSTATE(ctx).pos, translate_vec);
90 }
91
92 void voxelctx_x(Voxelctx *ctx, f32 value)
93 {
94         apply_translation(ctx, (v3f32) {value, 0.0f, 0.0f});
95 }
96
97 void voxelctx_y(Voxelctx *ctx, f32 value)
98 {
99         apply_translation(ctx, (v3f32) {0.0f, value, 0.0f});
100 }
101
102 void voxelctx_z(Voxelctx *ctx, f32 value)
103 {
104         apply_translation(ctx, (v3f32) {0.0f, 0.0f, value});
105 }
106
107 void voxelctx_rx(Voxelctx *ctx, f32 value)
108 {
109         mat4x4_rotate_X(VOXELCTXSTATE(ctx).mat, VOXELCTXSTATE(ctx).mat, value * M_PI / 180.0f);
110 }
111
112 void voxelctx_ry(Voxelctx *ctx, f32 value)
113 {
114         mat4x4_rotate_Y(VOXELCTXSTATE(ctx).mat, VOXELCTXSTATE(ctx).mat, value * M_PI / 180.0f);
115 }
116
117 void voxelctx_rz(Voxelctx *ctx, f32 value)
118 {
119         mat4x4_rotate_Z(VOXELCTXSTATE(ctx).mat, VOXELCTXSTATE(ctx).mat, value * M_PI / 180.0f);
120 }
121
122 static void apply_scale(Voxelctx *ctx, v3f32 scale)
123 {
124         VOXELCTXSTATE(ctx).scale[0] *= scale.x;
125         VOXELCTXSTATE(ctx).scale[1] *= scale.y;
126         VOXELCTXSTATE(ctx).scale[2] *= scale.z;
127
128         mat4x4_scale_aniso(VOXELCTXSTATE(ctx).mat, VOXELCTXSTATE(ctx).mat, scale.x, scale.y, scale.z);
129 }
130
131 void voxelctx_sx(Voxelctx *ctx, f32 value)
132 {
133         apply_scale(ctx, (v3f32) {value, 1.0f, 1.0f});
134 }
135
136 void voxelctx_sy(Voxelctx *ctx, f32 value)
137 {
138         apply_scale(ctx, (v3f32) {1.0f, value, 1.0f});
139 }
140
141 void voxelctx_sz(Voxelctx *ctx, f32 value)
142 {
143         apply_scale(ctx, (v3f32) {1.0f, 1.0f, value});
144 }
145
146 void voxelctx_s(Voxelctx *ctx, f32 value)
147 {
148         apply_scale(ctx, (v3f32) {value, value, value});
149 }
150
151 void voxelctx_pop(Voxelctx *ctx)
152 {
153         ListPair *next = ctx->statestack.first->next;
154         free(ctx->statestack.first->key);
155         free(ctx->statestack.first);
156         ctx->statestack.first = next;
157 }
158
159 void voxelctx_push(Voxelctx *ctx)
160 {
161         ListPair *pair = malloc(sizeof(ListPair));
162         pair->key = create_state(&VOXELCTXSTATE(ctx));
163         pair->value = NULL;
164         pair->next = ctx->statestack.first;
165
166         ctx->statestack.first = pair;
167 }
168
169 bool voxelctx_is_alive(Voxelctx *ctx)
170 {
171         if (VOXELCTXSTATE(ctx).life > 0) {
172                 VOXELCTXSTATE(ctx).life--;
173                 if (VOXELCTXSTATE(ctx).life <= 0)
174                         return false;
175         }
176
177         return VOXELCTXSTATE(ctx).scale[0] >= 1.0f && VOXELCTXSTATE(ctx).scale[1] >= 1.0f && VOXELCTXSTATE(ctx).scale[2] >= 1.0f;
178 }
179
180 void voxelctx_cube(Voxelctx *ctx, Node node, bool use_color)
181 {
182         if (! voxelctx_is_alive(ctx))
183                 return;
184
185         vec4 base_corners[8] = {
186                 {0.0f, 0.0f, 0.0f, 0.0f},
187                 {0.0f, 0.0f, 1.0f, 0.0f},
188                 {0.0f, 1.0f, 0.0f, 0.0f},
189                 {0.0f, 1.0f, 1.0f, 0.0f},
190                 {1.0f, 0.0f, 0.0f, 0.0f},
191                 {1.0f, 0.0f, 1.0f, 0.0f},
192                 {1.0f, 1.0f, 0.0f, 0.0f},
193                 {1.0f, 1.0f, 1.0f, 0.0f},
194         };
195
196         vec4 corners[8];
197
198         s32 max_len = 0;
199
200         vec4 center;
201
202         mat4x4_mul_vec4(center, VOXELCTXSTATE(ctx).mat, (vec4) {0.5f, 0.5f, 0.5f});
203
204         for (int i = 0; i < 8; i++) {
205                 mat4x4_mul_vec4(corners[i], VOXELCTXSTATE(ctx).mat, base_corners[i]);
206
207                 vec3 from_center;
208                 vec3_sub(from_center, corners[i], center);
209
210                 s32 len = ceil(vec3_len(from_center));
211
212                 if (max_len < len)
213                         max_len = len;
214         }
215
216         for (s32 x = -max_len; x <= +max_len; x++)
217         for (s32 y = -max_len; y <= +max_len; y++)
218         for (s32 z = -max_len; z <= +max_len; z++) {
219                 s32 v[3];
220
221                 for (int i = 0; i < 3; i++) {
222                         f32 f = trunc(
223                                 + f32_mix(corners[0][i], corners[4][i], (f32) x / (f32) max_len / 2.0f)
224                                 + f32_mix(corners[0][i], corners[2][i], (f32) y / (f32) max_len / 2.0f)
225                                 + f32_mix(corners[0][i], corners[1][i], (f32) z / (f32) max_len / 2.0f));
226
227                         v[i] = floor(VOXELCTXSTATE(ctx).pos[i] + f + 0.5f);
228                 }
229
230                 Blob buffer = {0, NULL};
231
232                 if (use_color)
233                         HSLData_write(&buffer, &(HSLData) {{
234                                 VOXELCTXSTATE(ctx).h / 360.0,
235                                 VOXELCTXSTATE(ctx).s,
236                                 VOXELCTXSTATE(ctx).l,
237                         }});
238
239                 mapgen_set_node(
240                         v3s32_add(ctx->pos, (v3s32) {v[0], v[2], v[1]}),
241                         map_node_create(node, buffer),
242                         ctx->mgs,
243                         ctx->changed_blocks
244                 );
245         }
246 }
247
248
249 void voxelctx_cylinder(Voxelctx *ctx, Node node, bool use_color)
250 {
251         voxelctx_cube(ctx, node, use_color);
252 }
253
254 /*
255 void voxelctx_cylinder(Voxelctx *ctx, Node node, bool use_color)
256 {
257         if (! voxelctx_is_alive(ctx))
258                 return;
259
260         return;
261
262         f32 xf = VOXELCTXSTATE(ctx).scale[0] / 2.0f;
263         for (s32 x = round(-xf + 0.5f); x <= round(xf); x++) {
264                 f32 yf = cos(x / VOXELCTXSTATE(ctx).scale[0] * M_PI) * VOXELCTXSTATE(ctx).scale[1] / 2.0f;
265                 for (s32 y = round(-yf); y <= round(yf); y++) {
266                         f32 zf = VOXELCTXSTATE(ctx).scale[2] / 2.0f;
267                         for (s32 z = round(-zf + 0.5f); z <= round(zf); z++) {
268                                 mapgen_set_node((v3s32) {
269                                         ctx->pos.x + round(VOXELCTXSTATE(ctx).pos[0] + x),
270                                         ctx->pos.y + round(VOXELCTXSTATE(ctx).pos[2] + z),
271                                         ctx->pos.z + round(VOXELCTXSTATE(ctx).pos[1] + y),
272                                 }, CREATE_NODE, ctx->mgs, ctx->changed_blocks);
273                         }
274                 }
275         }
276 }
277 */
278
279 f32 voxelctx_random(Voxelctx *ctx, f32 base, f32 vary)
280 {
281         return base + noise3d(ctx->pos.x, ctx->pos.y, ctx->pos.z, ctx->random++, seed + SO_VOXELCTX) * vary;
282 }