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, EmergeParams *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
272 m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
275 if (flags & MG_DUNGEONS)
276 generateDungeons(stone_surface_max_y);
278 // Generate the registered decorations
279 if (flags & MG_DECORATIONS)
280 m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);
282 // Sprinkle some dust on top after everything else was generated
283 if (flags & MG_BIOMES)
286 updateLiquid(&data->transforming_liquid, full_node_min, full_node_max);
288 if (flags & MG_LIGHT)
289 calcLighting(node_min - v3s16(0, 1, 0), node_max + v3s16(0, 1, 0),
290 full_node_min, full_node_max);
292 this->generating = false;
294 //printf("makeChunk: %lums\n", t.stop());
298 int MapgenValleys::getSpawnLevelAtPoint(v2s16 p)
300 // Check if in a river channel
301 float n_rivers = NoisePerlin2D(&noise_rivers->np, p.X, p.Y, seed);
302 if (std::fabs(n_rivers) <= river_size_factor)
303 // Unsuitable spawn point
304 return MAX_MAP_GENERATION_LIMIT;
306 float n_slope = NoisePerlin2D(&noise_inter_valley_slope->np, p.X, p.Y, seed);
307 float n_terrain_height = NoisePerlin2D(&noise_terrain_height->np, p.X, p.Y, seed);
308 float n_valley = NoisePerlin2D(&noise_valley_depth->np, p.X, p.Y, seed);
309 float n_valley_profile = NoisePerlin2D(&noise_valley_profile->np, p.X, p.Y, seed);
311 float valley_d = n_valley * n_valley;
312 float base = n_terrain_height + valley_d;
313 float river = std::fabs(n_rivers) - river_size_factor;
314 float tv = std::fmax(river / n_valley_profile, 0.0f);
315 float valley_h = valley_d * (1.0f - std::exp(-tv * tv));
316 float surface_y = base + valley_h;
317 float slope = n_slope * valley_h;
318 float river_y = base - 1.0f;
320 // Raising the maximum spawn level above 'water_level + 16' is necessary for custom
321 // parameters that set average terrain level much higher than water_level.
322 s16 max_spawn_y = std::fmax(
323 noise_terrain_height->np.offset +
324 noise_valley_depth->np.offset * noise_valley_depth->np.offset,
327 // Starting spawn search at max_spawn_y + 128 ensures 128 nodes of open
328 // space above spawn position. Avoids spawning in possibly sealed voids.
329 for (s16 y = max_spawn_y + 128; y >= water_level; y--) {
330 float n_fill = NoisePerlin3D(&noise_inter_valley_fill->np, p.X, y, p.Y, seed);
331 float surface_delta = (float)y - surface_y;
332 float density = slope * n_fill - surface_delta;
334 if (density > 0.0f) { // If solid
335 // Sometimes surface level is below river water level in places that are not
337 if (y < water_level || y > max_spawn_y || y < (s16)river_y)
338 // Unsuitable spawn point
339 return MAX_MAP_GENERATION_LIMIT;
341 // y + 2 because y is surface and due to biome 'dust' nodes.
345 // Unsuitable spawn position, no ground found
346 return MAX_MAP_GENERATION_LIMIT;
350 int MapgenValleys::generateTerrain()
352 MapNode n_air(CONTENT_AIR);
353 MapNode n_river_water(c_river_water_source);
354 MapNode n_stone(c_stone);
355 MapNode n_water(c_water_source);
357 noise_inter_valley_slope->perlinMap2D(node_min.X, node_min.Z);
358 noise_rivers->perlinMap2D(node_min.X, node_min.Z);
359 noise_terrain_height->perlinMap2D(node_min.X, node_min.Z);
360 noise_valley_depth->perlinMap2D(node_min.X, node_min.Z);
361 noise_valley_profile->perlinMap2D(node_min.X, node_min.Z);
363 noise_inter_valley_fill->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
365 const v3s16 &em = vm->m_area.getExtent();
366 s16 surface_max_y = -MAX_MAP_GENERATION_LIMIT;
369 for (s16 z = node_min.Z; z <= node_max.Z; z++)
370 for (s16 x = node_min.X; x <= node_max.X; x++, index_2d++) {
371 float n_slope = noise_inter_valley_slope->result[index_2d];
372 float n_rivers = noise_rivers->result[index_2d];
373 float n_terrain_height = noise_terrain_height->result[index_2d];
374 float n_valley = noise_valley_depth->result[index_2d];
375 float n_valley_profile = noise_valley_profile->result[index_2d];
377 float valley_d = n_valley * n_valley;
378 // 'base' represents the level of the river banks
379 float base = n_terrain_height + valley_d;
380 // 'river' represents the distance from the river edge
381 float river = std::fabs(n_rivers) - river_size_factor;
382 // Use the curve of the function 1-exp(-(x/a)^2) to model valleys.
383 // 'valley_h' represents the height of the terrain, from the rivers.
384 float tv = std::fmax(river / n_valley_profile, 0.0f);
385 float valley_h = valley_d * (1.0f - std::exp(-tv * tv));
386 // Approximate height of the terrain
387 float surface_y = base + valley_h;
388 float slope = n_slope * valley_h;
389 // River water surface is 1 node below river banks
390 float river_y = base - 1.0f;
392 // Rivers are placed where 'river' is negative
394 // Use the function -sqrt(1-x^2) which models a circle
395 float tr = river / river_size_factor + 1.0f;
396 float depth = (river_depth_bed *
397 std::sqrt(std::fmax(0.0f, 1.0f - tr * tr)));
398 // There is no logical equivalent to this using rangelim
399 surface_y = std::fmin(
400 std::fmax(base - depth, (float)(water_level - 3)),
405 // Optionally vary river depth according to heat and humidity
406 if (spflags & MGVALLEYS_VARY_RIVER_DEPTH) {
407 float t_heat = m_bgen->heatmap[index_2d];
408 float heat = (spflags & MGVALLEYS_ALT_CHILL) ?
409 // Match heat value calculated below in
410 // 'Optionally decrease heat with altitude'.
411 // In rivers, 'ground height ignoring riverbeds' is 'base'.
412 // As this only affects river water we can assume y > water_level.
413 t_heat + 5.0f - (base - water_level) * 20.0f / altitude_chill :
415 float delta = m_bgen->humidmap[index_2d] - 50.0f;
417 float t_evap = (heat - 32.0f) / 300.0f;
418 river_y += delta * std::fmax(t_evap, 0.08f);
422 // Highest solid node in column
423 s16 column_max_y = surface_y;
424 u32 index_3d = (z - node_min.Z) * zstride_1u1d + (x - node_min.X);
425 u32 index_data = vm->m_area.index(x, node_min.Y - 1, z);
427 for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
428 if (vm->m_data[index_data].getContent() == CONTENT_IGNORE) {
429 float n_fill = noise_inter_valley_fill->result[index_3d];
430 float surface_delta = (float)y - surface_y;
431 // Density = density noise + density gradient
432 float density = slope * n_fill - surface_delta;
434 if (density > 0.0f) {
435 vm->m_data[index_data] = n_stone; // Stone
436 if (y > surface_max_y)
438 if (y > column_max_y)
440 } else if (y <= water_level) {
441 vm->m_data[index_data] = n_water; // Water
442 } else if (y <= (s16)river_y) {
443 vm->m_data[index_data] = n_river_water; // River water
445 vm->m_data[index_data] = n_air; // Air
449 VoxelArea::add_y(em, index_data, 1);
453 // Optionally increase humidity around rivers
454 if (spflags & MGVALLEYS_HUMID_RIVERS) {
455 // Compensate to avoid increasing average humidity
456 m_bgen->humidmap[index_2d] *= 0.8f;
457 // Ground height ignoring riverbeds
458 float t_alt = std::fmax(base, (float)column_max_y);
459 float water_depth = (t_alt - base) / 4.0f;
460 m_bgen->humidmap[index_2d] *=
461 1.0f + std::pow(0.5f, std::fmax(water_depth, 1.0f));
464 // Optionally decrease humidity with altitude
465 if (spflags & MGVALLEYS_ALT_DRY) {
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->humidmap[index_2d] -=
471 (t_alt - water_level) * 10.0f / altitude_chill;
474 // Optionally decrease heat with altitude
475 if (spflags & MGVALLEYS_ALT_CHILL) {
476 // Compensate to avoid reducing the average heat
477 m_bgen->heatmap[index_2d] += 5.0f;
478 // Ground height ignoring riverbeds
479 float t_alt = std::fmax(base, (float)column_max_y);
480 // Only decrease above water_level
481 if (t_alt > water_level)
482 m_bgen->heatmap[index_2d] -=
483 (t_alt - water_level) * 20.0f / altitude_chill;
487 return surface_max_y;