]> git.lizzy.rs Git - minetest.git/blob - src/mapgen/mapgen_carpathian.cpp
Fix Mapgen Valleys getSpawnLevelAtPoint() (#7756)
[minetest.git] / src / mapgen / mapgen_carpathian.cpp
1 /*
2 Minetest
3 Copyright (C) 2017-2018 vlapsley, Vaughan Lapsley <vlapsley@gmail.com>
4 Copyright (C) 2010-2018 paramat
5 Copyright (C) 2010-2018 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 */
21
22
23 #include <cmath>
24 #include "mapgen.h"
25 #include "voxel.h"
26 #include "noise.h"
27 #include "mapblock.h"
28 #include "mapnode.h"
29 #include "map.h"
30 #include "content_sao.h"
31 #include "nodedef.h"
32 #include "voxelalgorithms.h"
33 //#include "profiler.h" // For TimeTaker
34 #include "settings.h" // For g_settings
35 #include "emerge.h"
36 #include "dungeongen.h"
37 #include "cavegen.h"
38 #include "mg_biome.h"
39 #include "mg_ore.h"
40 #include "mg_decoration.h"
41 #include "mapgen_carpathian.h"
42
43
44 FlagDesc flagdesc_mapgen_carpathian[] = {
45         {"caverns", MGCARPATHIAN_CAVERNS},
46         {NULL,      0}
47 };
48
49
50 ///////////////////////////////////////////////////////////////////////////////
51
52
53 MapgenCarpathian::MapgenCarpathian(
54                 int mapgenid, MapgenCarpathianParams *params, EmergeManager *emerge)
55         : MapgenBasic(mapgenid, params, emerge)
56 {
57         base_level       = params->base_level;
58
59         spflags          = params->spflags;
60         cave_width       = params->cave_width;
61         large_cave_depth = params->large_cave_depth;
62         lava_depth       = params->lava_depth;
63         cavern_limit     = params->cavern_limit;
64         cavern_taper     = params->cavern_taper;
65         cavern_threshold = params->cavern_threshold;
66         dungeon_ymin     = params->dungeon_ymin;
67         dungeon_ymax     = params->dungeon_ymax;
68
69         grad_wl = 1 - water_level;
70
71         //// 2D Terrain noise
72         noise_filler_depth  = new Noise(&params->np_filler_depth,  seed, csize.X, csize.Z);
73         noise_height1       = new Noise(&params->np_height1,       seed, csize.X, csize.Z);
74         noise_height2       = new Noise(&params->np_height2,       seed, csize.X, csize.Z);
75         noise_height3       = new Noise(&params->np_height3,       seed, csize.X, csize.Z);
76         noise_height4       = new Noise(&params->np_height4,       seed, csize.X, csize.Z);
77         noise_hills_terrain = new Noise(&params->np_hills_terrain, seed, csize.X, csize.Z);
78         noise_ridge_terrain = new Noise(&params->np_ridge_terrain, seed, csize.X, csize.Z);
79         noise_step_terrain  = new Noise(&params->np_step_terrain,  seed, csize.X, csize.Z);
80         noise_hills         = new Noise(&params->np_hills,         seed, csize.X, csize.Z);
81         noise_ridge_mnt     = new Noise(&params->np_ridge_mnt,     seed, csize.X, csize.Z);
82         noise_step_mnt      = new Noise(&params->np_step_mnt,      seed, csize.X, csize.Z);
83
84         //// 3D terrain noise
85         // 1 up 1 down overgeneration
86         noise_mnt_var = new Noise(&params->np_mnt_var, seed, csize.X, csize.Y + 2, csize.Z);
87
88         //// Cave noise
89         MapgenBasic::np_cave1  = params->np_cave1;
90         MapgenBasic::np_cave2  = params->np_cave2;
91         MapgenBasic::np_cavern = params->np_cavern;
92 }
93
94
95 MapgenCarpathian::~MapgenCarpathian()
96 {
97         delete noise_filler_depth;
98         delete noise_height1;
99         delete noise_height2;
100         delete noise_height3;
101         delete noise_height4;
102         delete noise_hills_terrain;
103         delete noise_ridge_terrain;
104         delete noise_step_terrain;
105         delete noise_hills;
106         delete noise_ridge_mnt;
107         delete noise_step_mnt;
108         delete noise_mnt_var;
109 }
110
111
112 MapgenCarpathianParams::MapgenCarpathianParams():
113         np_filler_depth  (0,  1,  v3f(128,  128,  128),  261,   3, 0.7,  2.0),
114         np_height1       (0,  5,  v3f(251,  251,  251),  9613,  5, 0.5,  2.0),
115         np_height2       (0,  5,  v3f(383,  383,  383),  1949,  5, 0.5,  2.0),
116         np_height3       (0,  5,  v3f(509,  509,  509),  3211,  5, 0.5,  2.0),
117         np_height4       (0,  5,  v3f(631,  631,  631),  1583,  5, 0.5,  2.0),
118         np_hills_terrain (1,  1,  v3f(1301, 1301, 1301), 1692,  5, 0.5,  2.0),
119         np_ridge_terrain (1,  1,  v3f(1889, 1889, 1889), 3568,  5, 0.5,  2.0),
120         np_step_terrain  (1,  1,  v3f(1889, 1889, 1889), 4157,  5, 0.5,  2.0),
121         np_hills         (0,  3,  v3f(257,  257,  257),  6604,  6, 0.5,  2.0),
122         np_ridge_mnt     (0,  12, v3f(743,  743,  743),  5520,  6, 0.7,  2.0),
123         np_step_mnt      (0,  8,  v3f(509,  509,  509),  2590,  6, 0.6,  2.0),
124         np_mnt_var       (0,  1,  v3f(499,  499,  499),  2490,  5, 0.55, 2.0),
125         np_cave1         (0,  12, v3f(61,   61,   61),   52534, 3, 0.5,  2.0),
126         np_cave2         (0,  12, v3f(67,   67,   67),   10325, 3, 0.5,  2.0),
127         np_cavern        (0,  1,  v3f(384,  128,  384),  723,   5, 0.63, 2.0)
128 {
129 }
130
131
132 void MapgenCarpathianParams::readParams(const Settings *settings)
133 {
134         settings->getFlagStrNoEx("mgcarpathian_spflags", spflags, flagdesc_mapgen_carpathian);
135         settings->getFloatNoEx("mgcarpathian_base_level",       base_level);
136         settings->getFloatNoEx("mgcarpathian_cave_width",       cave_width);
137         settings->getS16NoEx("mgcarpathian_large_cave_depth",   large_cave_depth);
138         settings->getS16NoEx("mgcarpathian_lava_depth",         lava_depth);
139         settings->getS16NoEx("mgcarpathian_cavern_limit",       cavern_limit);
140         settings->getS16NoEx("mgcarpathian_cavern_taper",       cavern_taper);
141         settings->getFloatNoEx("mgcarpathian_cavern_threshold", cavern_threshold);
142         settings->getS16NoEx("mgcarpathian_dungeon_ymin",       dungeon_ymin);
143         settings->getS16NoEx("mgcarpathian_dungeon_ymax",       dungeon_ymax);
144
145         settings->getNoiseParams("mgcarpathian_np_filler_depth",  np_filler_depth);
146         settings->getNoiseParams("mgcarpathian_np_height1",       np_height1);
147         settings->getNoiseParams("mgcarpathian_np_height2",       np_height2);
148         settings->getNoiseParams("mgcarpathian_np_height3",       np_height3);
149         settings->getNoiseParams("mgcarpathian_np_height4",       np_height4);
150         settings->getNoiseParams("mgcarpathian_np_hills_terrain", np_hills_terrain);
151         settings->getNoiseParams("mgcarpathian_np_ridge_terrain", np_ridge_terrain);
152         settings->getNoiseParams("mgcarpathian_np_step_terrain",  np_step_terrain);
153         settings->getNoiseParams("mgcarpathian_np_hills",         np_hills);
154         settings->getNoiseParams("mgcarpathian_np_ridge_mnt",     np_ridge_mnt);
155         settings->getNoiseParams("mgcarpathian_np_step_mnt",      np_step_mnt);
156         settings->getNoiseParams("mgcarpathian_np_mnt_var",       np_mnt_var);
157         settings->getNoiseParams("mgcarpathian_np_cave1",         np_cave1);
158         settings->getNoiseParams("mgcarpathian_np_cave2",         np_cave2);
159         settings->getNoiseParams("mgcarpathian_np_cavern",        np_cavern);
160 }
161
162
163 void MapgenCarpathianParams::writeParams(Settings *settings) const
164 {
165         settings->setFlagStr("mgcarpathian_spflags", spflags, flagdesc_mapgen_carpathian, U32_MAX);
166         settings->setFloat("mgcarpathian_base_level",       base_level);
167         settings->setFloat("mgcarpathian_cave_width",       cave_width);
168         settings->setS16("mgcarpathian_large_cave_depth",   large_cave_depth);
169         settings->setS16("mgcarpathian_lava_depth",         lava_depth);
170         settings->setS16("mgcarpathian_cavern_limit",       cavern_limit);
171         settings->setS16("mgcarpathian_cavern_taper",       cavern_taper);
172         settings->setFloat("mgcarpathian_cavern_threshold", cavern_threshold);
173         settings->setS16("mgcarpathian_dungeon_ymin",       dungeon_ymin);
174         settings->setS16("mgcarpathian_dungeon_ymax",       dungeon_ymax);
175
176         settings->setNoiseParams("mgcarpathian_np_filler_depth",  np_filler_depth);
177         settings->setNoiseParams("mgcarpathian_np_height1",       np_height1);
178         settings->setNoiseParams("mgcarpathian_np_height2",       np_height2);
179         settings->setNoiseParams("mgcarpathian_np_height3",       np_height3);
180         settings->setNoiseParams("mgcarpathian_np_height4",       np_height4);
181         settings->setNoiseParams("mgcarpathian_np_hills_terrain", np_hills_terrain);
182         settings->setNoiseParams("mgcarpathian_np_ridge_terrain", np_ridge_terrain);
183         settings->setNoiseParams("mgcarpathian_np_step_terrain",  np_step_terrain);
184         settings->setNoiseParams("mgcarpathian_np_hills",         np_hills);
185         settings->setNoiseParams("mgcarpathian_np_ridge_mnt",     np_ridge_mnt);
186         settings->setNoiseParams("mgcarpathian_np_step_mnt",      np_step_mnt);
187         settings->setNoiseParams("mgcarpathian_np_mnt_var",       np_mnt_var);
188         settings->setNoiseParams("mgcarpathian_np_cave1",         np_cave1);
189         settings->setNoiseParams("mgcarpathian_np_cave2",         np_cave2);
190         settings->setNoiseParams("mgcarpathian_np_cavern",        np_cavern);
191 }
192
193
194 ////////////////////////////////////////////////////////////////////////////////
195
196
197 // Lerp function
198 inline float MapgenCarpathian::getLerp(float noise1, float noise2, float mod)
199 {
200         return noise1 + mod * (noise2 - noise1);
201 }
202
203 // Steps function
204 float MapgenCarpathian::getSteps(float noise)
205 {
206         float w = 0.5f;
207         float k = std::floor(noise / w);
208         float f = (noise - k * w) / w;
209         float s = std::fmin(2.f * f, 1.f);
210         return (k + s) * w;
211 }
212
213
214 ////////////////////////////////////////////////////////////////////////////////
215
216
217 void MapgenCarpathian::makeChunk(BlockMakeData *data)
218 {
219         // Pre-conditions
220         assert(data->vmanip);
221         assert(data->nodedef);
222         assert(data->blockpos_requested.X >= data->blockpos_min.X &&
223                         data->blockpos_requested.Y >= data->blockpos_min.Y &&
224                         data->blockpos_requested.Z >= data->blockpos_min.Z);
225         assert(data->blockpos_requested.X <= data->blockpos_max.X &&
226                         data->blockpos_requested.Y <= data->blockpos_max.Y &&
227                         data->blockpos_requested.Z <= data->blockpos_max.Z);
228
229         this->generating = true;
230         this->vm = data->vmanip;
231         this->ndef = data->nodedef;
232
233         v3s16 blockpos_min = data->blockpos_min;
234         v3s16 blockpos_max = data->blockpos_max;
235         node_min = blockpos_min * MAP_BLOCKSIZE;
236         node_max = (blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
237         full_node_min = (blockpos_min - 1) * MAP_BLOCKSIZE;
238         full_node_max = (blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
239
240         // Create a block-specific seed
241         blockseed = getBlockSeed2(full_node_min, seed);
242
243         // Generate terrain
244         s16 stone_surface_max_y = generateTerrain();
245
246         // Create heightmap
247         updateHeightmap(node_min, node_max);
248
249         // Init biome generator, place biome-specific nodes, and build biomemap
250         if (flags & MG_BIOMES) {
251                 biomegen->calcBiomeNoise(node_min);
252                 generateBiomes();
253         }
254
255         // Generate tunnels, caverns and large randomwalk caves
256         if (flags & MG_CAVES) {
257                 // Generate tunnels first as caverns confuse them
258                 generateCavesNoiseIntersection(stone_surface_max_y);
259
260                 // Generate caverns
261                 bool near_cavern = false;
262                 if (spflags & MGCARPATHIAN_CAVERNS)
263                         near_cavern = generateCavernsNoise(stone_surface_max_y);
264
265                 // Generate large randomwalk caves
266                 if (near_cavern)
267                         // Disable large randomwalk caves in this mapchunk by setting
268                         // 'large cave depth' to world base. Avoids excessive liquid in
269                         // large caverns and floating blobs of overgenerated liquid.
270                         generateCavesRandomWalk(stone_surface_max_y,
271                                 -MAX_MAP_GENERATION_LIMIT);
272                 else
273                         generateCavesRandomWalk(stone_surface_max_y, large_cave_depth);
274         }
275
276         // Generate the registered ores
277         m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
278
279         // Generate dungeons
280         if ((flags & MG_DUNGEONS) && full_node_min.Y >= dungeon_ymin &&
281                         full_node_max.Y <= dungeon_ymax)
282                 generateDungeons(stone_surface_max_y);
283
284         // Generate the registered decorations
285         if (flags & MG_DECORATIONS)
286                 m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);
287
288         // Sprinkle some dust on top after everything else was generated
289         if (flags & MG_BIOMES)
290                 dustTopNodes();
291
292         // Update liquids
293         updateLiquid(&data->transforming_liquid, full_node_min, full_node_max);
294
295         // Calculate lighting
296         if (flags & MG_LIGHT) {
297                 calcLighting(node_min - v3s16(0, 1, 0), node_max + v3s16(0, 1, 0),
298                                 full_node_min, full_node_max);
299         }
300
301         this->generating = false;
302 }
303
304
305 ////////////////////////////////////////////////////////////////////////////////
306
307
308 int MapgenCarpathian::getSpawnLevelAtPoint(v2s16 p)
309 {
310         s16 level_at_point = terrainLevelAtPoint(p.X, p.Y);
311         if (level_at_point <= water_level || level_at_point > water_level + 32)
312                 return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
313
314         return level_at_point;
315 }
316
317
318 float MapgenCarpathian::terrainLevelAtPoint(s16 x, s16 z)
319 {
320         float height1 = NoisePerlin2D(&noise_height1->np, x, z, seed);
321         float height2 = NoisePerlin2D(&noise_height2->np, x, z, seed);
322         float height3 = NoisePerlin2D(&noise_height3->np, x, z, seed);
323         float height4 = NoisePerlin2D(&noise_height4->np, x, z, seed);
324         float hter = NoisePerlin2D(&noise_hills_terrain->np, x, z, seed);
325         float rter = NoisePerlin2D(&noise_ridge_terrain->np, x, z, seed);
326         float ster = NoisePerlin2D(&noise_step_terrain->np, x, z, seed);
327         float n_hills = NoisePerlin2D(&noise_hills->np, x, z, seed);
328         float n_ridge_mnt = NoisePerlin2D(&noise_ridge_mnt->np, x, z, seed);
329         float n_step_mnt = NoisePerlin2D(&noise_step_mnt->np, x, z, seed);
330
331         int height = -MAX_MAP_GENERATION_LIMIT;
332
333         for (s16 y = 1; y <= 30; y++) {
334                 float mnt_var = NoisePerlin3D(&noise_mnt_var->np, x, y, z, seed);
335
336                 // Gradient & shallow seabed
337                 s32 grad = (y < water_level) ? grad_wl + (water_level - y) * 3 : 1 - y;
338
339                 // Hill/Mountain height (hilliness)
340                 float hill1 = getLerp(height1, height2, mnt_var);
341                 float hill2 = getLerp(height3, height4, mnt_var);
342                 float hill3 = getLerp(height3, height2, mnt_var);
343                 float hill4 = getLerp(height1, height4, mnt_var);
344                 float hilliness =
345                         std::fmax(std::fmin(hill1, hill2), std::fmin(hill3, hill4));
346
347                 // Rolling hills
348                 float hill_mnt = hilliness * std::pow(n_hills, 2.f);
349                 float hills = std::pow(std::fabs(hter), 3.f) * hill_mnt;
350
351                 // Ridged mountains
352                 float ridge_mnt = hilliness * (1.f - std::fabs(n_ridge_mnt));
353                 float ridged_mountains = std::pow(std::fabs(rter), 3.f) * ridge_mnt;
354
355                 // Step (terraced) mountains
356                 float step_mnt = hilliness * getSteps(n_step_mnt);
357                 float step_mountains = std::pow(std::fabs(ster), 3.f) * step_mnt;
358
359                 // Final terrain level
360                 float mountains = hills + ridged_mountains + step_mountains;
361                 float surface_level = base_level + mountains + grad;
362
363                 if (y > surface_level && height < 0)
364                         height = y;
365         }
366
367         return height;
368 }
369
370
371 ////////////////////////////////////////////////////////////////////////////////
372
373
374 int MapgenCarpathian::generateTerrain()
375 {
376         MapNode mn_air(CONTENT_AIR);
377         MapNode mn_stone(c_stone);
378         MapNode mn_water(c_water_source);
379
380         // Calculate noise for terrain generation
381         noise_height1->perlinMap2D(node_min.X, node_min.Z);
382         noise_height2->perlinMap2D(node_min.X, node_min.Z);
383         noise_height3->perlinMap2D(node_min.X, node_min.Z);
384         noise_height4->perlinMap2D(node_min.X, node_min.Z);
385         noise_hills_terrain->perlinMap2D(node_min.X, node_min.Z);
386         noise_ridge_terrain->perlinMap2D(node_min.X, node_min.Z);
387         noise_step_terrain->perlinMap2D(node_min.X, node_min.Z);
388         noise_hills->perlinMap2D(node_min.X, node_min.Z);
389         noise_ridge_mnt->perlinMap2D(node_min.X, node_min.Z);
390         noise_step_mnt->perlinMap2D(node_min.X, node_min.Z);
391         noise_mnt_var->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
392
393         //// Place nodes
394         const v3s16 &em = vm->m_area.getExtent();
395         s16 stone_surface_max_y = -MAX_MAP_GENERATION_LIMIT;
396         u32 index2d = 0;
397
398         for (s16 z = node_min.Z; z <= node_max.Z; z++)
399         for (s16 x = node_min.X; x <= node_max.X; x++, index2d++) {
400                 // Hill/Mountain height (hilliness)
401                 float height1 = noise_height1->result[index2d];
402                 float height2 = noise_height2->result[index2d];
403                 float height3 = noise_height3->result[index2d];
404                 float height4 = noise_height4->result[index2d];
405
406                 // Rolling hills
407                 float hterabs = std::fabs(noise_hills_terrain->result[index2d]);
408                 float n_hills = noise_hills->result[index2d];
409                 float hill_mnt = hterabs * hterabs * hterabs * n_hills * n_hills;
410
411                 // Ridged mountains
412                 float rterabs = std::fabs(noise_ridge_terrain->result[index2d]);
413                 float n_ridge_mnt = noise_ridge_mnt->result[index2d];
414                 float ridge_mnt = rterabs * rterabs * rterabs *
415                         (1.f - std::fabs(n_ridge_mnt));
416
417                 // Step (terraced) mountains
418                 float sterabs = std::fabs(noise_step_terrain->result[index2d]);
419                 float n_step_mnt = noise_step_mnt->result[index2d];
420                 float step_mnt = sterabs * sterabs * sterabs * getSteps(n_step_mnt);
421
422                 // Initialise 3D noise index and voxelmanip index to column base
423                 u32 index3d = (z - node_min.Z) * zstride_1u1d + (x - node_min.X);
424                 u32 vi = vm->m_area.index(x, node_min.Y - 1, z);
425
426                 for (s16 y = node_min.Y - 1; y <= node_max.Y + 1;
427                                 y++,
428                                 index3d += ystride,
429                                 VoxelArea::add_y(em, vi, 1)) {
430                         if (vm->m_data[vi].getContent() != CONTENT_IGNORE)
431                                 continue;
432
433                         // Combine height noises and apply 3D variation
434                         float mnt_var = noise_mnt_var->result[index3d];
435                         float hill1 = getLerp(height1, height2, mnt_var);
436                         float hill2 = getLerp(height3, height4, mnt_var);
437                         float hill3 = getLerp(height3, height2, mnt_var);
438                         float hill4 = getLerp(height1, height4, mnt_var);
439
440                         // 'hilliness' determines whether hills/mountains are
441                         // small or large
442                         float hilliness =
443                                 std::fmax(std::fmin(hill1, hill2), std::fmin(hill3, hill4));
444                         float hills = hill_mnt * hilliness;
445                         float ridged_mountains = ridge_mnt * hilliness;
446                         float step_mountains = step_mnt * hilliness;
447
448                         // Gradient & shallow seabed
449                         s32 grad = (y < water_level) ? grad_wl + (water_level - y) * 3 :
450                                 1 - y;
451
452                         // Final terrain level
453                         float mountains = hills + ridged_mountains + step_mountains;
454                         float surface_level = base_level + mountains + grad;
455
456                         if (y < surface_level) {
457                                 vm->m_data[vi] = mn_stone; // Stone
458                                 if (y > stone_surface_max_y)
459                                         stone_surface_max_y = y;
460                         } else if (y <= water_level) {
461                                 vm->m_data[vi] = mn_water; // Sea water
462                         } else {
463                                 vm->m_data[vi] = mn_air; // Air
464                         }
465                 }
466         }
467
468         return stone_surface_max_y;
469 }