cleanup
[waspsaliva.git] / src / mapgen / mapgen_valleys.cpp
blobc4234857e8afc611a6ac0d4f90d0e27a43f677eb
1 /*
2 Minetest
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.
28 #include "mapgen.h"
29 #include "voxel.h"
30 #include "noise.h"
31 #include "mapblock.h"
32 #include "mapnode.h"
33 #include "map.h"
34 #include "nodedef.h"
35 #include "voxelalgorithms.h"
36 //#include "profiler.h" // For TimeTaker
37 #include "settings.h" // For g_settings
38 #include "emerge.h"
39 #include "dungeongen.h"
40 #include "mg_biome.h"
41 #include "mg_ore.h"
42 #include "mg_decoration.h"
43 #include "mapgen_valleys.h"
44 #include "cavegen.h"
45 #include <cmath>
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},
53 {NULL, 0}
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;
81 //// 2D Terrain noise
82 noise_filler_depth = new Noise(&params->np_filler_depth, seed, csize.X, csize.Z);
83 noise_inter_valley_slope = new Noise(&params->np_inter_valley_slope, seed, csize.X, csize.Z);
84 noise_rivers = new Noise(&params->np_rivers, seed, csize.X, csize.Z);
85 noise_terrain_height = new Noise(&params->np_terrain_height, seed, csize.X, csize.Z);
86 noise_valley_depth = new Noise(&params->np_valley_depth, seed, csize.X, csize.Z);
87 noise_valley_profile = new Noise(&params->np_valley_profile, seed, csize.X, csize.Z);
89 //// 3D Terrain noise
90 // 1-up 1-down overgeneration
91 noise_inter_valley_fill = new Noise(&params->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;
106 delete noise_rivers;
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)
210 // Pre-conditions
211 assert(data->vmanip);
212 assert(data->nodedef);
214 //TimeTaker t("makeChunk");
216 this->generating = true;
217 this->vm = data->vmanip;
218 this->ndef = data->nodedef;
220 v3s16 blockpos_min = data->blockpos_min;
221 v3s16 blockpos_max = data->blockpos_max;
222 node_min = blockpos_min * MAP_BLOCKSIZE;
223 node_max = (blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
224 full_node_min = (blockpos_min - 1) * MAP_BLOCKSIZE;
225 full_node_max = (blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
227 blockseed = getBlockSeed2(full_node_min, seed);
229 // Generate biome noises. Note this must be executed strictly before
230 // generateTerrain, because generateTerrain depends on intermediate
231 // biome-related noises.
232 m_bgen->calcBiomeNoise(node_min);
234 // Generate terrain
235 s16 stone_surface_max_y = generateTerrain();
237 // Create heightmap
238 updateHeightmap(node_min, node_max);
240 // Place biome-specific nodes and build biomemap
241 if (flags & MG_BIOMES) {
242 generateBiomes();
245 // Generate tunnels, caverns and large randomwalk caves
246 if (flags & MG_CAVES) {
247 // Generate tunnels first as caverns confuse them
248 generateCavesNoiseIntersection(stone_surface_max_y);
250 // Generate caverns
251 bool near_cavern = generateCavernsNoise(stone_surface_max_y);
253 // Generate large randomwalk caves
254 if (near_cavern)
255 // Disable large randomwalk caves in this mapchunk by setting
256 // 'large cave depth' to world base. Avoids excessive liquid in
257 // large caverns and floating blobs of overgenerated liquid.
258 generateCavesRandomWalk(stone_surface_max_y,
259 -MAX_MAP_GENERATION_LIMIT);
260 else
261 generateCavesRandomWalk(stone_surface_max_y, large_cave_depth);
264 // Generate the registered ores
265 if (flags & MG_ORES)
266 m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
268 // Dungeon creation
269 if (flags & MG_DUNGEONS)
270 generateDungeons(stone_surface_max_y);
272 // Generate the registered decorations
273 if (flags & MG_DECORATIONS)
274 m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);
276 // Sprinkle some dust on top after everything else was generated
277 if (flags & MG_BIOMES)
278 dustTopNodes();
280 updateLiquid(&data->transforming_liquid, full_node_min, full_node_max);
282 if (flags & MG_LIGHT)
283 calcLighting(node_min - v3s16(0, 1, 0), node_max + v3s16(0, 1, 0),
284 full_node_min, full_node_max);
286 this->generating = false;
288 //printf("makeChunk: %lums\n", t.stop());
292 int MapgenValleys::getSpawnLevelAtPoint(v2s16 p)
294 // Check if in a river channel
295 float n_rivers = NoisePerlin2D(&noise_rivers->np, p.X, p.Y, seed);
296 if (std::fabs(n_rivers) <= river_size_factor)
297 // Unsuitable spawn point
298 return MAX_MAP_GENERATION_LIMIT;
300 float n_slope = NoisePerlin2D(&noise_inter_valley_slope->np, p.X, p.Y, seed);
301 float n_terrain_height = NoisePerlin2D(&noise_terrain_height->np, p.X, p.Y, seed);
302 float n_valley = NoisePerlin2D(&noise_valley_depth->np, p.X, p.Y, seed);
303 float n_valley_profile = NoisePerlin2D(&noise_valley_profile->np, p.X, p.Y, seed);
305 float valley_d = n_valley * n_valley;
306 float base = n_terrain_height + valley_d;
307 float river = std::fabs(n_rivers) - river_size_factor;
308 float tv = std::fmax(river / n_valley_profile, 0.0f);
309 float valley_h = valley_d * (1.0f - std::exp(-tv * tv));
310 float surface_y = base + valley_h;
311 float slope = n_slope * valley_h;
312 float river_y = base - 1.0f;
314 // Raising the maximum spawn level above 'water_level + 16' is necessary for custom
315 // parameters that set average terrain level much higher than water_level.
316 s16 max_spawn_y = std::fmax(
317 noise_terrain_height->np.offset +
318 noise_valley_depth->np.offset * noise_valley_depth->np.offset,
319 water_level + 16);
321 // Starting spawn search at max_spawn_y + 128 ensures 128 nodes of open
322 // space above spawn position. Avoids spawning in possibly sealed voids.
323 for (s16 y = max_spawn_y + 128; y >= water_level; y--) {
324 float n_fill = NoisePerlin3D(&noise_inter_valley_fill->np, p.X, y, p.Y, seed);
325 float surface_delta = (float)y - surface_y;
326 float density = slope * n_fill - surface_delta;
328 if (density > 0.0f) { // If solid
329 // Sometimes surface level is below river water level in places that are not
330 // river channels.
331 if (y < water_level || y > max_spawn_y || y < (s16)river_y)
332 // Unsuitable spawn point
333 return MAX_MAP_GENERATION_LIMIT;
335 // y + 2 because y is surface and due to biome 'dust' nodes.
336 return y + 2;
339 // Unsuitable spawn position, no ground found
340 return MAX_MAP_GENERATION_LIMIT;
344 int MapgenValleys::generateTerrain()
346 MapNode n_air(CONTENT_AIR);
347 MapNode n_river_water(c_river_water_source);
348 MapNode n_stone(c_stone);
349 MapNode n_water(c_water_source);
351 noise_inter_valley_slope->perlinMap2D(node_min.X, node_min.Z);
352 noise_rivers->perlinMap2D(node_min.X, node_min.Z);
353 noise_terrain_height->perlinMap2D(node_min.X, node_min.Z);
354 noise_valley_depth->perlinMap2D(node_min.X, node_min.Z);
355 noise_valley_profile->perlinMap2D(node_min.X, node_min.Z);
357 noise_inter_valley_fill->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
359 const v3s16 &em = vm->m_area.getExtent();
360 s16 surface_max_y = -MAX_MAP_GENERATION_LIMIT;
361 u32 index_2d = 0;
363 for (s16 z = node_min.Z; z <= node_max.Z; z++)
364 for (s16 x = node_min.X; x <= node_max.X; x++, index_2d++) {
365 float n_slope = noise_inter_valley_slope->result[index_2d];
366 float n_rivers = noise_rivers->result[index_2d];
367 float n_terrain_height = noise_terrain_height->result[index_2d];
368 float n_valley = noise_valley_depth->result[index_2d];
369 float n_valley_profile = noise_valley_profile->result[index_2d];
371 float valley_d = n_valley * n_valley;
372 // 'base' represents the level of the river banks
373 float base = n_terrain_height + valley_d;
374 // 'river' represents the distance from the river edge
375 float river = std::fabs(n_rivers) - river_size_factor;
376 // Use the curve of the function 1-exp(-(x/a)^2) to model valleys.
377 // 'valley_h' represents the height of the terrain, from the rivers.
378 float tv = std::fmax(river / n_valley_profile, 0.0f);
379 float valley_h = valley_d * (1.0f - std::exp(-tv * tv));
380 // Approximate height of the terrain
381 float surface_y = base + valley_h;
382 float slope = n_slope * valley_h;
383 // River water surface is 1 node below river banks
384 float river_y = base - 1.0f;
386 // Rivers are placed where 'river' is negative
387 if (river < 0.0f) {
388 // Use the function -sqrt(1-x^2) which models a circle
389 float tr = river / river_size_factor + 1.0f;
390 float depth = (river_depth_bed *
391 std::sqrt(std::fmax(0.0f, 1.0f - tr * tr)));
392 // There is no logical equivalent to this using rangelim
393 surface_y = std::fmin(
394 std::fmax(base - depth, (float)(water_level - 3)),
395 surface_y);
396 slope = 0.0f;
399 // Optionally vary river depth according to heat and humidity
400 if (spflags & MGVALLEYS_VARY_RIVER_DEPTH) {
401 float t_heat = m_bgen->heatmap[index_2d];
402 float heat = (spflags & MGVALLEYS_ALT_CHILL) ?
403 // Match heat value calculated below in
404 // 'Optionally decrease heat with altitude'.
405 // In rivers, 'ground height ignoring riverbeds' is 'base'.
406 // As this only affects river water we can assume y > water_level.
407 t_heat + 5.0f - (base - water_level) * 20.0f / altitude_chill :
408 t_heat;
409 float delta = m_bgen->humidmap[index_2d] - 50.0f;
410 if (delta < 0.0f) {
411 float t_evap = (heat - 32.0f) / 300.0f;
412 river_y += delta * std::fmax(t_evap, 0.08f);
416 // Highest solid node in column
417 s16 column_max_y = surface_y;
418 u32 index_3d = (z - node_min.Z) * zstride_1u1d + (x - node_min.X);
419 u32 index_data = vm->m_area.index(x, node_min.Y - 1, z);
421 for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
422 if (vm->m_data[index_data].getContent() == CONTENT_IGNORE) {
423 float n_fill = noise_inter_valley_fill->result[index_3d];
424 float surface_delta = (float)y - surface_y;
425 // Density = density noise + density gradient
426 float density = slope * n_fill - surface_delta;
428 if (density > 0.0f) {
429 vm->m_data[index_data] = n_stone; // Stone
430 if (y > surface_max_y)
431 surface_max_y = y;
432 if (y > column_max_y)
433 column_max_y = y;
434 } else if (y <= water_level) {
435 vm->m_data[index_data] = n_water; // Water
436 } else if (y <= (s16)river_y) {
437 vm->m_data[index_data] = n_river_water; // River water
438 } else {
439 vm->m_data[index_data] = n_air; // Air
443 VoxelArea::add_y(em, index_data, 1);
444 index_3d += ystride;
447 // Optionally increase humidity around rivers
448 if (spflags & MGVALLEYS_HUMID_RIVERS) {
449 // Compensate to avoid increasing average humidity
450 m_bgen->humidmap[index_2d] *= 0.8f;
451 // Ground height ignoring riverbeds
452 float t_alt = std::fmax(base, (float)column_max_y);
453 float water_depth = (t_alt - base) / 4.0f;
454 m_bgen->humidmap[index_2d] *=
455 1.0f + std::pow(0.5f, std::fmax(water_depth, 1.0f));
458 // Optionally decrease humidity with altitude
459 if (spflags & MGVALLEYS_ALT_DRY) {
460 // Ground height ignoring riverbeds
461 float t_alt = std::fmax(base, (float)column_max_y);
462 // Only decrease above water_level
463 if (t_alt > water_level)
464 m_bgen->humidmap[index_2d] -=
465 (t_alt - water_level) * 10.0f / altitude_chill;
468 // Optionally decrease heat with altitude
469 if (spflags & MGVALLEYS_ALT_CHILL) {
470 // Compensate to avoid reducing the average heat
471 m_bgen->heatmap[index_2d] += 5.0f;
472 // Ground height ignoring riverbeds
473 float t_alt = std::fmax(base, (float)column_max_y);
474 // Only decrease above water_level
475 if (t_alt > water_level)
476 m_bgen->heatmap[index_2d] -=
477 (t_alt - water_level) * 20.0f / altitude_chill;
481 return surface_max_y;