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