Mgv5/v7: Fix generateBiomes biome recalculation logic Biomegen down to y = -192 for mgv5 deep oceans. Improve code
This commit is contained in:
parent
6b5dcd508b
commit
4c7d2b62cf
|
@ -327,7 +327,7 @@ void MapgenV5::calculateNoise()
|
||||||
noise_cave2->perlinMap3D(x, y, z);
|
noise_cave2->perlinMap3D(x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node_max.Y >= water_level) {
|
if (node_max.Y >= BIOMEGEN_BASE_V5) {
|
||||||
noise_filler_depth->perlinMap2D(x, z);
|
noise_filler_depth->perlinMap2D(x, z);
|
||||||
noise_heat->perlinMap2D(x, z);
|
noise_heat->perlinMap2D(x, z);
|
||||||
noise_humidity->perlinMap2D(x, z);
|
noise_humidity->perlinMap2D(x, z);
|
||||||
|
@ -396,7 +396,7 @@ int MapgenV5::generateBaseTerrain()
|
||||||
|
|
||||||
MgStoneType MapgenV5::generateBiomes(float *heat_map, float *humidity_map)
|
MgStoneType MapgenV5::generateBiomes(float *heat_map, float *humidity_map)
|
||||||
{
|
{
|
||||||
if (node_max.Y < water_level)
|
if (node_max.Y < BIOMEGEN_BASE_V5)
|
||||||
return STONE;
|
return STONE;
|
||||||
|
|
||||||
v3s16 em = vm->m_area.getExtent();
|
v3s16 em = vm->m_area.getExtent();
|
||||||
|
@ -406,74 +406,80 @@ MgStoneType MapgenV5::generateBiomes(float *heat_map, float *humidity_map)
|
||||||
for (s16 z = node_min.Z; z <= node_max.Z; z++)
|
for (s16 z = node_min.Z; z <= node_max.Z; z++)
|
||||||
for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
|
for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
|
||||||
Biome *biome = NULL;
|
Biome *biome = NULL;
|
||||||
s16 dfiller = 0;
|
u16 depth_top = 0;
|
||||||
s16 y0_top = 0;
|
u16 base_filler = 0;
|
||||||
s16 y0_filler = 0;
|
u16 depth_water_top = 0;
|
||||||
s16 depth_water_top = 0;
|
u32 vi = vm->m_area.index(x, node_max.Y, z);
|
||||||
|
|
||||||
s16 nplaced = 0;
|
// Check node at base of mapchunk above, either a node of a previously
|
||||||
u32 i = vm->m_area.index(x, node_max.Y, z);
|
// generated mapchunk or if not, a node of overgenerated base terrain.
|
||||||
|
content_t c_above = vm->m_data[vi + em.X].getContent();
|
||||||
|
bool air_above = c_above == CONTENT_AIR;
|
||||||
|
|
||||||
content_t c_above = vm->m_data[i + em.X].getContent();
|
// If there is air above enable top/filler placement, otherwise force nplaced to
|
||||||
bool have_air = c_above == CONTENT_AIR;
|
// stone level by setting a number that will exceed any possible filler depth.
|
||||||
|
u16 nplaced = (air_above) ? 0 : (u16)-1;
|
||||||
|
|
||||||
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[i].getContent();
|
content_t c = vm->m_data[vi].getContent();
|
||||||
|
|
||||||
if (c != CONTENT_IGNORE && c != CONTENT_AIR &&
|
// Biome is only (re)calculated for each stone/water upper surface found
|
||||||
(y == node_max.Y || have_air)) {
|
// below air while working downwards. The chosen biome then remains in
|
||||||
|
// effect for all nodes below until the next biome recalculation.
|
||||||
|
// Biome is (re)calculated when a stone/water node is either: detected
|
||||||
|
// below an air node, or, is at column top and might be underground
|
||||||
|
// or underwater and therefore might not be below air.
|
||||||
|
if (c != CONTENT_AIR && (y == node_max.Y || air_above)) {
|
||||||
biome = bmgr->getBiome(heat_map[index], humidity_map[index], y);
|
biome = bmgr->getBiome(heat_map[index], humidity_map[index], y);
|
||||||
dfiller = biome->depth_filler + noise_filler_depth->result[index];
|
depth_top = biome->depth_top;
|
||||||
y0_top = biome->depth_top;
|
base_filler = MYMAX(depth_top + biome->depth_filler
|
||||||
y0_filler = biome->depth_top + dfiller;
|
+ noise_filler_depth->result[index], 0);
|
||||||
depth_water_top = biome->depth_water_top;
|
depth_water_top = biome->depth_water_top;
|
||||||
|
|
||||||
|
// Detect stone type for dungeons during every biome calculation.
|
||||||
|
// This is more efficient than detecting per-node and will not
|
||||||
|
// miss any desert stone or sandstone biomes.
|
||||||
if (biome->c_stone == c_desert_stone)
|
if (biome->c_stone == c_desert_stone)
|
||||||
stone_type = DESERT_STONE;
|
stone_type = DESERT_STONE;
|
||||||
else if (biome->c_stone == c_sandstone)
|
else if (biome->c_stone == c_sandstone)
|
||||||
stone_type = SANDSTONE;
|
stone_type = SANDSTONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c == c_stone && have_air) {
|
if (c == c_stone) {
|
||||||
content_t c_below = vm->m_data[i - em.X].getContent();
|
content_t c_below = vm->m_data[vi - em.X].getContent();
|
||||||
|
|
||||||
if (c_below != CONTENT_AIR && c_below != c_water_source) {
|
// If the node below isn't solid, make this node stone, so that
|
||||||
if (nplaced < y0_top) {
|
// any top/filler nodes above are structurally supported.
|
||||||
vm->m_data[i] = MapNode(biome->c_top);
|
// This is done by aborting the cycle of top/filler placement
|
||||||
|
// immediately by forcing nplaced to stone level.
|
||||||
|
if (c_below == CONTENT_AIR || c_below == c_water_source)
|
||||||
|
nplaced = (u16)-1;
|
||||||
|
|
||||||
|
if (nplaced < depth_top) {
|
||||||
|
vm->m_data[vi] = MapNode(biome->c_top);
|
||||||
nplaced++;
|
nplaced++;
|
||||||
} else if (nplaced < y0_filler && nplaced >= y0_top) {
|
} else if (nplaced < base_filler) {
|
||||||
vm->m_data[i] = MapNode(biome->c_filler);
|
vm->m_data[vi] = MapNode(biome->c_filler);
|
||||||
nplaced++;
|
nplaced++;
|
||||||
} else if (c == c_stone) {
|
|
||||||
have_air = false;
|
|
||||||
nplaced = 0;
|
|
||||||
vm->m_data[i] = MapNode(biome->c_stone);
|
|
||||||
} else {
|
} else {
|
||||||
have_air = false;
|
vm->m_data[vi] = MapNode(biome->c_stone);
|
||||||
nplaced = 0;
|
|
||||||
}
|
|
||||||
} else if (c == c_stone) {
|
|
||||||
have_air = false;
|
|
||||||
nplaced = 0;
|
|
||||||
vm->m_data[i] = MapNode(biome->c_stone);
|
|
||||||
}
|
|
||||||
} else if (c == c_stone) {
|
|
||||||
have_air = false;
|
|
||||||
nplaced = 0;
|
|
||||||
vm->m_data[i] = MapNode(biome->c_stone);
|
|
||||||
} else if (c == c_water_source) {
|
|
||||||
have_air = true;
|
|
||||||
nplaced = 0;
|
|
||||||
if (y > water_level - depth_water_top)
|
|
||||||
vm->m_data[i] = MapNode(biome->c_water_top);
|
|
||||||
else
|
|
||||||
vm->m_data[i] = MapNode(biome->c_water);
|
|
||||||
} else if (c == CONTENT_AIR) {
|
|
||||||
have_air = true;
|
|
||||||
nplaced = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vm->m_area.add_y(em, i, -1);
|
air_above = false;
|
||||||
|
} else if (c == c_water_source) {
|
||||||
|
vm->m_data[vi] = MapNode((y > (s32)(water_level - depth_water_top)) ?
|
||||||
|
biome->c_water_top : biome->c_water);
|
||||||
|
nplaced = 0; // Enable top/filler placement for next surface
|
||||||
|
air_above = false; // Biome is not recalculated underwater
|
||||||
|
} else if (c == CONTENT_AIR) {
|
||||||
|
nplaced = 0; // Enable top/filler placement for next surface
|
||||||
|
air_above = true; // Biome will be recalculated at next surface
|
||||||
|
} else { // Possible various nodes overgenerated from neighbouring mapchunks
|
||||||
|
nplaced = (u16)-1; // Disable top/filler placement
|
||||||
|
air_above = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
vm->m_area.add_y(em, vi, -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "mapgen.h"
|
#include "mapgen.h"
|
||||||
|
|
||||||
#define LARGE_CAVE_DEPTH -256
|
#define LARGE_CAVE_DEPTH -256
|
||||||
|
#define BIOMEGEN_BASE_V5 -192
|
||||||
|
|
||||||
/////////////////// Mapgen V5 flags
|
/////////////////// Mapgen V5 flags
|
||||||
//#define MGV5_ 0x01
|
//#define MGV5_ 0x01
|
||||||
|
|
|
@ -362,7 +362,7 @@ void MapgenV7::calculateNoise()
|
||||||
noise_mount_height->perlinMap2D(x, z);
|
noise_mount_height->perlinMap2D(x, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node_max.Y >= water_level) {
|
if (node_max.Y >= BIOMEGEN_BASE_V7) {
|
||||||
noise_filler_depth->perlinMap2D(x, z);
|
noise_filler_depth->perlinMap2D(x, z);
|
||||||
noise_heat->perlinMap2D(x, z);
|
noise_heat->perlinMap2D(x, z);
|
||||||
noise_humidity->perlinMap2D(x, z);
|
noise_humidity->perlinMap2D(x, z);
|
||||||
|
@ -591,7 +591,7 @@ void MapgenV7::generateRidgeTerrain()
|
||||||
|
|
||||||
MgStoneType MapgenV7::generateBiomes(float *heat_map, float *humidity_map)
|
MgStoneType MapgenV7::generateBiomes(float *heat_map, float *humidity_map)
|
||||||
{
|
{
|
||||||
if (node_max.Y < water_level)
|
if (node_max.Y < BIOMEGEN_BASE_V7)
|
||||||
return STONE;
|
return STONE;
|
||||||
|
|
||||||
v3s16 em = vm->m_area.getExtent();
|
v3s16 em = vm->m_area.getExtent();
|
||||||
|
@ -601,74 +601,80 @@ MgStoneType MapgenV7::generateBiomes(float *heat_map, float *humidity_map)
|
||||||
for (s16 z = node_min.Z; z <= node_max.Z; z++)
|
for (s16 z = node_min.Z; z <= node_max.Z; z++)
|
||||||
for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
|
for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
|
||||||
Biome *biome = NULL;
|
Biome *biome = NULL;
|
||||||
s16 dfiller = 0;
|
u16 depth_top = 0;
|
||||||
s16 y0_top = 0;
|
u16 base_filler = 0;
|
||||||
s16 y0_filler = 0;
|
u16 depth_water_top = 0;
|
||||||
s16 depth_water_top = 0;
|
u32 vi = vm->m_area.index(x, node_max.Y, z);
|
||||||
|
|
||||||
s16 nplaced = 0;
|
// Check node at base of mapchunk above, either a node of a previously
|
||||||
u32 i = vm->m_area.index(x, node_max.Y, z);
|
// generated mapchunk or if not, a node of overgenerated base terrain.
|
||||||
|
content_t c_above = vm->m_data[vi + em.X].getContent();
|
||||||
|
bool air_above = c_above == CONTENT_AIR;
|
||||||
|
|
||||||
content_t c_above = vm->m_data[i + em.X].getContent();
|
// If there is air above enable top/filler placement, otherwise force nplaced to
|
||||||
bool have_air = c_above == CONTENT_AIR;
|
// stone level by setting a number that will exceed any possible filler depth.
|
||||||
|
u16 nplaced = (air_above) ? 0 : (u16)-1;
|
||||||
|
|
||||||
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[i].getContent();
|
content_t c = vm->m_data[vi].getContent();
|
||||||
|
|
||||||
if (c != CONTENT_IGNORE && c != CONTENT_AIR &&
|
// Biome is only (re)calculated for each stone/water upper surface found
|
||||||
(y == node_max.Y || have_air)) {
|
// below air while working downwards. The chosen biome then remains in
|
||||||
|
// effect for all nodes below until the next biome recalculation.
|
||||||
|
// Biome is (re)calculated when a stone/water node is either: detected
|
||||||
|
// below an air node, or, is at column top and might be underground
|
||||||
|
// or underwater and therefore might not be below air.
|
||||||
|
if (c != CONTENT_AIR && (y == node_max.Y || air_above)) {
|
||||||
biome = bmgr->getBiome(heat_map[index], humidity_map[index], y);
|
biome = bmgr->getBiome(heat_map[index], humidity_map[index], y);
|
||||||
dfiller = biome->depth_filler + noise_filler_depth->result[index];
|
depth_top = biome->depth_top;
|
||||||
y0_top = biome->depth_top;
|
base_filler = MYMAX(depth_top + biome->depth_filler
|
||||||
y0_filler = biome->depth_top + dfiller;
|
+ noise_filler_depth->result[index], 0);
|
||||||
depth_water_top = biome->depth_water_top;
|
depth_water_top = biome->depth_water_top;
|
||||||
|
|
||||||
|
// Detect stone type for dungeons during every biome calculation.
|
||||||
|
// This is more efficient than detecting per-node and will not
|
||||||
|
// miss any desert stone or sandstone biomes.
|
||||||
if (biome->c_stone == c_desert_stone)
|
if (biome->c_stone == c_desert_stone)
|
||||||
stone_type = DESERT_STONE;
|
stone_type = DESERT_STONE;
|
||||||
else if (biome->c_stone == c_sandstone)
|
else if (biome->c_stone == c_sandstone)
|
||||||
stone_type = SANDSTONE;
|
stone_type = SANDSTONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c == c_stone && have_air) {
|
if (c == c_stone) {
|
||||||
content_t c_below = vm->m_data[i - em.X].getContent();
|
content_t c_below = vm->m_data[vi - em.X].getContent();
|
||||||
|
|
||||||
if (c_below != CONTENT_AIR && c_below != c_water_source) {
|
// If the node below isn't solid, make this node stone, so that
|
||||||
if (nplaced < y0_top) {
|
// any top/filler nodes above are structurally supported.
|
||||||
vm->m_data[i] = MapNode(biome->c_top);
|
// This is done by aborting the cycle of top/filler placement
|
||||||
|
// immediately by forcing nplaced to stone level.
|
||||||
|
if (c_below == CONTENT_AIR || c_below == c_water_source)
|
||||||
|
nplaced = (u16)-1;
|
||||||
|
|
||||||
|
if (nplaced < depth_top) {
|
||||||
|
vm->m_data[vi] = MapNode(biome->c_top);
|
||||||
nplaced++;
|
nplaced++;
|
||||||
} else if (nplaced < y0_filler && nplaced >= y0_top) {
|
} else if (nplaced < base_filler) {
|
||||||
vm->m_data[i] = MapNode(biome->c_filler);
|
vm->m_data[vi] = MapNode(biome->c_filler);
|
||||||
nplaced++;
|
nplaced++;
|
||||||
} else if (c == c_stone) {
|
|
||||||
have_air = false;
|
|
||||||
nplaced = 0;
|
|
||||||
vm->m_data[i] = MapNode(biome->c_stone);
|
|
||||||
} else {
|
} else {
|
||||||
have_air = false;
|
vm->m_data[vi] = MapNode(biome->c_stone);
|
||||||
nplaced = 0;
|
|
||||||
}
|
|
||||||
} else if (c == c_stone) {
|
|
||||||
have_air = false;
|
|
||||||
nplaced = 0;
|
|
||||||
vm->m_data[i] = MapNode(biome->c_stone);
|
|
||||||
}
|
|
||||||
} else if (c == c_stone) {
|
|
||||||
have_air = false;
|
|
||||||
nplaced = 0;
|
|
||||||
vm->m_data[i] = MapNode(biome->c_stone);
|
|
||||||
} else if (c == c_water_source) {
|
|
||||||
have_air = true;
|
|
||||||
nplaced = 0;
|
|
||||||
if (y > water_level - depth_water_top)
|
|
||||||
vm->m_data[i] = MapNode(biome->c_water_top);
|
|
||||||
else
|
|
||||||
vm->m_data[i] = MapNode(biome->c_water);
|
|
||||||
} else if (c == CONTENT_AIR) {
|
|
||||||
have_air = true;
|
|
||||||
nplaced = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
vm->m_area.add_y(em, i, -1);
|
air_above = false;
|
||||||
|
} else if (c == c_water_source) {
|
||||||
|
vm->m_data[vi] = MapNode((y > (s32)(water_level - depth_water_top)) ?
|
||||||
|
biome->c_water_top : biome->c_water);
|
||||||
|
nplaced = 0; // Enable top/filler placement for next surface
|
||||||
|
air_above = false; // Biome is not recalculated underwater
|
||||||
|
} else if (c == CONTENT_AIR) {
|
||||||
|
nplaced = 0; // Enable top/filler placement for next surface
|
||||||
|
air_above = true; // Biome will be recalculated at next surface
|
||||||
|
} else { // Possible various nodes overgenerated from neighbouring mapchunks
|
||||||
|
nplaced = (u16)-1; // Disable top/filler placement
|
||||||
|
air_above = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
vm->m_area.add_y(em, vi, -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
|
||||||
#include "mapgen.h"
|
#include "mapgen.h"
|
||||||
|
|
||||||
|
#define BIOMEGEN_BASE_V7 -192
|
||||||
|
|
||||||
/////////////////// Mapgen V7 flags
|
/////////////////// Mapgen V7 flags
|
||||||
#define MGV7_MOUNTAINS 0x01
|
#define MGV7_MOUNTAINS 0x01
|
||||||
#define MGV7_RIDGES 0x02
|
#define MGV7_RIDGES 0x02
|
||||||
|
|
Loading…
Reference in New Issue