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