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 FATAL_ERROR_IF(biomegen->getType() != BIOMEGEN_ORIGINAL,
61 "MapgenValleys has a hard dependency on BiomeGenOriginal");
62 m_bgen = (BiomeGenOriginal *)biomegen;
64 spflags = params->spflags;
65 altitude_chill = params->altitude_chill;
66 river_depth_bed = params->river_depth + 1.0f;
67 river_size_factor = params->river_size / 100.0f;
69 cave_width = params->cave_width;
70 large_cave_depth = params->large_cave_depth;
71 small_cave_num_min = params->small_cave_num_min;
72 small_cave_num_max = params->small_cave_num_max;
73 large_cave_num_min = params->large_cave_num_min;
74 large_cave_num_max = params->large_cave_num_max;
75 large_cave_flooded = params->large_cave_flooded;
76 cavern_limit = params->cavern_limit;
77 cavern_taper = params->cavern_taper;
78 cavern_threshold = params->cavern_threshold;
79 dungeon_ymin = params->dungeon_ymin;
80 dungeon_ymax = params->dungeon_ymax;
83 noise_filler_depth = new Noise(¶ms->np_filler_depth, seed, csize.X, csize.Z);
84 noise_inter_valley_slope = new Noise(¶ms->np_inter_valley_slope, seed, csize.X, csize.Z);
85 noise_rivers = new Noise(¶ms->np_rivers, seed, csize.X, csize.Z);
86 noise_terrain_height = new Noise(¶ms->np_terrain_height, seed, csize.X, csize.Z);
87 noise_valley_depth = new Noise(¶ms->np_valley_depth, seed, csize.X, csize.Z);
88 noise_valley_profile = new Noise(¶ms->np_valley_profile, seed, csize.X, csize.Z);
91 // 1-up 1-down overgeneration
92 noise_inter_valley_fill = new Noise(¶ms->np_inter_valley_fill,
93 seed, csize.X, csize.Y + 2, csize.Z);
94 // 1-down overgeneraion
95 MapgenBasic::np_cave1 = params->np_cave1;
96 MapgenBasic::np_cave2 = params->np_cave2;
97 MapgenBasic::np_cavern = params->np_cavern;
98 MapgenBasic::np_dungeons = params->np_dungeons;
102 MapgenValleys::~MapgenValleys()
104 delete noise_filler_depth;
105 delete noise_inter_valley_fill;
106 delete noise_inter_valley_slope;
108 delete noise_terrain_height;
109 delete noise_valley_depth;
110 delete noise_valley_profile;
114 MapgenValleysParams::MapgenValleysParams():
115 np_filler_depth (0.0, 1.2, v3f(256, 256, 256), 1605, 3, 0.5, 2.0),
116 np_inter_valley_fill (0.0, 1.0, v3f(256, 512, 256), 1993, 6, 0.8, 2.0),
117 np_inter_valley_slope (0.5, 0.5, v3f(128, 128, 128), 746, 1, 1.0, 2.0),
118 np_rivers (0.0, 1.0, v3f(256, 256, 256), -6050, 5, 0.6, 2.0),
119 np_terrain_height (-10.0, 50.0, v3f(1024, 1024, 1024), 5202, 6, 0.4, 2.0),
120 np_valley_depth (5.0, 4.0, v3f(512, 512, 512), -1914, 1, 1.0, 2.0),
121 np_valley_profile (0.6, 0.50, v3f(512, 512, 512), 777, 1, 1.0, 2.0),
122 np_cave1 (0.0, 12.0, v3f(61, 61, 61), 52534, 3, 0.5, 2.0),
123 np_cave2 (0.0, 12.0, v3f(67, 67, 67), 10325, 3, 0.5, 2.0),
124 np_cavern (0.0, 1.0, v3f(768, 256, 768), 59033, 6, 0.63, 2.0),
125 np_dungeons (0.9, 0.5, v3f(500, 500, 500), 0, 2, 0.8, 2.0)
130 void MapgenValleysParams::readParams(const Settings *settings)
132 settings->getFlagStrNoEx("mgvalleys_spflags", spflags, flagdesc_mapgen_valleys);
133 settings->getU16NoEx("mgvalleys_altitude_chill", altitude_chill);
134 settings->getS16NoEx("mgvalleys_large_cave_depth", large_cave_depth);
135 settings->getU16NoEx("mgvalleys_small_cave_num_min", small_cave_num_min);
136 settings->getU16NoEx("mgvalleys_small_cave_num_max", small_cave_num_max);
137 settings->getU16NoEx("mgvalleys_large_cave_num_min", large_cave_num_min);
138 settings->getU16NoEx("mgvalleys_large_cave_num_max", large_cave_num_max);
139 settings->getFloatNoEx("mgvalleys_large_cave_flooded", large_cave_flooded);
140 settings->getU16NoEx("mgvalleys_river_depth", river_depth);
141 settings->getU16NoEx("mgvalleys_river_size", river_size);
142 settings->getFloatNoEx("mgvalleys_cave_width", cave_width);
143 settings->getS16NoEx("mgvalleys_cavern_limit", cavern_limit);
144 settings->getS16NoEx("mgvalleys_cavern_taper", cavern_taper);
145 settings->getFloatNoEx("mgvalleys_cavern_threshold", cavern_threshold);
146 settings->getS16NoEx("mgvalleys_dungeon_ymin", dungeon_ymin);
147 settings->getS16NoEx("mgvalleys_dungeon_ymax", dungeon_ymax);
149 settings->getNoiseParams("mgvalleys_np_filler_depth", np_filler_depth);
150 settings->getNoiseParams("mgvalleys_np_inter_valley_fill", np_inter_valley_fill);
151 settings->getNoiseParams("mgvalleys_np_inter_valley_slope", np_inter_valley_slope);
152 settings->getNoiseParams("mgvalleys_np_rivers", np_rivers);
153 settings->getNoiseParams("mgvalleys_np_terrain_height", np_terrain_height);
154 settings->getNoiseParams("mgvalleys_np_valley_depth", np_valley_depth);
155 settings->getNoiseParams("mgvalleys_np_valley_profile", np_valley_profile);
157 settings->getNoiseParams("mgvalleys_np_cave1", np_cave1);
158 settings->getNoiseParams("mgvalleys_np_cave2", np_cave2);
159 settings->getNoiseParams("mgvalleys_np_cavern", np_cavern);
160 settings->getNoiseParams("mgvalleys_np_dungeons", np_dungeons);
164 void MapgenValleysParams::writeParams(Settings *settings) const
166 settings->setFlagStr("mgvalleys_spflags", spflags, flagdesc_mapgen_valleys);
167 settings->setU16("mgvalleys_altitude_chill", altitude_chill);
168 settings->setS16("mgvalleys_large_cave_depth", large_cave_depth);
169 settings->setU16("mgvalleys_small_cave_num_min", small_cave_num_min);
170 settings->setU16("mgvalleys_small_cave_num_max", small_cave_num_max);
171 settings->setU16("mgvalleys_large_cave_num_min", large_cave_num_min);
172 settings->setU16("mgvalleys_large_cave_num_max", large_cave_num_max);
173 settings->setFloat("mgvalleys_large_cave_flooded", large_cave_flooded);
174 settings->setU16("mgvalleys_river_depth", river_depth);
175 settings->setU16("mgvalleys_river_size", river_size);
176 settings->setFloat("mgvalleys_cave_width", cave_width);
177 settings->setS16("mgvalleys_cavern_limit", cavern_limit);
178 settings->setS16("mgvalleys_cavern_taper", cavern_taper);
179 settings->setFloat("mgvalleys_cavern_threshold", cavern_threshold);
180 settings->setS16("mgvalleys_dungeon_ymin", dungeon_ymin);
181 settings->setS16("mgvalleys_dungeon_ymax", dungeon_ymax);
183 settings->setNoiseParams("mgvalleys_np_filler_depth", np_filler_depth);
184 settings->setNoiseParams("mgvalleys_np_inter_valley_fill", np_inter_valley_fill);
185 settings->setNoiseParams("mgvalleys_np_inter_valley_slope", np_inter_valley_slope);
186 settings->setNoiseParams("mgvalleys_np_rivers", np_rivers);
187 settings->setNoiseParams("mgvalleys_np_terrain_height", np_terrain_height);
188 settings->setNoiseParams("mgvalleys_np_valley_depth", np_valley_depth);
189 settings->setNoiseParams("mgvalleys_np_valley_profile", np_valley_profile);
191 settings->setNoiseParams("mgvalleys_np_cave1", np_cave1);
192 settings->setNoiseParams("mgvalleys_np_cave2", np_cave2);
193 settings->setNoiseParams("mgvalleys_np_cavern", np_cavern);
194 settings->setNoiseParams("mgvalleys_np_dungeons", np_dungeons);
198 void MapgenValleysParams::setDefaultSettings(Settings *settings)
200 settings->setDefault("mgvalleys_spflags", flagdesc_mapgen_valleys,
201 MGVALLEYS_ALT_CHILL | MGVALLEYS_HUMID_RIVERS |
202 MGVALLEYS_VARY_RIVER_DEPTH | MGVALLEYS_ALT_DRY);
206 /////////////////////////////////////////////////////////////////
209 void MapgenValleys::makeChunk(BlockMakeData *data)
212 assert(data->vmanip);
213 assert(data->nodedef);
215 //TimeTaker t("makeChunk");
217 this->generating = true;
218 this->vm = data->vmanip;
219 this->ndef = data->nodedef;
221 v3s16 blockpos_min = data->blockpos_min;
222 v3s16 blockpos_max = data->blockpos_max;
223 node_min = blockpos_min * MAP_BLOCKSIZE;
224 node_max = (blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
225 full_node_min = (blockpos_min - 1) * MAP_BLOCKSIZE;
226 full_node_max = (blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
228 blockseed = getBlockSeed2(full_node_min, seed);
230 // Generate biome noises. Note this must be executed strictly before
231 // generateTerrain, because generateTerrain depends on intermediate
232 // biome-related noises.
233 m_bgen->calcBiomeNoise(node_min);
236 s16 stone_surface_max_y = generateTerrain();
239 updateHeightmap(node_min, node_max);
241 // Place biome-specific nodes and build biomemap
242 if (flags & MG_BIOMES) {
246 // Generate tunnels, caverns and large randomwalk caves
247 if (flags & MG_CAVES) {
248 // Generate tunnels first as caverns confuse them
249 generateCavesNoiseIntersection(stone_surface_max_y);
252 bool near_cavern = generateCavernsNoise(stone_surface_max_y);
254 // Generate large randomwalk caves
256 // Disable large randomwalk caves in this mapchunk by setting
257 // 'large cave depth' to world base. Avoids excessive liquid in
258 // large caverns and floating blobs of overgenerated liquid.
259 generateCavesRandomWalk(stone_surface_max_y,
260 -MAX_MAP_GENERATION_LIMIT);
262 generateCavesRandomWalk(stone_surface_max_y, large_cave_depth);
265 // Generate the registered ores
267 m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
270 if (flags & MG_DUNGEONS)
271 generateDungeons(stone_surface_max_y);
273 // Generate the registered decorations
274 if (flags & MG_DECORATIONS)
275 m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);
277 // Sprinkle some dust on top after everything else was generated
278 if (flags & MG_BIOMES)
281 updateLiquid(&data->transforming_liquid, full_node_min, full_node_max);
283 if (flags & MG_LIGHT)
284 calcLighting(node_min - v3s16(0, 1, 0), node_max + v3s16(0, 1, 0),
285 full_node_min, full_node_max);
287 this->generating = false;
289 //printf("makeChunk: %lums\n", t.stop());
293 int MapgenValleys::getSpawnLevelAtPoint(v2s16 p)
295 // Check if in a river channel
296 float n_rivers = NoisePerlin2D(&noise_rivers->np, p.X, p.Y, seed);
297 if (std::fabs(n_rivers) <= river_size_factor)
298 // Unsuitable spawn point
299 return MAX_MAP_GENERATION_LIMIT;
301 float n_slope = NoisePerlin2D(&noise_inter_valley_slope->np, p.X, p.Y, seed);
302 float n_terrain_height = NoisePerlin2D(&noise_terrain_height->np, p.X, p.Y, seed);
303 float n_valley = NoisePerlin2D(&noise_valley_depth->np, p.X, p.Y, seed);
304 float n_valley_profile = NoisePerlin2D(&noise_valley_profile->np, p.X, p.Y, seed);
306 float valley_d = n_valley * n_valley;
307 float base = n_terrain_height + valley_d;
308 float river = std::fabs(n_rivers) - river_size_factor;
309 float tv = std::fmax(river / n_valley_profile, 0.0f);
310 float valley_h = valley_d * (1.0f - std::exp(-tv * tv));
311 float surface_y = base + valley_h;
312 float slope = n_slope * valley_h;
313 float river_y = base - 1.0f;
315 // Raising the maximum spawn level above 'water_level + 16' is necessary for custom
316 // parameters that set average terrain level much higher than water_level.
317 s16 max_spawn_y = std::fmax(
318 noise_terrain_height->np.offset +
319 noise_valley_depth->np.offset * noise_valley_depth->np.offset,
322 // Starting spawn search at max_spawn_y + 128 ensures 128 nodes of open
323 // space above spawn position. Avoids spawning in possibly sealed voids.
324 for (s16 y = max_spawn_y + 128; y >= water_level; y--) {
325 float n_fill = NoisePerlin3D(&noise_inter_valley_fill->np, p.X, y, p.Y, seed);
326 float surface_delta = (float)y - surface_y;
327 float density = slope * n_fill - surface_delta;
329 if (density > 0.0f) { // If solid
330 // Sometimes surface level is below river water level in places that are not
332 if (y < water_level || y > max_spawn_y || y < (s16)river_y)
333 // Unsuitable spawn point
334 return MAX_MAP_GENERATION_LIMIT;
336 // y + 2 because y is surface and due to biome 'dust' nodes.
340 // Unsuitable spawn position, no ground found
341 return MAX_MAP_GENERATION_LIMIT;
345 int MapgenValleys::generateTerrain()
347 MapNode n_air(CONTENT_AIR);
348 MapNode n_river_water(c_river_water_source);
349 MapNode n_stone(c_stone);
350 MapNode n_water(c_water_source);
352 noise_inter_valley_slope->perlinMap2D(node_min.X, node_min.Z);
353 noise_rivers->perlinMap2D(node_min.X, node_min.Z);
354 noise_terrain_height->perlinMap2D(node_min.X, node_min.Z);
355 noise_valley_depth->perlinMap2D(node_min.X, node_min.Z);
356 noise_valley_profile->perlinMap2D(node_min.X, node_min.Z);
358 noise_inter_valley_fill->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
360 const v3s16 &em = vm->m_area.getExtent();
361 s16 surface_max_y = -MAX_MAP_GENERATION_LIMIT;
364 for (s16 z = node_min.Z; z <= node_max.Z; z++)
365 for (s16 x = node_min.X; x <= node_max.X; x++, index_2d++) {
366 float n_slope = noise_inter_valley_slope->result[index_2d];
367 float n_rivers = noise_rivers->result[index_2d];
368 float n_terrain_height = noise_terrain_height->result[index_2d];
369 float n_valley = noise_valley_depth->result[index_2d];
370 float n_valley_profile = noise_valley_profile->result[index_2d];
372 float valley_d = n_valley * n_valley;
373 // 'base' represents the level of the river banks
374 float base = n_terrain_height + valley_d;
375 // 'river' represents the distance from the river edge
376 float river = std::fabs(n_rivers) - river_size_factor;
377 // Use the curve of the function 1-exp(-(x/a)^2) to model valleys.
378 // 'valley_h' represents the height of the terrain, from the rivers.
379 float tv = std::fmax(river / n_valley_profile, 0.0f);
380 float valley_h = valley_d * (1.0f - std::exp(-tv * tv));
381 // Approximate height of the terrain
382 float surface_y = base + valley_h;
383 float slope = n_slope * valley_h;
384 // River water surface is 1 node below river banks
385 float river_y = base - 1.0f;
387 // Rivers are placed where 'river' is negative
389 // Use the function -sqrt(1-x^2) which models a circle
390 float tr = river / river_size_factor + 1.0f;
391 float depth = (river_depth_bed *
392 std::sqrt(std::fmax(0.0f, 1.0f - tr * tr)));
393 // There is no logical equivalent to this using rangelim
394 surface_y = std::fmin(
395 std::fmax(base - depth, (float)(water_level - 3)),
400 // Optionally vary river depth according to heat and humidity
401 if (spflags & MGVALLEYS_VARY_RIVER_DEPTH) {
402 float t_heat = m_bgen->heatmap[index_2d];
403 float heat = (spflags & MGVALLEYS_ALT_CHILL) ?
404 // Match heat value calculated below in
405 // 'Optionally decrease heat with altitude'.
406 // In rivers, 'ground height ignoring riverbeds' is 'base'.
407 // As this only affects river water we can assume y > water_level.
408 t_heat + 5.0f - (base - water_level) * 20.0f / altitude_chill :
410 float delta = m_bgen->humidmap[index_2d] - 50.0f;
412 float t_evap = (heat - 32.0f) / 300.0f;
413 river_y += delta * std::fmax(t_evap, 0.08f);
417 // Highest solid node in column
418 s16 column_max_y = surface_y;
419 u32 index_3d = (z - node_min.Z) * zstride_1u1d + (x - node_min.X);
420 u32 index_data = vm->m_area.index(x, node_min.Y - 1, z);
422 for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
423 if (vm->m_data[index_data].getContent() == CONTENT_IGNORE) {
424 float n_fill = noise_inter_valley_fill->result[index_3d];
425 float surface_delta = (float)y - surface_y;
426 // Density = density noise + density gradient
427 float density = slope * n_fill - surface_delta;
429 if (density > 0.0f) {
430 vm->m_data[index_data] = n_stone; // Stone
431 if (y > surface_max_y)
433 if (y > column_max_y)
435 } else if (y <= water_level) {
436 vm->m_data[index_data] = n_water; // Water
437 } else if (y <= (s16)river_y) {
438 vm->m_data[index_data] = n_river_water; // River water
440 vm->m_data[index_data] = n_air; // Air
444 VoxelArea::add_y(em, index_data, 1);
448 // Optionally increase humidity around rivers
449 if (spflags & MGVALLEYS_HUMID_RIVERS) {
450 // Compensate to avoid increasing average humidity
451 m_bgen->humidmap[index_2d] *= 0.8f;
452 // Ground height ignoring riverbeds
453 float t_alt = std::fmax(base, (float)column_max_y);
454 float water_depth = (t_alt - base) / 4.0f;
455 m_bgen->humidmap[index_2d] *=
456 1.0f + std::pow(0.5f, std::fmax(water_depth, 1.0f));
459 // Optionally decrease humidity with altitude
460 if (spflags & MGVALLEYS_ALT_DRY) {
461 // Ground height ignoring riverbeds
462 float t_alt = std::fmax(base, (float)column_max_y);
463 // Only decrease above water_level
464 if (t_alt > water_level)
465 m_bgen->humidmap[index_2d] -=
466 (t_alt - water_level) * 10.0f / altitude_chill;
469 // Optionally decrease heat with altitude
470 if (spflags & MGVALLEYS_ALT_CHILL) {
471 // Compensate to avoid reducing the average heat
472 m_bgen->heatmap[index_2d] += 5.0f;
473 // Ground height ignoring riverbeds
474 float t_alt = std::fmax(base, (float)column_max_y);
475 // Only decrease above water_level
476 if (t_alt > water_level)
477 m_bgen->heatmap[index_2d] -=
478 (t_alt - water_level) * 20.0f / altitude_chill;
482 return surface_max_y;