Skip to content

Commit 872dce5

Browse files
authoredNov 20, 2020
Move Mapgen V7 river generation into the main generation loop (#10639)
All terrain generation now occurs in one loop, instead of rivers being carved afterwards in a separate loop. Fixes the removal of nodes added by mods in 'register on generated'. Avoids other problems and reduces the chance of future bugs. Mapchunk generation time is reduced. Also fixes a code mistake which resulted in river channel generation being disabled at floatland altitudes even when floatlands were disabled.
1 parent 2f6393f commit 872dce5

File tree

2 files changed

+32
-49
lines changed

2 files changed

+32
-49
lines changed
 

Diff for: ‎src/mapgen/mapgen_v7.cpp

+31-48
Original file line numberDiff line numberDiff line change
@@ -342,10 +342,6 @@ void MapgenV7::makeChunk(BlockMakeData *data)
342342
// Generate base and mountain terrain
343343
s16 stone_surface_max_y = generateTerrain();
344344

345-
// Generate rivers
346-
if (spflags & MGV7_RIDGES)
347-
generateRidgeTerrain();
348-
349345
// Create heightmap
350346
updateHeightmap(node_min, node_max);
351347

@@ -467,6 +463,23 @@ bool MapgenV7::getMountainTerrainFromMap(int idx_xyz, int idx_xz, s16 y)
467463
}
468464

469465

466+
bool MapgenV7::getRiverChannelFromMap(int idx_xyz, int idx_xz, s16 y)
467+
{
468+
// Maximum width of river channel. Creates the vertical canyon walls
469+
float width = 0.2f;
470+
float absuwatern = std::fabs(noise_ridge_uwater->result[idx_xz]) * 2.0f;
471+
if (absuwatern > width)
472+
return false;
473+
474+
float altitude = y - water_level;
475+
float height_mod = (altitude + 17.0f) / 2.5f;
476+
float width_mod = width - absuwatern;
477+
float nridge = noise_ridge->result[idx_xyz] * std::fmax(altitude, 0.0f) / 7.0f;
478+
479+
return nridge + width_mod * height_mod >= 0.6f;
480+
}
481+
482+
470483
bool MapgenV7::getFloatlandTerrainFromMap(int idx_xyz, float float_offset)
471484
{
472485
return noise_floatland->result[idx_xyz] + floatland_density - float_offset >= 0.0f;
@@ -521,6 +534,15 @@ int MapgenV7::generateTerrain()
521534
}
522535
}
523536

537+
// 'Generate rivers in this mapchunk' bool for
538+
// simplification of condition checks in y-loop.
539+
bool gen_rivers = (spflags & MGV7_RIDGES) && node_max.Y >= water_level - 16 &&
540+
!gen_floatlands;
541+
if (gen_rivers) {
542+
noise_ridge->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
543+
noise_ridge_uwater->perlinMap2D(node_min.X, node_min.Z);
544+
}
545+
524546
//// Place nodes
525547
const v3s16 &em = vm->m_area.getExtent();
526548
s16 stone_surface_max_y = -MAX_MAP_GENERATION_LIMIT;
@@ -544,10 +566,13 @@ int MapgenV7::generateTerrain()
544566
if (vm->m_data[vi].getContent() != CONTENT_IGNORE)
545567
continue;
546568

547-
if (y <= surface_y) {
569+
bool is_river_channel = gen_rivers &&
570+
getRiverChannelFromMap(index3d, index2d, y);
571+
if (y <= surface_y && !is_river_channel) {
548572
vm->m_data[vi] = n_stone; // Base terrain
549573
} else if ((spflags & MGV7_MOUNTAINS) &&
550-
getMountainTerrainFromMap(index3d, index2d, y)) {
574+
getMountainTerrainFromMap(index3d, index2d, y) &&
575+
!is_river_channel) {
551576
vm->m_data[vi] = n_stone; // Mountain terrain
552577
if (y > stone_surface_max_y)
553578
stone_surface_max_y = y;
@@ -569,45 +594,3 @@ int MapgenV7::generateTerrain()
569594

570595
return stone_surface_max_y;
571596
}
572-
573-
574-
void MapgenV7::generateRidgeTerrain()
575-
{
576-
if (node_max.Y < water_level - 16 ||
577-
(node_max.Y >= floatland_ymin && node_min.Y <= floatland_ymax))
578-
return;
579-
580-
noise_ridge->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
581-
noise_ridge_uwater->perlinMap2D(node_min.X, node_min.Z);
582-
583-
MapNode n_water(c_water_source);
584-
MapNode n_air(CONTENT_AIR);
585-
u32 index3d = 0;
586-
float width = 0.2f;
587-
588-
for (s16 z = node_min.Z; z <= node_max.Z; z++)
589-
for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
590-
u32 vi = vm->m_area.index(node_min.X, y, z);
591-
for (s16 x = node_min.X; x <= node_max.X; x++, index3d++, vi++) {
592-
u32 index2d = (z - node_min.Z) * csize.X + (x - node_min.X);
593-
float uwatern = noise_ridge_uwater->result[index2d] * 2.0f;
594-
if (std::fabs(uwatern) > width)
595-
continue;
596-
// Optimises, but also avoids removing nodes placed by mods in
597-
// 'on-generated', when generating outside mapchunk.
598-
content_t c = vm->m_data[vi].getContent();
599-
if (c != c_stone)
600-
continue;
601-
602-
float altitude = y - water_level;
603-
float height_mod = (altitude + 17.0f) / 2.5f;
604-
float width_mod = width - std::fabs(uwatern);
605-
float nridge = noise_ridge->result[index3d] *
606-
std::fmax(altitude, 0.0f) / 7.0f;
607-
if (nridge + width_mod * height_mod < 0.6f)
608-
continue;
609-
610-
vm->m_data[vi] = (y > water_level) ? n_air : n_water;
611-
}
612-
}
613-
}

Diff for: ‎src/mapgen/mapgen_v7.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,10 @@ class MapgenV7 : public MapgenBasic {
9494
float baseTerrainLevelFromMap(int index);
9595
bool getMountainTerrainAtPoint(s16 x, s16 y, s16 z);
9696
bool getMountainTerrainFromMap(int idx_xyz, int idx_xz, s16 y);
97+
bool getRiverChannelFromMap(int idx_xyz, int idx_xz, s16 y);
9798
bool getFloatlandTerrainFromMap(int idx_xyz, float float_offset);
9899

99100
int generateTerrain();
100-
void generateRidgeTerrain();
101101

102102
private:
103103
s16 mount_zero_level;

0 commit comments

Comments
 (0)
Please sign in to comment.