From 3af226cb0644e0a9b93a6892642470a308367da0 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Fri, 6 Sep 2024 11:30:10 +0200 Subject: [PATCH] Refactor "Cavegen y biome check" --- src/mapgen/cavegen.cpp | 16 +++++----------- src/mapgen/mapgen.cpp | 15 ++------------- src/mapgen/mg_biome.cpp | 35 ++++++++++++----------------------- src/mapgen/mg_biome.h | 14 ++++++++++---- 4 files changed, 29 insertions(+), 51 deletions(-) diff --git a/src/mapgen/cavegen.cpp b/src/mapgen/cavegen.cpp index 47272142f..e6ab66980 100644 --- a/src/mapgen/cavegen.cpp +++ b/src/mapgen/cavegen.cpp @@ -82,8 +82,6 @@ void CavesNoiseIntersection::generateCaves(MMVManip *vm, const v3s16 &em = vm->m_area.getExtent(); u32 index2d = 0; // Biomemap index - s16 *biome_transitions = m_bmgn->getBiomeTransitions(); - for (s16 z = nmin.Z; z <= nmax.Z; z++) for (s16 x = nmin.X; x <= nmax.X; x++, index2d++) { bool column_is_open = false; // Is column open to overground @@ -101,8 +99,7 @@ void CavesNoiseIntersection::generateCaves(MMVManip *vm, u16 depth_riverbed = biome->depth_riverbed; u16 nplaced = 0; - int cur_biome_depth = 0; - s16 biome_y_min = biome_transitions[cur_biome_depth]; + s16 biome_y_min = m_bmgn->getNextTransitionY(nmax.Y); // Don't excavate the overgenerated stone at nmax.Y + 1, // this creates a 'roof' over the tunnel, preventing light in @@ -114,15 +111,12 @@ void CavesNoiseIntersection::generateCaves(MMVManip *vm, // 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)); + biome_y_min = m_bmgn->getNextTransitionY(y); - // 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 && false) { + dstream << "cavegen: biome at " << y << " is " << biome->name + << ", next at " << biome_y_min << std::endl; } - - /*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(); diff --git a/src/mapgen/mapgen.cpp b/src/mapgen/mapgen.cpp index 80ffebc9e..0b821e02e 100644 --- a/src/mapgen/mapgen.cpp +++ b/src/mapgen/mapgen.cpp @@ -649,8 +649,6 @@ void MapgenBasic::generateBiomes() 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 x = node_min.X; x <= node_max.X; x++, index++) { Biome *biome = NULL; @@ -661,8 +659,7 @@ void MapgenBasic::generateBiomes() u16 depth_riverbed = 0; 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]; + s16 biome_y_min = biomegen->getNextTransitionY(node_max.Y); // Check node at base of mapchunk above, either a node of a previously // generated mapchunk or if not, a node of overgenerated base terrain. @@ -695,15 +692,7 @@ void MapgenBasic::generateBiomes() if (!biome || y < biome_y_min) { // (Re)calculate biome 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);*/ + biome_y_min = biomegen->getNextTransitionY(y); } // Add biome to biomemap at first stone surface detected diff --git a/src/mapgen/mg_biome.cpp b/src/mapgen/mg_biome.cpp index 83ecbd691..b270a5413 100644 --- a/src/mapgen/mg_biome.cpp +++ b/src/mapgen/mg_biome.cpp @@ -149,47 +149,36 @@ BiomeGenOriginal::BiomeGenOriginal(BiomeManager *biomemgr, // is disabled. 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 temp_transition_heights; - temp_transition_heights.reserve(m_bmgr->getNumObjects() * 2); + // Calculate cache of Y transition points + std::vector values; + values.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); + values.push_back(b->max_pos.Y); + values.push_back(b->min_pos.Y); } - // Sorting the biome transition points - std::sort(temp_transition_heights.begin(), temp_transition_heights.end(), std::greater()); + std::sort(values.begin(), values.end(), std::greater<>()); + values.erase(std::unique(values.begin(), values.end()), values.end()); - // 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); + m_transitions_y = std::move(values); } BiomeGenOriginal::~BiomeGenOriginal() { delete []biomemap; - delete []biome_transitions; delete noise_heat; delete noise_humidity; delete noise_heat_blend; delete noise_humidity_blend; } -s16* BiomeGenOriginal::getBiomeTransitions() const +s16 BiomeGenOriginal::getNextTransitionY(s16 y) const { - return biome_transitions; + // Find first value that is less than y using binary search + auto it = std::lower_bound(m_transitions_y.begin(), m_transitions_y.end(), y, std::greater_equal<>()); + return (it == m_transitions_y.end()) ? S16_MIN : *it; } BiomeGen *BiomeGenOriginal::clone(BiomeManager *biomemgr) const diff --git a/src/mapgen/mg_biome.h b/src/mapgen/mg_biome.h index 567a0fe81..389b36ee9 100644 --- a/src/mapgen/mg_biome.h +++ b/src/mapgen/mg_biome.h @@ -128,11 +128,14 @@ public: // 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 s16 *getBiomeTransitions() const = 0; + // Returns the next lower y position at which the biome could change. + // You can use this to optimize calls to getBiomeAtIndex(). + virtual s16 getNextTransitionY(s16 y) const { + return y == S16_MIN ? y : (y - 1); + }; // Result of calcBiomes bulk computation. biome_t *biomemap = nullptr; - s16 *biome_transitions = nullptr; protected: BiomeManager *m_bmgr = nullptr; @@ -167,7 +170,7 @@ struct BiomeParamsOriginal : public BiomeParams { NoiseParams np_humidity_blend; }; -class BiomeGenOriginal : public BiomeGen { +class BiomeGenOriginal final : public BiomeGen { public: BiomeGenOriginal(BiomeManager *biomemgr, const BiomeParamsOriginal *params, v3s16 chunksize); @@ -189,7 +192,7 @@ public: Biome *getBiomeAtIndex(size_t index, v3s16 pos) const; Biome *calcBiomeFromNoise(float heat, float humidity, v3s16 pos) const; - s16 *getBiomeTransitions() const; + s16 getNextTransitionY(s16 y) const; float *heatmap; float *humidmap; @@ -201,6 +204,9 @@ private: Noise *noise_humidity; Noise *noise_heat_blend; Noise *noise_humidity_blend; + + // ordered descending + std::vector m_transitions_y; };