mirror of
https://github.com/minetest/minetest.git
synced 2025-01-08 22:37:32 +01:00
Mapgen: Fix biome Y calculation regression
BiomeGen::getNextTransitionY(y) did not guarantee the condition (y < biome_y_min) of the next loop because the function may return the value (biome_y_min - 1). Hence, the biome was not updated until one Y coordinate after.
This commit is contained in:
parent
50928b9759
commit
480eb7d816
@ -84,7 +84,7 @@ void CavesNoiseIntersection::generateCaves(MMVManip *vm,
|
|||||||
u16 depth_riverbed = biome->depth_riverbed;
|
u16 depth_riverbed = biome->depth_riverbed;
|
||||||
u16 nplaced = 0;
|
u16 nplaced = 0;
|
||||||
|
|
||||||
s16 biome_y_min = m_bmgn->getNextTransitionY(nmax.Y);
|
s16 biome_y_next = m_bmgn->getNextTransitionY(nmax.Y);
|
||||||
|
|
||||||
// Don't excavate the overgenerated stone at nmax.Y + 1,
|
// Don't excavate the overgenerated stone at nmax.Y + 1,
|
||||||
// this creates a 'roof' over the tunnel, preventing light in
|
// this creates a 'roof' over the tunnel, preventing light in
|
||||||
@ -94,13 +94,13 @@ void CavesNoiseIntersection::generateCaves(MMVManip *vm,
|
|||||||
index3d -= m_ystride,
|
index3d -= m_ystride,
|
||||||
VoxelArea::add_y(em, vi, -1)) {
|
VoxelArea::add_y(em, vi, -1)) {
|
||||||
// We need this check to make sure that biomes don't generate too far down
|
// We need this check to make sure that biomes don't generate too far down
|
||||||
if (y < biome_y_min) {
|
if (y <= biome_y_next) {
|
||||||
biome = m_bmgn->getBiomeAtIndex(index2d, v3s16(x, y, z));
|
biome = m_bmgn->getBiomeAtIndex(index2d, v3s16(x, y, z));
|
||||||
biome_y_min = m_bmgn->getNextTransitionY(y);
|
biome_y_next = m_bmgn->getNextTransitionY(y);
|
||||||
|
|
||||||
if (x == nmin.X && z == nmin.Z && false) {
|
if (x == nmin.X && z == nmin.Z && false) {
|
||||||
dstream << "cavegen: biome at " << y << " is " << biome->name
|
dstream << "cavegen: biome at " << y << " is " << biome->name
|
||||||
<< ", next at " << biome_y_min << std::endl;
|
<< ", next at " << biome_y_next << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -644,7 +644,7 @@ void MapgenBasic::generateBiomes()
|
|||||||
u16 depth_riverbed = 0;
|
u16 depth_riverbed = 0;
|
||||||
u32 vi = vm->m_area.index(x, node_max.Y, z);
|
u32 vi = vm->m_area.index(x, node_max.Y, z);
|
||||||
|
|
||||||
s16 biome_y_min = biomegen->getNextTransitionY(node_max.Y);
|
s16 biome_y_next = biomegen->getNextTransitionY(node_max.Y);
|
||||||
|
|
||||||
// Check node at base of mapchunk above, either a node of a previously
|
// Check node at base of mapchunk above, either a node of a previously
|
||||||
// generated mapchunk or if not, a node of overgenerated base terrain.
|
// generated mapchunk or if not, a node of overgenerated base terrain.
|
||||||
@ -661,23 +661,29 @@ void MapgenBasic::generateBiomes()
|
|||||||
|
|
||||||
for (s16 y = node_max.Y; y >= node_min.Y; y--) {
|
for (s16 y = node_max.Y; y >= node_min.Y; y--) {
|
||||||
content_t c = vm->m_data[vi].getContent();
|
content_t c = vm->m_data[vi].getContent();
|
||||||
|
const bool biome_outdated = !biome || y <= biome_y_next;
|
||||||
// Biome is (re)calculated:
|
// Biome is (re)calculated:
|
||||||
// 1. At the surface of stone below air or water.
|
// 1. At the surface of stone below air or water.
|
||||||
// 2. At the surface of water below air.
|
// 2. At the surface of water below air.
|
||||||
// 3. When stone or water is detected but biome has not yet been calculated.
|
// 3. When stone or water is detected but biome has not yet been calculated.
|
||||||
// 4. When stone or water is detected just below a biome's lower limit.
|
// 4. When stone or water is detected just below a biome's lower limit.
|
||||||
bool is_stone_surface = (c == c_stone) &&
|
bool is_stone_surface = (c == c_stone) &&
|
||||||
(air_above || water_above || !biome || y < biome_y_min); // 1, 3, 4
|
(air_above || water_above || biome_outdated); // 1, 3, 4
|
||||||
|
|
||||||
bool is_water_surface =
|
bool is_water_surface =
|
||||||
(c == c_water_source || c == c_river_water_source) &&
|
(c == c_water_source || c == c_river_water_source) &&
|
||||||
(air_above || !biome || y < biome_y_min); // 2, 3, 4
|
(air_above || biome_outdated); // 2, 3, 4
|
||||||
|
|
||||||
if (is_stone_surface || is_water_surface) {
|
if (is_stone_surface || is_water_surface) {
|
||||||
if (!biome || y < biome_y_min) {
|
if (biome_outdated) {
|
||||||
// (Re)calculate biome
|
// (Re)calculate biome
|
||||||
biome = biomegen->getBiomeAtIndex(index, v3s16(x, y, z));
|
biome = biomegen->getBiomeAtIndex(index, v3s16(x, y, z));
|
||||||
biome_y_min = biomegen->getNextTransitionY(y);
|
biome_y_next = biomegen->getNextTransitionY(y);
|
||||||
|
|
||||||
|
if (x == node_min.X && z == node_min.Z && false) {
|
||||||
|
dstream << "biomegen: biome at " << y << " is " << biome->name
|
||||||
|
<< ", next at " << biome_y_next << std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add biome to biomemap at first stone surface detected
|
// Add biome to biomemap at first stone surface detected
|
||||||
|
@ -129,7 +129,10 @@ BiomeGenOriginal::BiomeGenOriginal(BiomeManager *biomemgr,
|
|||||||
for (size_t i = 0; i < m_bmgr->getNumObjects(); i++) {
|
for (size_t i = 0; i < m_bmgr->getNumObjects(); i++) {
|
||||||
Biome *b = (Biome *)m_bmgr->getRaw(i);
|
Biome *b = (Biome *)m_bmgr->getRaw(i);
|
||||||
values.push_back(b->max_pos.Y);
|
values.push_back(b->max_pos.Y);
|
||||||
values.push_back(b->min_pos.Y);
|
// We scan for biomes from high Y to low Y (top to bottom). Hence,
|
||||||
|
// biomes effectively transition at (min_pos.Y - 1).
|
||||||
|
if (b->min_pos.Y > -MAX_MAP_GENERATION_LIMIT)
|
||||||
|
values.push_back(b->min_pos.Y - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort(values.begin(), values.end(), std::greater<>());
|
std::sort(values.begin(), values.end(), std::greater<>());
|
||||||
|
@ -197,7 +197,8 @@ private:
|
|||||||
Noise *noise_heat_blend;
|
Noise *noise_heat_blend;
|
||||||
Noise *noise_humidity_blend;
|
Noise *noise_humidity_blend;
|
||||||
|
|
||||||
// ordered descending
|
/// Y values at which biomes may transition.
|
||||||
|
/// This array may only be used for downwards scanning!
|
||||||
std::vector<s16> m_transitions_y;
|
std::vector<s16> m_transitions_y;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -93,11 +93,10 @@ void TestMapgen::testBiomeGen(IGameDef *gamedef)
|
|||||||
const char *name;
|
const char *name;
|
||||||
s16 next_y;
|
s16 next_y;
|
||||||
} expected_biomes[] = {
|
} expected_biomes[] = {
|
||||||
{ MAX_MAP_GENERATION_LIMIT, "deciduous_forest", 1 },
|
{ MAX_MAP_GENERATION_LIMIT, "deciduous_forest", 0 },
|
||||||
// ^ FIXME: next_y should be 0 (min_pos.Y - 1)
|
|
||||||
{ 1, "deciduous_forest", 0 },
|
{ 1, "deciduous_forest", 0 },
|
||||||
{ 0, "deciduous_forest_shore", -MAX_MAP_GENERATION_LIMIT },
|
{ 0, "deciduous_forest_shore", S16_MIN },
|
||||||
{ -100, "deciduous_forest_shore", -MAX_MAP_GENERATION_LIMIT },
|
{ -100, "deciduous_forest_shore", S16_MIN },
|
||||||
};
|
};
|
||||||
for (const auto expected : expected_biomes) {
|
for (const auto expected : expected_biomes) {
|
||||||
Biome *biome = biomegen->getBiomeAtIndex(
|
Biome *biome = biomegen->getBiomeAtIndex(
|
||||||
|
Loading…
Reference in New Issue
Block a user