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
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)
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;
}
#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;
#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)
{
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)
return height;
}
-static void chunk_ocean(BiomeArgsChunk *args)
+static void before_chunk_ocean(BiomeArgsChunk *args)
{
OceanChunkData *chunk_data = args->chunk_data;
};
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;
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)
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;
// 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)
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)
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,
},
};
} BiomeArgsHeight;
typedef struct {
+ v3s32 offset;
v3s32 pos;
s32 diff;
f64 humidity;
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[];
#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)
{
};
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);
= 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;
}
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);
+ }
+ }
}
#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_
#include "server/biomes.h"
#include "server/server_terrain.h"
#include "server/trees.h"
-#include "server/voxelctx.h"
+#include "server/voxel_procedural.h"
// oak
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
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},
{-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,
&& 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] = {
.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,
},
.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,
},
.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,
},
--- /dev/null
+#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;
+}
--- /dev/null
+#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_
--- /dev/null
+#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;
+}
--- /dev/null
+#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_
+++ /dev/null
-#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;
-}
+++ /dev/null
-#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_
#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;