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, U32_MAX);
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 MapgenValleys::makeChunk(BlockMakeData *data)
200 assert(data->vmanip);
201 assert(data->nodedef);
202 assert(data->blockpos_requested.X >= data->blockpos_min.X &&
203 data->blockpos_requested.Y >= data->blockpos_min.Y &&
204 data->blockpos_requested.Z >= data->blockpos_min.Z);
205 assert(data->blockpos_requested.X <= data->blockpos_max.X &&
206 data->blockpos_requested.Y <= data->blockpos_max.Y &&
207 data->blockpos_requested.Z <= data->blockpos_max.Z);
209 //TimeTaker t("makeChunk");
211 this->generating = true;
212 this->vm = data->vmanip;
213 this->ndef = data->nodedef;
215 v3s16 blockpos_min = data->blockpos_min;
216 v3s16 blockpos_max = data->blockpos_max;
217 node_min = blockpos_min * MAP_BLOCKSIZE;
218 node_max = (blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
219 full_node_min = (blockpos_min - 1) * MAP_BLOCKSIZE;
220 full_node_max = (blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
222 blockseed = getBlockSeed2(full_node_min, seed);
224 // Generate biome noises. Note this must be executed strictly before
225 // generateTerrain, because generateTerrain depends on intermediate
226 // biome-related noises.
227 m_bgen->calcBiomeNoise(node_min);
230 s16 stone_surface_max_y = generateTerrain();
233 updateHeightmap(node_min, node_max);
235 // Place biome-specific nodes and build biomemap
236 if (flags & MG_BIOMES) {
240 // Generate tunnels, caverns and large randomwalk caves
241 if (flags & MG_CAVES) {
242 // Generate tunnels first as caverns confuse them
243 generateCavesNoiseIntersection(stone_surface_max_y);
246 bool near_cavern = generateCavernsNoise(stone_surface_max_y);
248 // Generate large randomwalk caves
250 // Disable large randomwalk caves in this mapchunk by setting
251 // 'large cave depth' to world base. Avoids excessive liquid in
252 // large caverns and floating blobs of overgenerated liquid.
253 generateCavesRandomWalk(stone_surface_max_y,
254 -MAX_MAP_GENERATION_LIMIT);
256 generateCavesRandomWalk(stone_surface_max_y, large_cave_depth);
259 // Generate the registered ores
260 m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
263 if (flags & MG_DUNGEONS)
264 generateDungeons(stone_surface_max_y);
266 // Generate the registered decorations
267 if (flags & MG_DECORATIONS)
268 m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);
270 // Sprinkle some dust on top after everything else was generated
271 if (flags & MG_BIOMES)
274 updateLiquid(&data->transforming_liquid, full_node_min, full_node_max);
276 if (flags & MG_LIGHT)
277 calcLighting(node_min - v3s16(0, 1, 0), node_max + v3s16(0, 1, 0),
278 full_node_min, full_node_max);
280 this->generating = false;
282 //printf("makeChunk: %lums\n", t.stop());
286 int MapgenValleys::getSpawnLevelAtPoint(v2s16 p)
288 // Check if in a river channel
289 float n_rivers = NoisePerlin2D(&noise_rivers->np, p.X, p.Y, seed);
290 if (std::fabs(n_rivers) <= river_size_factor)
291 // Unsuitable spawn point
292 return MAX_MAP_GENERATION_LIMIT;
294 float n_slope = NoisePerlin2D(&noise_inter_valley_slope->np, p.X, p.Y, seed);
295 float n_terrain_height = NoisePerlin2D(&noise_terrain_height->np, p.X, p.Y, seed);
296 float n_valley = NoisePerlin2D(&noise_valley_depth->np, p.X, p.Y, seed);
297 float n_valley_profile = NoisePerlin2D(&noise_valley_profile->np, p.X, p.Y, seed);
299 float valley_d = n_valley * n_valley;
300 float base = n_terrain_height + valley_d;
301 float river = std::fabs(n_rivers) - river_size_factor;
302 float tv = std::fmax(river / n_valley_profile, 0.0f);
303 float valley_h = valley_d * (1.0f - std::exp(-tv * tv));
304 float surface_y = base + valley_h;
305 float slope = n_slope * valley_h;
306 float river_y = base - 1.0f;
308 // Raising the maximum spawn level above 'water_level + 16' is necessary for custom
309 // parameters that set average terrain level much higher than water_level.
310 s16 max_spawn_y = std::fmax(
311 noise_terrain_height->np.offset +
312 noise_valley_depth->np.offset * noise_valley_depth->np.offset,
315 // Starting spawn search at max_spawn_y + 128 ensures 128 nodes of open
316 // space above spawn position. Avoids spawning in possibly sealed voids.
317 for (s16 y = max_spawn_y + 128; y >= water_level; y--) {
318 float n_fill = NoisePerlin3D(&noise_inter_valley_fill->np, p.X, y, p.Y, seed);
319 float surface_delta = (float)y - surface_y;
320 float density = slope * n_fill - surface_delta;
322 if (density > 0.0f) { // If solid
323 // Sometimes surface level is below river water level in places that are not
325 if (y < water_level || y > max_spawn_y || y < (s16)river_y)
326 // Unsuitable spawn point
327 return MAX_MAP_GENERATION_LIMIT;
329 // y + 2 because y is surface and due to biome 'dust' nodes.
333 // Unsuitable spawn position, no ground found
334 return MAX_MAP_GENERATION_LIMIT;
338 int MapgenValleys::generateTerrain()
340 MapNode n_air(CONTENT_AIR);
341 MapNode n_river_water(c_river_water_source);
342 MapNode n_stone(c_stone);
343 MapNode n_water(c_water_source);
345 noise_inter_valley_slope->perlinMap2D(node_min.X, node_min.Z);
346 noise_rivers->perlinMap2D(node_min.X, node_min.Z);
347 noise_terrain_height->perlinMap2D(node_min.X, node_min.Z);
348 noise_valley_depth->perlinMap2D(node_min.X, node_min.Z);
349 noise_valley_profile->perlinMap2D(node_min.X, node_min.Z);
351 noise_inter_valley_fill->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
353 const v3s16 &em = vm->m_area.getExtent();
354 s16 surface_max_y = -MAX_MAP_GENERATION_LIMIT;
357 for (s16 z = node_min.Z; z <= node_max.Z; z++)
358 for (s16 x = node_min.X; x <= node_max.X; x++, index_2d++) {
359 float n_slope = noise_inter_valley_slope->result[index_2d];
360 float n_rivers = noise_rivers->result[index_2d];
361 float n_terrain_height = noise_terrain_height->result[index_2d];
362 float n_valley = noise_valley_depth->result[index_2d];
363 float n_valley_profile = noise_valley_profile->result[index_2d];
365 float valley_d = n_valley * n_valley;
366 // 'base' represents the level of the river banks
367 float base = n_terrain_height + valley_d;
368 // 'river' represents the distance from the river edge
369 float river = std::fabs(n_rivers) - river_size_factor;
370 // Use the curve of the function 1-exp(-(x/a)^2) to model valleys.
371 // 'valley_h' represents the height of the terrain, from the rivers.
372 float tv = std::fmax(river / n_valley_profile, 0.0f);
373 float valley_h = valley_d * (1.0f - std::exp(-tv * tv));
374 // Approximate height of the terrain
375 float surface_y = base + valley_h;
376 float slope = n_slope * valley_h;
377 // River water surface is 1 node below river banks
378 float river_y = base - 1.0f;
380 // Rivers are placed where 'river' is negative
382 // Use the the function -sqrt(1-x^2) which models a circle
383 float tr = river / river_size_factor + 1.0f;
384 float depth = (river_depth_bed *
385 std::sqrt(std::fmax(0.0f, 1.0f - tr * tr)));
386 // There is no logical equivalent to this using rangelim
387 surface_y = std::fmin(
388 std::fmax(base - depth, (float)(water_level - 3)),
393 // Optionally vary river depth according to heat and humidity
394 if (spflags & MGVALLEYS_VARY_RIVER_DEPTH) {
395 float t_heat = m_bgen->heatmap[index_2d];
396 float heat = (spflags & MGVALLEYS_ALT_CHILL) ?
397 // Match heat value calculated below in
398 // 'Optionally decrease heat with altitude'.
399 // In rivers, 'ground height ignoring riverbeds' is 'base'.
400 // As this only affects river water we can assume y > water_level.
401 t_heat + 5.0f - (base - water_level) * 20.0f / altitude_chill :
403 float delta = m_bgen->humidmap[index_2d] - 50.0f;
405 float t_evap = (heat - 32.0f) / 300.0f;
406 river_y += delta * std::fmax(t_evap, 0.08f);
410 // Highest solid node in column
411 s16 column_max_y = surface_y;
412 u32 index_3d = (z - node_min.Z) * zstride_1u1d + (x - node_min.X);
413 u32 index_data = vm->m_area.index(x, node_min.Y - 1, z);
415 for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
416 if (vm->m_data[index_data].getContent() == CONTENT_IGNORE) {
417 float n_fill = noise_inter_valley_fill->result[index_3d];
418 float surface_delta = (float)y - surface_y;
419 // Density = density noise + density gradient
420 float density = slope * n_fill - surface_delta;
422 if (density > 0.0f) {
423 vm->m_data[index_data] = n_stone; // Stone
424 if (y > surface_max_y)
426 if (y > column_max_y)
428 } else if (y <= water_level) {
429 vm->m_data[index_data] = n_water; // Water
430 } else if (y <= (s16)river_y) {
431 vm->m_data[index_data] = n_river_water; // River water
433 vm->m_data[index_data] = n_air; // Air
437 VoxelArea::add_y(em, index_data, 1);
441 // Optionally increase humidity around rivers
442 if (spflags & MGVALLEYS_HUMID_RIVERS) {
443 // Compensate to avoid increasing average humidity
444 m_bgen->humidmap[index_2d] *= 0.8f;
445 // Ground height ignoring riverbeds
446 float t_alt = std::fmax(base, (float)column_max_y);
447 float water_depth = (t_alt - base) / 4.0f;
448 m_bgen->humidmap[index_2d] *=
449 1.0f + std::pow(0.5f, std::fmax(water_depth, 1.0f));
452 // Optionally decrease humidity with altitude
453 if (spflags & MGVALLEYS_ALT_DRY) {
454 // Ground height ignoring riverbeds
455 float t_alt = std::fmax(base, (float)column_max_y);
456 // Only decrease above water_level
457 if (t_alt > water_level)
458 m_bgen->humidmap[index_2d] -=
459 (t_alt - water_level) * 10.0f / altitude_chill;
462 // Optionally decrease heat with altitude
463 if (spflags & MGVALLEYS_ALT_CHILL) {
464 // Compensate to avoid reducing the average heat
465 m_bgen->heatmap[index_2d] += 5.0f;
466 // Ground height ignoring riverbeds
467 float t_alt = std::fmax(base, (float)column_max_y);
468 // Only decrease above water_level
469 if (t_alt > water_level)
470 m_bgen->heatmap[index_2d] -=
471 (t_alt - water_level) * 20.0f / altitude_chill;
475 return surface_max_y;