3 Copyright (C) 2016-2019 Duane Robertson <duane@duanerobertson.com>
4 Copyright (C) 2016-2019 paramat
6 Based on Valleys Mapgen by Gael de Sailly
7 (https://forum.minetest.net/viewtopic.php?f=9&t=11430)
8 and mapgen_v7, mapgen_flat by kwolekr and paramat.
10 Licensing changed by permission of Gael de Sailly.
12 This program is free software; you can redistribute it and/or modify
13 it under the terms of the GNU Lesser General Public License as published by
14 the Free Software Foundation; either version 2.1 of the License, or
15 (at your option) any later version.
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU Lesser General Public License for more details.
22 You should have received a copy of the GNU Lesser General Public License along
23 with this program; if not, write to the Free Software Foundation, Inc.,
24 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
35 #include "voxelalgorithms.h"
36 //#include "profiler.h" // For TimeTaker
37 #include "settings.h" // For g_settings
39 #include "dungeongen.h"
42 #include "mg_decoration.h"
43 #include "mapgen_valleys.h"
48 FlagDesc flagdesc_mapgen_valleys[] = {
49 {"altitude_chill", MGVALLEYS_ALT_CHILL},
50 {"humid_rivers", MGVALLEYS_HUMID_RIVERS},
51 {"vary_river_depth", MGVALLEYS_VARY_RIVER_DEPTH},
52 {"altitude_dry", MGVALLEYS_ALT_DRY},
57 MapgenValleys::MapgenValleys(MapgenValleysParams *params, EmergeManager *emerge)
58 : MapgenBasic(MAPGEN_VALLEYS, params, emerge)
60 // NOTE: MapgenValleys has a hard dependency on BiomeGenOriginal
61 m_bgen = (BiomeGenOriginal *)biomegen;
63 spflags = params->spflags;
64 altitude_chill = params->altitude_chill;
65 river_depth_bed = params->river_depth + 1.0f;
66 river_size_factor = params->river_size / 100.0f;
68 cave_width = params->cave_width;
69 large_cave_depth = params->large_cave_depth;
70 small_cave_num_min = params->small_cave_num_min;
71 small_cave_num_max = params->small_cave_num_max;
72 large_cave_num_min = params->large_cave_num_min;
73 large_cave_num_max = params->large_cave_num_max;
74 large_cave_flooded = params->large_cave_flooded;
75 cavern_limit = params->cavern_limit;
76 cavern_taper = params->cavern_taper;
77 cavern_threshold = params->cavern_threshold;
78 dungeon_ymin = params->dungeon_ymin;
79 dungeon_ymax = params->dungeon_ymax;
82 noise_filler_depth = new Noise(¶ms->np_filler_depth, seed, csize.X, csize.Z);
83 noise_inter_valley_slope = new Noise(¶ms->np_inter_valley_slope, seed, csize.X, csize.Z);
84 noise_rivers = new Noise(¶ms->np_rivers, seed, csize.X, csize.Z);
85 noise_terrain_height = new Noise(¶ms->np_terrain_height, seed, csize.X, csize.Z);
86 noise_valley_depth = new Noise(¶ms->np_valley_depth, seed, csize.X, csize.Z);
87 noise_valley_profile = new Noise(¶ms->np_valley_profile, seed, csize.X, csize.Z);
90 // 1-up 1-down overgeneration
91 noise_inter_valley_fill = new Noise(¶ms->np_inter_valley_fill,
92 seed, csize.X, csize.Y + 2, csize.Z);
93 // 1-down overgeneraion
94 MapgenBasic::np_cave1 = params->np_cave1;
95 MapgenBasic::np_cave2 = params->np_cave2;
96 MapgenBasic::np_cavern = params->np_cavern;
97 MapgenBasic::np_dungeons = params->np_dungeons;
101 MapgenValleys::~MapgenValleys()
103 delete noise_filler_depth;
104 delete noise_inter_valley_fill;
105 delete noise_inter_valley_slope;
107 delete noise_terrain_height;
108 delete noise_valley_depth;
109 delete noise_valley_profile;
113 MapgenValleysParams::MapgenValleysParams():
114 np_filler_depth (0.0, 1.2, v3f(256, 256, 256), 1605, 3, 0.5, 2.0),
115 np_inter_valley_fill (0.0, 1.0, v3f(256, 512, 256), 1993, 6, 0.8, 2.0),
116 np_inter_valley_slope (0.5, 0.5, v3f(128, 128, 128), 746, 1, 1.0, 2.0),
117 np_rivers (0.0, 1.0, v3f(256, 256, 256), -6050, 5, 0.6, 2.0),
118 np_terrain_height (-10.0, 50.0, v3f(1024, 1024, 1024), 5202, 6, 0.4, 2.0),
119 np_valley_depth (5.0, 4.0, v3f(512, 512, 512), -1914, 1, 1.0, 2.0),
120 np_valley_profile (0.6, 0.50, v3f(512, 512, 512), 777, 1, 1.0, 2.0),
121 np_cave1 (0.0, 12.0, v3f(61, 61, 61), 52534, 3, 0.5, 2.0),
122 np_cave2 (0.0, 12.0, v3f(67, 67, 67), 10325, 3, 0.5, 2.0),
123 np_cavern (0.0, 1.0, v3f(768, 256, 768), 59033, 6, 0.63, 2.0),
124 np_dungeons (0.9, 0.5, v3f(500, 500, 500), 0, 2, 0.8, 2.0)
129 void MapgenValleysParams::readParams(const Settings *settings)
131 settings->getFlagStrNoEx("mgvalleys_spflags", spflags, flagdesc_mapgen_valleys);
132 settings->getU16NoEx("mgvalleys_altitude_chill", altitude_chill);
133 settings->getS16NoEx("mgvalleys_large_cave_depth", large_cave_depth);
134 settings->getU16NoEx("mgvalleys_small_cave_num_min", small_cave_num_min);
135 settings->getU16NoEx("mgvalleys_small_cave_num_max", small_cave_num_max);
136 settings->getU16NoEx("mgvalleys_large_cave_num_min", large_cave_num_min);
137 settings->getU16NoEx("mgvalleys_large_cave_num_max", large_cave_num_max);
138 settings->getFloatNoEx("mgvalleys_large_cave_flooded", large_cave_flooded);
139 settings->getU16NoEx("mgvalleys_river_depth", river_depth);
140 settings->getU16NoEx("mgvalleys_river_size", river_size);
141 settings->getFloatNoEx("mgvalleys_cave_width", cave_width);
142 settings->getS16NoEx("mgvalleys_cavern_limit", cavern_limit);
143 settings->getS16NoEx("mgvalleys_cavern_taper", cavern_taper);
144 settings->getFloatNoEx("mgvalleys_cavern_threshold", cavern_threshold);
145 settings->getS16NoEx("mgvalleys_dungeon_ymin", dungeon_ymin);
146 settings->getS16NoEx("mgvalleys_dungeon_ymax", dungeon_ymax);
148 settings->getNoiseParams("mgvalleys_np_filler_depth", np_filler_depth);
149 settings->getNoiseParams("mgvalleys_np_inter_valley_fill", np_inter_valley_fill);
150 settings->getNoiseParams("mgvalleys_np_inter_valley_slope", np_inter_valley_slope);
151 settings->getNoiseParams("mgvalleys_np_rivers", np_rivers);
152 settings->getNoiseParams("mgvalleys_np_terrain_height", np_terrain_height);
153 settings->getNoiseParams("mgvalleys_np_valley_depth", np_valley_depth);
154 settings->getNoiseParams("mgvalleys_np_valley_profile", np_valley_profile);
156 settings->getNoiseParams("mgvalleys_np_cave1", np_cave1);
157 settings->getNoiseParams("mgvalleys_np_cave2", np_cave2);
158 settings->getNoiseParams("mgvalleys_np_cavern", np_cavern);
159 settings->getNoiseParams("mgvalleys_np_dungeons", np_dungeons);
163 void MapgenValleysParams::writeParams(Settings *settings) const
165 settings->setFlagStr("mgvalleys_spflags", spflags, flagdesc_mapgen_valleys);
166 settings->setU16("mgvalleys_altitude_chill", altitude_chill);
167 settings->setS16("mgvalleys_large_cave_depth", large_cave_depth);
168 settings->setU16("mgvalleys_small_cave_num_min", small_cave_num_min);
169 settings->setU16("mgvalleys_small_cave_num_max", small_cave_num_max);
170 settings->setU16("mgvalleys_large_cave_num_min", large_cave_num_min);
171 settings->setU16("mgvalleys_large_cave_num_max", large_cave_num_max);
172 settings->setFloat("mgvalleys_large_cave_flooded", large_cave_flooded);
173 settings->setU16("mgvalleys_river_depth", river_depth);
174 settings->setU16("mgvalleys_river_size", river_size);
175 settings->setFloat("mgvalleys_cave_width", cave_width);
176 settings->setS16("mgvalleys_cavern_limit", cavern_limit);
177 settings->setS16("mgvalleys_cavern_taper", cavern_taper);
178 settings->setFloat("mgvalleys_cavern_threshold", cavern_threshold);
179 settings->setS16("mgvalleys_dungeon_ymin", dungeon_ymin);
180 settings->setS16("mgvalleys_dungeon_ymax", dungeon_ymax);
182 settings->setNoiseParams("mgvalleys_np_filler_depth", np_filler_depth);
183 settings->setNoiseParams("mgvalleys_np_inter_valley_fill", np_inter_valley_fill);
184 settings->setNoiseParams("mgvalleys_np_inter_valley_slope", np_inter_valley_slope);
185 settings->setNoiseParams("mgvalleys_np_rivers", np_rivers);
186 settings->setNoiseParams("mgvalleys_np_terrain_height", np_terrain_height);
187 settings->setNoiseParams("mgvalleys_np_valley_depth", np_valley_depth);
188 settings->setNoiseParams("mgvalleys_np_valley_profile", np_valley_profile);
190 settings->setNoiseParams("mgvalleys_np_cave1", np_cave1);
191 settings->setNoiseParams("mgvalleys_np_cave2", np_cave2);
192 settings->setNoiseParams("mgvalleys_np_cavern", np_cavern);
193 settings->setNoiseParams("mgvalleys_np_dungeons", np_dungeons);
197 void MapgenValleysParams::setDefaultSettings(Settings *settings)
199 settings->setDefault("mgvalleys_spflags", flagdesc_mapgen_valleys,
200 MGVALLEYS_ALT_CHILL | MGVALLEYS_HUMID_RIVERS |
201 MGVALLEYS_VARY_RIVER_DEPTH | MGVALLEYS_ALT_DRY);
205 /////////////////////////////////////////////////////////////////
208 void MapgenValleys::makeChunk(BlockMakeData *data)
211 assert(data->vmanip);
212 assert(data->nodedef);
213 assert(data->blockpos_requested.X >= data->blockpos_min.X &&
214 data->blockpos_requested.Y >= data->blockpos_min.Y &&
215 data->blockpos_requested.Z >= data->blockpos_min.Z);
216 assert(data->blockpos_requested.X <= data->blockpos_max.X &&
217 data->blockpos_requested.Y <= data->blockpos_max.Y &&
218 data->blockpos_requested.Z <= data->blockpos_max.Z);
220 //TimeTaker t("makeChunk");
222 this->generating = true;
223 this->vm = data->vmanip;
224 this->ndef = data->nodedef;
226 v3s16 blockpos_min = data->blockpos_min;
227 v3s16 blockpos_max = data->blockpos_max;
228 node_min = blockpos_min * MAP_BLOCKSIZE;
229 node_max = (blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
230 full_node_min = (blockpos_min - 1) * MAP_BLOCKSIZE;
231 full_node_max = (blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
233 blockseed = getBlockSeed2(full_node_min, seed);
235 // Generate biome noises. Note this must be executed strictly before
236 // generateTerrain, because generateTerrain depends on intermediate
237 // biome-related noises.
238 m_bgen->calcBiomeNoise(node_min);
241 s16 stone_surface_max_y = generateTerrain();
244 updateHeightmap(node_min, node_max);
246 // Place biome-specific nodes and build biomemap
247 if (flags & MG_BIOMES) {
251 // Generate tunnels, caverns and large randomwalk caves
252 if (flags & MG_CAVES) {
253 // Generate tunnels first as caverns confuse them
254 generateCavesNoiseIntersection(stone_surface_max_y);
257 bool near_cavern = generateCavernsNoise(stone_surface_max_y);
259 // Generate large randomwalk caves
261 // Disable large randomwalk caves in this mapchunk by setting
262 // 'large cave depth' to world base. Avoids excessive liquid in
263 // large caverns and floating blobs of overgenerated liquid.
264 generateCavesRandomWalk(stone_surface_max_y,
265 -MAX_MAP_GENERATION_LIMIT);
267 generateCavesRandomWalk(stone_surface_max_y, large_cave_depth);
270 // Generate the registered ores
271 m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
274 if (flags & MG_DUNGEONS)
275 generateDungeons(stone_surface_max_y);
277 // Generate the registered decorations
278 if (flags & MG_DECORATIONS)
279 m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);
281 // Sprinkle some dust on top after everything else was generated
282 if (flags & MG_BIOMES)
285 updateLiquid(&data->transforming_liquid, full_node_min, full_node_max);
287 if (flags & MG_LIGHT)
288 calcLighting(node_min - v3s16(0, 1, 0), node_max + v3s16(0, 1, 0),
289 full_node_min, full_node_max);
291 this->generating = false;
293 //printf("makeChunk: %lums\n", t.stop());
297 int MapgenValleys::getSpawnLevelAtPoint(v2s16 p)
299 // Check if in a river channel
300 float n_rivers = NoisePerlin2D(&noise_rivers->np, p.X, p.Y, seed);
301 if (std::fabs(n_rivers) <= river_size_factor)
302 // Unsuitable spawn point
303 return MAX_MAP_GENERATION_LIMIT;
305 float n_slope = NoisePerlin2D(&noise_inter_valley_slope->np, p.X, p.Y, seed);
306 float n_terrain_height = NoisePerlin2D(&noise_terrain_height->np, p.X, p.Y, seed);
307 float n_valley = NoisePerlin2D(&noise_valley_depth->np, p.X, p.Y, seed);
308 float n_valley_profile = NoisePerlin2D(&noise_valley_profile->np, p.X, p.Y, seed);
310 float valley_d = n_valley * n_valley;
311 float base = n_terrain_height + valley_d;
312 float river = std::fabs(n_rivers) - river_size_factor;
313 float tv = std::fmax(river / n_valley_profile, 0.0f);
314 float valley_h = valley_d * (1.0f - std::exp(-tv * tv));
315 float surface_y = base + valley_h;
316 float slope = n_slope * valley_h;
317 float river_y = base - 1.0f;
319 // Raising the maximum spawn level above 'water_level + 16' is necessary for custom
320 // parameters that set average terrain level much higher than water_level.
321 s16 max_spawn_y = std::fmax(
322 noise_terrain_height->np.offset +
323 noise_valley_depth->np.offset * noise_valley_depth->np.offset,
326 // Starting spawn search at max_spawn_y + 128 ensures 128 nodes of open
327 // space above spawn position. Avoids spawning in possibly sealed voids.
328 for (s16 y = max_spawn_y + 128; y >= water_level; y--) {
329 float n_fill = NoisePerlin3D(&noise_inter_valley_fill->np, p.X, y, p.Y, seed);
330 float surface_delta = (float)y - surface_y;
331 float density = slope * n_fill - surface_delta;
333 if (density > 0.0f) { // If solid
334 // Sometimes surface level is below river water level in places that are not
336 if (y < water_level || y > max_spawn_y || y < (s16)river_y)
337 // Unsuitable spawn point
338 return MAX_MAP_GENERATION_LIMIT;
340 // y + 2 because y is surface and due to biome 'dust' nodes.
344 // Unsuitable spawn position, no ground found
345 return MAX_MAP_GENERATION_LIMIT;
349 int MapgenValleys::generateTerrain()
351 MapNode n_air(CONTENT_AIR);
352 MapNode n_river_water(c_river_water_source);
353 MapNode n_stone(c_stone);
354 MapNode n_water(c_water_source);
356 noise_inter_valley_slope->perlinMap2D(node_min.X, node_min.Z);
357 noise_rivers->perlinMap2D(node_min.X, node_min.Z);
358 noise_terrain_height->perlinMap2D(node_min.X, node_min.Z);
359 noise_valley_depth->perlinMap2D(node_min.X, node_min.Z);
360 noise_valley_profile->perlinMap2D(node_min.X, node_min.Z);
362 noise_inter_valley_fill->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
364 const v3s16 &em = vm->m_area.getExtent();
365 s16 surface_max_y = -MAX_MAP_GENERATION_LIMIT;
368 for (s16 z = node_min.Z; z <= node_max.Z; z++)
369 for (s16 x = node_min.X; x <= node_max.X; x++, index_2d++) {
370 float n_slope = noise_inter_valley_slope->result[index_2d];
371 float n_rivers = noise_rivers->result[index_2d];
372 float n_terrain_height = noise_terrain_height->result[index_2d];
373 float n_valley = noise_valley_depth->result[index_2d];
374 float n_valley_profile = noise_valley_profile->result[index_2d];
376 float valley_d = n_valley * n_valley;
377 // 'base' represents the level of the river banks
378 float base = n_terrain_height + valley_d;
379 // 'river' represents the distance from the river edge
380 float river = std::fabs(n_rivers) - river_size_factor;
381 // Use the curve of the function 1-exp(-(x/a)^2) to model valleys.
382 // 'valley_h' represents the height of the terrain, from the rivers.
383 float tv = std::fmax(river / n_valley_profile, 0.0f);
384 float valley_h = valley_d * (1.0f - std::exp(-tv * tv));
385 // Approximate height of the terrain
386 float surface_y = base + valley_h;
387 float slope = n_slope * valley_h;
388 // River water surface is 1 node below river banks
389 float river_y = base - 1.0f;
391 // Rivers are placed where 'river' is negative
393 // Use the the function -sqrt(1-x^2) which models a circle
394 float tr = river / river_size_factor + 1.0f;
395 float depth = (river_depth_bed *
396 std::sqrt(std::fmax(0.0f, 1.0f - tr * tr)));
397 // There is no logical equivalent to this using rangelim
398 surface_y = std::fmin(
399 std::fmax(base - depth, (float)(water_level - 3)),
404 // Optionally vary river depth according to heat and humidity
405 if (spflags & MGVALLEYS_VARY_RIVER_DEPTH) {
406 float t_heat = m_bgen->heatmap[index_2d];
407 float heat = (spflags & MGVALLEYS_ALT_CHILL) ?
408 // Match heat value calculated below in
409 // 'Optionally decrease heat with altitude'.
410 // In rivers, 'ground height ignoring riverbeds' is 'base'.
411 // As this only affects river water we can assume y > water_level.
412 t_heat + 5.0f - (base - water_level) * 20.0f / altitude_chill :
414 float delta = m_bgen->humidmap[index_2d] - 50.0f;
416 float t_evap = (heat - 32.0f) / 300.0f;
417 river_y += delta * std::fmax(t_evap, 0.08f);
421 // Highest solid node in column
422 s16 column_max_y = surface_y;
423 u32 index_3d = (z - node_min.Z) * zstride_1u1d + (x - node_min.X);
424 u32 index_data = vm->m_area.index(x, node_min.Y - 1, z);
426 for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
427 if (vm->m_data[index_data].getContent() == CONTENT_IGNORE) {
428 float n_fill = noise_inter_valley_fill->result[index_3d];
429 float surface_delta = (float)y - surface_y;
430 // Density = density noise + density gradient
431 float density = slope * n_fill - surface_delta;
433 if (density > 0.0f) {
434 vm->m_data[index_data] = n_stone; // Stone
435 if (y > surface_max_y)
437 if (y > column_max_y)
439 } else if (y <= water_level) {
440 vm->m_data[index_data] = n_water; // Water
441 } else if (y <= (s16)river_y) {
442 vm->m_data[index_data] = n_river_water; // River water
444 vm->m_data[index_data] = n_air; // Air
448 VoxelArea::add_y(em, index_data, 1);
452 // Optionally increase humidity around rivers
453 if (spflags & MGVALLEYS_HUMID_RIVERS) {
454 // Compensate to avoid increasing average humidity
455 m_bgen->humidmap[index_2d] *= 0.8f;
456 // Ground height ignoring riverbeds
457 float t_alt = std::fmax(base, (float)column_max_y);
458 float water_depth = (t_alt - base) / 4.0f;
459 m_bgen->humidmap[index_2d] *=
460 1.0f + std::pow(0.5f, std::fmax(water_depth, 1.0f));
463 // Optionally decrease humidity with altitude
464 if (spflags & MGVALLEYS_ALT_DRY) {
465 // Ground height ignoring riverbeds
466 float t_alt = std::fmax(base, (float)column_max_y);
467 // Only decrease above water_level
468 if (t_alt > water_level)
469 m_bgen->humidmap[index_2d] -=
470 (t_alt - water_level) * 10.0f / altitude_chill;
473 // Optionally decrease heat with altitude
474 if (spflags & MGVALLEYS_ALT_CHILL) {
475 // Compensate to avoid reducing the average heat
476 m_bgen->heatmap[index_2d] += 5.0f;
477 // Ground height ignoring riverbeds
478 float t_alt = std::fmax(base, (float)column_max_y);
479 // Only decrease above water_level
480 if (t_alt > water_level)
481 m_bgen->heatmap[index_2d] -=
482 (t_alt - water_level) * 20.0f / altitude_chill;
486 return surface_max_y;