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 static FlagDesc flagdesc_mapgen_valleys[] = {
48 {"altitude_chill", MGVALLEYS_ALT_CHILL},
49 {"humid_rivers", MGVALLEYS_HUMID_RIVERS},
54 ////////////////////////////////////////////////////////////////////////////////
57 MapgenValleys::MapgenValleys(int mapgenid, MapgenValleysParams *params,
58 EmergeManager *emerge)
59 : MapgenBasic(mapgenid, params, emerge)
61 // NOTE: MapgenValleys has a hard dependency on BiomeGenOriginal
62 m_bgen = (BiomeGenOriginal *)biomegen;
64 BiomeParamsOriginal *bp = (BiomeParamsOriginal *)params->bparams;
66 spflags = params->spflags;
67 altitude_chill = params->altitude_chill;
68 river_depth_bed = params->river_depth + 1.0f;
69 river_size_factor = params->river_size / 100.0f;
71 cave_width = params->cave_width;
72 large_cave_depth = params->large_cave_depth;
73 lava_depth = params->lava_depth;
74 cavern_limit = params->cavern_limit;
75 cavern_taper = params->cavern_taper;
76 cavern_threshold = params->cavern_threshold;
77 dungeon_ymin = params->dungeon_ymin;
78 dungeon_ymax = params->dungeon_ymax;
81 noise_filler_depth = new Noise(¶ms->np_filler_depth, seed, csize.X, csize.Z);
82 noise_inter_valley_slope = new Noise(¶ms->np_inter_valley_slope, seed, csize.X, csize.Z);
83 noise_rivers = new Noise(¶ms->np_rivers, seed, csize.X, csize.Z);
84 noise_terrain_height = new Noise(¶ms->np_terrain_height, seed, csize.X, csize.Z);
85 noise_valley_depth = new Noise(¶ms->np_valley_depth, seed, csize.X, csize.Z);
86 noise_valley_profile = new Noise(¶ms->np_valley_profile, seed, csize.X, csize.Z);
89 // 1-up 1-down overgeneration
90 noise_inter_valley_fill = new Noise(¶ms->np_inter_valley_fill,
91 seed, csize.X, csize.Y + 2, csize.Z);
92 // 1-down overgeneraion
93 MapgenBasic::np_cave1 = params->np_cave1;
94 MapgenBasic::np_cave2 = params->np_cave2;
95 MapgenBasic::np_cavern = params->np_cavern;
97 humid_rivers = (spflags & MGVALLEYS_HUMID_RIVERS);
98 use_altitude_chill = (spflags & MGVALLEYS_ALT_CHILL);
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
236 // Generate caverns, tunnels and classic caves
237 if (flags & MG_CAVES) {
239 bool near_cavern = generateCaverns(stone_surface_max_y);
240 // Generate tunnels and classic caves
242 // Disable classic caves in this mapchunk by setting
243 // 'large cave depth' to world base. Avoids excessive liquid in
244 // large caverns and floating blobs of overgenerated liquid.
245 generateCaves(stone_surface_max_y, -MAX_MAP_GENERATION_LIMIT);
247 generateCaves(stone_surface_max_y, large_cave_depth);
251 if ((flags & MG_DUNGEONS) && full_node_min.Y >= dungeon_ymin &&
252 full_node_max.Y <= dungeon_ymax)
253 generateDungeons(stone_surface_max_y);
255 // Generate the registered decorations
256 if (flags & MG_DECORATIONS)
257 m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);
259 // Generate the registered ores
260 m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
262 // Sprinkle some dust on top after everything else was generated
265 updateLiquid(&data->transforming_liquid, full_node_min, full_node_max);
267 if (flags & MG_LIGHT)
268 calcLighting(node_min - v3s16(0, 1, 0), node_max + v3s16(0, 1, 0),
269 full_node_min, full_node_max);
271 this->generating = false;
273 //printf("makeChunk: %lums\n", t.stop());
277 void MapgenValleys::calculateNoise()
280 int y = node_min.Y - 1;
283 noise_inter_valley_slope->perlinMap2D(x, z);
284 noise_rivers->perlinMap2D(x, z);
285 noise_terrain_height->perlinMap2D(x, z);
286 noise_valley_depth->perlinMap2D(x, z);
287 noise_valley_profile->perlinMap2D(x, z);
289 noise_inter_valley_fill->perlinMap3D(x, y, z);
291 float heat_offset = 0.0f;
292 float humidity_scale = 1.0f;
293 // Altitude chill tends to reduce the average heat.
294 if (use_altitude_chill)
296 // River humidity tends to increase the humidity range.
298 humidity_scale = 0.8f;
300 for (s32 index = 0; index < csize.X * csize.Z; index++) {
301 m_bgen->heatmap[index] += heat_offset;
302 m_bgen->humidmap[index] *= humidity_scale;
308 for (tn.z = node_min.Z; tn.z <= node_max.Z; tn.z++)
309 for (tn.x = node_min.X; tn.x <= node_max.X; tn.x++, index++) {
310 // The parameters that we actually need to generate terrain are passed
311 // by address (and the return value).
312 tn.terrain_height = noise_terrain_height->result[index];
313 // River noise is replaced with base terrain, which is basically the
314 // height of the water table.
315 tn.rivers = &noise_rivers->result[index];
316 // Valley depth noise is replaced with the valley number that represents
317 // the height of terrain over rivers and is used to determine how close
318 // a river is for humidity calculation.
319 tn.valley = &noise_valley_depth->result[index];
320 tn.valley_profile = noise_valley_profile->result[index];
321 // Slope noise is replaced by the calculated slope which is used to get
322 // terrain height in the slow method, to create sharper mountains.
323 tn.slope = &noise_inter_valley_slope->result[index];
324 tn.inter_valley_fill = noise_inter_valley_fill->result[index];
326 // This is the actual terrain height.
327 float mount = terrainLevelFromNoise(&tn);
328 noise_terrain_height->result[index] = mount;
333 float MapgenValleys::terrainLevelFromNoise(TerrainNoise *tn)
335 // The square function changes the behaviour of this noise: very often
336 // small, and sometimes very high.
337 float valley_d = MYSQUARE(*tn->valley);
339 // valley_d is here because terrain is generally higher where valleys are
340 // deep (mountains). base represents the height of the rivers, most of the
342 float base = tn->terrain_height + valley_d;
344 // "river" represents the distance from the river
345 float river = std::fabs(*tn->rivers) - river_size_factor;
347 // Use the curve of the function 1-exp(-(x/a)^2) to model valleys.
348 // "valley" represents the height of the terrain, from the rivers.
349 float tv = std::fmax(river / tn->valley_profile, 0.0f);
350 *tn->valley = valley_d * (1.0f - std::exp(-MYSQUARE(tv)));
352 // Approximate height of the terrain at this point
353 float mount = base + *tn->valley;
355 *tn->slope *= *tn->valley;
357 // Base ground is returned as rivers since it's basically the water table.
360 // Rivers are placed where "river" is negative, so where the original noise
361 // value is close to zero.
363 // Use the the function -sqrt(1-x^2) which models a circle
364 float tr = river / river_size_factor + 1.0f;
365 float depth = (river_depth_bed *
366 std::sqrt(std::fmax(0.0f, 1.0f - MYSQUARE(tr))));
368 // base - depth : height of the bottom of the river
369 // water_level - 3 : don't make rivers below 3 nodes under the surface.
370 // We use three because that's as low as the swamp biomes go.
371 // There is no logical equivalent to this using rangelim.
373 std::fmin(std::fmax(base - depth, (float)(water_level - 3)), mount);
375 // Slope has no influence on rivers
383 // This avoids duplicating the code in terrainLevelFromNoise, adding only the
384 // final step of terrain generation without a noise map.
386 float MapgenValleys::adjustedTerrainLevelFromNoise(TerrainNoise *tn)
388 float mount = terrainLevelFromNoise(tn);
389 s16 y_start = myround(mount);
391 for (s16 y = y_start; y <= y_start + 1000; y++) {
393 NoisePerlin3D(&noise_inter_valley_fill->np, tn->x, y, tn->z, seed);
394 if (fill * *tn->slope < y - mount) {
395 mount = std::fmax((float)(y - 1), mount);
404 int MapgenValleys::getSpawnLevelAtPoint(v2s16 p)
406 // Check if in a river
407 float rivers = NoisePerlin2D(&noise_rivers->np, p.X, p.Y, seed);
408 if (std::fabs(rivers) < river_size_factor)
409 return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
411 s16 level_at_point = terrainLevelAtPoint(p.X, p.Y);
412 if (level_at_point <= water_level ||
413 level_at_point > water_level + 16)
414 return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
416 return level_at_point;
420 float MapgenValleys::terrainLevelAtPoint(s16 x, s16 z)
424 float rivers = NoisePerlin2D(&noise_rivers->np, x, z, seed);
425 float valley = NoisePerlin2D(&noise_valley_depth->np, x, z, seed);
426 float inter_valley_slope =
427 NoisePerlin2D(&noise_inter_valley_slope->np, x, z, seed);
431 tn.terrain_height = NoisePerlin2D(&noise_terrain_height->np, x, z, seed);
434 tn.valley_profile = NoisePerlin2D(&noise_valley_profile->np, x, z, seed);
435 tn.slope = &inter_valley_slope;
436 tn.inter_valley_fill = 0.0f;
438 return adjustedTerrainLevelFromNoise(&tn);
442 int MapgenValleys::generateTerrain()
444 // Raising this reduces the rate of evaporation
445 static const float evaporation = 300.0f;
446 static const float humidity_dropoff = 4.0f;
447 // Constant to convert altitude chill to heat
448 static const float alt_to_heat = 20.0f;
449 // Humidity reduction by altitude
450 static const float alt_to_humid = 10.0f;
452 MapNode n_air(CONTENT_AIR);
453 MapNode n_river_water(c_river_water_source);
454 MapNode n_stone(c_stone);
455 MapNode n_water(c_water_source);
457 const v3s16 &em = vm->m_area.getExtent();
458 s16 surface_max_y = -MAX_MAP_GENERATION_LIMIT;
461 for (s16 z = node_min.Z; z <= node_max.Z; z++)
462 for (s16 x = node_min.X; x <= node_max.X; x++, index_2d++) {
463 float river_y = noise_rivers->result[index_2d];
464 float surface_y = noise_terrain_height->result[index_2d];
465 float slope = noise_inter_valley_slope->result[index_2d];
466 float t_heat = m_bgen->heatmap[index_2d];
468 heightmap[index_2d] = -MAX_MAP_GENERATION_LIMIT;
470 if (surface_y > surface_max_y)
471 surface_max_y = std::ceil(surface_y);
474 // Derive heat from (base) altitude. This will be most correct
475 // at rivers, since other surface heights may vary below.
476 if (use_altitude_chill && (surface_y > 0.0f || river_y > 0.0f))
477 t_heat -= alt_to_heat *
478 std::fmax(surface_y, river_y) / altitude_chill;
480 // If humidity is low or heat is high, lower the water table
481 float delta = m_bgen->humidmap[index_2d] - 50.0f;
483 float t_evap = (t_heat - 32.0f) / evaporation;
484 river_y += delta * std::fmax(t_evap, 0.08f);
488 u32 index_3d = (z - node_min.Z) * zstride_1u1d + (x - node_min.X);
489 u32 index_data = vm->m_area.index(x, node_min.Y - 1, z);
491 for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
492 if (vm->m_data[index_data].getContent() == CONTENT_IGNORE) {
493 float fill = noise_inter_valley_fill->result[index_3d];
494 float surface_delta = (float)y - surface_y;
495 bool river = y < river_y - 1;
497 if (slope * fill > surface_delta) {
498 vm->m_data[index_data] = n_stone; // Stone
499 if (y > heightmap[index_2d])
500 heightmap[index_2d] = y;
501 if (y > surface_max_y)
503 } else if (y <= water_level) {
504 vm->m_data[index_data] = n_water; // Water
506 vm->m_data[index_data] = n_river_water; // River water
508 vm->m_data[index_data] = n_air; // Air
512 VoxelArea::add_y(em, index_data, 1);
516 if (heightmap[index_2d] == -MAX_MAP_GENERATION_LIMIT) {
517 s16 surface_y_int = myround(surface_y);
519 if (surface_y_int > node_max.Y + 1 ||
520 surface_y_int < node_min.Y - 1) {
521 // If surface_y is outside the chunk, it's good enough
522 heightmap[index_2d] = surface_y_int;
524 // If the ground is outside of this chunk, but surface_y is
525 // within the chunk, give a value outside.
526 heightmap[index_2d] = node_min.Y - 2;
531 // Use base ground (water table) in a riverbed, to avoid an
532 // unnatural rise in humidity.
533 float t_alt = std::fmax(noise_rivers->result[index_2d],
534 (float)heightmap[index_2d]);
535 float humid = m_bgen->humidmap[index_2d];
536 float water_depth = (t_alt - river_y) / humidity_dropoff;
537 humid *= 1.0f + std::pow(0.5f, std::fmax(water_depth, 1.0f));
539 // Reduce humidity with altitude (ignoring riverbeds)
541 humid -= alt_to_humid * t_alt / altitude_chill;
543 m_bgen->humidmap[index_2d] = humid;
546 // Assign the heat adjusted by any changed altitudes.
547 // The altitude will change about half the time.
548 if (use_altitude_chill) {
549 // Ground height ignoring riverbeds
550 float t_alt = std::fmax(noise_rivers->result[index_2d],
551 (float)heightmap[index_2d]);
553 if (humid_rivers && heightmap[index_2d] == (s16)myround(surface_y))
554 // The altitude hasn't changed. Use the first result
555 m_bgen->heatmap[index_2d] = t_heat;
556 else if (t_alt > 0.0f)
557 m_bgen->heatmap[index_2d] -=
558 alt_to_heat * t_alt / altitude_chill;
562 return surface_max_y;