]> git.lizzy.rs Git - minetest.git/blob - src/mapgen/mapgen_carpathian.cpp
Fix various clang-tidy reported performance-type-promotion-in-math-fn
[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         spflags          = params->spflags;
58         cave_width       = params->cave_width;
59         large_cave_depth = params->large_cave_depth;
60         lava_depth       = params->lava_depth;
61         cavern_limit     = params->cavern_limit;
62         cavern_taper     = params->cavern_taper;
63         cavern_threshold = params->cavern_threshold;
64         dungeon_ymin     = params->dungeon_ymin;
65         dungeon_ymax     = params->dungeon_ymax;
66
67         grad_wl = 1 - water_level;
68
69         //// 2D Terrain noise
70         noise_base          = new Noise(&params->np_base,          seed, csize.X, csize.Z);
71         noise_filler_depth  = new Noise(&params->np_filler_depth,  seed, csize.X, csize.Z);
72         noise_height1       = new Noise(&params->np_height1,       seed, csize.X, csize.Z);
73         noise_height2       = new Noise(&params->np_height2,       seed, csize.X, csize.Z);
74         noise_height3       = new Noise(&params->np_height3,       seed, csize.X, csize.Z);
75         noise_height4       = new Noise(&params->np_height4,       seed, csize.X, csize.Z);
76         noise_hills_terrain = new Noise(&params->np_hills_terrain, seed, csize.X, csize.Z);
77         noise_ridge_terrain = new Noise(&params->np_ridge_terrain, seed, csize.X, csize.Z);
78         noise_step_terrain  = new Noise(&params->np_step_terrain,  seed, csize.X, csize.Z);
79         noise_hills         = new Noise(&params->np_hills,         seed, csize.X, csize.Z);
80         noise_ridge_mnt     = new Noise(&params->np_ridge_mnt,     seed, csize.X, csize.Z);
81         noise_step_mnt      = new Noise(&params->np_step_mnt,      seed, csize.X, csize.Z);
82
83         //// 3D terrain noise
84         // 1 up 1 down overgeneration
85         noise_mnt_var = new Noise(&params->np_mnt_var, seed, csize.X, csize.Y + 2, csize.Z);
86
87         //// Cave noise
88         MapgenBasic::np_cave1  = params->np_cave1;
89         MapgenBasic::np_cave2  = params->np_cave2;
90         MapgenBasic::np_cavern = params->np_cavern;
91 }
92
93
94 MapgenCarpathian::~MapgenCarpathian()
95 {
96         delete noise_base;
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_base          (12, 1,  v3f(2557, 2557, 2557), 6538,  4, 0.8,  0.5),
114         np_filler_depth  (0,  1,  v3f(128,  128,  128),  261,   3, 0.7,  2.0),
115         np_height1       (0,  5,  v3f(251,  251,  251),  9613,  5, 0.5,  2.0),
116         np_height2       (0,  5,  v3f(383,  383,  383),  1949,  5, 0.5,  2.0),
117         np_height3       (0,  5,  v3f(509,  509,  509),  3211,  5, 0.5,  2.0),
118         np_height4       (0,  5,  v3f(631,  631,  631),  1583,  5, 0.5,  2.0),
119         np_hills_terrain (1,  1,  v3f(1301, 1301, 1301), 1692,  5, 0.5,  2.0),
120         np_ridge_terrain (1,  1,  v3f(1889, 1889, 1889), 3568,  5, 0.5,  2.0),
121         np_step_terrain  (1,  1,  v3f(1889, 1889, 1889), 4157,  5, 0.5,  2.0),
122         np_hills         (0,  3,  v3f(257,  257,  257),  6604,  6, 0.5,  2.0),
123         np_ridge_mnt     (0,  12, v3f(743,  743,  743),  5520,  6, 0.7,  2.0),
124         np_step_mnt      (0,  8,  v3f(509,  509,  509),  2590,  6, 0.6,  2.0),
125         np_mnt_var       (0,  1,  v3f(499,  499,  499),  2490,  5, 0.55, 2.0),
126         np_cave1         (0,  12, v3f(61,   61,   61),   52534, 3, 0.5,  2.0),
127         np_cave2         (0,  12, v3f(67,   67,   67),   10325, 3, 0.5,  2.0),
128         np_cavern        (0,  1,  v3f(384,  128,  384),  723,   5, 0.63, 2.0)
129 {
130 }
131
132
133 void MapgenCarpathianParams::readParams(const Settings *settings)
134 {
135         settings->getFlagStrNoEx("mgcarpathian_spflags", spflags, flagdesc_mapgen_carpathian);
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_base",          np_base);
146         settings->getNoiseParams("mgcarpathian_np_filler_depth",  np_filler_depth);
147         settings->getNoiseParams("mgcarpathian_np_height1",       np_height1);
148         settings->getNoiseParams("mgcarpathian_np_height2",       np_height2);
149         settings->getNoiseParams("mgcarpathian_np_height3",       np_height3);
150         settings->getNoiseParams("mgcarpathian_np_height4",       np_height4);
151         settings->getNoiseParams("mgcarpathian_np_hills_terrain", np_hills_terrain);
152         settings->getNoiseParams("mgcarpathian_np_ridge_terrain", np_ridge_terrain);
153         settings->getNoiseParams("mgcarpathian_np_step_terrain",  np_step_terrain);
154         settings->getNoiseParams("mgcarpathian_np_hills",         np_hills);
155         settings->getNoiseParams("mgcarpathian_np_ridge_mnt",     np_ridge_mnt);
156         settings->getNoiseParams("mgcarpathian_np_step_mnt",      np_step_mnt);
157         settings->getNoiseParams("mgcarpathian_np_mnt_var",       np_mnt_var);
158         settings->getNoiseParams("mgcarpathian_np_cave1",         np_cave1);
159         settings->getNoiseParams("mgcarpathian_np_cave2",         np_cave2);
160         settings->getNoiseParams("mgcarpathian_np_cavern",        np_cavern);
161 }
162
163
164 void MapgenCarpathianParams::writeParams(Settings *settings) const
165 {
166         settings->setFlagStr("mgcarpathian_spflags", spflags, flagdesc_mapgen_carpathian, U32_MAX);
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_base",          np_base);
177         settings->setNoiseParams("mgcarpathian_np_filler_depth",  np_filler_depth);
178         settings->setNoiseParams("mgcarpathian_np_height1",       np_height1);
179         settings->setNoiseParams("mgcarpathian_np_height2",       np_height2);
180         settings->setNoiseParams("mgcarpathian_np_height3",       np_height3);
181         settings->setNoiseParams("mgcarpathian_np_height4",       np_height4);
182         settings->setNoiseParams("mgcarpathian_np_hills_terrain", np_hills_terrain);
183         settings->setNoiseParams("mgcarpathian_np_ridge_terrain", np_ridge_terrain);
184         settings->setNoiseParams("mgcarpathian_np_step_terrain",  np_step_terrain);
185         settings->setNoiseParams("mgcarpathian_np_hills",         np_hills);
186         settings->setNoiseParams("mgcarpathian_np_ridge_mnt",     np_ridge_mnt);
187         settings->setNoiseParams("mgcarpathian_np_step_mnt",      np_step_mnt);
188         settings->setNoiseParams("mgcarpathian_np_mnt_var",       np_mnt_var);
189         settings->setNoiseParams("mgcarpathian_np_cave1",         np_cave1);
190         settings->setNoiseParams("mgcarpathian_np_cave2",         np_cave2);
191         settings->setNoiseParams("mgcarpathian_np_cavern",        np_cavern);
192 }
193
194
195 ////////////////////////////////////////////////////////////////////////////////
196
197
198 // Lerp function
199 inline float MapgenCarpathian::getLerp(float noise1, float noise2, float mod)
200 {
201         return noise1 + mod * (noise2 - noise1);
202 }
203
204 // Steps function
205 float MapgenCarpathian::getSteps(float noise)
206 {
207         float w = 0.5f;
208         float k = std::floor(noise / w);
209         float f = (noise - k * w) / w;
210         float s = std::fmin(2.f * f, 1.f);
211         return (k + s) * w;
212 }
213
214
215 ////////////////////////////////////////////////////////////////////////////////
216
217
218 void MapgenCarpathian::makeChunk(BlockMakeData *data)
219 {
220         // Pre-conditions
221         assert(data->vmanip);
222         assert(data->nodedef);
223         assert(data->blockpos_requested.X >= data->blockpos_min.X &&
224                         data->blockpos_requested.Y >= data->blockpos_min.Y &&
225                         data->blockpos_requested.Z >= data->blockpos_min.Z);
226         assert(data->blockpos_requested.X <= data->blockpos_max.X &&
227                         data->blockpos_requested.Y <= data->blockpos_max.Y &&
228                         data->blockpos_requested.Z <= data->blockpos_max.Z);
229
230         this->generating = true;
231         this->vm = data->vmanip;
232         this->ndef = data->nodedef;
233
234         v3s16 blockpos_min = data->blockpos_min;
235         v3s16 blockpos_max = data->blockpos_max;
236         node_min = blockpos_min * MAP_BLOCKSIZE;
237         node_max = (blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
238         full_node_min = (blockpos_min - 1) * MAP_BLOCKSIZE;
239         full_node_max = (blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
240
241         // Create a block-specific seed
242         blockseed = getBlockSeed2(full_node_min, seed);
243
244         // Generate terrain
245         s16 stone_surface_max_y = generateTerrain();
246
247         // Create heightmap
248         updateHeightmap(node_min, node_max);
249
250         // Init biome generator, place biome-specific nodes, and build biomemap
251         biomegen->calcBiomeNoise(node_min);
252
253         MgStoneType mgstone_type;
254         content_t biome_stone;
255         generateBiomes(&mgstone_type, &biome_stone);
256
257         // Generate caverns, tunnels and classic caves
258         if (flags & MG_CAVES) {
259                 bool has_cavern = false;
260                 // Generate caverns
261                 if (spflags & MGCARPATHIAN_CAVERNS)
262                         has_cavern = generateCaverns(stone_surface_max_y);
263                 // Generate tunnels and classic caves
264                 if (has_cavern)
265                         // Disable classic caves in this mapchunk by setting
266                         // 'large cave depth' to world base. Avoids excessive liquid in
267                         // large caverns and floating blobs of overgenerated liquid.
268                         generateCaves(stone_surface_max_y, -MAX_MAP_GENERATION_LIMIT);
269                 else
270                         generateCaves(stone_surface_max_y, large_cave_depth);
271         }
272
273         // Generate dungeons
274         if ((flags & MG_DUNGEONS) && full_node_min.Y >= dungeon_ymin &&
275                         full_node_max.Y <= dungeon_ymax)
276                 generateDungeons(stone_surface_max_y, mgstone_type, biome_stone);
277
278         // Generate the registered decorations
279         if (flags & MG_DECORATIONS)
280                 m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);
281
282         // Generate the registered ores
283         m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
284
285         // Sprinkle some dust on top after everything else was generated
286         dustTopNodes();
287
288         // Update liquids
289         updateLiquid(&data->transforming_liquid, full_node_min, full_node_max);
290
291         // Calculate lighting
292         if (flags & MG_LIGHT) {
293                 calcLighting(node_min - v3s16(0, 1, 0), node_max + v3s16(0, 1, 0),
294                                 full_node_min, full_node_max);
295         }
296
297         this->generating = false;
298 }
299
300
301 ////////////////////////////////////////////////////////////////////////////////
302
303
304 int MapgenCarpathian::getSpawnLevelAtPoint(v2s16 p)
305 {
306         s16 level_at_point = terrainLevelAtPoint(p.X, p.Y);
307         if (level_at_point <= water_level || level_at_point > water_level + 32)
308                 return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
309
310         return level_at_point;
311 }
312
313
314 float MapgenCarpathian::terrainLevelAtPoint(s16 x, s16 z)
315 {
316         float ground = NoisePerlin2D(&noise_base->np, x, z, seed);
317         float height1 = NoisePerlin2D(&noise_height1->np, x, z, seed);
318         float height2 = NoisePerlin2D(&noise_height2->np, x, z, seed);
319         float height3 = NoisePerlin2D(&noise_height3->np, x, z, seed);
320         float height4 = NoisePerlin2D(&noise_height4->np, x, z, seed);
321         float hter = NoisePerlin2D(&noise_hills_terrain->np, x, z, seed);
322         float rter = NoisePerlin2D(&noise_ridge_terrain->np, x, z, seed);
323         float ster = NoisePerlin2D(&noise_step_terrain->np, x, z, seed);
324         float n_hills = NoisePerlin2D(&noise_hills->np, x, z, seed);
325         float n_ridge_mnt = NoisePerlin2D(&noise_ridge_mnt->np, x, z, seed);
326         float n_step_mnt = NoisePerlin2D(&noise_step_mnt->np, x, z, seed);
327
328         int height = -MAX_MAP_GENERATION_LIMIT;
329
330         for (s16 y = 1; y <= 30; y++) {
331                 float mnt_var = NoisePerlin3D(&noise_mnt_var->np, x, y, z, seed);
332
333                 // Gradient & shallow seabed
334                 s32 grad = (y < water_level) ? grad_wl + (water_level - y) * 3 : 1 - y;
335
336                 // Hill/Mountain height (hilliness)
337                 float hill1 = getLerp(height1, height2, mnt_var);
338                 float hill2 = getLerp(height3, height4, mnt_var);
339                 float hill3 = getLerp(height3, height2, mnt_var);
340                 float hill4 = getLerp(height1, height4, mnt_var);
341                 float hilliness =
342                         std::fmax(std::fmin(hill1, hill2), std::fmin(hill3, hill4));
343
344                 // Rolling hills
345                 float hill_mnt = hilliness * std::pow(n_hills, 2.f);
346                 float hills = std::pow(hter, 3.f) * hill_mnt;
347
348                 // Ridged mountains
349                 float ridge_mnt = hilliness * (1.f - std::fabs(n_ridge_mnt));
350                 float ridged_mountains = std::pow(rter, 3.f) * ridge_mnt;
351
352                 // Step (terraced) mountains
353                 float step_mnt = hilliness * getSteps(n_step_mnt);
354                 float step_mountains = std::pow(ster, 3.f) * step_mnt;
355
356                 // Final terrain level
357                 float mountains = hills + ridged_mountains + step_mountains;
358                 float surface_level = ground + mountains + grad;
359
360                 if (y > surface_level && height < 0)
361                         height = y;
362         }
363
364         return height;
365 }
366
367
368 ////////////////////////////////////////////////////////////////////////////////
369
370
371 int MapgenCarpathian::generateTerrain()
372 {
373         MapNode mn_air(CONTENT_AIR);
374         MapNode mn_stone(c_stone);
375         MapNode mn_water(c_water_source);
376
377         // Calculate noise for terrain generation
378         noise_base->perlinMap2D(node_min.X, node_min.Z);
379         noise_height1->perlinMap2D(node_min.X, node_min.Z);
380         noise_height2->perlinMap2D(node_min.X, node_min.Z);
381         noise_height3->perlinMap2D(node_min.X, node_min.Z);
382         noise_height4->perlinMap2D(node_min.X, node_min.Z);
383         noise_hills_terrain->perlinMap2D(node_min.X, node_min.Z);
384         noise_ridge_terrain->perlinMap2D(node_min.X, node_min.Z);
385         noise_step_terrain->perlinMap2D(node_min.X, node_min.Z);
386         noise_hills->perlinMap2D(node_min.X, node_min.Z);
387         noise_ridge_mnt->perlinMap2D(node_min.X, node_min.Z);
388         noise_step_mnt->perlinMap2D(node_min.X, node_min.Z);
389         noise_mnt_var->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
390
391         //// Place nodes
392         const v3s16 &em = vm->m_area.getExtent();
393         s16 stone_surface_max_y = -MAX_MAP_GENERATION_LIMIT;
394         u32 index2d = 0;
395
396         for (s16 z = node_min.Z; z <= node_max.Z; z++)
397         for (s16 x = node_min.X; x <= node_max.X; x++, index2d++) {
398                 // Base terrain
399                 float ground = noise_base->result[index2d];
400
401                 // Hill/Mountain height (hilliness)
402                 float height1 = noise_height1->result[index2d];
403                 float height2 = noise_height2->result[index2d];
404                 float height3 = noise_height3->result[index2d];
405                 float height4 = noise_height4->result[index2d];
406
407                 // Rolling hills
408                 float hterabs = std::fabs(noise_hills_terrain->result[index2d]);
409                 float n_hills = noise_hills->result[index2d];
410                 float hill_mnt = hterabs * hterabs * hterabs * n_hills * n_hills;
411
412                 // Ridged mountains
413                 float rterabs = std::fabs(noise_ridge_terrain->result[index2d]);
414                 float n_ridge_mnt = noise_ridge_mnt->result[index2d];
415                 float ridge_mnt = rterabs * rterabs * rterabs *
416                         (1.f - std::fabs(n_ridge_mnt));
417
418                 // Step (terraced) mountains
419                 float sterabs = std::fabs(noise_step_terrain->result[index2d]);
420                 float n_step_mnt = noise_step_mnt->result[index2d];
421                 float step_mnt = sterabs * sterabs * sterabs * getSteps(n_step_mnt);
422
423                 // Initialise 3D noise index and voxelmanip index to column base
424                 u32 index3d = (z - node_min.Z) * zstride_1u1d + (x - node_min.X);
425                 u32 vi = vm->m_area.index(x, node_min.Y - 1, z);
426
427                 for (s16 y = node_min.Y - 1; y <= node_max.Y + 1;
428                                 y++,
429                                 index3d += ystride,
430                                 VoxelArea::add_y(em, vi, 1)) {
431                         if (vm->m_data[vi].getContent() != CONTENT_IGNORE)
432                                 continue;
433
434                         // Combine height noises and apply 3D variation
435                         float mnt_var = noise_mnt_var->result[index3d];
436                         float hill1 = getLerp(height1, height2, mnt_var);
437                         float hill2 = getLerp(height3, height4, mnt_var);
438                         float hill3 = getLerp(height3, height2, mnt_var);
439                         float hill4 = getLerp(height1, height4, mnt_var);
440
441                         // 'hilliness' determines whether hills/mountains are
442                         // small or large
443                         float hilliness =
444                                 std::fmax(std::fmin(hill1, hill2), std::fmin(hill3, hill4));
445                         float hills = hill_mnt * hilliness;
446                         float ridged_mountains = ridge_mnt * hilliness;
447                         float step_mountains = step_mnt * hilliness;
448
449                         // Gradient & shallow seabed
450                         s32 grad = (y < water_level) ? grad_wl + (water_level - y) * 3 :
451                                 1 - y;
452
453                         // Final terrain level
454                         float mountains = hills + ridged_mountains + step_mountains;
455                         float surface_level = ground + mountains + grad;
456
457                         if (y < surface_level) {
458                                 vm->m_data[vi] = mn_stone; // Stone
459                                 if (y > stone_surface_max_y)
460                                         stone_surface_max_y = y;
461                         } else if (y <= water_level) {
462                                 vm->m_data[vi] = mn_water; // Sea water
463                         } else {
464                                 vm->m_data[vi] = mn_air; // Air
465                         }
466                 }
467         }
468
469         return stone_surface_max_y;
470 }