5 #include "server/terrain_gen.h"
6 #include "server/voxel_procedural.h"
8 #define VOXEL_PROCEDURAL_STATE(proc) (*((VoxelProceduralState *) (proc)->state.fst->dat))
10 static VoxelProceduralState *create_state(VoxelProceduralState *old)
12 VoxelProceduralState *state = malloc(sizeof *state);
21 state->scale[0] = 1.0f;
22 state->scale[1] = 1.0f;
23 state->scale[2] = 1.0f;
24 mat4x4_identity(state->mat);
34 VoxelProcedural *voxel_procedural_create(List *changed_chunks, TerrainGenStage tgs, v3s32 pos)
36 VoxelProcedural *proc = malloc(sizeof(VoxelProcedural));
38 proc->changed_chunks = changed_chunks;
43 list_ini(&proc->state);
44 list_apd(&proc->state, create_state(NULL));
49 void voxel_procedural_delete(VoxelProcedural *proc)
51 list_clr(&proc->state, &free, NULL, NULL);
55 static void move_value(f32 *x, f32 v, f32 range)
57 f32 dst = v >= 0 ? range : 0;
59 *x = f32_mix(*x, dst, v);
62 void voxel_procedural_hue(VoxelProcedural *proc, f32 value)
64 VOXEL_PROCEDURAL_STATE(proc).h += value;
67 void voxel_procedural_sat(VoxelProcedural *proc, f32 value)
69 move_value(&VOXEL_PROCEDURAL_STATE(proc).s, value, 1.0f);
72 void voxel_procedural_light(VoxelProcedural *proc, f32 value)
74 move_value(&VOXEL_PROCEDURAL_STATE(proc).l, value, 1.0f);
77 void voxel_procedural_life(VoxelProcedural *proc, s32 value)
79 VOXEL_PROCEDURAL_STATE(proc).life += value;
82 static void apply_translation(VoxelProcedural *proc, v3f32 translate)
84 vec4 dst, src = {translate.x, translate.y, translate.z, 0.0f};
85 mat4x4_mul_vec4(dst, VOXEL_PROCEDURAL_STATE(proc).mat, src);
86 vec4_add(VOXEL_PROCEDURAL_STATE(proc).pos, VOXEL_PROCEDURAL_STATE(proc).pos, dst);
89 void voxel_procedural_x(VoxelProcedural *proc, f32 value)
91 apply_translation(proc, (v3f32) {value, 0.0f, 0.0f});
94 void voxel_procedural_y(VoxelProcedural *proc, f32 value)
96 apply_translation(proc, (v3f32) {0.0f, value, 0.0f});
99 void voxel_procedural_z(VoxelProcedural *proc, f32 value)
101 apply_translation(proc, (v3f32) {0.0f, 0.0f, value});
104 void voxel_procedural_rx(VoxelProcedural *proc, f32 value)
106 mat4x4_rotate_X(VOXEL_PROCEDURAL_STATE(proc).mat, VOXEL_PROCEDURAL_STATE(proc).mat,
107 value * M_PI / 180.0f);
110 void voxel_procedural_ry(VoxelProcedural *proc, f32 value)
112 mat4x4_rotate_Y(VOXEL_PROCEDURAL_STATE(proc).mat, VOXEL_PROCEDURAL_STATE(proc).mat,
113 value * M_PI / 180.0f);
116 void voxel_procedural_rz(VoxelProcedural *proc, f32 value)
118 mat4x4_rotate_Z(VOXEL_PROCEDURAL_STATE(proc).mat, VOXEL_PROCEDURAL_STATE(proc).mat,
119 value * M_PI / 180.0f);
122 static void apply_scale(VoxelProcedural *proc, v3f32 scale)
124 VOXEL_PROCEDURAL_STATE(proc).scale[0] *= scale.x;
125 VOXEL_PROCEDURAL_STATE(proc).scale[1] *= scale.y;
126 VOXEL_PROCEDURAL_STATE(proc).scale[2] *= scale.z;
128 mat4x4_scale_aniso(VOXEL_PROCEDURAL_STATE(proc).mat, VOXEL_PROCEDURAL_STATE(proc).mat,
129 scale.x, scale.y, scale.z);
132 void voxel_procedural_sx(VoxelProcedural *proc, f32 value)
134 apply_scale(proc, (v3f32) {value, 1.0f, 1.0f});
137 void voxel_procedural_sy(VoxelProcedural *proc, f32 value)
139 apply_scale(proc, (v3f32) {1.0f, value, 1.0f});
142 void voxel_procedural_sz(VoxelProcedural *proc, f32 value)
144 apply_scale(proc, (v3f32) {1.0f, 1.0f, value});
147 void voxel_procedural_s(VoxelProcedural *proc, f32 value)
149 apply_scale(proc, (v3f32) {value, value, value});
152 void voxel_procedural_pop(VoxelProcedural *proc)
154 free(proc->state.fst->dat);
155 list_nrm(&proc->state, &proc->state.fst);
158 void voxel_procedural_push(VoxelProcedural *proc)
160 list_ppd(&proc->state, create_state(&VOXEL_PROCEDURAL_STATE(proc)));
163 bool voxel_procedural_is_alive(VoxelProcedural *proc)
165 if (VOXEL_PROCEDURAL_STATE(proc).life > 0 && --VOXEL_PROCEDURAL_STATE(proc).life <= 0)
169 VOXEL_PROCEDURAL_STATE(proc).scale[0] >= 1.0f &&
170 VOXEL_PROCEDURAL_STATE(proc).scale[1] >= 1.0f &&
171 VOXEL_PROCEDURAL_STATE(proc).scale[2] >= 1.0f;
174 void voxel_procedural_cube(VoxelProcedural *proc, NodeType node, bool use_color)
176 if (!voxel_procedural_is_alive(proc))
179 vec4 base_corners[8] = {
180 {0.0f, 0.0f, 0.0f, 0.0f},
181 {0.0f, 0.0f, 1.0f, 0.0f},
182 {0.0f, 1.0f, 0.0f, 0.0f},
183 {0.0f, 1.0f, 1.0f, 0.0f},
184 {1.0f, 0.0f, 0.0f, 0.0f},
185 {1.0f, 0.0f, 1.0f, 0.0f},
186 {1.0f, 1.0f, 0.0f, 0.0f},
187 {1.0f, 1.0f, 1.0f, 0.0f},
196 mat4x4_mul_vec4(center, VOXEL_PROCEDURAL_STATE(proc).mat, (vec4) {0.5f, 0.5f, 0.5f});
198 for (int i = 0; i < 8; i++) {
199 mat4x4_mul_vec4(corners[i], VOXEL_PROCEDURAL_STATE(proc).mat, base_corners[i]);
202 vec3_sub(from_center, corners[i], center);
204 s32 len = ceil(vec3_len(from_center));
210 for (s32 x = -max_len; x <= +max_len; x++)
211 for (s32 y = -max_len; y <= +max_len; y++)
212 for (s32 z = -max_len; z <= +max_len; z++) {
215 for (int i = 0; i < 3; i++) {
217 + f32_mix(corners[0][i], corners[4][i], (f32) x / (f32) max_len / 2.0f)
218 + f32_mix(corners[0][i], corners[2][i], (f32) y / (f32) max_len / 2.0f)
219 + f32_mix(corners[0][i], corners[1][i], (f32) z / (f32) max_len / 2.0f));
221 v[i] = floor(VOXEL_PROCEDURAL_STATE(proc).pos[i] + f + 0.5f);
224 Blob buffer = {0, NULL};
227 ColorData_write(&buffer, &(ColorData) {hsl_to_rgb((v3f32) {
228 VOXEL_PROCEDURAL_STATE(proc).h / 360.0,
229 VOXEL_PROCEDURAL_STATE(proc).s,
230 VOXEL_PROCEDURAL_STATE(proc).l,
233 server_terrain_gen_node(
234 v3s32_add(proc->pos, (v3s32) {v[0], v[2], v[1]}),
235 terrain_node_create(node, buffer),
245 void voxel_procedural_cylinder(VoxelProcedural *proc, NodeType node, bool use_color)
247 voxel_procedural_cube(proc, node, use_color);
251 void voxel_procedural_cylinder(VoxelProcedural *proc, Node node, bool use_color)
253 if (!voxel_procedural_is_alive(proc))
258 f32 xf = VOXEL_PROCEDURAL_STATE(proc).scale[0] / 2.0f;
259 for (s32 x = round(-xf + 0.5f); x <= round(xf); x++) {
260 f32 yf = cos(x / VOXEL_PROCEDURAL_STATE(proc).scale[0] * M_PI) * VOXEL_PROCEDURAL_STATE(proc).scale[1] / 2.0f;
261 for (s32 y = round(-yf); y <= round(yf); y++) {
262 f32 zf = VOXEL_PROCEDURAL_STATE(proc).scale[2] / 2.0f;
263 for (s32 z = round(-zf + 0.5f); z <= round(zf); z++) {
264 mapgen_set_node((v3s32) {
265 proc->pos.x + round(VOXEL_PROCEDURAL_STATE(proc).pos[0] + x),
266 proc->pos.y + round(VOXEL_PROCEDURAL_STATE(proc).pos[2] + z),
267 proc->pos.z + round(VOXEL_PROCEDURAL_STATE(proc).pos[1] + y),
268 }, CREATE_NODE, proc->tgs, proc->changed_chunks);
275 f32 voxel_procedural_random(VoxelProcedural *proc, f32 base, f32 vary)
277 return base + noise3d(proc->pos.x, proc->pos.y, proc->pos.z, proc->random++, seed + OFFSET_VOXEL_PROCEDURAL) * vary;