mirror of
https://github.com/luanti-org/luanti.git
synced 2025-07-02 16:38:41 +00:00
Add new Mapgen V7 floatland implementation (#9296)
Floatland structure is vertically-compressed 3D noise. Uses a lacunarity of 1.618 (the golden ratio) for high quality noise. Floatlands appear between user-settable Y limits, with smooth tapering at each limit. Simple user-settable density adjustment. Shadow propagation is disabled in and just below floatlands, no shadows are cast on the world surface. Can be reconfigured to create a solid upper world layer between the Y limits, lakes/seas can be optionally added to this.
This commit is contained in:
parent
d76785b4c7
commit
af0f7ac4a2
3 changed files with 160 additions and 12 deletions
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
Minetest
|
||||
Copyright (C) 2013-2019 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
|
||||
Copyright (C) 2014-2019 paramat
|
||||
Copyright (C) 2014-2020 paramat
|
||||
Copyright (C) 2013-2016 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
|
@ -56,6 +56,12 @@ MapgenV7::MapgenV7(MapgenV7Params *params, EmergeParams *emerge)
|
|||
{
|
||||
spflags = params->spflags;
|
||||
mount_zero_level = params->mount_zero_level;
|
||||
floatland_ymin = params->floatland_ymin;
|
||||
floatland_ymax = params->floatland_ymax;
|
||||
floatland_taper = params->floatland_taper;
|
||||
float_taper_exp = params->float_taper_exp;
|
||||
floatland_density = params->floatland_density;
|
||||
floatland_ywater = params->floatland_ywater;
|
||||
|
||||
cave_width = params->cave_width;
|
||||
large_cave_depth = params->large_cave_depth;
|
||||
|
@ -70,6 +76,9 @@ MapgenV7::MapgenV7(MapgenV7Params *params, EmergeParams *emerge)
|
|||
dungeon_ymin = params->dungeon_ymin;
|
||||
dungeon_ymax = params->dungeon_ymax;
|
||||
|
||||
// Allocate floatland noise offset cache
|
||||
this->float_offset_cache = new float[csize.Y + 2];
|
||||
|
||||
// 2D noise
|
||||
noise_terrain_base =
|
||||
new Noise(¶ms->np_terrain_base, seed, csize.X, csize.Z);
|
||||
|
@ -100,6 +109,12 @@ MapgenV7::MapgenV7(MapgenV7Params *params, EmergeParams *emerge)
|
|||
new Noise(¶ms->np_ridge, seed, csize.X, csize.Y + 2, csize.Z);
|
||||
}
|
||||
|
||||
if (spflags & MGV7_FLOATLANDS) {
|
||||
// 3D noise, 1 up, 1 down overgeneration
|
||||
noise_floatland =
|
||||
new Noise(¶ms->np_floatland, seed, csize.X, csize.Y + 2, csize.Z);
|
||||
}
|
||||
|
||||
// 3D noise, 1 down overgeneration
|
||||
MapgenBasic::np_cave1 = params->np_cave1;
|
||||
MapgenBasic::np_cave2 = params->np_cave2;
|
||||
|
@ -126,6 +141,12 @@ MapgenV7::~MapgenV7()
|
|||
delete noise_ridge_uwater;
|
||||
delete noise_ridge;
|
||||
}
|
||||
|
||||
if (spflags & MGV7_FLOATLANDS) {
|
||||
delete noise_floatland;
|
||||
}
|
||||
|
||||
delete []float_offset_cache;
|
||||
}
|
||||
|
||||
|
||||
|
@ -139,6 +160,7 @@ MapgenV7Params::MapgenV7Params():
|
|||
np_ridge_uwater (0.0, 1.0, v3f(1000, 1000, 1000), 85039, 5, 0.6, 2.0),
|
||||
np_mountain (-0.6, 1.0, v3f(250, 350, 250), 5333, 5, 0.63, 2.0),
|
||||
np_ridge (0.0, 1.0, v3f(100, 100, 100), 6467, 4, 0.75, 2.0),
|
||||
np_floatland (0.0, 0.7, v3f(384, 96, 384), 1009, 4, 0.75, 1.618),
|
||||
np_cavern (0.0, 1.0, v3f(384, 128, 384), 723, 5, 0.63, 2.0),
|
||||
np_cave1 (0.0, 12.0, v3f(61, 61, 61), 52534, 3, 0.5, 2.0),
|
||||
np_cave2 (0.0, 12.0, v3f(67, 67, 67), 10325, 3, 0.5, 2.0),
|
||||
|
@ -151,6 +173,13 @@ void MapgenV7Params::readParams(const Settings *settings)
|
|||
{
|
||||
settings->getFlagStrNoEx("mgv7_spflags", spflags, flagdesc_mapgen_v7);
|
||||
settings->getS16NoEx("mgv7_mount_zero_level", mount_zero_level);
|
||||
settings->getS16NoEx("mgv7_floatland_ymin", floatland_ymin);
|
||||
settings->getS16NoEx("mgv7_floatland_ymax", floatland_ymax);
|
||||
settings->getS16NoEx("mgv7_floatland_taper", floatland_taper);
|
||||
settings->getFloatNoEx("mgv7_float_taper_exp", float_taper_exp);
|
||||
settings->getFloatNoEx("mgv7_floatland_density", floatland_density);
|
||||
settings->getS16NoEx("mgv7_floatland_ywater", floatland_ywater);
|
||||
|
||||
settings->getFloatNoEx("mgv7_cave_width", cave_width);
|
||||
settings->getS16NoEx("mgv7_large_cave_depth", large_cave_depth);
|
||||
settings->getU16NoEx("mgv7_small_cave_num_min", small_cave_num_min);
|
||||
|
@ -173,6 +202,7 @@ void MapgenV7Params::readParams(const Settings *settings)
|
|||
settings->getNoiseParams("mgv7_np_ridge_uwater", np_ridge_uwater);
|
||||
settings->getNoiseParams("mgv7_np_mountain", np_mountain);
|
||||
settings->getNoiseParams("mgv7_np_ridge", np_ridge);
|
||||
settings->getNoiseParams("mgv7_np_floatland", np_floatland);
|
||||
settings->getNoiseParams("mgv7_np_cavern", np_cavern);
|
||||
settings->getNoiseParams("mgv7_np_cave1", np_cave1);
|
||||
settings->getNoiseParams("mgv7_np_cave2", np_cave2);
|
||||
|
@ -184,6 +214,13 @@ void MapgenV7Params::writeParams(Settings *settings) const
|
|||
{
|
||||
settings->setFlagStr("mgv7_spflags", spflags, flagdesc_mapgen_v7);
|
||||
settings->setS16("mgv7_mount_zero_level", mount_zero_level);
|
||||
settings->setS16("mgv7_floatland_ymin", floatland_ymin);
|
||||
settings->setS16("mgv7_floatland_ymax", floatland_ymax);
|
||||
settings->setS16("mgv7_floatland_taper", floatland_taper);
|
||||
settings->setFloat("mgv7_float_taper_exp", float_taper_exp);
|
||||
settings->setFloat("mgv7_floatland_density", floatland_density);
|
||||
settings->setS16("mgv7_floatland_ywater", floatland_ywater);
|
||||
|
||||
settings->setFloat("mgv7_cave_width", cave_width);
|
||||
settings->setS16("mgv7_large_cave_depth", large_cave_depth);
|
||||
settings->setU16("mgv7_small_cave_num_min", small_cave_num_min);
|
||||
|
@ -206,6 +243,7 @@ void MapgenV7Params::writeParams(Settings *settings) const
|
|||
settings->setNoiseParams("mgv7_np_ridge_uwater", np_ridge_uwater);
|
||||
settings->setNoiseParams("mgv7_np_mountain", np_mountain);
|
||||
settings->setNoiseParams("mgv7_np_ridge", np_ridge);
|
||||
settings->setNoiseParams("mgv7_np_floatland", np_floatland);
|
||||
settings->setNoiseParams("mgv7_np_cavern", np_cavern);
|
||||
settings->setNoiseParams("mgv7_np_cave1", np_cave1);
|
||||
settings->setNoiseParams("mgv7_np_cave2", np_cave2);
|
||||
|
@ -357,8 +395,9 @@ void MapgenV7::makeChunk(BlockMakeData *data)
|
|||
updateLiquid(&data->transforming_liquid, full_node_min, full_node_max);
|
||||
|
||||
// Calculate lighting
|
||||
// TODO disable in and just below floatlands
|
||||
bool propagate_shadow = true;
|
||||
// Limit floatland shadows
|
||||
bool propagate_shadow = !((spflags & MGV7_FLOATLANDS) &&
|
||||
node_max.Y >= floatland_ymin - csize.Y * 2 && node_min.Y <= floatland_ymax);
|
||||
|
||||
if (flags & MG_LIGHT)
|
||||
calcLighting(node_min - v3s16(0, 1, 0), node_max + v3s16(0, 1, 0),
|
||||
|
@ -427,6 +466,12 @@ bool MapgenV7::getMountainTerrainFromMap(int idx_xyz, int idx_xz, s16 y)
|
|||
}
|
||||
|
||||
|
||||
bool MapgenV7::getFloatlandTerrainFromMap(int idx_xyz, float float_offset)
|
||||
{
|
||||
return noise_floatland->result[idx_xyz] + floatland_density - float_offset >= 0.0f;
|
||||
}
|
||||
|
||||
|
||||
int MapgenV7::generateTerrain()
|
||||
{
|
||||
MapNode n_air(CONTENT_AIR);
|
||||
|
@ -446,6 +491,35 @@ int MapgenV7::generateTerrain()
|
|||
noise_mountain->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
|
||||
}
|
||||
|
||||
//// Floatlands
|
||||
// 'Generate floatlands in this mapchunk' bool for
|
||||
// simplification of condition checks in y-loop.
|
||||
bool gen_floatlands = false;
|
||||
u8 cache_index = 0;
|
||||
// Y values where floatland tapering starts
|
||||
s16 float_taper_ymax = floatland_ymax - floatland_taper;
|
||||
s16 float_taper_ymin = floatland_ymin + floatland_taper;
|
||||
|
||||
if ((spflags & MGV7_FLOATLANDS) &&
|
||||
node_max.Y >= floatland_ymin && node_min.Y <= floatland_ymax) {
|
||||
gen_floatlands = true;
|
||||
// Calculate noise for floatland generation
|
||||
noise_floatland->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
|
||||
|
||||
// Cache floatland noise offset values, for floatland tapering
|
||||
for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++, cache_index++) {
|
||||
float float_offset = 0.0f;
|
||||
if (y > float_taper_ymax) {
|
||||
float_offset = std::pow((y - float_taper_ymax) / (float)floatland_taper,
|
||||
float_taper_exp) * 4.0f;
|
||||
} else if (y < float_taper_ymin) {
|
||||
float_offset = std::pow((float_taper_ymin - y) / (float)floatland_taper,
|
||||
float_taper_exp) * 4.0f;
|
||||
}
|
||||
float_offset_cache[cache_index] = float_offset;
|
||||
}
|
||||
}
|
||||
|
||||
//// Place nodes
|
||||
const v3s16 &em = vm->m_area.getExtent();
|
||||
s16 stone_surface_max_y = -MAX_MAP_GENERATION_LIMIT;
|
||||
|
@ -457,13 +531,15 @@ int MapgenV7::generateTerrain()
|
|||
if (surface_y > stone_surface_max_y)
|
||||
stone_surface_max_y = surface_y;
|
||||
|
||||
cache_index = 0;
|
||||
u32 vi = vm->m_area.index(x, node_min.Y - 1, z);
|
||||
u32 index3d = (z - node_min.Z) * zstride_1u1d + (x - node_min.X);
|
||||
|
||||
for (s16 y = node_min.Y - 1; y <= node_max.Y + 1;
|
||||
y++,
|
||||
index3d += ystride,
|
||||
VoxelArea::add_y(em, vi, 1)) {
|
||||
VoxelArea::add_y(em, vi, 1),
|
||||
cache_index++) {
|
||||
if (vm->m_data[vi].getContent() != CONTENT_IGNORE)
|
||||
continue;
|
||||
|
||||
|
@ -474,10 +550,18 @@ int MapgenV7::generateTerrain()
|
|||
vm->m_data[vi] = n_stone; // Mountain terrain
|
||||
if (y > stone_surface_max_y)
|
||||
stone_surface_max_y = y;
|
||||
} else if (y <= water_level) {
|
||||
} else if (gen_floatlands &&
|
||||
getFloatlandTerrainFromMap(index3d,
|
||||
float_offset_cache[cache_index])) {
|
||||
vm->m_data[vi] = n_stone; // Floatland terrain
|
||||
if (y > stone_surface_max_y)
|
||||
stone_surface_max_y = y;
|
||||
} else if (y <= water_level) { // Surface water
|
||||
vm->m_data[vi] = n_water;
|
||||
} else if (gen_floatlands && y >= float_taper_ymax && y <= floatland_ywater) {
|
||||
vm->m_data[vi] = n_water; // Water for solid floatland layer only
|
||||
} else {
|
||||
vm->m_data[vi] = n_air;
|
||||
vm->m_data[vi] = n_air; // Air
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -488,8 +572,8 @@ int MapgenV7::generateTerrain()
|
|||
|
||||
void MapgenV7::generateRidgeTerrain()
|
||||
{
|
||||
// TODO disable river canyons in floatlands
|
||||
if (node_max.Y < water_level - 16)
|
||||
if (node_max.Y < water_level - 16 ||
|
||||
(node_max.Y >= floatland_ymin && node_min.Y <= floatland_ymax))
|
||||
return;
|
||||
|
||||
noise_ridge->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue