mirror of
https://github.com/minetest/minetest.git
synced 2024-11-05 07:13:46 +01:00
Cavegen y biome check (#13472)
This commit is contained in:
parent
1ef9fc9d1f
commit
29b7aea38b
@ -38,14 +38,16 @@ static NoiseParams nparams_caveliquids(0, 1, v3f(150.0, 150.0, 150.0), 776, 3, 0
|
|||||||
////
|
////
|
||||||
|
|
||||||
CavesNoiseIntersection::CavesNoiseIntersection(
|
CavesNoiseIntersection::CavesNoiseIntersection(
|
||||||
const NodeDefManager *nodedef, BiomeManager *biomemgr, v3s16 chunksize,
|
const NodeDefManager *nodedef, BiomeManager *biomemgr, BiomeGen *biomegen, v3s16 chunksize,
|
||||||
NoiseParams *np_cave1, NoiseParams *np_cave2, s32 seed, float cave_width)
|
NoiseParams *np_cave1, NoiseParams *np_cave2, s32 seed, float cave_width)
|
||||||
{
|
{
|
||||||
assert(nodedef);
|
assert(nodedef);
|
||||||
assert(biomemgr);
|
assert(biomemgr);
|
||||||
|
assert(biomegen);
|
||||||
|
|
||||||
m_ndef = nodedef;
|
m_ndef = nodedef;
|
||||||
m_bmgr = biomemgr;
|
m_bmgr = biomemgr;
|
||||||
|
m_bmgn = biomegen;
|
||||||
|
|
||||||
m_csize = chunksize;
|
m_csize = chunksize;
|
||||||
m_cave_width = cave_width;
|
m_cave_width = cave_width;
|
||||||
@ -80,6 +82,8 @@ void CavesNoiseIntersection::generateCaves(MMVManip *vm,
|
|||||||
const v3s16 &em = vm->m_area.getExtent();
|
const v3s16 &em = vm->m_area.getExtent();
|
||||||
u32 index2d = 0; // Biomemap index
|
u32 index2d = 0; // Biomemap index
|
||||||
|
|
||||||
|
s16 *biome_transitions = m_bmgn->getBiomeTransitions();
|
||||||
|
|
||||||
for (s16 z = nmin.Z; z <= nmax.Z; z++)
|
for (s16 z = nmin.Z; z <= nmax.Z; z++)
|
||||||
for (s16 x = nmin.X; x <= nmax.X; x++, index2d++) {
|
for (s16 x = nmin.X; x <= nmax.X; x++, index2d++) {
|
||||||
bool column_is_open = false; // Is column open to overground
|
bool column_is_open = false; // Is column open to overground
|
||||||
@ -96,6 +100,10 @@ void CavesNoiseIntersection::generateCaves(MMVManip *vm,
|
|||||||
u16 base_filler = depth_top + biome->depth_filler;
|
u16 base_filler = depth_top + biome->depth_filler;
|
||||||
u16 depth_riverbed = biome->depth_riverbed;
|
u16 depth_riverbed = biome->depth_riverbed;
|
||||||
u16 nplaced = 0;
|
u16 nplaced = 0;
|
||||||
|
|
||||||
|
int cur_biome_depth = 0;
|
||||||
|
s16 biome_y_min = biome_transitions[cur_biome_depth];
|
||||||
|
|
||||||
// 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
|
||||||
// tunnels at mapchunk borders when generating mapchunks upwards.
|
// tunnels at mapchunk borders when generating mapchunks upwards.
|
||||||
@ -103,6 +111,20 @@ void CavesNoiseIntersection::generateCaves(MMVManip *vm,
|
|||||||
for (s16 y = nmax.Y; y >= nmin.Y - 1; y--,
|
for (s16 y = nmax.Y; y >= nmin.Y - 1; y--,
|
||||||
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
|
||||||
|
if (y < biome_y_min) {
|
||||||
|
biome = m_bmgn->getBiomeAtIndex(index2d, v3s16(x, y, z));
|
||||||
|
|
||||||
|
// Finding the height of the next biome
|
||||||
|
// On first iteration this may loop a couple times after than it should just run once
|
||||||
|
while (y < biome_y_min) {
|
||||||
|
biome_y_min = biome_transitions[++cur_biome_depth];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*if (x == nmin.X && z == nmin.Z)
|
||||||
|
printf("Cave: check @ %i -> %s -> again at %i\n", y, biome->name.c_str(), biome_y_min);*/
|
||||||
|
}
|
||||||
|
|
||||||
content_t c = vm->m_data[vi].getContent();
|
content_t c = vm->m_data[vi].getContent();
|
||||||
|
|
||||||
if (c == CONTENT_AIR || c == biome->c_water_top ||
|
if (c == CONTENT_AIR || c == biome->c_water_top ||
|
||||||
|
@ -26,6 +26,8 @@ typedef u16 biome_t; // copy from mg_biome.h to avoid an unnecessary include
|
|||||||
|
|
||||||
class GenerateNotifier;
|
class GenerateNotifier;
|
||||||
|
|
||||||
|
class BiomeGen;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
CavesNoiseIntersection is a cave digging algorithm that carves smooth,
|
CavesNoiseIntersection is a cave digging algorithm that carves smooth,
|
||||||
web-like, continuous tunnels at points where the density of the intersection
|
web-like, continuous tunnels at points where the density of the intersection
|
||||||
@ -42,7 +44,7 @@ class CavesNoiseIntersection
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CavesNoiseIntersection(const NodeDefManager *nodedef,
|
CavesNoiseIntersection(const NodeDefManager *nodedef,
|
||||||
BiomeManager *biomemgr, v3s16 chunksize, NoiseParams *np_cave1,
|
BiomeManager *biomemgr, BiomeGen *biomegen, v3s16 chunksize, NoiseParams *np_cave1,
|
||||||
NoiseParams *np_cave2, s32 seed, float cave_width);
|
NoiseParams *np_cave2, s32 seed, float cave_width);
|
||||||
~CavesNoiseIntersection();
|
~CavesNoiseIntersection();
|
||||||
|
|
||||||
@ -52,6 +54,8 @@ private:
|
|||||||
const NodeDefManager *m_ndef;
|
const NodeDefManager *m_ndef;
|
||||||
BiomeManager *m_bmgr;
|
BiomeManager *m_bmgr;
|
||||||
|
|
||||||
|
BiomeGen *m_bmgn;
|
||||||
|
|
||||||
// configurable parameters
|
// configurable parameters
|
||||||
v3s16 m_csize;
|
v3s16 m_csize;
|
||||||
float m_cave_width;
|
float m_cave_width;
|
||||||
|
@ -636,6 +636,8 @@ void MapgenBasic::generateBiomes()
|
|||||||
|
|
||||||
noise_filler_depth->perlinMap2D(node_min.X, node_min.Z);
|
noise_filler_depth->perlinMap2D(node_min.X, node_min.Z);
|
||||||
|
|
||||||
|
s16 *biome_transitions = biomegen->getBiomeTransitions();
|
||||||
|
|
||||||
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;
|
||||||
@ -644,9 +646,11 @@ void MapgenBasic::generateBiomes()
|
|||||||
u16 base_filler = 0;
|
u16 base_filler = 0;
|
||||||
u16 depth_water_top = 0;
|
u16 depth_water_top = 0;
|
||||||
u16 depth_riverbed = 0;
|
u16 depth_riverbed = 0;
|
||||||
s16 biome_y_min = -MAX_MAP_GENERATION_LIMIT;
|
|
||||||
u32 vi = vm->m_area.index(x, node_max.Y, z);
|
u32 vi = vm->m_area.index(x, node_max.Y, z);
|
||||||
|
|
||||||
|
int cur_biome_depth = 0;
|
||||||
|
s16 biome_y_min = biome_transitions[cur_biome_depth];
|
||||||
|
|
||||||
// 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.
|
||||||
content_t c_above = vm->m_data[vi + em.X].getContent();
|
content_t c_above = vm->m_data[vi + em.X].getContent();
|
||||||
@ -675,9 +679,20 @@ void MapgenBasic::generateBiomes()
|
|||||||
(air_above || !biome || y < biome_y_min); // 2, 3, 4
|
(air_above || !biome || y < biome_y_min); // 2, 3, 4
|
||||||
|
|
||||||
if (is_stone_surface || is_water_surface) {
|
if (is_stone_surface || is_water_surface) {
|
||||||
|
if (!biome || y < biome_y_min) {
|
||||||
// (Re)calculate biome
|
// (Re)calculate biome
|
||||||
biome = biomegen->getBiomeAtIndex(index, v3s16(x, y, z));
|
biome = biomegen->getBiomeAtIndex(index, v3s16(x, y, z));
|
||||||
|
|
||||||
|
// Finding the height of the next biome
|
||||||
|
// On first iteration this may loop a couple times after than it should just run once
|
||||||
|
while (y < biome_y_min) {
|
||||||
|
biome_y_min = biome_transitions[++cur_biome_depth];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*if (x == node_min.X && z == node_min.Z)
|
||||||
|
printf("Map: check @ %i -> %s -> again at %i\n", y, biome->name.c_str(), biome_y_min);*/
|
||||||
|
}
|
||||||
|
|
||||||
// Add biome to biomemap at first stone surface detected
|
// Add biome to biomemap at first stone surface detected
|
||||||
if (biomemap[index] == BIOME_NONE && is_stone_surface)
|
if (biomemap[index] == BIOME_NONE && is_stone_surface)
|
||||||
biomemap[index] = biome->index;
|
biomemap[index] = biome->index;
|
||||||
@ -693,7 +708,6 @@ void MapgenBasic::generateBiomes()
|
|||||||
noise_filler_depth->result[index], 0.0f);
|
noise_filler_depth->result[index], 0.0f);
|
||||||
depth_water_top = biome->depth_water_top;
|
depth_water_top = biome->depth_water_top;
|
||||||
depth_riverbed = biome->depth_riverbed;
|
depth_riverbed = biome->depth_riverbed;
|
||||||
biome_y_min = biome->min_pos.Y;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c == c_stone) {
|
if (c == c_stone) {
|
||||||
@ -833,7 +847,7 @@ void MapgenBasic::generateCavesNoiseIntersection(s16 max_stone_y)
|
|||||||
if (node_min.Y > max_stone_y || cave_width >= 10.0f)
|
if (node_min.Y > max_stone_y || cave_width >= 10.0f)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CavesNoiseIntersection caves_noise(ndef, m_bmgr, csize,
|
CavesNoiseIntersection caves_noise(ndef, m_bmgr, biomegen, csize,
|
||||||
&np_cave1, &np_cave2, seed, cave_width);
|
&np_cave1, &np_cave2, seed, cave_width);
|
||||||
|
|
||||||
caves_noise.generateCaves(vm, node_min, node_max, biomemap);
|
caves_noise.generateCaves(vm, node_min, node_max, biomemap);
|
||||||
|
@ -147,18 +147,50 @@ BiomeGenOriginal::BiomeGenOriginal(BiomeManager *biomemgr,
|
|||||||
// fallback biome when biome generation (which calculates the biomemap IDs)
|
// fallback biome when biome generation (which calculates the biomemap IDs)
|
||||||
// is disabled.
|
// is disabled.
|
||||||
memset(biomemap, 0, sizeof(biome_t) * m_csize.X * m_csize.Z);
|
memset(biomemap, 0, sizeof(biome_t) * m_csize.X * m_csize.Z);
|
||||||
|
|
||||||
|
// Calculating the bounding position of each biome so we know when we might switch
|
||||||
|
// First gathering all heights where we might switch
|
||||||
|
std::vector<s16> temp_transition_heights;
|
||||||
|
temp_transition_heights.reserve(m_bmgr->getNumObjects() * 2);
|
||||||
|
for (size_t i = 0; i < m_bmgr->getNumObjects(); i++) {
|
||||||
|
Biome *b = (Biome *)m_bmgr->getRaw(i);
|
||||||
|
temp_transition_heights.push_back(b->max_pos.Y);
|
||||||
|
temp_transition_heights.push_back(b->min_pos.Y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sorting the biome transition points
|
||||||
|
std::sort(temp_transition_heights.begin(), temp_transition_heights.end(), std::greater<int>());
|
||||||
|
|
||||||
|
// Getting rid of duplicate biome transition points
|
||||||
|
s16 last = temp_transition_heights[0];
|
||||||
|
size_t out_pos = 1;
|
||||||
|
for (size_t i = 1; i < temp_transition_heights.size(); i++){
|
||||||
|
if (temp_transition_heights[i] != last) {
|
||||||
|
last = temp_transition_heights[i];
|
||||||
|
temp_transition_heights[out_pos++] = last;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
biome_transitions = new s16[out_pos];
|
||||||
|
memcpy(biome_transitions, temp_transition_heights.data(), sizeof(s16) * out_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
BiomeGenOriginal::~BiomeGenOriginal()
|
BiomeGenOriginal::~BiomeGenOriginal()
|
||||||
{
|
{
|
||||||
delete []biomemap;
|
delete []biomemap;
|
||||||
|
|
||||||
|
delete []biome_transitions;
|
||||||
delete noise_heat;
|
delete noise_heat;
|
||||||
delete noise_humidity;
|
delete noise_humidity;
|
||||||
delete noise_heat_blend;
|
delete noise_heat_blend;
|
||||||
delete noise_humidity_blend;
|
delete noise_humidity_blend;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s16* BiomeGenOriginal::getBiomeTransitions() const
|
||||||
|
{
|
||||||
|
return biome_transitions;
|
||||||
|
}
|
||||||
|
|
||||||
BiomeGen *BiomeGenOriginal::clone(BiomeManager *biomemgr) const
|
BiomeGen *BiomeGenOriginal::clone(BiomeManager *biomemgr) const
|
||||||
{
|
{
|
||||||
return new BiomeGenOriginal(biomemgr, m_params, m_csize);
|
return new BiomeGenOriginal(biomemgr, m_params, m_csize);
|
||||||
|
@ -128,8 +128,11 @@ public:
|
|||||||
// Same as above, but uses a raw numeric index correlating to the (x,z) position.
|
// Same as above, but uses a raw numeric index correlating to the (x,z) position.
|
||||||
virtual Biome *getBiomeAtIndex(size_t index, v3s16 pos) const = 0;
|
virtual Biome *getBiomeAtIndex(size_t index, v3s16 pos) const = 0;
|
||||||
|
|
||||||
|
virtual s16 *getBiomeTransitions() const = 0;
|
||||||
|
|
||||||
// Result of calcBiomes bulk computation.
|
// Result of calcBiomes bulk computation.
|
||||||
biome_t *biomemap = nullptr;
|
biome_t *biomemap = nullptr;
|
||||||
|
s16 *biome_transitions = nullptr;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
BiomeManager *m_bmgr = nullptr;
|
BiomeManager *m_bmgr = nullptr;
|
||||||
@ -186,6 +189,7 @@ public:
|
|||||||
Biome *getBiomeAtIndex(size_t index, v3s16 pos) const;
|
Biome *getBiomeAtIndex(size_t index, v3s16 pos) const;
|
||||||
|
|
||||||
Biome *calcBiomeFromNoise(float heat, float humidity, v3s16 pos) const;
|
Biome *calcBiomeFromNoise(float heat, float humidity, v3s16 pos) const;
|
||||||
|
s16 *getBiomeTransitions() const;
|
||||||
|
|
||||||
float *heatmap;
|
float *heatmap;
|
||||||
float *humidmap;
|
float *humidmap;
|
||||||
|
Loading…
Reference in New Issue
Block a user