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