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>
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.
11 Licensing changed by permission of Gael de Sailly.
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.
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.
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.
34 #include "content_sao.h"
36 #include "voxelalgorithms.h"
37 #include "settings.h" // For g_settings
39 #include "dungeongen.h"
43 #include "mg_decoration.h"
44 #include "mapgen_valleys.h"
51 //#include "util/timetaker.h"
52 //#include "profiler.h"
55 //static Profiler mapgen_prof;
56 //Profiler *mapgen_profiler = &mapgen_prof;
58 static FlagDesc flagdesc_mapgen_valleys[] = {
59 {"altitude_chill", MGVALLEYS_ALT_CHILL},
60 {"humid_rivers", MGVALLEYS_HUMID_RIVERS},
64 ///////////////////////////////////////////////////////////////////////////////
67 MapgenValleys::MapgenValleys(int mapgenid, MapgenParams *params, EmergeManager *emerge)
68 : MapgenBasic(mapgenid, params, emerge)
70 // NOTE: MapgenValleys has a hard dependency on BiomeGenOriginal
71 this->m_bgen = (BiomeGenOriginal *)biomegen;
73 this->map_gen_limit = MYMIN(MAX_MAP_GENERATION_LIMIT,
74 g_settings->getU16("map_generation_limit"));
76 MapgenValleysParams *sp = (MapgenValleysParams *)params->sparams;
77 BiomeParamsOriginal *bp = (BiomeParamsOriginal *)params->bparams;
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;
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);
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);
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;
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;
113 tcave_cache = new float[csize.Y + 2];
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");
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)
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;
138 MapgenValleys::~MapgenValleys()
142 delete noise_filler_depth;
143 delete noise_inter_valley_fill;
144 delete noise_inter_valley_slope;
146 delete noise_massive_caves;
147 delete noise_terrain_height;
148 delete noise_valley_depth;
149 delete noise_valley_profile;
151 delete[] tcave_cache;
155 MapgenValleysParams::MapgenValleysParams()
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.
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);
180 void MapgenValleysParams::readParams(const Settings *settings)
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);
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);
205 void MapgenValleysParams::writeParams(Settings *settings) const
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);
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);
230 ///////////////////////////////////////
233 void MapgenValleys::makeChunk(BlockMakeData *data)
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);
245 this->generating = true;
246 this->vm = data->vmanip;
247 this->ndef = data->nodedef;
249 //TimeTaker t("makeChunk");
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);
258 blockseed = getBlockSeed2(full_node_min, seed);
260 // Generate noise maps and base terrain height.
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);
268 // Generate base terrain with initial heightmaps
269 s16 stone_surface_max_y = generateTerrain();
272 m_bgen->getBiomes(heightmap);
274 // Place biome-specific nodes
275 MgStoneType stone_type = generateBiomes();
278 if (flags & MG_CAVES)
279 generateCaves(stone_surface_max_y, large_cave_depth);
282 if ((flags & MG_DUNGEONS) && node_max.Y < 50 && (stone_surface_max_y >= node_min.Y)) {
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;
294 dp.diagonal_dirs = false;
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;
304 dp.diagonal_dirs = true;
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;
314 dp.diagonal_dirs = false;
316 dp.holesize = v3s16(2, 2, 2);
317 dp.roomsize = v3s16(2, 0, 2);
318 dp.notifytype = GENNOTIFY_DUNGEON;
321 DungeonGen dgen(this, &dp);
322 dgen.generate(blockseed, full_node_min, full_node_max);
325 // Generate the registered decorations
326 if (flags & MG_DECORATIONS)
327 m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);
329 // Generate the registered ores
330 m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
332 // Sprinkle some dust on top after everything else was generated
335 //TimeTaker tll("liquid_lighting");
337 updateLiquid(&data->transforming_liquid, full_node_min, full_node_max);
339 if (flags & MG_LIGHT)
341 node_min - v3s16(0, 1, 0),
342 node_max + v3s16(0, 1, 0),
346 //mapgen_profiler->avg("liquid_lighting", tll.stop() / 1000.f);
347 //mapgen_profiler->avg("makeChunk", t.stop() / 1000.f);
349 this->generating = false;
353 // Populate the noise tables and do most of the
354 // calculation necessary to determine terrain height.
355 void MapgenValleys::calculateNoise()
357 //TimeTaker t("calculateNoise", NULL, PRECISION_MICRO);
360 int y = node_min.Y - 1;
363 //TimeTaker tcn("actualNoise");
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);
371 noise_inter_valley_fill->perlinMap3D(x, y, z);
373 //mapgen_profiler->avg("noisemaps", tcn.stop() / 1000.f);
375 float heat_offset = 0.f;
376 float humidity_scale = 1.f;
378 // Altitude chill tends to reduce the average heat.
379 if (use_altitude_chill)
382 // River humidity tends to increase the humidity range.
384 humidity_scale = 0.8f;
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;
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];
415 // This is the actual terrain height.
416 float mount = terrainLevelFromNoise(&tn);
417 noise_terrain_height->result[index] = mount;
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)
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);
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;
435 // "river" represents the distance from the river, in arbitrary units.
436 float river = fabs(*tn->rivers) - river_size_factor;
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.
444 float t = river / tn->valley_profile;
445 *tn->valley = valley_d * (1.f - exp(- MYSQUARE(t)));
448 // approximate height of the terrain at this point
449 float mount = base + *tn->valley;
451 *tn->slope *= *tn->valley;
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.
458 // Use the the function -sqrt(1-x^2) which models a circle.
461 float t = river / river_size_factor + 1;
462 depth = (river_depth_bed * sqrt(MYMAX(0, 1.f - MYSQUARE(t))));
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);
471 // Slope has no influence on rivers.
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)
483 float mount = terrainLevelFromNoise(tn);
484 s16 y_start = myround(mount);
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);
489 if (fill * *tn->slope < y - mount) {
490 mount = MYMAX(y - 1, mount);
499 int MapgenValleys::getSpawnLevelAtPoint(v2s16 p)
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
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
511 return level_at_point;
515 float MapgenValleys::terrainLevelAtPoint(s16 x, s16 z)
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);
525 tn.terrain_height = NoisePerlin2D(&noise_terrain_height->np, x, z, seed);
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;
532 return adjustedTerrainLevelFromNoise(&tn);
536 int MapgenValleys::generateTerrain()
538 // Raising this reduces the rate of evaporation.
539 static const float evaporation = 300.f;
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;
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);
553 v3s16 em = vm->m_area.getExtent();
554 s16 surface_max_y = -MAX_MAP_GENERATION_LIMIT;
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];
564 heightmap[index_2d] = -MAX_MAP_GENERATION_LIMIT;
566 if (surface_y > surface_max_y)
567 surface_max_y = ceil(surface_y);
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;
575 // If humidity is low or heat is high, lower the water table.
576 float delta = m_bgen->humidmap[index_2d] - 50.f;
578 float t_evap = (t_heat - 32.f) / evaporation;
579 river_y += delta * MYMAX(t_evap, 0.08f);
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);
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;
593 if (fabs(surface_delta) <= 0.5f && y > water_level && river) {
595 vm->m_data[index_data] = n_sand;
596 } else if (slope * fill > surface_delta) {
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)
603 } else if (y <= water_level) {
605 vm->m_data[index_data] = n_water;
608 vm->m_data[index_data] = n_river_water;
610 vm->m_data[index_data] = n_air;
614 vm->m_area.add_y(em, index_data, 1);
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;
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;
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));
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.
647 humid -= alt_to_humid * t_alt / altitude_chill;
649 m_bgen->humidmap[index_2d] = humid;
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;
665 return surface_max_y;
668 void MapgenValleys::generateCaves(s16 max_stone_y, s16 large_cave_depth)
670 if (max_stone_y < node_min.Y)
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);
676 PseudoRandom ps(blockseed + 72202);
678 MapNode n_air(CONTENT_AIR);
679 MapNode n_lava(c_lava_source);
680 MapNode n_water(c_river_water_source);
682 v3s16 em = vm->m_area.getExtent();
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.
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;
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);
698 for (s16 y = node_min.Y - 1; y <= node_max.Y; y++) {
699 float tcave = massive_cave_threshold;
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);
709 tcave_cache[y - node_min.Y + 1] = tcave;
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;
723 // Reduce the odds of overflows even further.
724 if (node_max.Y > water_level) {
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);
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--,
745 vm->m_area.add_y(em, index_data, -1)) {
747 float terrain = noise_terrain_height->result[index_2d];
750 if (y > terrain + 10)
752 else if (y < terrain - 40)
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;
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]);
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.
773 if (d1 * d2 > cave_width && ndef->get(c).is_ground_content) {
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);
782 vm->m_area.add_y(em, j, 1);
784 if (sr > terrain - y) {
785 // Put dirt in tunnels near the surface.
787 vm->m_data[index_data] = MapNode(biome->c_filler);
789 vm->m_data[index_data] = MapNode(biome->c_top);
790 } else if (sr < 3 && underground) {
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;
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;
806 tunnel_air_above = false;
809 tunnel_air_above = false;
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);
820 cave.makeCave(vm, node_min, node_max, &ps, true, max_stone_y, heightmap);