]> git.lizzy.rs Git - dragonblocks_alpha.git/commitdiff
Fix boulder shapes: depth-search to ground
authorElias Fleckenstein <eliasfleckenstein@web.de>
Sun, 17 Apr 2022 22:35:54 +0000 (00:35 +0200)
committerElias Fleckenstein <eliasfleckenstein@web.de>
Sun, 17 Apr 2022 22:35:54 +0000 (00:35 +0200)
16 files changed:
src/CMakeLists.txt
src/client/client_node.c
src/environment.c
src/perlin.h
src/server/biomes.c
src/server/biomes.h
src/server/terrain_gen.c
src/server/terrain_gen.h
src/server/trees.c
src/server/voxel_depth_search.c [new file with mode: 0644]
src/server/voxel_depth_search.h [new file with mode: 0644]
src/server/voxel_procedural.c [new file with mode: 0644]
src/server/voxel_procedural.h [new file with mode: 0644]
src/server/voxelctx.c [deleted file]
src/server/voxelctx.h [deleted file]
src/terrain.h

index df59104fdf6a87b61e105ea296464f7918c9b3c1..fe2de5104403c2192abc09e0693ad68b3b782438 100644 (file)
@@ -140,7 +140,8 @@ add_executable(dragonblocks_server
        server/server_terrain.c
        server/terrain_gen.c
        server/trees.c
-       server/voxelctx.c
+       server/voxel_depth_search.c
+       server/voxel_procedural.c
 )
 
 target_link_libraries(dragonblocks_server
index 970059074e5bf7338a20fbe633d90abff8c0d6d4..3a406196fc2f4138f3d13ce1e3d339368a5a9529 100644 (file)
@@ -29,8 +29,8 @@ static void render_grass(NodeArgsRender *args)
 
 static void render_stone(NodeArgsRender *args)
 {
-       args->vertex.cube.textureCoordinates.x += noise2d(args->pos.x, args->pos.z, 0, seed + SO_TEXTURE_OFFSET_S);
-       args->vertex.cube.textureCoordinates.y += noise2d(args->pos.x, args->pos.z, 0, seed + SO_TEXTURE_OFFSET_T);
+       args->vertex.cube.textureCoordinates.x += noise2d(args->pos.x, args->pos.z, 0, seed + OFFSET_TEXTURE_OFFSET_S);
+       args->vertex.cube.textureCoordinates.y += noise2d(args->pos.x, args->pos.z, 0, seed + OFFSET_TEXTURE_OFFSET_T);
 }
 
 static void render_color(NodeArgsRender *args)
index 5341603e8bbb74a019d10fb5d9f3ad7651de53f5..200eee72389f46f7b32e11568bb86d3f93ddc58e 100644 (file)
@@ -3,10 +3,10 @@
 
 f64 get_humidity(v3s32 pos)
 {
-       return smooth2d(U32(pos.x) / 128.0, U32(pos.z) / 128.0, 0, seed + SO_WETNESS) * 0.5 + 0.5;
+       return smooth2d(U32(pos.x) / 128.0, U32(pos.z) / 128.0, 0, seed + OFFSET_WETNESS) * 0.5 + 0.5;
 }
 
 f64 get_temperature(v3s32 pos)
 {
-       return smooth2d(U32(pos.x) / 128.0, U32(pos.z) / 128.0, 0, seed + SO_TEMPERATURE) * 0.5 + 0.5 - (pos.y - 32.0) / 64.0;
+       return smooth2d(U32(pos.x) / 128.0, U32(pos.z) / 128.0, 0, seed + OFFSET_TEMPERATURE) * 0.5 + 0.5 - (pos.y - 32.0) / 64.0;
 }
index 15a63c995f85baf05f647ffc60303b2c458c728d..2aab5e121d05adb6c902a8e8cd6a54ec55abd466 100644 (file)
@@ -7,31 +7,31 @@
 #define U32(x) (((u32) 1 << 31) + (x))
 
 typedef enum {
-       SO_NONE,
-       SO_HEIGHT,
-       SO_MOUNTAIN,
-       SO_OCEAN,
-       SO_MOUNTAIN_HEIGHT,
-       SO_BOULDER,
-       SO_WETNESS,
-       SO_TEXTURE_OFFSET_S,
-       SO_TEXTURE_OFFSET_T,
-       SO_TEMPERATURE,
-       SO_VULCANO,
-       SO_VULCANO_HEIGHT,
-       SO_VULCANO_STONE,
-       SO_VULCANO_CRATER_TOP,
-       SO_HILLYNESS,
-       SO_VOXELCTX,
-       SO_OAKTREE,
-       SO_OAKTREE_AREA,
-       SO_PINETREE,
-       SO_PINETREE_AREA,
-       SO_PINETREE_HEIGHT,
-       SO_PINETREE_BRANCH,
-       SO_PINETREE_BRANCH_DIR,
-       SO_PALMTREE,
-       SO_PALMTREE_AREA,
+       OFFSET_NONE,
+       OFFSET_HEIGHT,
+       OFFSET_MOUNTAIN,
+       OFFSET_OCEAN,
+       OFFSET_MOUNTAIN_HEIGHT,
+       OFFSET_BOULDER,
+       OFFSET_WETNESS,
+       OFFSET_TEXTURE_OFFSET_S,
+       OFFSET_TEXTURE_OFFSET_T,
+       OFFSET_TEMPERATURE,
+       OFFSET_VULCANO,
+       OFFSET_VULCANO_HEIGHT,
+       OFFSET_VULCANO_STONE,
+       OFFSET_VULCANO_CRATER_TOP,
+       OFFSET_HILLYNESS,
+       OFFSET_VOXEL_PROCEDURAL,
+       OFFSET_OAKTREE,
+       OFFSET_OAKTREE_AREA,
+       OFFSET_PINETREE,
+       OFFSET_PINETREE_AREA,
+       OFFSET_PINETREE_HEIGHT,
+       OFFSET_PINETREE_BRANCH,
+       OFFSET_PINETREE_BRANCH_DIR,
+       OFFSET_PALMTREE,
+       OFFSET_PALMTREE_AREA,
 } SeedOffset;
 
 extern s32 seed;
index fb0aea78d86bf092958a4b3ca25282b631248873..c0342575dc1e33a04ad42ac5901f1bc938e95ae5 100644 (file)
@@ -1,7 +1,10 @@
 #include <math.h>
+#include <stdlib.h>
+#include <string.h>
 #include "server/biomes.h"
 #include "server/server_terrain.h"
 #include "server/terrain_gen.h"
+#include "server/voxel_depth_search.h"
 
 Biome get_biome(v2s32 pos, f64 *factor)
 {
@@ -24,7 +27,7 @@ Biome get_biome(v2s32 pos, f64 *factor)
 
 static s32 height_mountain(BiomeArgsHeight *args)
 {
-       return pow((args->height + 96) * pow(((smooth2d(U32(args->pos.x) / 48.0, U32(args->pos.y) / 48.0, 0, seed + SO_MOUNTAIN_HEIGHT) + 1.0) * 256.0 + 128.0), args->factor), 1.0 / (args->factor + 1.0)) - 96;
+       return pow((args->height + 96) * pow(((smooth2d(U32(args->pos.x) / 48.0, U32(args->pos.y) / 48.0, 0, seed + OFFSET_MOUNTAIN_HEIGHT) + 1.0) * 256.0 + 128.0), args->factor), 1.0 / (args->factor + 1.0)) - 96;
 }
 
 static NodeType generate_mountain(BiomeArgsGenerate *args)
@@ -113,7 +116,7 @@ static s32 calculate_ocean_floor(f64 factor, s32 height)
        return height;
 }
 
-static void chunk_ocean(BiomeArgsChunk *args)
+static void before_chunk_ocean(BiomeArgsChunk *args)
 {
        OceanChunkData *chunk_data = args->chunk_data;
 
@@ -123,12 +126,12 @@ static void chunk_ocean(BiomeArgsChunk *args)
        };
 
        f64 factor;
-       chunk_data->has_vulcano = noise2d(chunk_data->vulcano_pos.x, chunk_data->vulcano_pos.y, 0, seed + SO_VULCANO) > 0.0
+       chunk_data->has_vulcano = noise2d(chunk_data->vulcano_pos.x, chunk_data->vulcano_pos.y, 0, seed + OFFSET_VULCANO) > 0.0
                && get_biome((v2s32) {chunk_data->vulcano_pos.x, chunk_data->vulcano_pos.y}, &factor) == BIOME_OCEAN
                && get_ocean_level(factor) == OCEAN_DEEP;
 }
 
