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