]> git.lizzy.rs Git - dragonfireclient.git/blob - src/mapgen_carpathian.cpp
Remove 3D noise from getSteps function (#6360)
[dragonfireclient.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.55, 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 noise)
199 {
200         float w = 0.5f;
201         float k = floor(noise / w);
202         float f = (noise - 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
246         MgStoneType mgstone_type;
247         content_t biome_stone;
248         generateBiomes(&mgstone_type, &biome_stone, water_level - 1);
249
250         // Generate caverns, tunnels and classic caves
251         if (flags & MG_CAVES) {
252                 bool has_cavern = false;
253                 // Generate caverns
254                 if (spflags & MGCARPATHIAN_CAVERNS)
255                         has_cavern = generateCaverns(stone_surface_max_y);
256                 // Generate tunnels and classic caves
257                 if (has_cavern)
258                         // Disable classic caves in this mapchunk by setting
259                         // 'large cave depth' to world base. Avoids excessive liquid in
260                         // large caverns and floating blobs of overgenerated liquid.
261                         generateCaves(stone_surface_max_y, -MAX_MAP_GENERATION_LIMIT);
262                 else
263                         generateCaves(stone_surface_max_y, large_cave_depth);
264         }
265
266         // Generate dungeons
267         if (flags & MG_DUNGEONS)
268                 generateDungeons(stone_surface_max_y, mgstone_type, biome_stone);
269
270         // Generate the registered decorations
271         if (flags & MG_DECORATIONS)
272                 m_emerge->decomgr->placeAllDecos(this, blockseed,
273                         node_min, node_max, water_level - 1);
274
275         // Generate the registered ores
276         m_emerge->oremgr->placeAllOres(this, blockseed,
277                 node_min, node_max, water_level - 1);
278
279         // Sprinkle some dust on top after everything else was generated
280         dustTopNodes();
281
282         // Update liquids
283         updateLiquid(&data->transforming_liquid, full_node_min, full_node_max);
284
285         // Calculate lighting
286         if (flags & MG_LIGHT) {
287                 calcLighting(node_min - v3s16(0, 1, 0), node_max + v3s16(0, 1, 0),
288                                 full_node_min, full_node_max);
289         }
290
291         this->generating = false;
292 }
293
294
295 ///////////////////////////////////////////////////////////////////////////////
296
297
298 int MapgenCarpathian::getSpawnLevelAtPoint(v2s16 p)
299 {
300         s16 level_at_point = terrainLevelAtPoint(p.X, p.Y);
301         if (level_at_point <= water_level || level_at_point > water_level + 32)
302                 return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
303
304         return level_at_point;
305 }
306
307
308 float MapgenCarpathian::terrainLevelAtPoint(s16 x, s16 z)
309 {
310         float ground = NoisePerlin2D(&noise_base->np, x, z, seed);
311         float height1 = NoisePerlin2D(&noise_height1->np, x, z, seed);
312         float height2 = NoisePerlin2D(&noise_height2->np, x, z, seed);
313         float height3 = NoisePerlin2D(&noise_height3->np, x, z, seed);
314         float height4 = NoisePerlin2D(&noise_height4->np, x, z, seed);
315         float hter = NoisePerlin2D(&noise_hills_terrain->np, x, z, seed);
316         float rter = NoisePerlin2D(&noise_ridge_terrain->np, x, z, seed);
317         float ster = NoisePerlin2D(&noise_step_terrain->np, x, z, seed);
318         float n_hills = NoisePerlin2D(&noise_hills->np, x, z, seed);
319         float n_ridge_mnt = NoisePerlin2D(&noise_ridge_mnt->np, x, z, seed);
320         float n_step_mnt = NoisePerlin2D(&noise_step_mnt->np, x, z, seed);
321
322         int height = -MAX_MAP_GENERATION_LIMIT;
323
324         for (s16 y = 1; y <= 30; y++) {
325                 float mnt_var = NoisePerlin3D(&noise_mnt_var->np, x, y, z, seed);
326
327                 // Gradient & shallow seabed
328                 s32 grad = (y < water_level) ? grad_wl + (water_level - y) * 3 : 1 - y;
329
330                 // Hill/Mountain height (hilliness)
331                 float hill1 = getLerp(height1, height2, mnt_var);
332                 float hill2 = getLerp(height3, height4, mnt_var);
333                 float hill3 = getLerp(height3, height2, mnt_var);
334                 float hill4 = getLerp(height1, height4, mnt_var);
335                 float hilliness = std::fmax(std::fmin(hill1, hill2), std::fmin(hill3, hill4));
336
337                 // Rolling hills
338                 float hill_mnt = hilliness * pow(n_hills, 2.f);
339                 float hills = pow(hter, 3.f) * hill_mnt;
340
341                 // Ridged mountains
342                 float ridge_mnt = hilliness * (1.f - fabs(n_ridge_mnt));
343                 float ridged_mountains = pow(rter, 3.f) * ridge_mnt;
344
345                 // Step (terraced) mountains
346                 float step_mnt = hilliness * getSteps(n_step_mnt);
347                 float step_mountains = pow(ster, 3.f) * step_mnt;
348
349                 // Final terrain level
350                 float mountains = hills + ridged_mountains + step_mountains;
351                 float surface_level = ground + mountains + grad;
352
353                 if (y > surface_level && height < 0)
354                         height = y;
355         }
356
357         return height;
358 }
359
360
361 ///////////////////////////////////////////////////////////////////////////////
362
363
364 int MapgenCarpathian::generateTerrain()
365 {
366         MapNode mn_air(CONTENT_AIR);
367         MapNode mn_stone(c_stone);
368         MapNode mn_water(c_water_source);
369
370         s16 stone_surface_max_y = -MAX_MAP_GENERATION_LIMIT;
371         u32 index2d = 0;
372         u32 index3d = 0;
373
374         // Calculate noise for terrain generation
375         noise_base->perlinMap2D(node_min.X, node_min.Z);
376         noise_height1->perlinMap2D(node_min.X, node_min.Z);
377         noise_height2->perlinMap2D(node_min.X, node_min.Z);
378         noise_height3->perlinMap2D(node_min.X, node_min.Z);
379         noise_height4->perlinMap2D(node_min.X, node_min.Z);
380         noise_hills_terrain->perlinMap2D(node_min.X, node_min.Z);
381         noise_ridge_terrain->perlinMap2D(node_min.X, node_min.Z);
382         noise_step_terrain->perlinMap2D(node_min.X, node_min.Z);
383         noise_hills->perlinMap2D(node_min.X, node_min.Z);
384         noise_ridge_mnt->perlinMap2D(node_min.X, node_min.Z);
385         noise_step_mnt->perlinMap2D(node_min.X, node_min.Z);
386         noise_mnt_var->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
387
388         //// Place nodes
389         for (s16 z = node_min.Z; z <= node_max.Z; z++) {
390                 for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
391                         u32 vi = vm->m_area.index(node_min.X, y, z);
392                         for (s16 x = node_min.X; x <= node_max.X;
393                                         x++, vi++, index2d++, index3d++) {
394                                 if (vm->m_data[vi].getContent() != CONTENT_IGNORE)
395                                         continue;
396
397                                 // Base terrain
398                                 float ground = noise_base->result[index2d];
399
400                                 // Gradient & shallow seabed
401                                 s32 grad = (y < water_level) ? grad_wl + (water_level - y) * 3 : 1 - y;
402
403                                 // Hill/Mountain height (hilliness)
404                                 float height1 = noise_height1->result[index2d];
405                                 float height2 = noise_height2->result[index2d];
406                                 float height3 = noise_height3->result[index2d];
407                                 float height4 = noise_height4->result[index2d];
408                                 float mnt_var = noise_mnt_var->result[index3d];
409                                 // Combine height noises and apply 3D variation
410                                 float hill1 = getLerp(height1, height2, mnt_var);
411                                 float hill2 = getLerp(height3, height4, mnt_var);
412                                 float hill3 = getLerp(height3, height2, mnt_var);
413                                 float hill4 = getLerp(height1, height4, mnt_var);
414                                 // 'hilliness' determines whether hills/mountains are
415                                 // small or large
416                                 float hilliness = std::fmax(std::fmin(hill1, hill2), std::fmin(hill3, hill4));
417
418                                 // Rolling hills
419                                 float hter = noise_hills_terrain->result[index2d];
420                                 float n_hills = noise_hills->result[index2d];
421                                 float hill_mnt = hilliness * pow(n_hills, 2.f);
422                                 float hills = pow(fabs(hter), 3.f) * hill_mnt;
423
424                                 // Ridged mountains
425                                 float rter = noise_ridge_terrain->result[index2d];
426                                 float n_ridge_mnt = noise_ridge_mnt->result[index2d];
427                                 float ridge_mnt = hilliness * (1.f - fabs(n_ridge_mnt));
428                                 float ridged_mountains = pow(fabs(rter), 3.f) * ridge_mnt;
429
430                                 // Step (terraced) mountains
431                                 float ster = noise_step_terrain->result[index2d];
432                                 float n_step_mnt = noise_step_mnt->result[index2d];
433                                 float step_mnt = hilliness * getSteps(n_step_mnt);
434                                 float step_mountains = pow(fabs(ster), 3.f) * step_mnt;
435
436                                 // Final terrain level
437                                 float mountains = hills + ridged_mountains + step_mountains;
438                                 float surface_level = ground + mountains + grad;
439
440                                 if (y < surface_level) {
441                                         vm->m_data[vi] = mn_stone; // Stone
442                                         if (y > stone_surface_max_y)
443                                                 stone_surface_max_y = y;
444                                 } else if (y <= water_level) {
445                                         vm->m_data[vi] = mn_water; // Sea water
446                                 } else {
447                                         vm->m_data[vi] = mn_air; // Air
448                                 }
449                         }
450                         index2d -= ystride;
451                 }
452                 index2d += ystride;
453         }
454
455         return stone_surface_max_y;
456 }