]> git.lizzy.rs Git - dragonfireclient.git/blob - src/mapgen/mapgen_valleys.cpp
Update settingtypes.txt for new languages
[dragonfireclient.git] / src / mapgen / mapgen_valleys.cpp
1 /*
2 Minetest
3 Copyright (C) 2016-2019 Duane Robertson <duane@duanerobertson.com>
4 Copyright (C) 2016-2019 paramat
5
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.
9
10 Licensing changed by permission of Gael de Sailly.
11
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.
16
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.
21
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.
25 */
26
27
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>
46
47
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}
54 };
55
56
57 MapgenValleys::MapgenValleys(MapgenValleysParams *params, EmergeManager *emerge)
58         : MapgenBasic(MAPGEN_VALLEYS, params, emerge)
59 {
60         // NOTE: MapgenValleys has a hard dependency on BiomeGenOriginal
61         m_bgen = (BiomeGenOriginal *)biomegen;
62
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;
67
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;
80
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);
88
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;
98 }
99
100
101 MapgenValleys::~MapgenValleys()
102 {
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;
110 }
111
112
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)
125 {
126 }
127
128
129 void MapgenValleysParams::readParams(const Settings *settings)
130 {
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);
147
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);
155
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);
160 }
161
162
163 void MapgenValleysParams::writeParams(Settings *settings) const
164 {
165         settings->setFlagStr("mgvalleys_spflags", spflags, flagdesc_mapgen_valleys, U32_MAX);
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);
181
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);
189
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);
194 }
195
196
197 void MapgenValleys::makeChunk(BlockMakeData *data)
198 {
199         // Pre-conditions
200         assert(data->vmanip);
201         assert(data->nodedef);
202         assert(data->blockpos_requested.X >= data->blockpos_min.X &&
203                 data->blockpos_requested.Y >= data->blockpos_min.Y &&
204                 data->blockpos_requested.Z >= data->blockpos_min.Z);
205         assert(data->blockpos_requested.X <= data->blockpos_max.X &&
206                 data->blockpos_requested.Y <= data->blockpos_max.Y &&
207                 data->blockpos_requested.Z <= data->blockpos_max.Z);
208
209         //TimeTaker t("makeChunk");
210
211         this->generating = true;
212         this->vm = data->vmanip;
213         this->ndef = data->nodedef;
214
215         v3s16 blockpos_min = data->blockpos_min;
216         v3s16 blockpos_max = data->blockpos_max;
217         node_min = blockpos_min * MAP_BLOCKSIZE;
218         node_max = (blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
219         full_node_min = (blockpos_min - 1) * MAP_BLOCKSIZE;
220         full_node_max = (blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
221
222         blockseed = getBlockSeed2(full_node_min, seed);
223
224         // Generate biome noises. Note this must be executed strictly before
225         // generateTerrain, because generateTerrain depends on intermediate
226         // biome-related noises.
227         m_bgen->calcBiomeNoise(node_min);
228
229         // Generate terrain
230         s16 stone_surface_max_y = generateTerrain();
231
232         // Create heightmap
233         updateHeightmap(node_min, node_max);
234
235         // Place biome-specific nodes and build biomemap
236         if (flags & MG_BIOMES) {
237                 generateBiomes();
238         }
239
240         // Generate tunnels, caverns and large randomwalk caves
241         if (flags & MG_CAVES) {
242                 // Generate tunnels first as caverns confuse them
243                 generateCavesNoiseIntersection(stone_surface_max_y);
244
245                 // Generate caverns
246                 bool near_cavern = generateCavernsNoise(stone_surface_max_y);
247
248                 // Generate large randomwalk caves
249                 if (near_cavern)
250                         // Disable large randomwalk caves in this mapchunk by setting
251                         // 'large cave depth' to world base. Avoids excessive liquid in
252                         // large caverns and floating blobs of overgenerated liquid.
253                         generateCavesRandomWalk(stone_surface_max_y,
254                                 -MAX_MAP_GENERATION_LIMIT);
255                 else
256                         generateCavesRandomWalk(stone_surface_max_y, large_cave_depth);
257         }
258
259         // Generate the registered ores
260         m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
261
262         // Dungeon creation
263         if (flags & MG_DUNGEONS)
264                 generateDungeons(stone_surface_max_y);
265
266         // Generate the registered decorations
267         if (flags & MG_DECORATIONS)
268                 m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);
269
270         // Sprinkle some dust on top after everything else was generated
271         if (flags & MG_BIOMES)
272                 dustTopNodes();
273
274         updateLiquid(&data->transforming_liquid, full_node_min, full_node_max);
275
276         if (flags & MG_LIGHT)
277                 calcLighting(node_min - v3s16(0, 1, 0), node_max + v3s16(0, 1, 0),
278                         full_node_min, full_node_max);
279
280         this->generating = false;
281
282         //printf("makeChunk: %lums\n", t.stop());
283 }
284
285
286 int MapgenValleys::getSpawnLevelAtPoint(v2s16 p)
287 {
288         // Check if in a river channel
289         float n_rivers = NoisePerlin2D(&noise_rivers->np, p.X, p.Y, seed);
290         if (std::fabs(n_rivers) <= river_size_factor)
291                 // Unsuitable spawn point
292                 return MAX_MAP_GENERATION_LIMIT;
293
294         float n_slope          = NoisePerlin2D(&noise_inter_valley_slope->np, p.X, p.Y, seed);
295         float n_terrain_height = NoisePerlin2D(&noise_terrain_height->np, p.X, p.Y, seed);
296         float n_valley         = NoisePerlin2D(&noise_valley_depth->np, p.X, p.Y, seed);
297         float n_valley_profile = NoisePerlin2D(&noise_valley_profile->np, p.X, p.Y, seed);
298
299         float valley_d = n_valley * n_valley;
300         float base = n_terrain_height + valley_d;
301         float river = std::fabs(n_rivers) - river_size_factor;
302         float tv = std::fmax(river / n_valley_profile, 0.0f);
303         float valley_h = valley_d * (1.0f - std::exp(-tv * tv));
304         float surface_y = base + valley_h;
305         float slope = n_slope * valley_h;
306         float river_y = base - 1.0f;
307
308         // Raising the maximum spawn level above 'water_level + 16' is necessary for custom
309         // parameters that set average terrain level much higher than water_level.
310         s16 max_spawn_y = std::fmax(
311                 noise_terrain_height->np.offset +
312                 noise_valley_depth->np.offset * noise_valley_depth->np.offset,
313                 water_level + 16);
314
315         // Starting spawn search at max_spawn_y + 128 ensures 128 nodes of open
316         // space above spawn position. Avoids spawning in possibly sealed voids.
317         for (s16 y = max_spawn_y + 128; y >= water_level; y--) {
318                 float n_fill = NoisePerlin3D(&noise_inter_valley_fill->np, p.X, y, p.Y, seed);
319                 float surface_delta = (float)y - surface_y;
320                 float density = slope * n_fill - surface_delta;
321
322                 if (density > 0.0f) {  // If solid
323                         // Sometimes surface level is below river water level in places that are not
324                         // river channels.
325                         if (y < water_level || y > max_spawn_y || y < (s16)river_y)
326                                 // Unsuitable spawn point
327                                 return MAX_MAP_GENERATION_LIMIT;
328
329                         // y + 2 because y is surface and due to biome 'dust' nodes.
330                         return y + 2;
331                 }
332         }
333         // Unsuitable spawn position, no ground found
334         return MAX_MAP_GENERATION_LIMIT;
335 }
336
337
338 int MapgenValleys::generateTerrain()
339 {
340         MapNode n_air(CONTENT_AIR);
341         MapNode n_river_water(c_river_water_source);
342         MapNode n_stone(c_stone);
343         MapNode n_water(c_water_source);
344
345         noise_inter_valley_slope->perlinMap2D(node_min.X, node_min.Z);
346         noise_rivers->perlinMap2D(node_min.X, node_min.Z);
347         noise_terrain_height->perlinMap2D(node_min.X, node_min.Z);
348         noise_valley_depth->perlinMap2D(node_min.X, node_min.Z);
349         noise_valley_profile->perlinMap2D(node_min.X, node_min.Z);
350
351         noise_inter_valley_fill->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
352
353         const v3s16 &em = vm->m_area.getExtent();
354         s16 surface_max_y = -MAX_MAP_GENERATION_LIMIT;
355         u32 index_2d = 0;
356
357         for (s16 z = node_min.Z; z <= node_max.Z; z++)
358         for (s16 x = node_min.X; x <= node_max.X; x++, index_2d++) {
359                 float n_slope          = noise_inter_valley_slope->result[index_2d];
360                 float n_rivers         = noise_rivers->result[index_2d];
361                 float n_terrain_height = noise_terrain_height->result[index_2d];
362                 float n_valley         = noise_valley_depth->result[index_2d];
363                 float n_valley_profile = noise_valley_profile->result[index_2d];
364
365                 float valley_d = n_valley * n_valley;
366                 // 'base' represents the level of the river banks
367                 float base = n_terrain_height + valley_d;
368                 // 'river' represents the distance from the river edge
369                 float river = std::fabs(n_rivers) - river_size_factor;
370                 // Use the curve of the function 1-exp(-(x/a)^2) to model valleys.
371                 // 'valley_h' represents the height of the terrain, from the rivers.
372                 float tv = std::fmax(river / n_valley_profile, 0.0f);
373                 float valley_h = valley_d * (1.0f - std::exp(-tv * tv));
374                 // Approximate height of the terrain
375                 float surface_y = base + valley_h;
376                 float slope = n_slope * valley_h;
377                 // River water surface is 1 node below river banks
378                 float river_y = base - 1.0f;
379
380                 // Rivers are placed where 'river' is negative
381                 if (river < 0.0f) {
382                         // Use the the function -sqrt(1-x^2) which models a circle
383                         float tr = river / river_size_factor + 1.0f;
384                         float depth = (river_depth_bed *
385                                 std::sqrt(std::fmax(0.0f, 1.0f - tr * tr)));
386                         // There is no logical equivalent to this using rangelim
387                         surface_y = std::fmin(
388                                 std::fmax(base - depth, (float)(water_level - 3)),
389                                 surface_y);
390                         slope = 0.0f;
391                 }
392
393                 // Optionally vary river depth according to heat and humidity
394                 if (spflags & MGVALLEYS_VARY_RIVER_DEPTH) {
395                         float t_heat = m_bgen->heatmap[index_2d];
396                         float heat = (spflags & MGVALLEYS_ALT_CHILL) ?
397                                 // Match heat value calculated below in
398                                 // 'Optionally decrease heat with altitude'.
399                                 // In rivers, 'ground height ignoring riverbeds' is 'base'.
400                                 // As this only affects river water we can assume y > water_level.
401                                 t_heat + 5.0f - (base - water_level) * 20.0f / altitude_chill :
402                                 t_heat;
403                         float delta = m_bgen->humidmap[index_2d] - 50.0f;
404                         if (delta < 0.0f) {
405                                 float t_evap = (heat - 32.0f) / 300.0f;
406                                 river_y += delta * std::fmax(t_evap, 0.08f);
407                         }
408                 }
409
410                 // Highest solid node in column
411                 s16 column_max_y = surface_y;
412                 u32 index_3d = (z - node_min.Z) * zstride_1u1d + (x - node_min.X);
413                 u32 index_data = vm->m_area.index(x, node_min.Y - 1, z);
414
415                 for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
416                         if (vm->m_data[index_data].getContent() == CONTENT_IGNORE) {
417                                 float n_fill = noise_inter_valley_fill->result[index_3d];
418                                 float surface_delta = (float)y - surface_y;
419                                 // Density = density noise + density gradient
420                                 float density = slope * n_fill - surface_delta;
421
422                                 if (density > 0.0f) {
423                                         vm->m_data[index_data] = n_stone; // Stone
424                                         if (y > surface_max_y)
425                                                 surface_max_y = y;
426                                         if (y > column_max_y)
427                                                 column_max_y = y;
428                                 } else if (y <= water_level) {
429                                         vm->m_data[index_data] = n_water; // Water
430                                 } else if (y <= (s16)river_y) {
431                                         vm->m_data[index_data] = n_river_water; // River water
432                                 } else {
433                                         vm->m_data[index_data] = n_air; // Air
434                                 }
435                         }
436
437                         VoxelArea::add_y(em, index_data, 1);
438                         index_3d += ystride;
439                 }
440
441                 // Optionally increase humidity around rivers
442                 if (spflags & MGVALLEYS_HUMID_RIVERS) {
443                         // Compensate to avoid increasing average humidity
444                         m_bgen->humidmap[index_2d] *= 0.8f;
445                         // Ground height ignoring riverbeds
446                         float t_alt = std::fmax(base, (float)column_max_y);
447                         float water_depth = (t_alt - base) / 4.0f;
448                         m_bgen->humidmap[index_2d] *=
449                                 1.0f + std::pow(0.5f, std::fmax(water_depth, 1.0f));
450                 }
451
452                 // Optionally decrease humidity with altitude
453                 if (spflags & MGVALLEYS_ALT_DRY) {
454                         // Ground height ignoring riverbeds
455                         float t_alt = std::fmax(base, (float)column_max_y);
456                         // Only decrease above water_level
457                         if (t_alt > water_level)
458                                 m_bgen->humidmap[index_2d] -=
459                                         (t_alt - water_level) * 10.0f / altitude_chill;
460                 }
461
462                 // Optionally decrease heat with altitude
463                 if (spflags & MGVALLEYS_ALT_CHILL) {
464                         // Compensate to avoid reducing the average heat
465                         m_bgen->heatmap[index_2d] += 5.0f;
466                         // Ground height ignoring riverbeds
467                         float t_alt = std::fmax(base, (float)column_max_y);
468                         // Only decrease above water_level
469                         if (t_alt > water_level)
470                                 m_bgen->heatmap[index_2d] -=
471                                         (t_alt - water_level) * 20.0f / altitude_chill;
472                 }
473         }
474
475         return surface_max_y;
476 }