-static void row_ocean(BiomeArgsRow *args)
+static void before_row_ocean(BiomeArgsRow *args)
 {
        OceanChunkData *chunk_data = args->chunk_data;
        OceanRowData *row_data = args->row_data;
@@ -140,7 +143,7 @@ static void row_ocean(BiomeArgsRow *args)
 
                if (dist < vulcano_radius) {
                        f64 crater_factor = pow(asin(1.0 - dist / vulcano_radius), 2.0);
-                       f64 vulcano_height = (pnoise2d(U32(args->pos.x) / 100.0, U32(args->pos.y) / 100.0, 0.2, 2, seed + SO_VULCANO_HEIGHT) * 0.5 + 0.5) * 128.0 * crater_factor + 1.0 - 30.0;
+                       f64 vulcano_height = (pnoise2d(U32(args->pos.x) / 100.0, U32(args->pos.y) / 100.0, 0.2, 2, seed + OFFSET_VULCANO_HEIGHT) * 0.5 + 0.5) * 128.0 * crater_factor + 1.0 - 30.0;
                        bool is_crater = vulcano_height > 0;
 
                        if (!is_crater)
@@ -152,9 +155,9 @@ static void row_ocean(BiomeArgsRow *args)
                        row_data->vulcano = true;
                        row_data->vulcano_crater = is_crater;
                        row_data->vulcano_height = floor(vulcano_height + 0.5);
-                       row_data->vulcano_crater_top = 50 + floor((pnoise2d(U32(args->pos.x) / 3.0, U32(args->pos.y) / 3.0, 0.0, 1, seed + SO_VULCANO_CRATER_TOP) * 0.5 + 0.5) * 3.0 + 0.5);
+                       row_data->vulcano_crater_top = 50 + floor((pnoise2d(U32(args->pos.x) / 3.0, U32(args->pos.y) / 3.0, 0.0, 1, seed + OFFSET_VULCANO_CRATER_TOP) * 0.5 + 0.5) * 3.0 + 0.5);
                        row_data->vulcano_stone = is_crater
-                               ? ((pnoise2d(U32(args->pos.x) / 16.0, U32(args->pos.y) / 16.0, 0.85, 3, seed + SO_VULCANO_STONE) * 0.5 + 0.5) * crater_factor > 0.4
+                               ? ((pnoise2d(U32(args->pos.x) / 16.0, U32(args->pos.y) / 16.0, 0.85, 3, seed + OFFSET_VULCANO_STONE) * 0.5 + 0.5) * crater_factor > 0.4
                                        ? NODE_VULCANO_STONE
                                        : NODE_STONE)
                                : NODE_SAND;
@@ -200,14 +203,27 @@ static NodeType generate_ocean(BiomeArgsGenerate *args)
 
 // hills biome
 
-static bool boulder_touching_ground(v3s32 pos, s32 diff)
+typedef struct {
+       Tree boulder_visit;
+       bool boulder_success[CHUNK_SIZE][CHUNK_SIZE][CHUNK_SIZE];
+} HillsChunkData;
+
+static void before_chunk_hills(BiomeArgsChunk *args)
 {
-       for (s32 dir = diff > 0 ? -1 : +1; dir > 0 ? diff <= 0 : diff >= 0; pos.y += dir, diff += dir) {
-               if (smooth3d(U32(pos.x) / 12.0, U32(pos.y) / 6.0, U32(pos.z) / 12.0, 0, seed + SO_BOULDER) < 0.8)
-                       return false;
-       }
+       HillsChunkData *chunk_data = args->chunk_data;
+       tree_ini(&chunk_data->boulder_visit);
+       memset(chunk_data->boulder_success, 0, sizeof chunk_data->boulder_success);
+}
 
-       return true;
+static void wrap_free(void *ptr)
+{
+       free(ptr);
+}
+
+static void after_chunk_hills(BiomeArgsChunk *args)
+{
+       HillsChunkData *chunk_data = args->chunk_data;
+       tree_clr(&chunk_data->boulder_visit, &wrap_free, NULL, NULL, 0);
 }
 
 static s32 height_hills(BiomeArgsHeight *args)
@@ -215,9 +231,30 @@ static s32 height_hills(BiomeArgsHeight *args)
        return args->height;
 }
 
+static bool is_boulder(s32 diff, v3s32 pos)
+{
+       return diff < 16 &&
+               smooth3d(U32(pos.x) / 16.0, U32(pos.y) / 12.0, U32(pos.z) / 16.0, 0, seed + OFFSET_BOULDER) > 0.8;
+}
+
+static DepthSearchNodeType boulder_get_node_type(v3s32 pos)
+{
+       s32 diff = pos.y - terrain_gen_get_base_height((v2s32) {pos.x, pos.z});
+
+       if (diff <= 0)
+               return DEPTH_SEARCH_TARGET;
+
+       return is_boulder(diff, pos) ? DEPTH_SEARCH_PATH : DEPTH_SEARCH_BLOCK;
+}
+
 static NodeType generate_hills(BiomeArgsGenerate *args)
 {
-       if (boulder_touching_ground(args->pos, args->diff))
+       HillsChunkData *chunk_data = args->chunk_data;
+
+       if (is_boulder(args->diff, args->pos) && (args->diff <= 0 || voxel_depth_search(args->pos,
+                       &boulder_get_node_type,
+                       &chunk_data->boulder_success[args->offset.x][args->offset.y][args->offset.z],
+                       &chunk_data->boulder_visit)))
                return NODE_STONE;
 
        if (args->diff <= -5)
@@ -233,38 +270,44 @@ static NodeType generate_hills(BiomeArgsGenerate *args)
 BiomeDef biomes[COUNT_BIOME] = {
        {
                .probability = 0.2,
-               .offset = SO_MOUNTAIN,
+               .offset = OFFSET_MOUNTAIN,
                .threshold = 1024.0,
                .snow = true,
                .height = &height_mountain,
                .generate = &generate_mountain,
                .chunk_data_size = 0,
-               .chunk = NULL,
+               .before_chunk = NULL,
+               .after_chunk = NULL,
                .row_data_size = 0,
-               .row = NULL,
+               .before_row = NULL,
+               .after_row = NULL,
        },
        {
                .probability = 0.2,
-               .offset = SO_OCEAN,
+               .offset = OFFSET_OCEAN,
                .threshold = 2048.0,
                .snow = false,
                .height = &height_ocean,
                .generate = &generate_ocean,
                .chunk_data_size = sizeof(OceanChunkData),
-               .chunk = &chunk_ocean,
+               .before_chunk = &before_chunk_ocean,
+               .after_chunk = NULL,
                .row_data_size = sizeof(OceanRowData),
-               .row = &row_ocean,
+               .before_row = &before_row_ocean,
+               .after_row = NULL,
        },
        {
                .probability = 1.0,
-               .offset = SO_NONE,
+               .offset = OFFSET_NONE,
                .threshold = 0.0,
                .snow = true,
                .height = &height_hills,
                .generate = &generate_hills,
-               .chunk_data_size = 0,
-               .chunk = NULL,
+               .chunk_data_size = sizeof(HillsChunkData),
+               .before_chunk = &before_chunk_hills,
+               .after_chunk = &after_chunk_hills,
                .row_data_size = 0,
-               .row = NULL,
+               .before_row = NULL,
+               .after_row = NULL,
        },
 };
index 3994100713b16a9eb5506c20b45a949b90b4c628..dce835dd4d46479e7e47f70c7cd5a4a4bb8c609d 100644 (file)
@@ -34,6 +34,7 @@ typedef struct {
 } BiomeArgsHeight;
 
 typedef struct {
+       v3s32 offset;
        v3s32 pos;
        s32 diff;
        f64 humidity;
@@ -53,9 +54,11 @@ typedef struct {
        s32 (*height)(BiomeArgsHeight *args);
        NodeType (*generate)(BiomeArgsGenerate *args);
        size_t chunk_data_size;
-       void (*chunk)(BiomeArgsChunk *args);
+       void (*before_chunk)(BiomeArgsChunk *args);
+       void (*after_chunk)(BiomeArgsChunk *args);
        size_t row_data_size;
-       void (*row)(BiomeArgsRow *args);
+       void (*before_row)(BiomeArgsRow *args);
+       void (*after_row)(BiomeArgsRow *args);
 } BiomeDef;
 
 extern BiomeDef biomes[];
index 5b0c1d14cc1d8da7946fc49b039938c8a599b4f0..b258b1d2208f73ad32120c76c54f1388393e8564 100644 (file)
@@ -7,6 +7,14 @@
 #include "server/terrain_gen.h"
 #include "server/trees.h"
 
+s32 terrain_gen_get_base_height(v2s32 pos)
+{
+       return 1.0
+               * (pnoise2d(U32(pos.x) /  32.0, U32(pos.y) /  32.0, 0.45, 5, seed + OFFSET_HEIGHT)    * 16.0 + 0.0)
+               * (pnoise2d(U32(pos.x) / 256.0, U32(pos.y) / 256.0, 0.45, 5, seed + OFFSET_HILLYNESS) *  0.5 + 0.5)
+               + 32.0;
+}
+
 // generate a chunk (does not manage chunk state or threading)
 void terrain_gen_chunk(TerrainChunk *chunk, List *changed_chunks)
 {
@@ -28,12 +36,12 @@ void terrain_gen_chunk(TerrainChunk *chunk, List *changed_chunks)
        };
 
        unsigned char *chunk_data[COUNT_BIOME] = {NULL};
-       bool chunk_called[COUNT_BIOME] = {false};
+       bool has_biome[COUNT_BIOME] = {false};
 
-       for (u8 x = 0; x < CHUNK_SIZE; x++) {
+       for (s32 x = 0; x < CHUNK_SIZE; x++) {
                s32 pos_x = chunkp.x + x;
 
-               for (u8 z = 0; z < CHUNK_SIZE; z++) {
+               for (s32 z = 0; z < CHUNK_SIZE; z++) {
                        row_args.pos = height_args.pos = (v2s32) {pos_x, chunkp.z + z};
 
                        condition_args.biome = get_biome(row_args.pos, &condition_args.factor);
@@ -43,32 +51,32 @@ void terrain_gen_chunk(TerrainChunk *chunk, List *changed_chunks)
                                = condition_args.factor;
 
                        if (biome_def->chunk_data_size && !chunk_data[condition_args.biome])
-                               chunk_data[condition_args.biome] =      malloc(biome_def->chunk_data_size);
+                               chunk_data[condition_args.biome] = malloc(biome_def->chunk_data_size);
 
                        chunk_args.chunk_data = row_args.chunk_data = height_args.chunk_data =
                                generate_args.chunk_data = condition_args.chunk_data =
                                chunk_data[condition_args.biome];
 
-                       if (biome_def->chunk && !chunk_called[condition_args.biome]) {
-                               biome_def->chunk(&chunk_args);
-                               chunk_called[condition_args.biome] = true;
+                       if (!has_biome[condition_args.biome]) {
+                               if (biome_def->before_chunk)
+                                       biome_def->before_chunk(&chunk_args);
+
+                               has_biome[condition_args.biome] = true;
                        }
 
                        unsigned char row_data[biome_def->row_data_size];
                        row_args.row_data = height_args.row_data = generate_args.row_data =
                                condition_args.row_data = row_data;
 
-                       if (biome_def->row)
-                               biome_def->row(&row_args);
-
-                       height_args.height = 1.0
-                               * (pnoise2d(U32(height_args.pos.x) /  32.0, U32(height_args.pos.y) /  32.0, 0.45, 5, seed + SO_HEIGHT)    * 16.0 + 0.0)
-                               * (pnoise2d(U32(height_args.pos.x) / 256.0, U32(height_args.pos.y) / 256.0, 0.45, 5, seed + SO_HILLYNESS) *  0.5 + 0.5)
-                               + 32.0;
+                       if (biome_def->before_row)
+                               biome_def->before_row(&row_args);
 
+                       height_args.height = terrain_gen_get_base_height(height_args.pos);
                        s32 height = biome_def->height(&height_args);
 
-                       for (u8 y = 0; y < CHUNK_SIZE; y++) {
+                       for (s32 y = 0; y < CHUNK_SIZE; y++) {
+                               generate_args.offset = (v3s32) {x, y, z};
+
                                generate_args.pos = condition_args.pos = (v3s32)
                                        {row_args.pos.x, chunkp.y + y, row_args.pos.y};
                                generate_args.diff = generate_args.pos.y - height;
@@ -104,10 +112,21 @@ void terrain_gen_chunk(TerrainChunk *chunk, List *changed_chunks)
                                }
                                pthread_mutex_unlock(&chunk->mtx);
                        }
+
+                       if (biome_def->after_row)
+                               biome_def->after_row(&row_args);
                }
        }
 
-       for (Biome i = 0; i < COUNT_BIOME; i++)
-               if (chunk_data[i])
-                       free(chunk_data[i]);
+       for (Biome i = 0; i < COUNT_BIOME; i++) {
+               if (has_biome[i]) {
+                       chunk_args.chunk_data = chunk_data[i];
+
+                       if (biomes[i].after_chunk)
+                               biomes[i].after_chunk(&chunk_args);
+
+                       if (chunk_args.chunk_data)
+                               free(chunk_args.chunk_data);
+               }
+       }
 }
index 76bf81394b921e706e275d61466febcff6fde808..ce07148538571fd7889c50c2ca2b4096497f60cd 100644 (file)
@@ -4,6 +4,7 @@
 #include "server/server_terrain.h"
 #include "terrain.h"
 
+s32 terrain_gen_get_base_height(v2s32 pos);
 void terrain_gen_chunk(TerrainChunk *chunk, List *changed_chunks); // generate a chunk (does not manage chunk state or threading)
 
 #endif // _TERRAIN_GEN_H_
index 4de22852259e2b7d4aea2cf9c27cc9e546f772be..2d165c26c1d80f9db098007e82e3e616b0aa14ec 100644 (file)
@@ -2,7 +2,7 @@
 #include "server/biomes.h"
 #include "server/server_terrain.h"
 #include "server/trees.h"
-#include "server/voxelctx.h"
+#include "server/voxel_procedural.h"
 
 // oak
 
@@ -11,98 +11,98 @@ static bool oak_condition(TreeArgsCondition *args)
        return args->biome == BIOME_HILLS;
 }
 
-static void oak_tree_leaf(Voxelctx *ctx)
+static void oak_tree_leaf(VoxelProcedural *proc)
 {
-       if (!voxelctx_is_alive(ctx))
+       if (!voxel_procedural_is_alive(proc))
                return;
 
-       voxelctx_push(ctx);
-               voxelctx_cube(ctx, NODE_OAK_LEAVES, true);
-       voxelctx_pop(ctx);
-
-       voxelctx_push(ctx);
-               voxelctx_x(ctx, 0.5f);
-               voxelctx_sx(ctx, 0.9f);
-               voxelctx_sy(ctx, 0.9f);
-               voxelctx_sz(ctx, 0.8f);
-               voxelctx_ry(ctx, 25.0f);
-               voxelctx_x(ctx, 0.4f);
-               oak_tree_leaf(ctx);
-       voxelctx_pop(ctx);
+       voxel_procedural_push(proc);
+               voxel_procedural_cube(proc, NODE_OAK_LEAVES, true);
+       voxel_procedural_pop(proc);
+
+       voxel_procedural_push(proc);
+               voxel_procedural_x(proc, 0.5f);
+               voxel_procedural_sx(proc, 0.9f);
+               voxel_procedural_sy(proc, 0.9f);
+               voxel_procedural_sz(proc, 0.8f);
+               voxel_procedural_ry(proc, 25.0f);
+               voxel_procedural_x(proc, 0.4f);
+               oak_tree_leaf(proc);
+       voxel_procedural_pop(proc);
 }
 
-static void oak_tree_top(Voxelctx *ctx)
+static void oak_tree_top(VoxelProcedural *proc)
 {
-       if (!voxelctx_is_alive(ctx))
+       if (!voxel_procedural_is_alive(proc))
                return;
 
-       voxelctx_push(ctx);
+       voxel_procedural_push(proc);
        for (int i = 0; i < 8; i++) {
-               voxelctx_rz(ctx, 360.0f / 8.0f);
-               voxelctx_push(ctx);
-                       voxelctx_life(ctx, 8);
-                       voxelctx_sy(ctx, 2.0f);
-                       voxelctx_z(ctx, voxelctx_random(ctx, 0.0f, 5.0f));
-                       voxelctx_s(ctx, 5.0f);
-                       voxelctx_light(ctx, -0.4f);
-                       voxelctx_sat(ctx, 0.5f);
-                       voxelctx_hue(ctx, voxelctx_random(ctx, 60.0f, 20.0f));
-                       voxelctx_ry(ctx, -45.0f);
-                       oak_tree_leaf(ctx);
-               voxelctx_pop(ctx);
+               voxel_procedural_rz(proc, 360.0f / 8.0f);
+               voxel_procedural_push(proc);
+                       voxel_procedural_life(proc, 8);
+                       voxel_procedural_sy(proc, 2.0f);
+                       voxel_procedural_z(proc, voxel_procedural_random(proc, 0.0f, 5.0f));
+                       voxel_procedural_s(proc, 5.0f);
+                       voxel_procedural_light(proc, -0.4f);
+                       voxel_procedural_sat(proc, 0.5f);
+                       voxel_procedural_hue(proc, voxel_procedural_random(proc, 60.0f, 20.0f));
+                       voxel_procedural_ry(proc, -45.0f);
+                       oak_tree_leaf(proc);
+               voxel_procedural_pop(proc);
        }
-       voxelctx_pop(ctx);
+       voxel_procedural_pop(proc);
 }
 
-static void oak_tree_part(Voxelctx *ctx, f32 n)
+static void oak_tree_part(VoxelProcedural *proc, f32 n)
 {
-       if (!voxelctx_is_alive(ctx))
+       if (!voxel_procedural_is_alive(proc))
                return;
 
-       voxelctx_push(ctx);
+       voxel_procedural_push(proc);
        for (int i = 1; i <= n; i++) {
-               voxelctx_z(ctx, 1.0f);
-               voxelctx_rz(ctx, voxelctx_random(ctx, 30.0f, 10.0f));
-               voxelctx_rx(ctx, voxelctx_random(ctx, 0.0f, 10.0f));
+               voxel_procedural_z(proc, 1.0f);
+               voxel_procedural_rz(proc, voxel_procedural_random(proc, 30.0f, 10.0f));
+               voxel_procedural_rx(proc, voxel_procedural_random(proc, 0.0f, 10.0f));
 
-               voxelctx_push(ctx);
-                       voxelctx_s(ctx, 4.0f);
-                       voxelctx_x(ctx, 0.1f);
-                       voxelctx_light(ctx, voxelctx_random(ctx, 0.0f, 0.1f));
-                       voxelctx_cylinder(ctx, NODE_OAK_WOOD, true);
-               voxelctx_pop(ctx);
+               voxel_procedural_push(proc);
+                       voxel_procedural_s(proc, 4.0f);
+                       voxel_procedural_x(proc, 0.1f);
+                       voxel_procedural_light(proc, voxel_procedural_random(proc, 0.0f, 0.1f));
+                       voxel_procedural_cylinder(proc, NODE_OAK_WOOD, true);
+               voxel_procedural_pop(proc);
 
                if (i == (int) (n - 2.0f)) {
-                       voxelctx_push(ctx);
-                               oak_tree_top(ctx);
-                       voxelctx_pop(ctx);
+                       voxel_procedural_push(proc);
+                               oak_tree_top(proc);
+                       voxel_procedural_pop(proc);
                }
        }
-       voxelctx_pop(ctx);
+       voxel_procedural_pop(proc);
 }
 
 static void oak_tree(v3s32 pos, List *changed_chunks)
 {
-       Voxelctx *ctx = voxelctx_create(changed_chunks, STAGE_TREES, pos);
+       VoxelProcedural *proc = voxel_procedural_create(changed_chunks, STAGE_TREES, pos);
 
-       voxelctx_hue(ctx, 40.0f);
-       voxelctx_light(ctx, -0.5f);
-       voxelctx_sat(ctx, 0.5f);
+       voxel_procedural_hue(proc, 40.0f);
+       voxel_procedural_light(proc, -0.5f);
+       voxel_procedural_sat(proc, 0.5f);
 
-       f32 n = voxelctx_random(ctx, 40.0f, 10.0f);
+       f32 n = voxel_procedural_random(proc, 40.0f, 10.0f);
 
-       voxelctx_push(ctx);
+       voxel_procedural_push(proc);
        for (int i = 1; i <= 3; i++) {
-               voxelctx_rz(ctx, voxelctx_random(ctx, 120.0f, 45.0f));
-               voxelctx_push(ctx);
-                       voxelctx_y(ctx, 0.5f);
-                       voxelctx_light(ctx, voxelctx_random(ctx, -0.3f, 0.05f));
-                       oak_tree_part(ctx, n);
-               voxelctx_pop(ctx);
+               voxel_procedural_rz(proc, voxel_procedural_random(proc, 120.0f, 45.0f));
+               voxel_procedural_push(proc);
+                       voxel_procedural_y(proc, 0.5f);
+                       voxel_procedural_light(proc, voxel_procedural_random(proc, -0.3f, 0.05f));
+                       oak_tree_part(proc, n);
+               voxel_procedural_pop(proc);
        }
-       voxelctx_pop(ctx);
+       voxel_procedural_pop(proc);
 
-       voxelctx_delete(ctx);
+       voxel_procedural_delete(proc);
 }
 
 // pine
@@ -114,9 +114,9 @@ static bool pine_condition(TreeArgsCondition *args)
 
 static void pine_tree(v3s32 pos, List *changed_chunks)
 {
-       s32 tree_top = (noise2d(pos.x, pos.z, 0, seed + SO_PINETREE_HEIGHT) * 0.5 + 0.5) * (35.0 - 20.0) + 20.0 + pos.y;
+       s32 tree_top = (noise2d(pos.x, pos.z, 0, seed + OFFSET_PINETREE_HEIGHT) * 0.5 + 0.5) * (35.0 - 20.0) + 20.0 + pos.y;
        for (v3s32 tree_pos = pos; tree_pos.y < tree_top; tree_pos.y++) {
-               f64 branch_length = noise3d(tree_pos.x, tree_pos.y, tree_pos.z, 0, seed + SO_PINETREE_BRANCH) * 3.0;
+               f64 branch_length = noise3d(tree_pos.x, tree_pos.y, tree_pos.z, 0, seed + OFFSET_PINETREE_BRANCH) * 3.0;
 
                v3s32 dirs[4] = {
                        {+0, +0, +1},
@@ -125,7 +125,7 @@ static void pine_tree(v3s32 pos, List *changed_chunks)
                        {-1, +0, +0},
                };
 
-               s32 dir = (noise3d(tree_pos.x, tree_pos.y, tree_pos.z, 0, seed + SO_PINETREE_BRANCH_DIR) * 0.5 + 0.5) * 4.0;
+               s32 dir = (noise3d(tree_pos.x, tree_pos.y, tree_pos.z, 0, seed + OFFSET_PINETREE_BRANCH_DIR) * 0.5 + 0.5) * 4.0;
 
                for (v3s32 branch_pos = tree_pos; branch_length > 0; branch_length--, branch_pos = v3s32_add(branch_pos, dirs[dir]))
                        server_terrain_gen_node(branch_pos,
@@ -147,58 +147,58 @@ static bool palm_condition(TreeArgsCondition *args)
                && ocean_get_node_at((v3s32) {args->pos.x, args->pos.y - 1, args->pos.z}, 0, args->row_data) == NODE_SAND;
 }
 
-static void palm_branch(Voxelctx *ctx)
+static void palm_branch(VoxelProcedural *proc)
 {
-       if (!voxelctx_is_alive(ctx))
+       if (!voxel_procedural_is_alive(proc))
                return;
 
-       voxelctx_cube(ctx, NODE_PALM_LEAVES, true);
-       voxelctx_push(ctx);
-               voxelctx_z(ctx, 0.5f);
-               voxelctx_s(ctx, 0.8f);
-               voxelctx_rx(ctx, voxelctx_random(ctx, 20.0f, 4.0f));
-               voxelctx_z(ctx, 0.5f);
-               palm_branch(ctx);
-       voxelctx_pop(ctx);
+       voxel_procedural_cube(proc, NODE_PALM_LEAVES, true);
+       voxel_procedural_push(proc);
+               voxel_procedural_z(proc, 0.5f);
+               voxel_procedural_s(proc, 0.8f);
+               voxel_procedural_rx(proc, voxel_procedural_random(proc, 20.0f, 4.0f));
+               voxel_procedural_z(proc, 0.5f);
+               palm_branch(proc);
+       voxel_procedural_pop(proc);
 }
 
 static void palm_tree(v3s32 pos, List *changed_chunks)
 {
-       Voxelctx *ctx = voxelctx_create(changed_chunks, STAGE_TREES, (v3s32) {pos.x, pos.y - 1, pos.z});
+       VoxelProcedural *proc = voxel_procedural_create(changed_chunks, STAGE_TREES, (v3s32) {pos.x, pos.y - 1, pos.z});
 
-       f32 s = voxelctx_random(ctx, 8.0f, 2.0f);
+       f32 s = voxel_procedural_random(proc, 8.0f, 2.0f);
 
-       voxelctx_push(ctx);
+       voxel_procedural_push(proc);
        for (int i = 1; i <= s; i++) {
-               voxelctx_z(ctx, 1.0f);
-               voxelctx_push(ctx);
-                       voxelctx_s(ctx, 1.0f);
-                       voxelctx_light(ctx, voxelctx_random(ctx, -0.8f, 0.1f));
-                       voxelctx_sat(ctx, 0.5f);
-                       voxelctx_cube(ctx, NODE_PALM_WOOD, true);
-               voxelctx_pop(ctx);
+               voxel_procedural_z(proc, 1.0f);
+               voxel_procedural_push(proc);
+                       voxel_procedural_s(proc, 1.0f);
+                       voxel_procedural_light(proc, voxel_procedural_random(proc, -0.8f, 0.1f));
+                       voxel_procedural_sat(proc, 0.5f);
+                       voxel_procedural_cube(proc, NODE_PALM_WOOD, true);
+               voxel_procedural_pop(proc);
        }
-       voxelctx_pop(ctx);
+       voxel_procedural_pop(proc);
 
-       voxelctx_z(ctx, s);
-       voxelctx_sat(ctx, 1.0f),
-       voxelctx_light(ctx, -0.5f);
-       voxelctx_hue(ctx, voxelctx_random(ctx, 50.0f, 30.0f));
+       voxel_procedural_z(proc, s);
+       voxel_procedural_sat(proc, 1.0f),
+       voxel_procedural_light(proc, -0.5f);
+       voxel_procedural_hue(proc, voxel_procedural_random(proc, 50.0f, 30.0f));
 
-       voxelctx_push(ctx);
+       voxel_procedural_push(proc);
        for (int i = 0; i < 6; i++) {
-               voxelctx_rz(ctx, 360.0f / 6.0f);
-               voxelctx_rz(ctx, voxelctx_random(ctx, 0.0f, 10.0f));
-               voxelctx_push(ctx);
-                       voxelctx_light(ctx, voxelctx_random(ctx, 0.0f, 0.3f));
-                       voxelctx_rx(ctx, 90.0f);
-                       voxelctx_s(ctx, 2.0f);
-                       palm_branch(ctx);
-               voxelctx_pop(ctx);
+               voxel_procedural_rz(proc, 360.0f / 6.0f);
+               voxel_procedural_rz(proc, voxel_procedural_random(proc, 0.0f, 10.0f));
+               voxel_procedural_push(proc);
+                       voxel_procedural_light(proc, voxel_procedural_random(proc, 0.0f, 0.3f));
+                       voxel_procedural_rx(proc, 90.0f);
+                       voxel_procedural_s(proc, 2.0f);
+                       palm_branch(proc);
+               voxel_procedural_pop(proc);
        }
-       voxelctx_pop(ctx);
+       voxel_procedural_pop(proc);
 
-       voxelctx_delete(ctx);
+       voxel_procedural_delete(proc);
 }
 
 TreeDef tree_definitions[NUM_TREES] = {
@@ -207,8 +207,8 @@ TreeDef tree_definitions[NUM_TREES] = {
                .spread = 64.0f,
                .probability = 0.0005f,
                .area_probability = 0.3f,
-               .offset = SO_OAKTREE,
-               .area_offset = SO_OAKTREE_AREA,
+               .offset = OFFSET_OAKTREE,
+               .area_offset = OFFSET_OAKTREE_AREA,
                .condition = &oak_condition,
                .generate = &oak_tree,
        },
@@ -217,8 +217,8 @@ TreeDef tree_definitions[NUM_TREES] = {
                .spread = 256.0f,
                .probability = 0.01f,
                .area_probability = 0.1f,
-               .offset = SO_PINETREE,
-               .area_offset = SO_PINETREE_AREA,
+               .offset = OFFSET_PINETREE,
+               .area_offset = OFFSET_PINETREE_AREA,
                .condition = &pine_condition,
                .generate = &pine_tree,
        },
@@ -227,8 +227,8 @@ TreeDef tree_definitions[NUM_TREES] = {
                .spread = 16.0f,
                .probability = 0.005f,
                .area_probability = 0.5f,
-               .offset = SO_PALMTREE,
-               .area_offset = SO_PALMTREE_AREA,
+               .offset = OFFSET_PALMTREE,
+               .area_offset = OFFSET_PALMTREE_AREA,
                .condition = &palm_condition,
                .generate = &palm_tree,
        },
diff --git a/src/server/voxel_depth_search.c b/src/server/voxel_depth_search.c
new file mode 100644 (file)
index 0000000..722aeda
--- /dev/null
@@ -0,0 +1,37 @@
+#include <stdlib.h>
+#include "voxel_depth_search.h"
+
+v3s32 dirs[6] = {
+       {+0, -1, +0}, // this is commonly used to find ground, search downwards first
+       {-1, +0, +0},
+       {+0, +0, -1},
+       {+1, +0, +0},
+       {+0, +0, +1},
+       {+0, +1, +0},
+};
+
+static int cmp_depth_search_node(const DepthSearchNode *node, const v3s32 *pos)
+{
+       return v3s32_cmp(&node->pos, pos);
+}
+
+bool voxel_depth_search(v3s32 pos, DepthSearchNodeType (*get_type)(v3s32 pos), bool *success, Tree *visit)
+{
+       TreeNode **tree_node = tree_nfd(visit, &pos, &cmp_depth_search_node);
+       if (*tree_node)
+               return *success = *((DepthSearchNode *) (*tree_node)->dat)->success;
+
+       DepthSearchNode *node = malloc(sizeof *node);
+       tree_nmk(visit, tree_node, node);
+       node->type = get_type(pos);
+       node->pos = pos;
+       if ((*(node->success = success) = (node->type == DEPTH_SEARCH_TARGET)))
+               return true;
+
+       if (node->type == DEPTH_SEARCH_PATH)
+               for (int i = 0; i < 6; i++)
+                       if (voxel_depth_search(v3s32_add(pos, dirs[i]), get_type, success, visit))
+                               return true;
+
+       return false;
+}
diff --git a/src/server/voxel_depth_search.h b/src/server/voxel_depth_search.h
new file mode 100644 (file)
index 0000000..2712707
--- /dev/null
@@ -0,0 +1,22 @@
+#ifndef _VOXEL_DEPTH_SEARCH_
+#define _VOXEL_DEPTH_SEARCH_
+
+#include <dragonstd/tree.h>
+#include <stdbool.h>
+#include "types.h"
+
+typedef enum {
+       DEPTH_SEARCH_TARGET, // goal has been reached
+       DEPTH_SEARCH_PATH,   // can used this as path
+       DEPTH_SEARCH_BLOCK   // cannot use this as paths
+} DepthSearchNodeType;
+
+typedef struct {
+       v3s32 pos;
+       DepthSearchNodeType type;
+       bool *success;
+} DepthSearchNode;
+
+bool voxel_depth_search(v3s32 pos, DepthSearchNodeType (*get_type)(v3s32 pos), bool *success, Tree *visit);
+
+#endif // _VOXEL_DEPTH_SEARCH_
diff --git a/src/server/voxel_procedural.c b/src/server/voxel_procedural.c
new file mode 100644 (file)
index 0000000..ff61ea8
--- /dev/null
@@ -0,0 +1,278 @@
+#include <stdlib.h>
+#include <pthread.h>
+#include "color.h"
+#include "perlin.h"
+#include "server/terrain_gen.h"
+#include "server/voxel_procedural.h"
+
+#define VOXEL_PROCEDURAL_STATE(proc) (*((VoxelProceduralState *) (proc)->state.fst->dat))
+
+static VoxelProceduralState *create_state(VoxelProceduralState *old)
+{
+       VoxelProceduralState *state = malloc(sizeof *state);
+
+       if (old) {
+               *state = *old;
+       } else {
+               state->pos[0] = 0.0f;
+               state->pos[1] = 0.0f;
+               state->pos[2] = 0.0f;
+               state->pos[3] = 0.0f;
+               state->scale[0] = 1.0f;
+               state->scale[1] = 1.0f;
+               state->scale[2] = 1.0f;
+               mat4x4_identity(state->mat);
+               state->h = 0.0f;
+               state->s = 0.0f;
+               state->l = 1.0f;
+               state->life = 0;
+       }
+
+       return state;
+}
+
+VoxelProcedural *voxel_procedural_create(List *changed_chunks, TerrainGenStage tgs, v3s32 pos)
+{
+       VoxelProcedural *proc = malloc(sizeof(VoxelProcedural));
+
+       proc->changed_chunks = changed_chunks;
+       proc->tgs = tgs;
+       proc->pos = pos;
+       proc->random = 0;
+
+       list_ini(&proc->state);
+       list_apd(&proc->state, create_state(NULL));
+
+       return proc;
+}
+
+void voxel_procedural_delete(VoxelProcedural *proc)
+{
+       list_clr(&proc->state, &free, NULL, NULL);
+       free(proc);
+}
+
+static void move_value(f32 *x, f32 v, f32 range)
+{
+    f32 dst = v >= 0 ? range : 0;
+    v = fabs(v);
+    *x = f32_mix(*x, dst, v);
+}
+
+void voxel_procedural_hue(VoxelProcedural *proc, f32 value)
+{
+       VOXEL_PROCEDURAL_STATE(proc).h += value;
+}
+
+void voxel_procedural_sat(VoxelProcedural *proc, f32 value)
+{
+       move_value(&VOXEL_PROCEDURAL_STATE(proc).s, value, 1.0f);
+}
+
+void voxel_procedural_light(VoxelProcedural *proc, f32 value)
+{
+       move_value(&VOXEL_PROCEDURAL_STATE(proc).l, value, 1.0f);
+}
+
+void voxel_procedural_life(VoxelProcedural *proc, s32 value)
+{
+       VOXEL_PROCEDURAL_STATE(proc).life += value;
+}
+
+static void apply_translation(VoxelProcedural *proc, v3f32 translate)
+{
+       vec4 dst, src = {translate.x, translate.y, translate.z, 0.0f};
+       mat4x4_mul_vec4(dst, VOXEL_PROCEDURAL_STATE(proc).mat, src);
+       vec4_add(VOXEL_PROCEDURAL_STATE(proc).pos, VOXEL_PROCEDURAL_STATE(proc).pos, dst);
+}
+
+void voxel_procedural_x(VoxelProcedural *proc, f32 value)
+{
+       apply_translation(proc, (v3f32) {value, 0.0f, 0.0f});
+}
+
+void voxel_procedural_y(VoxelProcedural *proc, f32 value)
+{
+       apply_translation(proc, (v3f32) {0.0f, value, 0.0f});
+}
+
+void voxel_procedural_z(VoxelProcedural *proc, f32 value)
+{
+       apply_translation(proc, (v3f32) {0.0f, 0.0f, value});
+}
+
+void voxel_procedural_rx(VoxelProcedural *proc, f32 value)
+{
+       mat4x4_rotate_X(VOXEL_PROCEDURAL_STATE(proc).mat, VOXEL_PROCEDURAL_STATE(proc).mat,
+               value * M_PI / 180.0f);
+}
+
+void voxel_procedural_ry(VoxelProcedural *proc, f32 value)
+{
+       mat4x4_rotate_Y(VOXEL_PROCEDURAL_STATE(proc).mat, VOXEL_PROCEDURAL_STATE(proc).mat,
+               value * M_PI / 180.0f);
+}
+
+void voxel_procedural_rz(VoxelProcedural *proc, f32 value)
+{
+       mat4x4_rotate_Z(VOXEL_PROCEDURAL_STATE(proc).mat, VOXEL_PROCEDURAL_STATE(proc).mat,
+               value * M_PI / 180.0f);
+}
+
+static void apply_scale(VoxelProcedural *proc, v3f32 scale)
+{
+       VOXEL_PROCEDURAL_STATE(proc).scale[0] *= scale.x;
+       VOXEL_PROCEDURAL_STATE(proc).scale[1] *= scale.y;
+       VOXEL_PROCEDURAL_STATE(proc).scale[2] *= scale.z;
+
+       mat4x4_scale_aniso(VOXEL_PROCEDURAL_STATE(proc).mat, VOXEL_PROCEDURAL_STATE(proc).mat,
+               scale.x, scale.y, scale.z);
+}
+
+void voxel_procedural_sx(VoxelProcedural *proc, f32 value)
+{
+       apply_scale(proc, (v3f32) {value, 1.0f, 1.0f});
+}
+
+void voxel_procedural_sy(VoxelProcedural *proc, f32 value)
+{
+       apply_scale(proc, (v3f32) {1.0f, value, 1.0f});
+}
+
+void voxel_procedural_sz(VoxelProcedural *proc, f32 value)
+{
+       apply_scale(proc, (v3f32) {1.0f, 1.0f, value});
+}
+
+void voxel_procedural_s(VoxelProcedural *proc, f32 value)
+{
+       apply_scale(proc, (v3f32) {value, value, value});
+}
+
+void voxel_procedural_pop(VoxelProcedural *proc)
+{
+       free(proc->state.fst->dat);
+       list_nrm(&proc->state, &proc->state.fst);
+}
+
+void voxel_procedural_push(VoxelProcedural *proc)
+{
+       list_ppd(&proc->state, create_state(&VOXEL_PROCEDURAL_STATE(proc)));
+}
+
+bool voxel_procedural_is_alive(VoxelProcedural *proc)
+{
+       if (VOXEL_PROCEDURAL_STATE(proc).life > 0 && --VOXEL_PROCEDURAL_STATE(proc).life <= 0)
+               return false;
+
+       return
+               VOXEL_PROCEDURAL_STATE(proc).scale[0] >= 1.0f &&
+               VOXEL_PROCEDURAL_STATE(proc).scale[1] >= 1.0f &&
+               VOXEL_PROCEDURAL_STATE(proc).scale[2] >= 1.0f;
+}
+
+void voxel_procedural_cube(VoxelProcedural *proc, NodeType node, bool use_color)
+{
+       if (!voxel_procedural_is_alive(proc))
+               return;
+
+       vec4 base_corners[8] = {
+               {0.0f, 0.0f, 0.0f, 0.0f},
+               {0.0f, 0.0f, 1.0f, 0.0f},
+               {0.0f, 1.0f, 0.0f, 0.0f},
+               {0.0f, 1.0f, 1.0f, 0.0f},
+               {1.0f, 0.0f, 0.0f, 0.0f},
+               {1.0f, 0.0f, 1.0f, 0.0f},
+               {1.0f, 1.0f, 0.0f, 0.0f},
+               {1.0f, 1.0f, 1.0f, 0.0f},
+       };
+
+       vec4 corners[8];
+
+       s32 max_len = 0;
+
+       vec4 center;
+
+       mat4x4_mul_vec4(center, VOXEL_PROCEDURAL_STATE(proc).mat, (vec4) {0.5f, 0.5f, 0.5f});
+
+       for (int i = 0; i < 8; i++) {
+               mat4x4_mul_vec4(corners[i], VOXEL_PROCEDURAL_STATE(proc).mat, base_corners[i]);
+
+               vec3 from_center;
+               vec3_sub(from_center, corners[i], center);
+
+               s32 len = ceil(vec3_len(from_center));
+
+               if (max_len < len)
+                       max_len = len;
+       }
+
+       for (s32 x = -max_len; x <= +max_len; x++)
+       for (s32 y = -max_len; y <= +max_len; y++)
+       for (s32 z = -max_len; z <= +max_len; z++) {
+               s32 v[3];
+
+               for (int i = 0; i < 3; i++) {
+                       f32 f = trunc(
+                               + f32_mix(corners[0][i], corners[4][i], (f32) x / (f32) max_len / 2.0f)
+                               + f32_mix(corners[0][i], corners[2][i], (f32) y / (f32) max_len / 2.0f)
+                               + f32_mix(corners[0][i], corners[1][i], (f32) z / (f32) max_len / 2.0f));
+
+                       v[i] = floor(VOXEL_PROCEDURAL_STATE(proc).pos[i] + f + 0.5f);
+               }
+
+               Blob buffer = {0, NULL};
+
+               if (use_color)
+                       ColorData_write(&buffer, &(ColorData) {hsl_to_rgb((v3f32) {
+                               VOXEL_PROCEDURAL_STATE(proc).h / 360.0,
+                               VOXEL_PROCEDURAL_STATE(proc).s,
+                               VOXEL_PROCEDURAL_STATE(proc).l,
+                       })});
+
+               server_terrain_gen_node(
+                       v3s32_add(proc->pos, (v3s32) {v[0], v[2], v[1]}),
+                       terrain_node_create(node, buffer),
+                       proc->tgs,
+                       proc->changed_chunks
+               );
+
+               Blob_free(&buffer);
+       }
+}
+
+
+void voxel_procedural_cylinder(VoxelProcedural *proc, NodeType node, bool use_color)
+{
+       voxel_procedural_cube(proc, node, use_color);
+}
+
+/*
+void voxel_procedural_cylinder(VoxelProcedural *proc, Node node, bool use_color)
+{
+       if (!voxel_procedural_is_alive(proc))
+               return;
+
+       return;
+
+       f32 xf = VOXEL_PROCEDURAL_STATE(proc).scale[0] / 2.0f;
+       for (s32 x = round(-xf + 0.5f); x <= round(xf); x++) {
+               f32 yf = cos(x / VOXEL_PROCEDURAL_STATE(proc).scale[0] * M_PI) * VOXEL_PROCEDURAL_STATE(proc).scale[1] / 2.0f;
+               for (s32 y = round(-yf); y <= round(yf); y++) {
+                       f32 zf = VOXEL_PROCEDURAL_STATE(proc).scale[2] / 2.0f;
+                       for (s32 z = round(-zf + 0.5f); z <= round(zf); z++) {
+                               mapgen_set_node((v3s32) {
+                                       proc->pos.x + round(VOXEL_PROCEDURAL_STATE(proc).pos[0] + x),
+                                       proc->pos.y + round(VOXEL_PROCEDURAL_STATE(proc).pos[2] + z),
+                                       proc->pos.z + round(VOXEL_PROCEDURAL_STATE(proc).pos[1] + y),
+                               }, CREATE_NODE, proc->tgs, proc->changed_chunks);
+                       }
+               }
+       }
+}
+*/
+
+f32 voxel_procedural_random(VoxelProcedural *proc, f32 base, f32 vary)
+{
+       return base + noise3d(proc->pos.x, proc->pos.y, proc->pos.z, proc->random++, seed + OFFSET_VOXEL_PROCEDURAL) * vary;
+}
diff --git a/src/server/voxel_procedural.h b/src/server/voxel_procedural.h
new file mode 100644 (file)
index 0000000..c953add
--- /dev/null
@@ -0,0 +1,50 @@
+#ifndef _VOXEL_PROCEDURAL_H_
+#define _VOXEL_PROCEDURAL_H_
+
+#include <dragonstd/list.h>
+#include <linmath.h/linmath.h>
+#include "server/server_terrain.h"
+#include "types.h"
+
+// Note: This is a close reimplementation of goxel procedural scripting capabilities
+
+typedef struct {
+       vec4 pos;
+       vec3 scale;
+       mat4x4 mat;
+       f32 h, s, l;
+       s32 life;
+} VoxelProceduralState;
+
+typedef struct {
+       v3s32 pos;
+       List *changed_chunks;
+       TerrainGenStage tgs;
+       s32 random;
+       List state;
+} VoxelProcedural;
+
+VoxelProcedural *voxel_procedural_create(List *changed_chunks, TerrainGenStage tgs, v3s32 pos);
+void voxel_procedural_delete(VoxelProcedural *proc);
+void voxel_procedural_hue(VoxelProcedural *proc, f32 value);
+void voxel_procedural_sat(VoxelProcedural *proc, f32 value);
+void voxel_procedural_light(VoxelProcedural *proc, f32 value);
+void voxel_procedural_life(VoxelProcedural *proc, s32 value);
+void voxel_procedural_x(VoxelProcedural *proc, f32 value);
+void voxel_procedural_y(VoxelProcedural *proc, f32 value);
+void voxel_procedural_z(VoxelProcedural *proc, f32 value);
+void voxel_procedural_rx(VoxelProcedural *proc, f32 value);
+void voxel_procedural_ry(VoxelProcedural *proc, f32 value);
+void voxel_procedural_rz(VoxelProcedural *proc, f32 value);
+void voxel_procedural_sx(VoxelProcedural *proc, f32 value);
+void voxel_procedural_sy(VoxelProcedural *proc, f32 value);
+void voxel_procedural_sz(VoxelProcedural *proc, f32 value);
+void voxel_procedural_s(VoxelProcedural *proc, f32 value);
+void voxel_procedural_pop(VoxelProcedural *proc);
+void voxel_procedural_push(VoxelProcedural *proc);
+bool voxel_procedural_is_alive(VoxelProcedural *proc);
+void voxel_procedural_cube(VoxelProcedural *proc, NodeType node, bool use_color);
+void voxel_procedural_cylinder(VoxelProcedural *proc, NodeType node, bool use_color);
+f32 voxel_procedural_random(VoxelProcedural *proc, f32 base, f32 vary);
+
+#endif // _VOXEL_PROCEDURAL_H_
diff --git a/src/server/voxelctx.c b/src/server/voxelctx.c
deleted file mode 100644 (file)
index 7148102..0000000
+++ /dev/null
@@ -1,272 +0,0 @@
-#include <stdlib.h>
-#include <pthread.h>
-#include "color.h"
-#include "perlin.h"
-#include "server/terrain_gen.h"
-#include "server/voxelctx.h"
-
-static VoxelctxState *create_state(VoxelctxState *old)
-{
-       VoxelctxState *state = malloc(sizeof *state);
-
-       if (old) {
-               *state = *old;
-       } else {
-               state->pos[0] = 0.0f;
-               state->pos[1] = 0.0f;
-               state->pos[2] = 0.0f;
-               state->pos[3] = 0.0f;
-               state->scale[0] = 1.0f;
-               state->scale[1] = 1.0f;
-               state->scale[2] = 1.0f;
-               mat4x4_identity(state->mat);
-               state->h = 0.0f;
-               state->s = 0.0f;
-               state->l = 1.0f;
-               state->life = 0;
-       }
-
-       return state;
-}
-
-Voxelctx *voxelctx_create(List *changed_chunks, TerrainGenStage tgs, v3s32 pos)
-{
-       Voxelctx *ctx = malloc(sizeof(Voxelctx));
-
-       ctx->changed_chunks = changed_chunks;
-       ctx->tgs = tgs;
-       ctx->pos = pos;
-       list_ini(&ctx->statestack);
-       ctx->random = 0;
-
-       list_apd(&ctx->statestack, create_state(NULL));
-
-       return ctx;
-}
-
-void voxelctx_delete(Voxelctx *ctx)
-{
-       list_clr(&ctx->statestack, &free, NULL, NULL);
-       free(ctx);
-}
-
-static void move_value(f32 *x, f32 v, f32 range)
-{
-    f32 dst = v >= 0 ? range : 0;
-    v = fabs(v);
-    *x = f32_mix(*x, dst, v);
-}
-
-void voxelctx_hue(Voxelctx *ctx, f32 value)
-{
-       VOXELCTXSTATE(ctx).h += value;
-}
-
-void voxelctx_sat(Voxelctx *ctx, f32 value)
-{
-       move_value(&VOXELCTXSTATE(ctx).s, value, 1.0f);
-}
-
-void voxelctx_light(Voxelctx *ctx, f32 value)
-{
-       move_value(&VOXELCTXSTATE(ctx).l, value, 1.0f);
-}
-
-void voxelctx_life(Voxelctx *ctx, s32 value)
-{
-       VOXELCTXSTATE(ctx).life += value;
-}
-
-static void apply_translation(Voxelctx *ctx, v3f32 translate)
-{
-       vec4 translate_vec;
-       mat4x4_mul_vec4(translate_vec, VOXELCTXSTATE(ctx).mat, (vec4) {translate.x, translate.y, translate.z, 0.0f});
-       vec4_add(VOXELCTXSTATE(ctx).pos, VOXELCTXSTATE(ctx).pos, translate_vec);
-}
-
-void voxelctx_x(Voxelctx *ctx, f32 value)
-{
-       apply_translation(ctx, (v3f32) {value, 0.0f, 0.0f});
-}
-
-void voxelctx_y(Voxelctx *ctx, f32 value)
-{
-       apply_translation(ctx, (v3f32) {0.0f, value, 0.0f});
-}
-
-void voxelctx_z(Voxelctx *ctx, f32 value)
-{
-       apply_translation(ctx, (v3f32) {0.0f, 0.0f, value});
-}
-
-void voxelctx_rx(Voxelctx *ctx, f32 value)
-{
-       mat4x4_rotate_X(VOXELCTXSTATE(ctx).mat, VOXELCTXSTATE(ctx).mat, value * M_PI / 180.0f);
-}
-
-void voxelctx_ry(Voxelctx *ctx, f32 value)
-{
-       mat4x4_rotate_Y(VOXELCTXSTATE(ctx).mat, VOXELCTXSTATE(ctx).mat, value * M_PI / 180.0f);
-}
-
-void voxelctx_rz(Voxelctx *ctx, f32 value)
-{
-       mat4x4_rotate_Z(VOXELCTXSTATE(ctx).mat, VOXELCTXSTATE(ctx).mat, value * M_PI / 180.0f);
-}
-
-static void apply_scale(Voxelctx *ctx, v3f32 scale)
-{
-       VOXELCTXSTATE(ctx).scale[0] *= scale.x;
-       VOXELCTXSTATE(ctx).scale[1] *= scale.y;
-       VOXELCTXSTATE(ctx).scale[2] *= scale.z;
-
-       mat4x4_scale_aniso(VOXELCTXSTATE(ctx).mat, VOXELCTXSTATE(ctx).mat, scale.x, scale.y, scale.z);
-}
-
-void voxelctx_sx(Voxelctx *ctx, f32 value)
-{
-       apply_scale(ctx, (v3f32) {value, 1.0f, 1.0f});
-}
-
-void voxelctx_sy(Voxelctx *ctx, f32 value)
-{
-       apply_scale(ctx, (v3f32) {1.0f, value, 1.0f});
-}
-
-void voxelctx_sz(Voxelctx *ctx, f32 value)
-{
-       apply_scale(ctx, (v3f32) {1.0f, 1.0f, value});
-}
-
-void voxelctx_s(Voxelctx *ctx, f32 value)
-{
-       apply_scale(ctx, (v3f32) {value, value, value});
-}
-
-void voxelctx_pop(Voxelctx *ctx)
-{
-       free(ctx->statestack.fst->dat);
-       list_nrm(&ctx->statestack, &ctx->statestack.fst);
-}
-
-void voxelctx_push(Voxelctx *ctx)
-{
-       list_ppd(&ctx->statestack, create_state(&VOXELCTXSTATE(ctx)));
-}
-
-bool voxelctx_is_alive(Voxelctx *ctx)
-{
-       if (VOXELCTXSTATE(ctx).life > 0) {
-               VOXELCTXSTATE(ctx).life--;
-               if (VOXELCTXSTATE(ctx).life <= 0)
-                       return false;
-       }
-
-       return VOXELCTXSTATE(ctx).scale[0] >= 1.0f && VOXELCTXSTATE(ctx).scale[1] >= 1.0f && VOXELCTXSTATE(ctx).scale[2] >= 1.0f;
-}
-
-void voxelctx_cube(Voxelctx *ctx, NodeType node, bool use_color)
-{
-       if (!voxelctx_is_alive(ctx))
-               return;
-
-       vec4 base_corners[8] = {
-               {0.0f, 0.0f, 0.0f, 0.0f},
-               {0.0f, 0.0f, 1.0f, 0.0f},
-               {0.0f, 1.0f, 0.0f, 0.0f},
-               {0.0f, 1.0f, 1.0f, 0.0f},
-               {1.0f, 0.0f, 0.0f, 0.0f},
-               {1.0f, 0.0f, 1.0f, 0.0f},
-               {1.0f, 1.0f, 0.0f, 0.0f},
-               {1.0f, 1.0f, 1.0f, 0.0f},
-       };
-
-       vec4 corners[8];
-
-       s32 max_len = 0;
-
-       vec4 center;
-
-       mat4x4_mul_vec4(center, VOXELCTXSTATE(ctx).mat, (vec4) {0.5f, 0.5f, 0.5f});
-
-       for (int i = 0; i < 8; i++) {
-               mat4x4_mul_vec4(corners[i], VOXELCTXSTATE(ctx).mat, base_corners[i]);
-
-               vec3 from_center;
-               vec3_sub(from_center, corners[i], center);
-
-               s32 len = ceil(vec3_len(from_center));
-
-               if (max_len < len)
-                       max_len = len;
-       }
-
-       for (s32 x = -max_len; x <= +max_len; x++)
-       for (s32 y = -max_len; y <= +max_len; y++)
-       for (s32 z = -max_len; z <= +max_len; z++) {
-               s32 v[3];
-
-               for (int i = 0; i < 3; i++) {
-                       f32 f = trunc(
-                               + f32_mix(corners[0][i], corners[4][i], (f32) x / (f32) max_len / 2.0f)
-                               + f32_mix(corners[0][i], corners[2][i], (f32) y / (f32) max_len / 2.0f)
-                               + f32_mix(corners[0][i], corners[1][i], (f32) z / (f32) max_len / 2.0f));
-
-                       v[i] = floor(VOXELCTXSTATE(ctx).pos[i] + f + 0.5f);
-               }
-
-               Blob buffer = {0, NULL};
-
-               if (use_color)
-                       ColorData_write(&buffer, &(ColorData) {hsl_to_rgb((v3f32) {
-                               VOXELCTXSTATE(ctx).h / 360.0,
-                               VOXELCTXSTATE(ctx).s,
-                               VOXELCTXSTATE(ctx).l,
-                       })});
-
-               server_terrain_gen_node(
-                       v3s32_add(ctx->pos, (v3s32) {v[0], v[2], v[1]}),
-                       terrain_node_create(node, buffer),
-                       ctx->tgs,
-                       ctx->changed_chunks
-               );
-
-               Blob_free(&buffer);
-       }
-}
-
-
-void voxelctx_cylinder(Voxelctx *ctx, NodeType node, bool use_color)
-{
-       voxelctx_cube(ctx, node, use_color);
-}
-
-/*
-void voxelctx_cylinder(Voxelctx *ctx, Node node, bool use_color)
-{
-       if (!voxelctx_is_alive(ctx))
-               return;
-
-       return;
-
-       f32 xf = VOXELCTXSTATE(ctx).scale[0] / 2.0f;
-       for (s32 x = round(-xf + 0.5f); x <= round(xf); x++) {
-               f32 yf = cos(x / VOXELCTXSTATE(ctx).scale[0] * M_PI) * VOXELCTXSTATE(ctx).scale[1] / 2.0f;
-               for (s32 y = round(-yf); y <= round(yf); y++) {
-                       f32 zf = VOXELCTXSTATE(ctx).scale[2] / 2.0f;
-                       for (s32 z = round(-zf + 0.5f); z <= round(zf); z++) {
-                               mapgen_set_node((v3s32) {
-                                       ctx->pos.x + round(VOXELCTXSTATE(ctx).pos[0] + x),
-                                       ctx->pos.y + round(VOXELCTXSTATE(ctx).pos[2] + z),
-                                       ctx->pos.z + round(VOXELCTXSTATE(ctx).pos[1] + y),
-                               }, CREATE_NODE, ctx->tgs, ctx->changed_chunks);
-                       }
-               }
-       }
-}
-*/
-
-f32 voxelctx_random(Voxelctx *ctx, f32 base, f32 vary)
-{
-       return base + noise3d(ctx->pos.x, ctx->pos.y, ctx->pos.z, ctx->random++, seed + SO_VOXELCTX) * vary;
-}
diff --git a/src/server/voxelctx.h b/src/server/voxelctx.h
deleted file mode 100644 (file)
index 2469be0..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-#ifndef _VOXELCTX_H_
-#define _VOXELCTX_H_
-
-#define VOXELCTXSTATE(ctx) (*((VoxelctxState *) (ctx)->statestack.fst->dat))
-
-#include <dragonstd/list.h>
-#include <linmath.h/linmath.h>
-#include "server/server_terrain.h"
-#include "types.h"
-
-typedef struct {
-       vec4 pos;
-       vec3 scale;
-       mat4x4 mat;
-       f32 h, s, l;
-       s32 life;
-} VoxelctxState;
-
-typedef struct {
-       v3s32 pos;
-       List *changed_chunks;
-       TerrainGenStage tgs;
-       List statestack;
-       s32 random;
-} Voxelctx;
-
-Voxelctx *voxelctx_create(List *changed_chunks, TerrainGenStage tgs, v3s32 pos);
-void voxelctx_delete(Voxelctx *ctx);
-void voxelctx_hue(Voxelctx *ctx, f32 value);
-void voxelctx_sat(Voxelctx *ctx, f32 value);
-void voxelctx_light(Voxelctx *ctx, f32 value);
-void voxelctx_life(Voxelctx *ctx, s32 value);
-void voxelctx_x(Voxelctx *ctx, f32 value);
-void voxelctx_y(Voxelctx *ctx, f32 value);
-void voxelctx_z(Voxelctx *ctx, f32 value);
-void voxelctx_rx(Voxelctx *ctx, f32 value);
-void voxelctx_ry(Voxelctx *ctx, f32 value);
-void voxelctx_rz(Voxelctx *ctx, f32 value);
-void voxelctx_sx(Voxelctx *ctx, f32 value);
-void voxelctx_sy(Voxelctx *ctx, f32 value);
-void voxelctx_sz(Voxelctx *ctx, f32 value);
-void voxelctx_s(Voxelctx *ctx, f32 value);
-void voxelctx_pop(Voxelctx *ctx);
-void voxelctx_push(Voxelctx *ctx);
-bool voxelctx_is_alive(Voxelctx *ctx);
-void voxelctx_cube(Voxelctx *ctx, NodeType node, bool use_color);
-void voxelctx_cylinder(Voxelctx *ctx, NodeType node, bool use_color);
-f32 voxelctx_random(Voxelctx *ctx, f32 base, f32 vary);
-
-#endif // _VOXELCTX_H_
index 111e17597e54d8487125e2b730e5b3bcdbe0373d..44098c74c8802a705be8dad918505e3f50d6c78b 100644 (file)
@@ -9,9 +9,9 @@
 #include "types.h"
 
 #define CHUNK_ITERATE \
-       for (u8 x = 0; x < CHUNK_SIZE; x++) \
-       for (u8 y = 0; y < CHUNK_SIZE; y++) \
-       for (u8 z = 0; z < CHUNK_SIZE; z++)
+       for (s32 x = 0; x < CHUNK_SIZE; x++) \
+       for (s32 y = 0; y < CHUNK_SIZE; y++) \
+       for (s32 z = 0; z < CHUNK_SIZE; z++)
 
 typedef struct TerrainNode {
        NodeType type;