Biomes: Add vertical biome blend ()

Add 'vertical blend' parameter to biome registration that defines how
many nodes above the biome's 'y max' limit the blend will extend.
This commit is contained in:
Paramat
2018-01-04 23:10:55 +00:00
committed by Loïc Blot
parent ff2ceed381
commit 549cfd9db8
4 changed files with 38 additions and 19 deletions

@ -4989,18 +4989,18 @@ Definition tables
y_min = 1,
y_max = 31000,
-- ^ Lower and upper limits for biome.
vertical_blend = 8,
-- ^ Vertical distance in nodes above 'y_max' over which the biome will
-- ^ blend with the biome above.
-- ^ Set to 0 for no vertical blend. Defaults to 0.
heat_point = 0,
humidity_point = 50,
-- ^ Characteristic average temperature and humidity for the biome.
-- ^ These values create 'biome points' on a voronoi diagram that has heat
-- ^ and humidity as axes. The resulting voronoi cells determine which
-- ^ heat/humidity points belong to which biome, and therefore determine
-- ^ the area and location of each biome in the world.
-- ^ The biome points need to be carefully and evenly spaced on the voronoi
-- ^ diagram to result in roughly equal size biomes.
-- ^ Characteristic temperature and humidity for the biome.
-- ^ These values create 'biome points' on a voronoi diagram with heat and
-- ^ humidity as axes. The resulting voronoi cells determine the
-- ^ distribution of the biomes.
-- ^ Heat and humidity have average values of 50, vary mostly between
-- ^ 0 and 100 but also often exceed these values.
-- ^ Heat is not in degrees Celsius, both values are abstract.
-- ^ 0 and 100 but can exceed these values.
}
### Decoration definition (`register_decoration`)

@ -50,6 +50,7 @@ BiomeManager::BiomeManager(Server *server) :
b->y_max = MAX_MAP_GENERATION_LIMIT;
b->heat_point = 0.0;
b->humidity_point = 0.0;
b->vertical_blend = 0;
b->m_nodenames.emplace_back("mapgen_stone");
b->m_nodenames.emplace_back("mapgen_stone");
@ -201,25 +202,41 @@ Biome *BiomeGenOriginal::getBiomeAtIndex(size_t index, s16 y) const
Biome *BiomeGenOriginal::calcBiomeFromNoise(float heat, float humidity, s16 y) const
{
Biome *b, *biome_closest = NULL;
Biome *biome_closest = nullptr;
Biome *biome_closest_blend = nullptr;
float dist_min = FLT_MAX;
float dist_min_blend = FLT_MAX;
for (size_t i = 1; i < m_bmgr->getNumObjects(); i++) {
b = (Biome *)m_bmgr->getRaw(i);
if (!b || y > b->y_max || y < b->y_min)
Biome *b = (Biome *)m_bmgr->getRaw(i);
if (!b || y > b->y_max + b->vertical_blend || y < b->y_min)
continue;
float d_heat = heat - b->heat_point;
float d_heat = heat - b->heat_point;
float d_humidity = humidity - b->humidity_point;
float dist = (d_heat * d_heat) +
(d_humidity * d_humidity);
if (dist < dist_min) {
dist_min = dist;
biome_closest = b;
float dist = (d_heat * d_heat) + (d_humidity * d_humidity);
if (y <= b->y_max) { // Within y limits of biome b
if (dist < dist_min) {
dist_min = dist;
biome_closest = b;
}
} else if (dist < dist_min_blend) { // Blend area above biome b
dist_min_blend = dist;
biome_closest_blend = b;
}
}
return biome_closest ? biome_closest : (Biome *)m_bmgr->getRaw(BIOME_NONE);
// Carefully tune pseudorandom seed variation to avoid single node dither
// and create larger scale blending patterns.
mysrand(y + (heat - humidity) * 2);
if (biome_closest_blend &&
myrand_range(0, biome_closest_blend->vertical_blend) >=
y - biome_closest_blend->y_max)
return biome_closest_blend;
return (biome_closest) ? biome_closest : (Biome *)m_bmgr->getRaw(BIOME_NONE);
}

@ -67,6 +67,7 @@ public:
s16 y_max;
float heat_point;
float humidity_point;
s16 vertical_blend;
virtual void resolveNodeNames();
};

@ -392,6 +392,7 @@ Biome *read_biome_def(lua_State *L, int index, INodeDefManager *ndef)
b->y_max = getintfield_default(L, index, "y_max", 31000);
b->heat_point = getfloatfield_default(L, index, "heat_point", 0.f);
b->humidity_point = getfloatfield_default(L, index, "humidity_point", 0.f);
b->vertical_blend = getintfield_default(L, index, "vertical_blend", 0);
b->flags = 0; //reserved
std::vector<std::string> &nn = b->m_nodenames;