]> git.lizzy.rs Git - minetest.git/blob - src/mapgen_valleys.cpp
Mapgen: Deduplicate common constructor code
[minetest.git] / src / mapgen_valleys.cpp
1 /*
2 Minetest Valleys C
3 Copyright (C) 2010-2015 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
4 Copyright (C) 2010-2015 paramat, Matt Gregory
5 Copyright (C) 2016 Duane Robertson <duane@duanerobertson.com>
6
7 Based on Valleys Mapgen by Gael de Sailly
8  (https://forum.minetest.net/viewtopic.php?f=9&t=11430)
9 and mapgen_v7, mapgen_flat by kwolekr and paramat.
10
11 Licensing changed by permission of Gael de Sailly.
12
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU Lesser General Public License as published by
15 the Free Software Foundation; either version 2.1 of the License, or
16 (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 GNU Lesser General Public License for more details.
22
23 You should have received a copy of the GNU Lesser General Public License along
24 with this program; if not, write to the Free Software Foundation, Inc.,
25 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 */
27
28 #include "mapgen.h"
29 #include "voxel.h"
30 #include "noise.h"
31 #include "mapblock.h"
32 #include "mapnode.h"
33 #include "map.h"
34 #include "content_sao.h"
35 #include "nodedef.h"
36 #include "voxelalgorithms.h"
37 #include "settings.h" // For g_settings
38 #include "emerge.h"
39 #include "dungeongen.h"
40 #include "treegen.h"
41 #include "mg_biome.h"
42 #include "mg_ore.h"
43 #include "mg_decoration.h"
44 #include "mapgen_valleys.h"
45 #include "cavegen.h"
46
47
48 //#undef NDEBUG
49 //#include "assert.h"
50
51 //#include "util/timetaker.h"
52 //#include "profiler.h"
53
54
55 //static Profiler mapgen_prof;
56 //Profiler *mapgen_profiler = &mapgen_prof;
57
58 static FlagDesc flagdesc_mapgen_valleys[] = {
59         {"altitude_chill", MGVALLEYS_ALT_CHILL},
60         {"humid_rivers",   MGVALLEYS_HUMID_RIVERS},
61         {NULL,             0}
62 };
63
64 ///////////////////////////////////////////////////////////////////////////////
65
66
67 MapgenValleys::MapgenValleys(int mapgenid, MapgenParams *params, EmergeManager *emerge)
68         : MapgenBasic(mapgenid, params, emerge)
69 {
70         // NOTE: MapgenValleys has a hard dependency on BiomeGenOriginal
71         this->m_bgen = (BiomeGenOriginal *)biomegen;
72
73         this->map_gen_limit = MYMIN(MAX_MAP_GENERATION_LIMIT,
74                         g_settings->getU16("map_generation_limit"));
75
76         MapgenValleysParams *sp = (MapgenValleysParams *)params->sparams;
77         BiomeParamsOriginal *bp = (BiomeParamsOriginal *)params->bparams;
78
79         this->spflags            = sp->spflags;
80         this->altitude_chill     = sp->altitude_chill;
81         this->large_cave_depth   = sp->large_cave_depth;
82         this->lava_features_lim  = rangelim(sp->lava_features, 0, 10);
83         this->massive_cave_depth = sp->massive_cave_depth;
84         this->river_depth_bed    = sp->river_depth + 1.f;
85         this->river_size_factor  = sp->river_size / 100.f;
86         this->water_features_lim = rangelim(sp->water_features, 0, 10);
87         this->cave_width         = sp->cave_width;
88
89         //// 2D Terrain noise
90         noise_filler_depth       = new Noise(&sp->np_filler_depth,       seed, csize.X, csize.Z);
91         noise_inter_valley_slope = new Noise(&sp->np_inter_valley_slope, seed, csize.X, csize.Z);
92         noise_rivers             = new Noise(&sp->np_rivers,             seed, csize.X, csize.Z);
93         noise_terrain_height     = new Noise(&sp->np_terrain_height,     seed, csize.X, csize.Z);
94         noise_valley_depth       = new Noise(&sp->np_valley_depth,       seed, csize.X, csize.Z);
95         noise_valley_profile     = new Noise(&sp->np_valley_profile,     seed, csize.X, csize.Z);
96
97         //// 3D Terrain noise
98         // 1-up 1-down overgeneration
99         noise_inter_valley_fill = new Noise(&sp->np_inter_valley_fill, seed, csize.X, csize.Y + 2, csize.Z);
100         // 1-down overgeneraion
101         noise_cave1             = new Noise(&sp->np_cave1,             seed, csize.X, csize.Y + 1, csize.Z);
102         noise_cave2             = new Noise(&sp->np_cave2,             seed, csize.X, csize.Y + 1, csize.Z);
103         noise_massive_caves     = new Noise(&sp->np_massive_caves,     seed, csize.X, csize.Y + 1, csize.Z);
104
105         this->humid_rivers       = (spflags & MGVALLEYS_HUMID_RIVERS);
106         this->use_altitude_chill = (spflags & MGVALLEYS_ALT_CHILL);
107         this->humidity_adjust    = bp->np_humidity.offset - 50.f;
108
109         // a small chance of overflows if the settings are very high
110         this->cave_water_max_height = water_level + MYMAX(0, water_features_lim - 4) * 50;
111         this->lava_max_height       = water_level + MYMAX(0, lava_features_lim - 4) * 50;
112
113         tcave_cache = new float[csize.Y + 2];
114
115         // Resolve content to be used
116         c_cobble               = ndef->getId("mapgen_cobble");
117         c_lava_source          = ndef->getId("mapgen_lava_source");
118         c_mossycobble          = ndef->getId("mapgen_mossycobble");
119         c_sand                 = ndef->getId("mapgen_sand");
120         c_sandstonebrick       = ndef->getId("mapgen_sandstonebrick");
121         c_stair_cobble         = ndef->getId("mapgen_stair_cobble");
122         c_stair_sandstonebrick = ndef->getId("mapgen_stair_sandstonebrick");
123
124         // Fall back to more basic content if not defined
125         if (c_mossycobble == CONTENT_IGNORE)
126                 c_mossycobble = c_cobble;
127         if (c_sand == CONTENT_IGNORE)
128                 c_sand = c_stone;
129         if (c_sandstonebrick == CONTENT_IGNORE)
130                 c_sandstonebrick = c_sandstone;
131         if (c_stair_cobble == CONTENT_IGNORE)
132                 c_stair_cobble = c_cobble;
133         if (c_stair_sandstonebrick == CONTENT_IGNORE)
134                 c_stair_sandstonebrick = c_sandstone;
135 }
136
137
138 MapgenValleys::~MapgenValleys()
139 {
140         delete noise_cave1;
141         delete noise_cave2;
142         delete noise_filler_depth;
143         delete noise_inter_valley_fill;
144         delete noise_inter_valley_slope;
145         delete noise_rivers;
146         delete noise_massive_caves;
147         delete noise_terrain_height;
148         delete noise_valley_depth;
149         delete noise_valley_profile;
150
151         delete[] tcave_cache;
152 }
153
154
155 MapgenValleysParams::MapgenValleysParams()
156 {
157         spflags            = MGVALLEYS_HUMID_RIVERS | MGVALLEYS_ALT_CHILL;
158         altitude_chill     = 90; // The altitude at which temperature drops by 20C.
159         large_cave_depth   = -33;
160         lava_features      = 0;  // How often water will occur in caves.
161         massive_cave_depth = -256;  // highest altitude of massive caves
162         river_depth        = 4;  // How deep to carve river channels.
163         river_size         = 5;  // How wide to make rivers.
164         water_features     = 0;  // How often water will occur in caves.
165         cave_width         = 0.3;
166
167         np_cave1              = NoiseParams(0,     12,   v3f(96,   96,   96),   52534, 4, 0.5,   2.0);
168         np_cave2              = NoiseParams(0,     12,   v3f(96,   96,   96),   10325, 4, 0.5,   2.0);
169         np_filler_depth       = NoiseParams(0.f,   1.2f, v3f(256,  256,  256),  1605,  3, 0.5f,  2.f);
170         np_inter_valley_fill  = NoiseParams(0.f,   1.f,  v3f(256,  512,  256),  1993,  6, 0.8f,  2.f);
171         np_inter_valley_slope = NoiseParams(0.5f,  0.5f, v3f(128,  128,  128),  746,   1, 1.f,   2.f);
172         np_rivers             = NoiseParams(0.f,   1.f,  v3f(256,  256,  256),  -6050, 5, 0.6f,  2.f);
173         np_massive_caves      = NoiseParams(0.f,   1.f,  v3f(768,  256,  768),  59033, 6, 0.63f, 2.f);
174         np_terrain_height     = NoiseParams(-10.f, 50.f, v3f(1024, 1024, 1024), 5202,  6, 0.4f,  2.f);
175         np_valley_depth       = NoiseParams(5.f,   4.f,  v3f(512,  512,  512),  -1914, 1, 1.f,   2.f);
176         np_valley_profile     = NoiseParams(0.6f,  0.5f, v3f(512,  512,  512),  777,   1, 1.f,   2.f);
177 }
178
179
180 void MapgenValleysParams::readParams(const Settings *settings)
181 {
182         settings->getFlagStrNoEx("mgvalleys_spflags",        spflags, flagdesc_mapgen_valleys);
183         settings->getU16NoEx("mgvalleys_altitude_chill",     altitude_chill);
184         settings->getS16NoEx("mgvalleys_large_cave_depth",   large_cave_depth);
185         settings->getU16NoEx("mgvalleys_lava_features",      lava_features);
186         settings->getS16NoEx("mgvalleys_massive_cave_depth", massive_cave_depth);
187         settings->getU16NoEx("mgvalleys_river_depth",        river_depth);
188         settings->getU16NoEx("mgvalleys_river_size",         river_size);
189         settings->getU16NoEx("mgvalleys_water_features",     water_features);
190         settings->getFloatNoEx("mgvalleys_cave_width",       cave_width);
191
192         settings->getNoiseParams("mgvalleys_np_cave1",              np_cave1);
193         settings->getNoiseParams("mgvalleys_np_cave2",              np_cave2);
194         settings->getNoiseParams("mgvalleys_np_filler_depth",       np_filler_depth);
195         settings->getNoiseParams("mgvalleys_np_inter_valley_fill",  np_inter_valley_fill);
196         settings->getNoiseParams("mgvalleys_np_inter_valley_slope", np_inter_valley_slope);
197         settings->getNoiseParams("mgvalleys_np_rivers",             np_rivers);
198         settings->getNoiseParams("mgvalleys_np_massive_caves",      np_massive_caves);
199         settings->getNoiseParams("mgvalleys_np_terrain_height",     np_terrain_height);
200         settings->getNoiseParams("mgvalleys_np_valley_depth",       np_valley_depth);
201         settings->getNoiseParams("mgvalleys_np_valley_profile",     np_valley_profile);
202 }
203
204
205 void MapgenValleysParams::writeParams(Settings *settings) const
206 {
207         settings->setFlagStr("mgvalleys_spflags",        spflags, flagdesc_mapgen_valleys, U32_MAX);
208         settings->setU16("mgvalleys_altitude_chill",     altitude_chill);
209         settings->setS16("mgvalleys_large_cave_depth",   large_cave_depth);
210         settings->setU16("mgvalleys_lava_features",      lava_features);
211         settings->setS16("mgvalleys_massive_cave_depth", massive_cave_depth);
212         settings->setU16("mgvalleys_river_depth",        river_depth);
213         settings->setU16("mgvalleys_river_size",         river_size);
214         settings->setU16("mgvalleys_water_features",     water_features);
215         settings->setFloat("mgvalleys_cave_width",       cave_width);
216
217         settings->setNoiseParams("mgvalleys_np_cave1",              np_cave1);
218         settings->setNoiseParams("mgvalleys_np_cave2",              np_cave2);
219         settings->setNoiseParams("mgvalleys_np_filler_depth",       np_filler_depth);
220         settings->setNoiseParams("mgvalleys_np_inter_valley_fill",  np_inter_valley_fill);
221         settings->setNoiseParams("mgvalleys_np_inter_valley_slope", np_inter_valley_slope);
222         settings->setNoiseParams("mgvalleys_np_rivers",             np_rivers);
223         settings->setNoiseParams("mgvalleys_np_massive_caves",      np_massive_caves);
224         settings->setNoiseParams("mgvalleys_np_terrain_height",     np_terrain_height);
225         settings->setNoiseParams("mgvalleys_np_valley_depth",       np_valley_depth);
226         settings->setNoiseParams("mgvalleys_np_valley_profile",     np_valley_profile);
227 }
228
229
230 ///////////////////////////////////////
231
232
233 void MapgenValleys::makeChunk(BlockMakeData *data)
234 {
235         // Pre-conditions
236         assert(data->vmanip);
237         assert(data->nodedef);
238         assert(data->blockpos_requested.X >= data->blockpos_min.X &&
239                 data->blockpos_requested.Y >= data->blockpos_min.Y &&
240                 data->blockpos_requested.Z >= data->blockpos_min.Z);
241         assert(data->blockpos_requested.X <= data->blockpos_max.X &&
242                 data->blockpos_requested.Y <= data->blockpos_max.Y &&
243                 data->blockpos_requested.Z <= data->blockpos_max.Z);
244
245         this->generating = true;
246         this->vm = data->vmanip;
247         this->ndef = data->nodedef;
248
249         //TimeTaker t("makeChunk");
250
251         v3s16 blockpos_min = data->blockpos_min;
252         v3s16 blockpos_max = data->blockpos_max;
253         node_min = blockpos_min * MAP_BLOCKSIZE;
254         node_max = (blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
255         full_node_min = (blockpos_min - 1) * MAP_BLOCKSIZE;
256         full_node_max = (blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
257
258         blockseed = getBlockSeed2(full_node_min, seed);
259
260         // Generate noise maps and base terrain height.
261         calculateNoise();
262
263         // Generate biome noises.  Note this must be executed strictly before
264         // generateTerrain, because generateTerrain depends on intermediate
265         // biome-related noises.
266         m_bgen->calcBiomeNoise(node_min);
267
268         // Generate base terrain with initial heightmaps
269         s16 stone_surface_max_y = generateTerrain();
270
271         // Build biomemap
272         m_bgen->getBiomes(heightmap);
273
274         // Place biome-specific nodes
275         MgStoneType stone_type = generateBiomes();
276
277         // Cave creation.
278         if (flags & MG_CAVES)
279                 generateCaves(stone_surface_max_y, large_cave_depth);
280
281         // Dungeon creation
282         if ((flags & MG_DUNGEONS) && node_max.Y < 50 && (stone_surface_max_y >= node_min.Y)) {
283                 DungeonParams dp;
284
285                 dp.np_rarity  = nparams_dungeon_rarity;
286                 dp.np_density = nparams_dungeon_density;
287                 dp.np_wetness = nparams_dungeon_wetness;
288                 dp.c_water    = c_water_source;
289                 if (stone_type == MGSTONE_STONE) {
290                         dp.c_cobble = c_cobble;
291                         dp.c_moss   = c_mossycobble;
292                         dp.c_stair  = c_stair_cobble;
293
294                         dp.diagonal_dirs = false;
295                         dp.mossratio     = 3.f;
296                         dp.holesize      = v3s16(1, 2, 1);
297                         dp.roomsize      = v3s16(0, 0, 0);
298                         dp.notifytype    = GENNOTIFY_DUNGEON;
299                 } else if (stone_type == MGSTONE_DESERT_STONE) {
300                         dp.c_cobble = c_desert_stone;
301                         dp.c_moss   = c_desert_stone;
302                         dp.c_stair  = c_desert_stone;
303
304                         dp.diagonal_dirs = true;
305                         dp.mossratio     = 0.f;
306                         dp.holesize      = v3s16(2, 3, 2);
307                         dp.roomsize      = v3s16(2, 5, 2);
308                         dp.notifytype    = GENNOTIFY_TEMPLE;
309                 } else if (stone_type == MGSTONE_SANDSTONE) {
310                         dp.c_cobble = c_sandstonebrick;
311                         dp.c_moss   = c_sandstonebrick;
312                         dp.c_stair  = c_sandstonebrick;
313
314                         dp.diagonal_dirs = false;
315                         dp.mossratio     = 0.f;
316                         dp.holesize      = v3s16(2, 2, 2);
317                         dp.roomsize      = v3s16(2, 0, 2);
318                         dp.notifytype    = GENNOTIFY_DUNGEON;
319                 }
320
321                 DungeonGen dgen(this, &dp);
322                 dgen.generate(blockseed, full_node_min, full_node_max);
323         }
324
325         // Generate the registered decorations
326         if (flags & MG_DECORATIONS)
327                 m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);
328
329         // Generate the registered ores
330         m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
331
332         // Sprinkle some dust on top after everything else was generated
333         dustTopNodes();
334
335         //TimeTaker tll("liquid_lighting");
336
337         updateLiquid(&data->transforming_liquid, full_node_min, full_node_max);
338
339         if (flags & MG_LIGHT)
340                 calcLighting(
341                                 node_min - v3s16(0, 1, 0),
342                                 node_max + v3s16(0, 1, 0),
343                                 full_node_min,
344                                 full_node_max);
345
346         //mapgen_profiler->avg("liquid_lighting", tll.stop() / 1000.f);
347         //mapgen_profiler->avg("makeChunk", t.stop() / 1000.f);
348
349         this->generating = false;
350 }
351
352
353 // Populate the noise tables and do most of the
354 // calculation necessary to determine terrain height.
355 void MapgenValleys::calculateNoise()
356 {
357         //TimeTaker t("calculateNoise", NULL, PRECISION_MICRO);
358
359         int x = node_min.X;
360         int y = node_min.Y - 1;
361         int z = node_min.Z;
362
363         //TimeTaker tcn("actualNoise");
364
365         noise_inter_valley_slope->perlinMap2D(x, z);
366         noise_rivers->perlinMap2D(x, z);
367         noise_terrain_height->perlinMap2D(x, z);
368         noise_valley_depth->perlinMap2D(x, z);
369         noise_valley_profile->perlinMap2D(x, z);
370
371         noise_inter_valley_fill->perlinMap3D(x, y, z);
372
373         //mapgen_profiler->avg("noisemaps", tcn.stop() / 1000.f);
374
375         float heat_offset = 0.f;
376         float humidity_scale = 1.f;
377
378         // Altitude chill tends to reduce the average heat.
379         if (use_altitude_chill)
380                 heat_offset = 5.f;
381
382         // River humidity tends to increase the humidity range.
383         if (humid_rivers) {
384                 humidity_scale = 0.8f;
385         }
386
387         for (s32 index = 0; index < csize.X * csize.Z; index++) {
388                 m_bgen->heatmap[index] += heat_offset;
389                 m_bgen->humidmap[index] *= humidity_scale;
390         }
391
392         TerrainNoise tn;
393
394         u32 index = 0;
395         for (tn.z = node_min.Z; tn.z <= node_max.Z; tn.z++)
396         for (tn.x = node_min.X; tn.x <= node_max.X; tn.x++, index++) {
397                 // The parameters that we actually need to generate terrain
398                 //  are passed by address (and the return value).
399                 tn.terrain_height    = noise_terrain_height->result[index];
400                 // River noise is replaced with base terrain, which
401                 // is basically the height of the water table.
402                 tn.rivers            = &noise_rivers->result[index];
403                 // Valley depth noise is replaced with the valley
404                 // number that represents the height of terrain
405                 // over rivers and is used to determine about
406                 // how close a river is for humidity calculation.
407                 tn.valley            = &noise_valley_depth->result[index];
408                 tn.valley_profile    = noise_valley_profile->result[index];
409                 // Slope noise is replaced by the calculated slope
410                 // which is used to get terrain height in the slow
411                 // method, to create sharper mountains.
412                 tn.slope             = &noise_inter_valley_slope->result[index];
413                 tn.inter_valley_fill = noise_inter_valley_fill->result[index];
414
415                 // This is the actual terrain height.
416                 float mount = terrainLevelFromNoise(&tn);
417                 noise_terrain_height->result[index] = mount;
418         }
419 }
420
421
422 // This keeps us from having to maintain two similar sets of
423 //  complicated code to determine ground level.
424 float MapgenValleys::terrainLevelFromNoise(TerrainNoise *tn)
425 {
426         // The square function changes the behaviour of this noise:
427         //  very often small, and sometimes very high.
428         float valley_d = MYSQUARE(*tn->valley);
429
430         // valley_d is here because terrain is generally higher where valleys
431         //  are deep (mountains). base represents the height of the
432         //  rivers, most of the surface is above.
433         float base = tn->terrain_height + valley_d;
434
435         // "river" represents the distance from the river, in arbitrary units.
436         float river = fabs(*tn->rivers) - river_size_factor;
437
438         // Use the curve of the function 1-exp(-(x/a)^2) to model valleys.
439         //  Making "a" vary (0 < a <= 1) changes the shape of the valleys.
440         //  Try it with a geometry software !
441         //   (here x = "river" and a = valley_profile).
442         //  "valley" represents the height of the terrain, from the rivers.
443         {
444                 float t = river / tn->valley_profile;
445                 *tn->valley = valley_d * (1.f - exp(- MYSQUARE(t)));
446         }
447
448         // approximate height of the terrain at this point
449         float mount = base + *tn->valley;
450
451         *tn->slope *= *tn->valley;
452
453         // Rivers are placed where "river" is negative, so where the original
454         //  noise value is close to zero.
455         // Base ground is returned as rivers since it's basically the water table.
456         *tn->rivers = base;
457         if (river < 0.f) {
458                 // Use the the function -sqrt(1-x^2) which models a circle.
459                 float depth;
460                 {
461                         float t = river / river_size_factor + 1;
462                         depth = (river_depth_bed * sqrt(MYMAX(0, 1.f - MYSQUARE(t))));
463                 }
464
465                 // base - depth : height of the bottom of the river
466                 // water_level - 3 : don't make rivers below 3 nodes under the surface
467                 // We use three because that's as low as the swamp biomes go.
468                 // There is no logical equivalent to this using rangelim.
469                 mount = MYMIN(MYMAX(base - depth, (float)(water_level - 3)), mount);
470
471                 // Slope has no influence on rivers.
472                 *tn->slope = 0.f;
473         }
474
475         return mount;
476 }
477
478
479 // This avoids duplicating the code in terrainLevelFromNoise, adding
480 // only the final step of terrain generation without a noise map.
481 float MapgenValleys::adjustedTerrainLevelFromNoise(TerrainNoise *tn)
482 {
483         float mount = terrainLevelFromNoise(tn);
484         s16 y_start = myround(mount);
485
486         for (s16 y = y_start; y <= y_start + 1000; y++) {
487                 float fill = NoisePerlin3D(&noise_inter_valley_fill->np, tn->x, y, tn->z, seed);
488
489                 if (fill * *tn->slope < y - mount) {
490                         mount = MYMAX(y - 1, mount);
491                         break;
492                 }
493         }
494
495         return mount;
496 }
497
498
499 int MapgenValleys::getSpawnLevelAtPoint(v2s16 p)
500 {
501         // Check to make sure this isn't a request for a location in a river.
502         float rivers = NoisePerlin2D(&noise_rivers->np, p.X, p.Y, seed);
503         if (fabs(rivers) < river_size_factor)
504                 return MAX_MAP_GENERATION_LIMIT;  // Unsuitable spawn point
505
506         s16 level_at_point = terrainLevelAtPoint(p.X, p.Y);
507         if (level_at_point <= water_level ||
508                         level_at_point > water_level + 32)
509                 return MAX_MAP_GENERATION_LIMIT;  // Unsuitable spawn point
510         else
511                 return level_at_point;
512 }
513
514
515 float MapgenValleys::terrainLevelAtPoint(s16 x, s16 z)
516 {
517         TerrainNoise tn;
518
519         float rivers = NoisePerlin2D(&noise_rivers->np, x, z, seed);
520         float valley = NoisePerlin2D(&noise_valley_depth->np, x, z, seed);
521         float inter_valley_slope = NoisePerlin2D(&noise_inter_valley_slope->np, x, z, seed);
522
523         tn.x                 = x;
524         tn.z                 = z;
525         tn.terrain_height    = NoisePerlin2D(&noise_terrain_height->np, x, z, seed);
526         tn.rivers            = &rivers;
527         tn.valley            = &valley;
528         tn.valley_profile    = NoisePerlin2D(&noise_valley_profile->np, x, z, seed);
529         tn.slope             = &inter_valley_slope;
530         tn.inter_valley_fill = 0.f;
531
532         return adjustedTerrainLevelFromNoise(&tn);
533 }
534
535
536 int MapgenValleys::generateTerrain()
537 {
538         // Raising this reduces the rate of evaporation.
539         static const float evaporation = 300.f;
540         // from the lua
541         static const float humidity_dropoff = 4.f;
542         // constant to convert altitude chill (compatible with lua) to heat
543         static const float alt_to_heat = 20.f;
544         // humidity reduction by altitude
545         static const float alt_to_humid = 10.f;
546
547         MapNode n_air(CONTENT_AIR);
548         MapNode n_river_water(c_river_water_source);
549         MapNode n_sand(c_sand);
550         MapNode n_stone(c_stone);
551         MapNode n_water(c_water_source);
552
553         v3s16 em = vm->m_area.getExtent();
554         s16 surface_max_y = -MAX_MAP_GENERATION_LIMIT;
555         u32 index_2d = 0;
556
557         for (s16 z = node_min.Z; z <= node_max.Z; z++)
558         for (s16 x = node_min.X; x <= node_max.X; x++, index_2d++) {
559                 float river_y = noise_rivers->result[index_2d];
560                 float surface_y = noise_terrain_height->result[index_2d];
561                 float slope = noise_inter_valley_slope->result[index_2d];
562                 float t_heat = m_bgen->heatmap[index_2d];
563
564                 heightmap[index_2d] = -MAX_MAP_GENERATION_LIMIT;
565
566                 if (surface_y > surface_max_y)
567                         surface_max_y = ceil(surface_y);
568
569                 if (humid_rivers) {
570                         // Derive heat from (base) altitude. This will be most correct
571                         // at rivers, since other surface heights may vary below.
572                         if (use_altitude_chill && (surface_y > 0.f || river_y > 0.f))
573                                 t_heat -= alt_to_heat * MYMAX(surface_y, river_y) / altitude_chill;
574
575                         // If humidity is low or heat is high, lower the water table.
576                         float delta = m_bgen->humidmap[index_2d] - 50.f;
577                         if (delta < 0.f) {
578                                 float t_evap = (t_heat - 32.f) / evaporation;
579                                 river_y += delta * MYMAX(t_evap, 0.08f);
580                         }
581                 }
582
583                 u32 index_3d = (z - node_min.Z) * zstride_1u1d + (x - node_min.X);
584                 u32 index_data = vm->m_area.index(x, node_min.Y - 1, z);
585
586                 // Mapgens concern themselves with stone and water.
587                 for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
588                         if (vm->m_data[index_data].getContent() == CONTENT_IGNORE) {
589                                 float fill = noise_inter_valley_fill->result[index_3d];
590                                 float surface_delta = (float)y - surface_y;
591                                 bool river = y + 1 < river_y;
592
593                                 if (fabs(surface_delta) <= 0.5f && y > water_level && river) {
594                                         // river bottom
595                                         vm->m_data[index_data] = n_sand;
596                                 } else if (slope * fill > surface_delta) {
597                                         // ground
598                                         vm->m_data[index_data] = n_stone;
599                                         if (y > heightmap[index_2d])
600                                                 heightmap[index_2d] = y;
601                                         if (y > surface_max_y)
602                                                 surface_max_y = y;
603                                 } else if (y <= water_level) {
604                                         // sea
605                                         vm->m_data[index_data] = n_water;
606                                 } else if (river) {
607                                         // river
608                                         vm->m_data[index_data] = n_river_water;
609                                 } else {
610                                         vm->m_data[index_data] = n_air;
611                                 }
612                         }
613
614                         vm->m_area.add_y(em, index_data, 1);
615                         index_3d += ystride;
616                 }
617
618                 // This happens if we're generating a chunk that doesn't
619                 // contain the terrain surface, in which case, we need
620                 // to set heightmap to a value outside of the chunk,
621                 // to avoid confusing lua mods that use heightmap.
622                 if (heightmap[index_2d] == -MAX_MAP_GENERATION_LIMIT) {
623                         s16 surface_y_int = myround(surface_y);
624                         if (surface_y_int > node_max.Y + 1 || surface_y_int < node_min.Y - 1) {
625                                 // If surface_y is outside the chunk, it's good enough.
626                                 heightmap[index_2d] = surface_y_int;
627                         } else {
628                                 // If the ground is outside of this chunk, but surface_y
629                                 // is within the chunk, give a value outside.
630                                 heightmap[index_2d] = node_min.Y - 2;
631                         }
632                 }
633
634                 if (humid_rivers) {
635                         // Use base ground (water table) in a riverbed, to
636                         // avoid an unnatural rise in humidity.
637                         float t_alt = MYMAX(noise_rivers->result[index_2d], (float)heightmap[index_2d]);
638                         float humid = m_bgen->humidmap[index_2d];
639                         float water_depth = (t_alt - river_y) / humidity_dropoff;
640                         humid *= 1.f + pow(0.5f, MYMAX(water_depth, 1.f));
641
642                         // Reduce humidity with altitude (ignoring riverbeds).
643                         // This is similar to the lua version's seawater adjustment,
644                         // but doesn't increase the base humidity, which causes
645                         // problems with the default biomes.
646                         if (t_alt > 0.f)
647                                 humid -= alt_to_humid * t_alt / altitude_chill;
648
649                         m_bgen->humidmap[index_2d] = humid;
650                 }
651
652                 // Assign the heat adjusted by any changed altitudes.
653                 // The altitude will change about half the time.
654                 if (use_altitude_chill) {
655                         // ground height ignoring riverbeds
656                         float t_alt = MYMAX(noise_rivers->result[index_2d], (float)heightmap[index_2d]);
657                         if (humid_rivers && heightmap[index_2d] == (s16)myround(surface_y))
658                                 // The altitude hasn't changed. Use the first result.
659                                 m_bgen->heatmap[index_2d] = t_heat;
660                         else if (t_alt > 0.f)
661                                 m_bgen->heatmap[index_2d] -= alt_to_heat * t_alt / altitude_chill;
662                 }
663         }
664
665         return surface_max_y;
666 }
667
668 void MapgenValleys::generateCaves(s16 max_stone_y, s16 large_cave_depth)
669 {
670         if (max_stone_y < node_min.Y)
671                 return;
672
673         noise_cave1->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
674         noise_cave2->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
675
676         PseudoRandom ps(blockseed + 72202);
677
678         MapNode n_air(CONTENT_AIR);
679         MapNode n_lava(c_lava_source);
680         MapNode n_water(c_river_water_source);
681
682         v3s16 em = vm->m_area.getExtent();
683
684         // Cave blend distance near YMIN, YMAX
685         const float massive_cave_blend = 128.f;
686         // noise threshold for massive caves
687         const float massive_cave_threshold = 0.6f;
688         // mct: 1 = small rare caves, 0.5 1/3rd ground volume, 0 = 1/2 ground volume.
689
690         float yblmin = -map_gen_limit + massive_cave_blend * 1.5f;
691         float yblmax = massive_cave_depth - massive_cave_blend * 1.5f;
692         bool made_a_big_one = false;
693
694         // Cache the tcave values as they only vary by altitude.
695         if (node_max.Y <= massive_cave_depth) {
696                 noise_massive_caves->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
697
698                 for (s16 y = node_min.Y - 1; y <= node_max.Y; y++) {
699                         float tcave = massive_cave_threshold;
700
701                         if (y < yblmin) {
702                                 float t = (yblmin - y) / massive_cave_blend;
703                                 tcave += MYSQUARE(t);
704                         } else if (y > yblmax) {
705                                 float t = (y - yblmax) / massive_cave_blend;
706                                 tcave += MYSQUARE(t);
707                         }
708
709                         tcave_cache[y - node_min.Y + 1] = tcave;
710                 }
711         }
712
713         // lava_depth varies between one and ten as you approach
714         //  the bottom of the world.
715         s16 lava_depth = ceil((lava_max_height - node_min.Y + 1) * 10.f / map_gen_limit);
716         // This allows random lava spawns to be less common at the surface.
717         s16 lava_chance = MYCUBE(lava_features_lim) * lava_depth;
718         // water_depth varies between ten and one on the way down.
719         s16 water_depth = ceil((map_gen_limit - abs(node_min.Y) + 1) * 10.f / map_gen_limit);
720         // This allows random water spawns to be more common at the surface.
721         s16 water_chance = MYCUBE(water_features_lim) * water_depth;
722
723         // Reduce the odds of overflows even further.
724         if (node_max.Y > water_level) {
725                 lava_chance /= 3;
726                 water_chance /= 3;
727         }
728
729         u32 index_2d = 0;
730         for (s16 z = node_min.Z; z <= node_max.Z; z++)
731         for (s16 x = node_min.X; x <= node_max.X; x++, index_2d++) {
732                 Biome *biome = (Biome *)m_bmgr->getRaw(biomemap[index_2d]);
733                 bool tunnel_air_above = false;
734                 bool underground = false;
735                 u32 index_data = vm->m_area.index(x, node_max.Y, z);
736                 u32 index_3d = (z - node_min.Z) * zstride_1d + csize.Y * ystride + (x - node_min.X);
737
738                 // Dig caves on down loop to check for air above.
739                 // Don't excavate the overgenerated stone at node_max.Y + 1,
740                 // this creates a 'roof' over the tunnel, preventing light in
741                 // tunnels at mapchunk borders when generating mapchunks upwards.
742                 // This 'roof' is removed when the mapchunk above is generated.
743                 for (s16 y = node_max.Y; y >= node_min.Y - 1; y--,
744                                 index_3d -= ystride,
745                                 vm->m_area.add_y(em, index_data, -1)) {
746
747                         float terrain = noise_terrain_height->result[index_2d];
748
749                         // Saves some time.
750                         if (y > terrain + 10)
751                                 continue;
752                         else if (y < terrain - 40)
753                                 underground = true;
754
755                         // Dig massive caves.
756                         if (node_max.Y <= massive_cave_depth
757                                         && noise_massive_caves->result[index_3d]
758                                         > tcave_cache[y - node_min.Y + 1]) {
759                                 vm->m_data[index_data] = n_air;
760                                 made_a_big_one = true;
761                                 continue;
762                         }
763
764                         content_t c = vm->m_data[index_data].getContent();
765                         float d1 = contour(noise_cave1->result[index_3d]);
766                         float d2 = contour(noise_cave2->result[index_3d]);
767
768                         // River water is not set as ground content
769                         // in the default game. This can produce strange results
770                         // when a tunnel undercuts a river. However, that's not for
771                         // the mapgen to correct. Fix it in lua.
772
773                         if (d1 * d2 > cave_width && ndef->get(c).is_ground_content) {
774                                 // in a tunnel
775                                 vm->m_data[index_data] = n_air;
776                                 tunnel_air_above = true;
777                         } else if (c == biome->c_filler || c == biome->c_stone) {
778                                 if (tunnel_air_above) {
779                                         // at the tunnel floor
780                                         s16 sr = ps.range(0, 39);
781                                         u32 j = index_data;
782                                         vm->m_area.add_y(em, j, 1);
783
784                                         if (sr > terrain - y) {
785                                                 // Put dirt in tunnels near the surface.
786                                                 if (underground)
787                                                         vm->m_data[index_data] = MapNode(biome->c_filler);
788                                                 else
789                                                         vm->m_data[index_data] = MapNode(biome->c_top);
790                                         } else if (sr < 3 && underground) {
791                                                 sr = abs(ps.next());
792                                                 if (lava_features_lim > 0 && y <= lava_max_height
793                                                                 && c == biome->c_stone && sr < lava_chance)
794                                                         vm->m_data[j] = n_lava;
795
796                                                 sr -= lava_chance;
797
798                                                 // If sr < 0 then we should have already placed lava --
799                                                 // don't immediately dump water on it.
800                                                 if (water_features_lim > 0 && y <= cave_water_max_height
801                                                                 && sr >= 0 && sr < water_chance)
802                                                         vm->m_data[j] = n_water;
803                                         }
804                                 }
805
806                                 tunnel_air_above = false;
807                                 underground = true;
808                         } else {
809                                 tunnel_air_above = false;
810                         }
811                 }
812         }
813
814         if (node_max.Y <= large_cave_depth && !made_a_big_one) {
815                 u32 bruises_count = ps.range(0, 2);
816                 for (u32 i = 0; i < bruises_count; i++) {
817                         CavesRandomWalk cave(ndef, &gennotify, seed, water_level,
818                                 c_water_source, c_lava_source);
819
820                         cave.makeCave(vm, node_min, node_max, &ps, true, max_stone_y, heightmap);
821                 }
822         }
823 }