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 lava_depth = params->lava_depth;
71 cavern_limit = params->cavern_limit;
72 cavern_taper = params->cavern_taper;
73 cavern_threshold = params->cavern_threshold;
74 dungeon_ymin = params->dungeon_ymin;
75 dungeon_ymax = params->dungeon_ymax;
78 noise_filler_depth = new Noise(¶ms->np_filler_depth, seed, csize.X, csize.Z);
79 noise_inter_valley_slope = new Noise(¶ms->np_inter_valley_slope, seed, csize.X, csize.Z);
80 noise_rivers = new Noise(¶ms->np_rivers, seed, csize.X, csize.Z);
81 noise_terrain_height = new Noise(¶ms->np_terrain_height, seed, csize.X, csize.Z);
82 noise_valley_depth = new Noise(¶ms->np_valley_depth, seed, csize.X, csize.Z);
83 noise_valley_profile = new Noise(¶ms->np_valley_profile, seed, csize.X, csize.Z);
86 // 1-up 1-down overgeneration
87 noise_inter_valley_fill = new Noise(¶ms->np_inter_valley_fill,
88 seed, csize.X, csize.Y + 2, csize.Z);
89 // 1-down overgeneraion
90 MapgenBasic::np_cave1 = params->np_cave1;
91 MapgenBasic::np_cave2 = params->np_cave2;
92 MapgenBasic::np_cavern = params->np_cavern;
93 MapgenBasic::np_dungeons = params->np_dungeons;
97 MapgenValleys::~MapgenValleys()
99 delete noise_filler_depth;
100 delete noise_inter_valley_fill;
101 delete noise_inter_valley_slope;
103 delete noise_terrain_height;
104 delete noise_valley_depth;
105 delete noise_valley_profile;
109 MapgenValleysParams::MapgenValleysParams():
110 np_filler_depth (0.0, 1.2, v3f(256, 256, 256), 1605, 3, 0.5, 2.0),
111 np_inter_valley_fill (0.0, 1.0, v3f(256, 512, 256), 1993, 6, 0.8, 2.0),
112 np_inter_valley_slope (0.5, 0.5, v3f(128, 128, 128), 746, 1, 1.0, 2.0),
113 np_rivers (0.0, 1.0, v3f(256, 256, 256), -6050, 5, 0.6, 2.0),
114 np_terrain_height (-10.0, 50.0, v3f(1024, 1024, 1024), 5202, 6, 0.4, 2.0),
115 np_valley_depth (5.0, 4.0, v3f(512, 512, 512), -1914, 1, 1.0, 2.0),
116 np_valley_profile (0.6, 0.50, v3f(512, 512, 512), 777, 1, 1.0, 2.0),
117 np_cave1 (0.0, 12.0, v3f(61, 61, 61), 52534, 3, 0.5, 2.0),
118 np_cave2 (0.0, 12.0, v3f(67, 67, 67), 10325, 3, 0.5, 2.0),
119 np_cavern (0.0, 1.0, v3f(768, 256, 768), 59033, 6, 0.63, 2.0),
120 np_dungeons (0.9, 0.5, v3f(500, 500, 500), 0, 2, 0.8, 2.0)
125 void MapgenValleysParams::readParams(const Settings *settings)
127 settings->getFlagStrNoEx("mgvalleys_spflags", spflags, flagdesc_mapgen_valleys);
128 settings->getU16NoEx("mgvalleys_altitude_chill", altitude_chill);
129 settings->getS16NoEx("mgvalleys_large_cave_depth", large_cave_depth);
130 settings->getS16NoEx("mgvalleys_lava_depth", lava_depth);
131 settings->getU16NoEx("mgvalleys_river_depth", river_depth);
132 settings->getU16NoEx("mgvalleys_river_size", river_size);
133 settings->getFloatNoEx("mgvalleys_cave_width", cave_width);
134 settings->getS16NoEx("mgvalleys_cavern_limit", cavern_limit);
135 settings->getS16NoEx("mgvalleys_cavern_taper", cavern_taper);
136 settings->getFloatNoEx("mgvalleys_cavern_threshold", cavern_threshold);
137 settings->getS16NoEx("mgvalleys_dungeon_ymin", dungeon_ymin);
138 settings->getS16NoEx("mgvalleys_dungeon_ymax", dungeon_ymax);
140 settings->getNoiseParams("mgvalleys_np_filler_depth", np_filler_depth);
141 settings->getNoiseParams("mgvalleys_np_inter_valley_fill", np_inter_valley_fill);
142 settings->getNoiseParams("mgvalleys_np_inter_valley_slope", np_inter_valley_slope);
143 settings->getNoiseParams("mgvalleys_np_rivers", np_rivers);
144 settings->getNoiseParams("mgvalleys_np_terrain_height", np_terrain_height);
145 settings->getNoiseParams("mgvalleys_np_valley_depth", np_valley_depth);
146 settings->getNoiseParams("mgvalleys_np_valley_profile", np_valley_profile);
148 settings->getNoiseParams("mgvalleys_np_cave1", np_cave1);
149 settings->getNoiseParams("mgvalleys_np_cave2", np_cave2);
150 settings->getNoiseParams("mgvalleys_np_cavern", np_cavern);
151 settings->getNoiseParams("mgvalleys_np_dungeons", np_dungeons);
155 void MapgenValleysParams::writeParams(Settings *settings) const
157 settings->setFlagStr("mgvalleys_spflags", spflags, flagdesc_mapgen_valleys, U32_MAX);
158 settings->setU16("mgvalleys_altitude_chill", altitude_chill);
159 settings->setS16("mgvalleys_large_cave_depth", large_cave_depth);
160 settings->setS16("mgvalleys_lava_depth", lava_depth);
161 settings->setU16("mgvalleys_river_depth", river_depth);
162 settings->setU16("mgvalleys_river_size", river_size);
163 settings->setFloat("mgvalleys_cave_width", cave_width);
164 settings->setS16("mgvalleys_cavern_limit", cavern_limit);
165 settings->setS16("mgvalleys_cavern_taper", cavern_taper);
166 settings->setFloat("mgvalleys_cavern_threshold", cavern_threshold);
167 settings->setS16("mgvalleys_dungeon_ymin", dungeon_ymin);
168 settings->setS16("mgvalleys_dungeon_ymax", dungeon_ymax);
170 settings->setNoiseParams("mgvalleys_np_filler_depth", np_filler_depth);
171 settings->setNoiseParams("mgvalleys_np_inter_valley_fill", np_inter_valley_fill);
172 settings->setNoiseParams("mgvalleys_np_inter_valley_slope", np_inter_valley_slope);
173 settings->setNoiseParams("mgvalleys_np_rivers", np_rivers);
174 settings->setNoiseParams("mgvalleys_np_terrain_height", np_terrain_height);
175 settings->setNoiseParams("mgvalleys_np_valley_depth", np_valley_depth);
176 settings->setNoiseParams("mgvalleys_np_valley_profile", np_valley_profile);
178 settings->setNoiseParams("mgvalleys_np_cave1", np_cave1);
179 settings->setNoiseParams("mgvalleys_np_cave2", np_cave2);
180 settings->setNoiseParams("mgvalleys_np_cavern", np_cavern);
181 settings->setNoiseParams("mgvalleys_np_dungeons", np_dungeons);
185 void MapgenValleys::makeChunk(BlockMakeData *data)
188 assert(data->vmanip);
189 assert(data->nodedef);
190 assert(data->blockpos_requested.X >= data->blockpos_min.X &&
191 data->blockpos_requested.Y >= data->blockpos_min.Y &&
192 data->blockpos_requested.Z >= data->blockpos_min.Z);
193 assert(data->blockpos_requested.X <= data->blockpos_max.X &&
194 data->blockpos_requested.Y <= data->blockpos_max.Y &&
195 data->blockpos_requested.Z <= data->blockpos_max.Z);
197 //TimeTaker t("makeChunk");
199 this->generating = true;
200 this->vm = data->vmanip;
201 this->ndef = data->nodedef;
203 v3s16 blockpos_min = data->blockpos_min;
204 v3s16 blockpos_max = data->blockpos_max;
205 node_min = blockpos_min * MAP_BLOCKSIZE;
206 node_max = (blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
207 full_node_min = (blockpos_min - 1) * MAP_BLOCKSIZE;
208 full_node_max = (blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
210 blockseed = getBlockSeed2(full_node_min, seed);
212 // Generate biome noises. Note this must be executed strictly before
213 // generateTerrain, because generateTerrain depends on intermediate
214 // biome-related noises.
215 m_bgen->calcBiomeNoise(node_min);
218 s16 stone_surface_max_y = generateTerrain();
221 updateHeightmap(node_min, node_max);
223 // Place biome-specific nodes and build biomemap
224 if (flags & MG_BIOMES) {
228 // Generate tunnels, caverns and large randomwalk caves
229 if (flags & MG_CAVES) {
230 // Generate tunnels first as caverns confuse them
231 generateCavesNoiseIntersection(stone_surface_max_y);
234 bool near_cavern = generateCavernsNoise(stone_surface_max_y);
236 // Generate large randomwalk caves
238 // Disable large randomwalk caves in this mapchunk by setting
239 // 'large cave depth' to world base. Avoids excessive liquid in
240 // large caverns and floating blobs of overgenerated liquid.
241 generateCavesRandomWalk(stone_surface_max_y,
242 -MAX_MAP_GENERATION_LIMIT);
244 generateCavesRandomWalk(stone_surface_max_y, large_cave_depth);
247 // Generate the registered ores
248 m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
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 // Sprinkle some dust on top after everything else was generated
260 if (flags & MG_BIOMES)
263 updateLiquid(&data->transforming_liquid, full_node_min, full_node_max);
265 if (flags & MG_LIGHT)
266 calcLighting(node_min - v3s16(0, 1, 0), node_max + v3s16(0, 1, 0),
267 full_node_min, full_node_max);
269 this->generating = false;
271 //printf("makeChunk: %lums\n", t.stop());
275 int MapgenValleys::getSpawnLevelAtPoint(v2s16 p)
277 // Check if in a river channel
278 float n_rivers = NoisePerlin2D(&noise_rivers->np, p.X, p.Y, seed);
279 if (std::fabs(n_rivers) <= river_size_factor)
280 // Unsuitable spawn point
281 return MAX_MAP_GENERATION_LIMIT;
283 float n_slope = NoisePerlin2D(&noise_inter_valley_slope->np, p.X, p.Y, seed);
284 float n_terrain_height = NoisePerlin2D(&noise_terrain_height->np, p.X, p.Y, seed);
285 float n_valley = NoisePerlin2D(&noise_valley_depth->np, p.X, p.Y, seed);
286 float n_valley_profile = NoisePerlin2D(&noise_valley_profile->np, p.X, p.Y, seed);
288 float valley_d = n_valley * n_valley;
289 float base = n_terrain_height + valley_d;
290 float river = std::fabs(n_rivers) - river_size_factor;
291 float tv = std::fmax(river / n_valley_profile, 0.0f);
292 float valley_h = valley_d * (1.0f - std::exp(-tv * tv));
293 float surface_y = base + valley_h;
294 float slope = n_slope * valley_h;
295 float river_y = base - 1.0f;
297 // Raising the maximum spawn level above 'water_level + 16' is necessary for custom
298 // parameters that set average terrain level much higher than water_level.
299 s16 max_spawn_y = std::fmax(
300 noise_terrain_height->np.offset +
301 noise_valley_depth->np.offset * noise_valley_depth->np.offset,
304 // Starting spawn search at max_spawn_y + 128 ensures 128 nodes of open
305 // space above spawn position. Avoids spawning in possibly sealed voids.
306 for (s16 y = max_spawn_y + 128; y >= water_level; y--) {
307 float n_fill = NoisePerlin3D(&noise_inter_valley_fill->np, p.X, y, p.Y, seed);
308 float surface_delta = (float)y - surface_y;
309 float density = slope * n_fill - surface_delta;
311 if (density > 0.0f) { // If solid
312 // Sometimes surface level is below river water level in places that are not
314 if (y < water_level || y > max_spawn_y || y < (s16)river_y)
315 // Unsuitable spawn point
316 return MAX_MAP_GENERATION_LIMIT;
318 // y + 2 because y is surface and due to biome 'dust' nodes.
322 // Unsuitable spawn position, no ground found
323 return MAX_MAP_GENERATION_LIMIT;
327 int MapgenValleys::generateTerrain()
329 MapNode n_air(CONTENT_AIR);
330 MapNode n_river_water(c_river_water_source);
331 MapNode n_stone(c_stone);
332 MapNode n_water(c_water_source);
334 noise_inter_valley_slope->perlinMap2D(node_min.X, node_min.Z);
335 noise_rivers->perlinMap2D(node_min.X, node_min.Z);
336 noise_terrain_height->perlinMap2D(node_min.X, node_min.Z);
337 noise_valley_depth->perlinMap2D(node_min.X, node_min.Z);
338 noise_valley_profile->perlinMap2D(node_min.X, node_min.Z);
340 noise_inter_valley_fill->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
342 const v3s16 &em = vm->m_area.getExtent();
343 s16 surface_max_y = -MAX_MAP_GENERATION_LIMIT;
346 for (s16 z = node_min.Z; z <= node_max.Z; z++)
347 for (s16 x = node_min.X; x <= node_max.X; x++, index_2d++) {
348 float n_slope = noise_inter_valley_slope->result[index_2d];
349 float n_rivers = noise_rivers->result[index_2d];
350 float n_terrain_height = noise_terrain_height->result[index_2d];
351 float n_valley = noise_valley_depth->result[index_2d];
352 float n_valley_profile = noise_valley_profile->result[index_2d];
354 float valley_d = n_valley * n_valley;
355 // 'base' represents the level of the river banks
356 float base = n_terrain_height + valley_d;
357 // 'river' represents the distance from the river edge
358 float river = std::fabs(n_rivers) - river_size_factor;
359 // Use the curve of the function 1-exp(-(x/a)^2) to model valleys.
360 // 'valley_h' represents the height of the terrain, from the rivers.
361 float tv = std::fmax(river / n_valley_profile, 0.0f);
362 float valley_h = valley_d * (1.0f - std::exp(-tv * tv));
363 // Approximate height of the terrain
364 float surface_y = base + valley_h;
365 float slope = n_slope * valley_h;
366 // River water surface is 1 node below river banks
367 float river_y = base - 1.0f;
369 // Rivers are placed where 'river' is negative
371 // Use the the function -sqrt(1-x^2) which models a circle
372 float tr = river / river_size_factor + 1.0f;
373 float depth = (river_depth_bed *
374 std::sqrt(std::fmax(0.0f, 1.0f - tr * tr)));
375 // There is no logical equivalent to this using rangelim
376 surface_y = std::fmin(
377 std::fmax(base - depth, (float)(water_level - 3)),
382 // Optionally vary river depth according to heat and humidity
383 if (spflags & MGVALLEYS_VARY_RIVER_DEPTH) {
384 float t_heat = m_bgen->heatmap[index_2d];
385 float heat = (spflags & MGVALLEYS_ALT_CHILL) ?
386 // Match heat value calculated below in
387 // 'Optionally decrease heat with altitude'.
388 // In rivers, 'ground height ignoring riverbeds' is 'base'.
389 // As this only affects river water we can assume y > water_level.
390 t_heat + 5.0f - (base - water_level) * 20.0f / altitude_chill :
392 float delta = m_bgen->humidmap[index_2d] - 50.0f;
394 float t_evap = (heat - 32.0f) / 300.0f;
395 river_y += delta * std::fmax(t_evap, 0.08f);
399 // Highest solid node in column
400 s16 column_max_y = surface_y;
401 u32 index_3d = (z - node_min.Z) * zstride_1u1d + (x - node_min.X);
402 u32 index_data = vm->m_area.index(x, node_min.Y - 1, z);
404 for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
405 if (vm->m_data[index_data].getContent() == CONTENT_IGNORE) {
406 float n_fill = noise_inter_valley_fill->result[index_3d];
407 float surface_delta = (float)y - surface_y;
408 // Density = density noise + density gradient
409 float density = slope * n_fill - surface_delta;
411 if (density > 0.0f) {
412 vm->m_data[index_data] = n_stone; // Stone
413 if (y > surface_max_y)
415 if (y > column_max_y)
417 } else if (y <= water_level) {
418 vm->m_data[index_data] = n_water; // Water
419 } else if (y <= (s16)river_y) {
420 vm->m_data[index_data] = n_river_water; // River water
422 vm->m_data[index_data] = n_air; // Air
426 VoxelArea::add_y(em, index_data, 1);
430 // Optionally increase humidity around rivers
431 if (spflags & MGVALLEYS_HUMID_RIVERS) {
432 // Compensate to avoid increasing average humidity
433 m_bgen->humidmap[index_2d] *= 0.8f;
434 // Ground height ignoring riverbeds
435 float t_alt = std::fmax(base, (float)column_max_y);
436 float water_depth = (t_alt - base) / 4.0f;
437 m_bgen->humidmap[index_2d] *=
438 1.0f + std::pow(0.5f, std::fmax(water_depth, 1.0f));
441 // Optionally decrease humidity with altitude
442 if (spflags & MGVALLEYS_ALT_DRY) {
443 // Ground height ignoring riverbeds
444 float t_alt = std::fmax(base, (float)column_max_y);
445 // Only decrease above water_level
446 if (t_alt > water_level)
447 m_bgen->humidmap[index_2d] -=
448 (t_alt - water_level) * 10.0f / altitude_chill;
451 // Optionally decrease heat with altitude
452 if (spflags & MGVALLEYS_ALT_CHILL) {
453 // Compensate to avoid reducing the average heat
454 m_bgen->heatmap[index_2d] += 5.0f;
455 // Ground height ignoring riverbeds
456 float t_alt = std::fmax(base, (float)column_max_y);
457 // Only decrease above water_level
458 if (t_alt > water_level)
459 m_bgen->heatmap[index_2d] -=
460 (t_alt - water_level) * 20.0f / altitude_chill;
464 return surface_max_y;