3 Copyright (C) 2016-2018 Duane Robertson <duane@duanerobertson.com>
4 Copyright (C) 2016-2018 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.
34 #include "voxelalgorithms.h"
35 //#include "profiler.h" // For TimeTaker
36 #include "settings.h" // For g_settings
38 #include "dungeongen.h"
41 #include "mg_decoration.h"
42 #include "mapgen_valleys.h"
47 FlagDesc flagdesc_mapgen_valleys[] = {
48 {"altitude_chill", MGVALLEYS_ALT_CHILL},
49 {"humid_rivers", MGVALLEYS_HUMID_RIVERS},
50 {"vary_river_depth", MGVALLEYS_VARY_RIVER_DEPTH},
51 {"altitude_dry", MGVALLEYS_ALT_DRY},
56 ////////////////////////////////////////////////////////////////////////////////
59 MapgenValleys::MapgenValleys(int mapgenid, MapgenValleysParams *params,
60 EmergeManager *emerge)
61 : MapgenBasic(mapgenid, params, emerge)
63 // NOTE: MapgenValleys has a hard dependency on BiomeGenOriginal
64 m_bgen = (BiomeGenOriginal *)biomegen;
66 BiomeParamsOriginal *bp = (BiomeParamsOriginal *)params->bparams;
68 spflags = params->spflags;
69 altitude_chill = params->altitude_chill;
70 river_depth_bed = params->river_depth + 1.0f;
71 river_size_factor = params->river_size / 100.0f;
73 cave_width = params->cave_width;
74 large_cave_depth = params->large_cave_depth;
75 lava_depth = params->lava_depth;
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;
99 humidity_adjust = bp->np_humidity.offset - 50.0f;
103 MapgenValleys::~MapgenValleys()
105 delete noise_filler_depth;
106 delete noise_inter_valley_fill;
107 delete noise_inter_valley_slope;
109 delete noise_terrain_height;
110 delete noise_valley_depth;
111 delete noise_valley_profile;
115 MapgenValleysParams::MapgenValleysParams():
116 np_filler_depth (0.0, 1.2, v3f(256, 256, 256), 1605, 3, 0.5, 2.0),
117 np_inter_valley_fill (0.0, 1.0, v3f(256, 512, 256), 1993, 6, 0.8, 2.0),
118 np_inter_valley_slope (0.5, 0.5, v3f(128, 128, 128), 746, 1, 1.0, 2.0),
119 np_rivers (0.0, 1.0, v3f(256, 256, 256), -6050, 5, 0.6, 2.0),
120 np_terrain_height (-10.0, 50.0, v3f(1024, 1024, 1024), 5202, 6, 0.4, 2.0),
121 np_valley_depth (5.0, 4.0, v3f(512, 512, 512), -1914, 1, 1.0, 2.0),
122 np_valley_profile (0.6, 0.50, v3f(512, 512, 512), 777, 1, 1.0, 2.0),
123 np_cave1 (0.0, 12.0, v3f(61, 61, 61), 52534, 3, 0.5, 2.0),
124 np_cave2 (0.0, 12.0, v3f(67, 67, 67), 10325, 3, 0.5, 2.0),
125 np_cavern (0.0, 1.0, v3f(768, 256, 768), 59033, 6, 0.63, 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->getS16NoEx("mgvalleys_lava_depth", lava_depth);
136 settings->getU16NoEx("mgvalleys_river_depth", river_depth);
137 settings->getU16NoEx("mgvalleys_river_size", river_size);
138 settings->getFloatNoEx("mgvalleys_cave_width", cave_width);
139 settings->getS16NoEx("mgvalleys_cavern_limit", cavern_limit);
140 settings->getS16NoEx("mgvalleys_cavern_taper", cavern_taper);
141 settings->getFloatNoEx("mgvalleys_cavern_threshold", cavern_threshold);
142 settings->getS16NoEx("mgvalleys_dungeon_ymin", dungeon_ymin);
143 settings->getS16NoEx("mgvalleys_dungeon_ymax", dungeon_ymax);
145 settings->getNoiseParams("mgvalleys_np_filler_depth", np_filler_depth);
146 settings->getNoiseParams("mgvalleys_np_inter_valley_fill", np_inter_valley_fill);
147 settings->getNoiseParams("mgvalleys_np_inter_valley_slope", np_inter_valley_slope);
148 settings->getNoiseParams("mgvalleys_np_rivers", np_rivers);
149 settings->getNoiseParams("mgvalleys_np_terrain_height", np_terrain_height);
150 settings->getNoiseParams("mgvalleys_np_valley_depth", np_valley_depth);
151 settings->getNoiseParams("mgvalleys_np_valley_profile", np_valley_profile);
153 settings->getNoiseParams("mgvalleys_np_cave1", np_cave1);
154 settings->getNoiseParams("mgvalleys_np_cave2", np_cave2);
155 settings->getNoiseParams("mgvalleys_np_cavern", np_cavern);
159 void MapgenValleysParams::writeParams(Settings *settings) const
161 settings->setFlagStr("mgvalleys_spflags", spflags, flagdesc_mapgen_valleys, U32_MAX);
162 settings->setU16("mgvalleys_altitude_chill", altitude_chill);
163 settings->setS16("mgvalleys_large_cave_depth", large_cave_depth);
164 settings->setS16("mgvalleys_lava_depth", lava_depth);
165 settings->setU16("mgvalleys_river_depth", river_depth);
166 settings->setU16("mgvalleys_river_size", river_size);
167 settings->setFloat("mgvalleys_cave_width", cave_width);
168 settings->setS16("mgvalleys_cavern_limit", cavern_limit);
169 settings->setS16("mgvalleys_cavern_taper", cavern_taper);
170 settings->setFloat("mgvalleys_cavern_threshold", cavern_threshold);
171 settings->setS16("mgvalleys_dungeon_ymin", dungeon_ymin);
172 settings->setS16("mgvalleys_dungeon_ymax", dungeon_ymax);
174 settings->setNoiseParams("mgvalleys_np_filler_depth", np_filler_depth);
175 settings->setNoiseParams("mgvalleys_np_inter_valley_fill", np_inter_valley_fill);
176 settings->setNoiseParams("mgvalleys_np_inter_valley_slope", np_inter_valley_slope);
177 settings->setNoiseParams("mgvalleys_np_rivers", np_rivers);
178 settings->setNoiseParams("mgvalleys_np_terrain_height", np_terrain_height);
179 settings->setNoiseParams("mgvalleys_np_valley_depth", np_valley_depth);
180 settings->setNoiseParams("mgvalleys_np_valley_profile", np_valley_profile);
182 settings->setNoiseParams("mgvalleys_np_cave1", np_cave1);
183 settings->setNoiseParams("mgvalleys_np_cave2", np_cave2);
184 settings->setNoiseParams("mgvalleys_np_cavern", np_cavern);
188 ////////////////////////////////////////////////////////////////////////////////
191 void MapgenValleys::makeChunk(BlockMakeData *data)
194 assert(data->vmanip);
195 assert(data->nodedef);
196 assert(data->blockpos_requested.X >= data->blockpos_min.X &&
197 data->blockpos_requested.Y >= data->blockpos_min.Y &&
198 data->blockpos_requested.Z >= data->blockpos_min.Z);
199 assert(data->blockpos_requested.X <= data->blockpos_max.X &&
200 data->blockpos_requested.Y <= data->blockpos_max.Y &&
201 data->blockpos_requested.Z <= data->blockpos_max.Z);
203 //TimeTaker t("makeChunk");
205 this->generating = true;
206 this->vm = data->vmanip;
207 this->ndef = data->nodedef;
209 v3s16 blockpos_min = data->blockpos_min;
210 v3s16 blockpos_max = data->blockpos_max;
211 node_min = blockpos_min * MAP_BLOCKSIZE;
212 node_max = (blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
213 full_node_min = (blockpos_min - 1) * MAP_BLOCKSIZE;
214 full_node_max = (blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
216 blockseed = getBlockSeed2(full_node_min, seed);
218 // Generate biome noises. Note this must be executed strictly before
219 // generateTerrain, because generateTerrain depends on intermediate
220 // biome-related noises.
221 m_bgen->calcBiomeNoise(node_min);
223 // Generate noise maps and base terrain height.
224 // Modify heat and humidity maps.
227 // Generate base terrain with initial heightmaps
228 s16 stone_surface_max_y = generateTerrain();
230 // Recalculate heightmap
231 updateHeightmap(node_min, node_max);
233 // Place biome-specific nodes and build biomemap
234 if (flags & MG_BIOMES)
237 // Generate tunnels, caverns and large randomwalk caves
238 if (flags & MG_CAVES) {
239 // Generate tunnels first as caverns confuse them
240 generateCavesNoiseIntersection(stone_surface_max_y);
243 bool near_cavern = generateCavernsNoise(stone_surface_max_y);
245 // Generate large randomwalk caves
247 // Disable large randomwalk caves in this mapchunk by setting
248 // 'large cave depth' to world base. Avoids excessive liquid in
249 // large caverns and floating blobs of overgenerated liquid.
250 generateCavesRandomWalk(stone_surface_max_y,
251 -MAX_MAP_GENERATION_LIMIT);
253 generateCavesRandomWalk(stone_surface_max_y, large_cave_depth);
256 // Generate the registered ores
257 m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
260 if ((flags & MG_DUNGEONS) && full_node_min.Y >= dungeon_ymin &&
261 full_node_max.Y <= dungeon_ymax)
262 generateDungeons(stone_surface_max_y);
264 // Generate the registered decorations
265 if (flags & MG_DECORATIONS)
266 m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);
268 // Sprinkle some dust on top after everything else was generated
269 if (flags & MG_BIOMES)
272 updateLiquid(&data->transforming_liquid, full_node_min, full_node_max);
274 if (flags & MG_LIGHT)
275 calcLighting(node_min - v3s16(0, 1, 0), node_max + v3s16(0, 1, 0),
276 full_node_min, full_node_max);
278 this->generating = false;
280 //printf("makeChunk: %lums\n", t.stop());
284 void MapgenValleys::calculateNoise()
287 int y = node_min.Y - 1;
290 noise_inter_valley_slope->perlinMap2D(x, z);
291 noise_rivers->perlinMap2D(x, z);
292 noise_terrain_height->perlinMap2D(x, z);
293 noise_valley_depth->perlinMap2D(x, z);
294 noise_valley_profile->perlinMap2D(x, z);
296 noise_inter_valley_fill->perlinMap3D(x, y, z);
298 float heat_offset = 0.0f;
299 float humidity_scale = 1.0f;
300 // Altitude chill tends to reduce the average heat.
301 if (spflags & MGVALLEYS_ALT_CHILL)
303 // River humidity tends to increase the humidity range.
304 if (spflags & MGVALLEYS_HUMID_RIVERS)
305 humidity_scale = 0.8f;
307 for (s32 index = 0; index < csize.X * csize.Z; index++) {
308 m_bgen->heatmap[index] += heat_offset;
309 m_bgen->humidmap[index] *= humidity_scale;
315 for (tn.z = node_min.Z; tn.z <= node_max.Z; tn.z++)
316 for (tn.x = node_min.X; tn.x <= node_max.X; tn.x++, index++) {
317 // The parameters that we actually need to generate terrain are passed
318 // by address (and the return value).
319 tn.terrain_height = noise_terrain_height->result[index];
320 // River noise is replaced with base terrain, which is basically the
321 // height of the water table.
322 tn.rivers = &noise_rivers->result[index];
323 // Valley depth noise is replaced with the valley number that represents
324 // the height of terrain over rivers and is used to determine how close
325 // a river is for humidity calculation.
326 tn.valley = &noise_valley_depth->result[index];
327 tn.valley_profile = noise_valley_profile->result[index];
328 // Slope noise is replaced by the calculated slope which is used to get
329 // terrain height in the slow method, to create sharper mountains.
330 tn.slope = &noise_inter_valley_slope->result[index];
331 tn.inter_valley_fill = noise_inter_valley_fill->result[index];
333 // This is the actual terrain height.
334 float mount = terrainLevelFromNoise(&tn);
335 noise_terrain_height->result[index] = mount;
340 float MapgenValleys::terrainLevelFromNoise(TerrainNoise *tn)
342 // The square function changes the behaviour of this noise: very often
343 // small, and sometimes very high.
344 float valley_d = MYSQUARE(*tn->valley);
346 // valley_d is here because terrain is generally higher where valleys are
347 // deep (mountains). base represents the height of the rivers, most of the
349 float base = tn->terrain_height + valley_d;
351 // "river" represents the distance from the river
352 float river = std::fabs(*tn->rivers) - river_size_factor;
354 // Use the curve of the function 1-exp(-(x/a)^2) to model valleys.
355 // "valley" represents the height of the terrain, from the rivers.
356 float tv = std::fmax(river / tn->valley_profile, 0.0f);
357 *tn->valley = valley_d * (1.0f - std::exp(-MYSQUARE(tv)));
359 // Approximate height of the terrain at this point
360 float mount = base + *tn->valley;
362 *tn->slope *= *tn->valley;
364 // Base ground is returned as rivers since it's basically the water table.
367 // Rivers are placed where "river" is negative, so where the original noise
368 // value is close to zero.
370 // Use the the function -sqrt(1-x^2) which models a circle
371 float tr = river / river_size_factor + 1.0f;
372 float depth = (river_depth_bed *
373 std::sqrt(std::fmax(0.0f, 1.0f - MYSQUARE(tr))));
375 // base - depth : height of the bottom of the river
376 // water_level - 3 : don't make rivers below 3 nodes under the surface.
377 // We use three because that's as low as the swamp biomes go.
378 // There is no logical equivalent to this using rangelim.
380 std::fmin(std::fmax(base - depth, (float)(water_level - 3)), mount);
382 // Slope has no influence on rivers
390 // This avoids duplicating the code in terrainLevelFromNoise, adding only the
391 // final step of terrain generation without a noise map.
393 float MapgenValleys::adjustedTerrainLevelFromNoise(TerrainNoise *tn)
395 float mount = terrainLevelFromNoise(tn);
396 s16 y_start = myround(mount);
398 for (s16 y = y_start; y <= y_start + 1000; y++) {
400 NoisePerlin3D(&noise_inter_valley_fill->np, tn->x, y, tn->z, seed);
401 if (fill * *tn->slope < y - mount) {
402 mount = std::fmax((float)(y - 1), mount);
411 int MapgenValleys::getSpawnLevelAtPoint(v2s16 p)
413 // Check if in a river
414 float rivers = NoisePerlin2D(&noise_rivers->np, p.X, p.Y, seed);
415 if (std::fabs(rivers) < river_size_factor)
416 return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
418 s16 level_at_point = terrainLevelAtPoint(p.X, p.Y);
419 if (level_at_point <= water_level ||
420 level_at_point > water_level + 16)
421 return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
423 return level_at_point;
427 float MapgenValleys::terrainLevelAtPoint(s16 x, s16 z)
431 float rivers = NoisePerlin2D(&noise_rivers->np, x, z, seed);
432 float valley = NoisePerlin2D(&noise_valley_depth->np, x, z, seed);
433 float inter_valley_slope =
434 NoisePerlin2D(&noise_inter_valley_slope->np, x, z, seed);
438 tn.terrain_height = NoisePerlin2D(&noise_terrain_height->np, x, z, seed);
441 tn.valley_profile = NoisePerlin2D(&noise_valley_profile->np, x, z, seed);
442 tn.slope = &inter_valley_slope;
443 tn.inter_valley_fill = 0.0f;
445 return adjustedTerrainLevelFromNoise(&tn);
449 int MapgenValleys::generateTerrain()
451 // Raising this reduces the rate of evaporation
452 static const float evaporation = 300.0f;
453 static const float humidity_dropoff = 4.0f;
454 // Constant to convert altitude chill to heat
455 static const float alt_to_heat = 20.0f;
456 // Humidity reduction by altitude
457 static const float alt_to_humid = 10.0f;
459 MapNode n_air(CONTENT_AIR);
460 MapNode n_river_water(c_river_water_source);
461 MapNode n_stone(c_stone);
462 MapNode n_water(c_water_source);
464 const v3s16 &em = vm->m_area.getExtent();
465 s16 surface_max_y = -MAX_MAP_GENERATION_LIMIT;
468 for (s16 z = node_min.Z; z <= node_max.Z; z++)
469 for (s16 x = node_min.X; x <= node_max.X; x++, index_2d++) {
470 float river_y = noise_rivers->result[index_2d];
471 float surface_y = noise_terrain_height->result[index_2d];
472 float slope = noise_inter_valley_slope->result[index_2d];
473 float t_heat = m_bgen->heatmap[index_2d];
475 heightmap[index_2d] = -MAX_MAP_GENERATION_LIMIT;
477 if (surface_y > surface_max_y)
478 surface_max_y = std::ceil(surface_y);
480 // Optionally vary river depth according to heat and humidity
481 if (spflags & MGVALLEYS_VARY_RIVER_DEPTH) {
482 float heat = ((spflags & MGVALLEYS_ALT_CHILL) &&
483 (surface_y > 0.0f || river_y > 0.0f)) ?
484 t_heat - alt_to_heat *
485 std::fmax(surface_y, river_y) / altitude_chill :
487 float delta = m_bgen->humidmap[index_2d] - 50.0f;
489 float t_evap = (heat - 32.0f) / evaporation;
490 river_y += delta * std::fmax(t_evap, 0.08f);
494 u32 index_3d = (z - node_min.Z) * zstride_1u1d + (x - node_min.X);
495 u32 index_data = vm->m_area.index(x, node_min.Y - 1, z);
497 for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
498 if (vm->m_data[index_data].getContent() == CONTENT_IGNORE) {
499 float fill = noise_inter_valley_fill->result[index_3d];
500 float surface_delta = (float)y - surface_y;
501 bool river = y < river_y - 1;
503 if (slope * fill > surface_delta) {
504 vm->m_data[index_data] = n_stone; // Stone
505 if (y > heightmap[index_2d])
506 heightmap[index_2d] = y;
507 if (y > surface_max_y)
509 } else if (y <= water_level) {
510 vm->m_data[index_data] = n_water; // Water
512 vm->m_data[index_data] = n_river_water; // River water
514 vm->m_data[index_data] = n_air; // Air
518 VoxelArea::add_y(em, index_data, 1);
522 if (heightmap[index_2d] == -MAX_MAP_GENERATION_LIMIT) {
523 s16 surface_y_int = myround(surface_y);
525 if (surface_y_int > node_max.Y + 1 ||
526 surface_y_int < node_min.Y - 1) {
527 // If surface_y is outside the chunk, it's good enough
528 heightmap[index_2d] = surface_y_int;
530 // If the ground is outside of this chunk, but surface_y is
531 // within the chunk, give a value outside.
532 heightmap[index_2d] = node_min.Y - 2;
536 // Optionally increase humidity around rivers
537 if (spflags & MGVALLEYS_HUMID_RIVERS) {
538 // Ground height ignoring riverbeds
539 float t_alt = std::fmax(noise_rivers->result[index_2d],
540 (float)heightmap[index_2d]);
541 float water_depth = (t_alt - river_y) / humidity_dropoff;
542 m_bgen->humidmap[index_2d] *=
543 1.0f + std::pow(0.5f, std::fmax(water_depth, 1.0f));
546 // Optionally decrease humidity with altitude
547 if (spflags & MGVALLEYS_ALT_DRY) {
548 // Ground height ignoring riverbeds
549 float t_alt = std::fmax(noise_rivers->result[index_2d],
550 (float)heightmap[index_2d]);
552 m_bgen->humidmap[index_2d] -=
553 alt_to_humid * t_alt / altitude_chill;
556 // Optionally decrease heat with altitude
557 if (spflags & MGVALLEYS_ALT_CHILL) {
558 // Ground height ignoring riverbeds
559 float t_alt = std::fmax(noise_rivers->result[index_2d],
560 (float)heightmap[index_2d]);
562 m_bgen->heatmap[index_2d] -=
563 alt_to_heat * t_alt / altitude_chill;
567 return surface_max_y;