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 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.
35 #include "content_sao.h"
37 #include "voxelalgorithms.h"
38 #include "settings.h" // For g_settings
40 #include "dungeongen.h"
44 #include "mg_decoration.h"
45 #include "mapgen_valleys.h"
50 //#include "util/timetaker.h"
51 //#include "profiler.h"
54 //static Profiler mapgen_prof;
55 //Profiler *mapgen_profiler = &mapgen_prof;
57 static FlagDesc flagdesc_mapgen_valleys[] = {
58 {"altitude_chill", MG_VALLEYS_ALT_CHILL},
59 {"cliffs", MG_VALLEYS_CLIFFS},
60 {"fast", MG_VALLEYS_FAST},
61 {"humid_rivers", MG_VALLEYS_HUMID_RIVERS},
62 {"rugged", MG_VALLEYS_RUGGED},
66 ///////////////////////////////////////////////////////////////////////////////
69 MapgenValleys::MapgenValleys(int mapgenid, MapgenParams *params, EmergeManager *emerge)
70 : Mapgen(mapgenid, params, emerge)
72 this->m_emerge = emerge;
73 this->bmgr = emerge->biomemgr;
75 //// amount of elements to skip for the next index
76 //// for noise/height/biome maps (not vmanip)
77 this->ystride = csize.X;
78 this->zstride = csize.X * (csize.Y + 2);
80 this->biomemap = new u8[csize.X * csize.Z];
81 this->heightmap = new s16[csize.X * csize.Z];
83 this->humidmap = NULL;
85 MapgenValleysParams *sp = (MapgenValleysParams *)params->sparams;
86 this->spflags = sp->spflags;
88 this->cliff_terrain = (spflags & MG_VALLEYS_CLIFFS);
89 this->fast_terrain = (spflags & MG_VALLEYS_FAST);
90 this->humid_rivers = (spflags & MG_VALLEYS_HUMID_RIVERS);
91 this->rugged_terrain = (spflags & MG_VALLEYS_RUGGED);
92 this->use_altitude_chill = (spflags & MG_VALLEYS_ALT_CHILL);
94 this->altitude_chill = sp->altitude_chill;
95 this->cave_water_max_height = sp->cave_water_max_height;
96 this->humidity_adjust = sp->humidity - 50.f;
97 this->humidity_break_point = sp->humidity_break_point;
98 this->lava_max_height = sp->lava_max_height;
99 this->river_depth = sp->river_depth + 1.f;
100 this->river_size = sp->river_size / 100.f;
101 this->temperature_adjust = sp->temperature - 50.f;
102 this->water_features = MYMAX(1, MYMIN(11, 11 - sp->water_features));
104 //// 2D Terrain noise
105 noise_cliffs = new Noise(&sp->np_cliffs, seed, csize.X, csize.Z);
106 noise_corr = new Noise(&sp->np_corr, seed, csize.X, csize.Z);
107 noise_filler_depth = new Noise(&sp->np_filler_depth, seed, csize.X, csize.Z);
108 noise_inter_valley_slope = new Noise(&sp->np_inter_valley_slope, seed, csize.X, csize.Z);
109 noise_rivers = new Noise(&sp->np_rivers, seed, csize.X, csize.Z);
110 noise_terrain_height = new Noise(&sp->np_terrain_height, seed, csize.X, csize.Z);
111 noise_valley_depth = new Noise(&sp->np_valley_depth, seed, csize.X, csize.Z);
112 noise_valley_profile = new Noise(&sp->np_valley_profile, seed, csize.X, csize.Z);
114 if (this->fast_terrain)
115 noise_inter_valley_fill = new Noise(&sp->np_inter_valley_fill, seed, csize.X, csize.Z);
117 //// 3D Terrain noise
118 noise_simple_caves_1 = new Noise(&sp->np_simple_caves_1, seed, csize.X, csize.Y + 2, csize.Z);
119 noise_simple_caves_2 = new Noise(&sp->np_simple_caves_2, seed, csize.X, csize.Y + 2, csize.Z);
121 if (!this->fast_terrain)
122 noise_inter_valley_fill = new Noise(&sp->np_inter_valley_fill, seed, csize.X, csize.Y + 2, csize.Z);
125 noise_heat_blend = new Noise(¶ms->np_biome_heat_blend, seed, csize.X, csize.Z);
126 noise_heat = new Noise(¶ms->np_biome_heat, seed, csize.X, csize.Z);
127 noise_humidity_blend = new Noise(¶ms->np_biome_humidity_blend, seed, csize.X, csize.Z);
128 noise_humidity = new Noise(¶ms->np_biome_humidity, seed, csize.X, csize.Z);
130 //// Resolve nodes to be used
131 INodeDefManager *ndef = emerge->ndef;
133 c_cobble = ndef->getId("mapgen_cobble");
134 c_desert_stone = ndef->getId("mapgen_desert_stone");
135 c_dirt = ndef->getId("mapgen_dirt");
136 c_lava_source = ndef->getId("mapgen_lava_source");
137 c_mossycobble = ndef->getId("mapgen_mossycobble");
138 c_river_water_source = ndef->getId("mapgen_river_water_source");
139 c_sand = ndef->getId("mapgen_sand");
140 c_sandstonebrick = ndef->getId("mapgen_sandstonebrick");
141 c_sandstone = ndef->getId("mapgen_sandstone");
142 c_stair_cobble = ndef->getId("mapgen_stair_cobble");
143 c_stair_sandstonebrick = ndef->getId("mapgen_stair_sandstonebrick");
144 c_stone = ndef->getId("mapgen_stone");
145 c_water_source = ndef->getId("mapgen_water_source");
147 if (c_mossycobble == CONTENT_IGNORE)
148 c_mossycobble = c_cobble;
149 if (c_river_water_source == CONTENT_IGNORE)
150 c_river_water_source = c_water_source;
151 if (c_sand == CONTENT_IGNORE)
153 if (c_sandstonebrick == CONTENT_IGNORE)
154 c_sandstonebrick = c_sandstone;
155 if (c_stair_cobble == CONTENT_IGNORE)
156 c_stair_cobble = c_cobble;
157 if (c_stair_sandstonebrick == CONTENT_IGNORE)
158 c_stair_sandstonebrick = c_sandstone;
162 MapgenValleys::~MapgenValleys()
166 delete noise_filler_depth;
168 delete noise_heat_blend;
169 delete noise_humidity;
170 delete noise_humidity_blend;
171 delete noise_inter_valley_fill;
172 delete noise_inter_valley_slope;
174 delete noise_simple_caves_1;
175 delete noise_simple_caves_2;
176 delete noise_terrain_height;
177 delete noise_valley_depth;
178 delete noise_valley_profile;
185 MapgenValleysParams::MapgenValleysParams()
187 spflags = MG_VALLEYS_CLIFFS | MG_VALLEYS_RUGGED
188 | MG_VALLEYS_HUMID_RIVERS | MG_VALLEYS_ALT_CHILL;
190 altitude_chill = 90; // The altitude at which temperature drops by 20C.
191 // Water in caves will never be higher than this.
192 cave_water_max_height = MAX_MAP_GENERATION_LIMIT;
194 // the maximum humidity around rivers in otherwise dry areas
195 humidity_break_point = 65;
196 lava_max_height = 0; // Lava will never be higher than this.
197 river_depth = 4; // How deep to carve river channels.
198 river_size = 5; // How wide to make rivers.
200 water_features = 3; // How often water will occur in caves.
202 np_cliffs = NoiseParams(0.f, 1.f, v3f(750, 750, 750), 8445, 5, 1.f, 2.f);
203 np_corr = NoiseParams(0.f, 1.f, v3f(40, 40, 40), -3536, 4, 1.f, 2.f);
204 np_filler_depth = NoiseParams(0.f, 1.2f, v3f(256, 256, 256), 1605, 3, 0.5f, 2.f);
205 np_inter_valley_fill = NoiseParams(0.f, 1.f, v3f(256, 512, 256), 1993, 6, 0.8f, 2.f);
206 np_inter_valley_slope = NoiseParams(0.5f, 0.5f, v3f(128, 128, 128), 746, 1, 1.f, 2.f);
207 np_rivers = NoiseParams(0.f, 1.f, v3f(256, 256, 256), -6050, 5, 0.6f, 2.f);
208 np_simple_caves_1 = NoiseParams(0.f, 1.f, v3f(64, 64, 64), -8402, 3, 0.5f, 2.f);
209 np_simple_caves_2 = NoiseParams(0.f, 1.f, v3f(64, 64, 64), 3944, 3, 0.5f, 2.f);
210 np_terrain_height = NoiseParams(-10.f, 50.f, v3f(1024, 1024, 1024), 5202, 6, 0.4f, 2.f);
211 np_valley_depth = NoiseParams(5.f, 4.f, v3f(512, 512, 512), -1914, 1, 1.f, 2.f);
212 np_valley_profile = NoiseParams(0.6f, 0.5f, v3f(512, 512, 512), 777, 1, 1.f, 2.f);
216 void MapgenValleysParams::readParams(const Settings *settings)
218 settings->getFlagStrNoEx("mg_valleys_spflags", spflags, flagdesc_mapgen_valleys);
220 settings->getU16NoEx("mg_valleys_altitude_chill", altitude_chill);
221 settings->getS16NoEx("mg_valleys_cave_water_max_height", cave_water_max_height);
222 settings->getS16NoEx("mg_valleys_humidity", humidity);
223 settings->getS16NoEx("mg_valleys_humidity_break_point", humidity_break_point);
224 settings->getS16NoEx("mg_valleys_lava_max_height", lava_max_height);
225 settings->getU16NoEx("mg_valleys_river_depth", river_depth);
226 settings->getU16NoEx("mg_valleys_river_size", river_size);
227 settings->getS16NoEx("mg_valleys_temperature", temperature);
228 settings->getU16NoEx("mg_valleys_water_features", water_features);
230 settings->getNoiseParams("mg_valleys_np_cliffs", np_cliffs);
231 settings->getNoiseParams("mg_valleys_np_corr", np_corr);
232 settings->getNoiseParams("mg_valleys_np_filler_depth", np_filler_depth);
233 settings->getNoiseParams("mg_valleys_np_inter_valley_fill", np_inter_valley_fill);
234 settings->getNoiseParams("mg_valleys_np_inter_valley_slope", np_inter_valley_slope);
235 settings->getNoiseParams("mg_valleys_np_rivers", np_rivers);
236 settings->getNoiseParams("mg_valleys_np_simple_caves_1", np_simple_caves_1);
237 settings->getNoiseParams("mg_valleys_np_simple_caves_2", np_simple_caves_2);
238 settings->getNoiseParams("mg_valleys_np_terrain_height", np_terrain_height);
239 settings->getNoiseParams("mg_valleys_np_valley_depth", np_valley_depth);
240 settings->getNoiseParams("mg_valleys_np_valley_profile", np_valley_profile);
244 void MapgenValleysParams::writeParams(Settings *settings) const
246 settings->setFlagStr("mg_valleys_spflags", spflags, flagdesc_mapgen_valleys, U32_MAX);
248 settings->setU16("mg_valleys_altitude_chill", altitude_chill);
249 settings->setS16("mg_valleys_cave_water_max_height", cave_water_max_height);
250 settings->setS16("mg_valleys_humidity", humidity);
251 settings->setS16("mg_valleys_humidity_break_point", humidity_break_point);
252 settings->setS16("mg_valleys_lava_max_height", lava_max_height);
253 settings->setU16("mg_valleys_river_depth", river_depth);
254 settings->setU16("mg_valleys_river_size", river_size);
255 settings->setS16("mg_valleys_temperature", temperature);
256 settings->setU16("mg_valleys_water_features", water_features);
258 settings->setNoiseParams("mg_valleys_np_cliffs", np_cliffs);
259 settings->setNoiseParams("mg_valleys_np_corr", np_corr);
260 settings->setNoiseParams("mg_valleys_np_filler_depth", np_filler_depth);
261 settings->setNoiseParams("mg_valleys_np_inter_valley_fill", np_inter_valley_fill);
262 settings->setNoiseParams("mg_valleys_np_inter_valley_slope", np_inter_valley_slope);
263 settings->setNoiseParams("mg_valleys_np_rivers", np_rivers);
264 settings->setNoiseParams("mg_valleys_np_simple_caves_1", np_simple_caves_1);
265 settings->setNoiseParams("mg_valleys_np_simple_caves_2", np_simple_caves_2);
266 settings->setNoiseParams("mg_valleys_np_terrain_height", np_terrain_height);
267 settings->setNoiseParams("mg_valleys_np_valley_depth", np_valley_depth);
268 settings->setNoiseParams("mg_valleys_np_valley_profile", np_valley_profile);
272 ///////////////////////////////////////
275 void MapgenValleys::makeChunk(BlockMakeData *data)
278 assert(data->vmanip);
279 assert(data->nodedef);
280 assert(data->blockpos_requested.X >= data->blockpos_min.X &&
281 data->blockpos_requested.Y >= data->blockpos_min.Y &&
282 data->blockpos_requested.Z >= data->blockpos_min.Z);
283 assert(data->blockpos_requested.X <= data->blockpos_max.X &&
284 data->blockpos_requested.Y <= data->blockpos_max.Y &&
285 data->blockpos_requested.Z <= data->blockpos_max.Z);
287 this->generating = true;
288 this->vm = data->vmanip;
289 this->ndef = data->nodedef;
291 //TimeTaker t("makeChunk");
293 v3s16 blockpos_min = data->blockpos_min;
294 v3s16 blockpos_max = data->blockpos_max;
295 node_min = blockpos_min * MAP_BLOCKSIZE;
296 node_max = (blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
297 full_node_min = (blockpos_min - 1) * MAP_BLOCKSIZE;
298 full_node_max = (blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
300 blockseed = getBlockSeed2(full_node_min, seed);
302 // Generate noise maps and base terrain height.
305 // Generate base terrain with initial heightmaps
306 s16 stone_surface_max_y = generateTerrain();
308 // Create biomemap at heightmap surface
309 bmgr->calcBiomes(csize.X, csize.Z, heatmap, humidmap, heightmap, biomemap);
311 // Actually place the biome-specific nodes
312 MgStoneType stone_type = generateBiomes(heatmap, humidmap);
315 if (flags & MG_CAVES)
316 generateSimpleCaves(stone_surface_max_y);
319 if ((flags & MG_DUNGEONS) && node_max.Y < 50 && (stone_surface_max_y >= node_min.Y)) {
322 dp.np_rarity = nparams_dungeon_rarity;
323 dp.np_density = nparams_dungeon_density;
324 dp.np_wetness = nparams_dungeon_wetness;
325 dp.c_water = c_water_source;
326 if (stone_type == STONE) {
327 dp.c_cobble = c_cobble;
328 dp.c_moss = c_mossycobble;
329 dp.c_stair = c_stair_cobble;
331 dp.diagonal_dirs = false;
333 dp.holesize = v3s16(1, 2, 1);
334 dp.roomsize = v3s16(0, 0, 0);
335 dp.notifytype = GENNOTIFY_DUNGEON;
336 } else if (stone_type == DESERT_STONE) {
337 dp.c_cobble = c_desert_stone;
338 dp.c_moss = c_desert_stone;
339 dp.c_stair = c_desert_stone;
341 dp.diagonal_dirs = true;
343 dp.holesize = v3s16(2, 3, 2);
344 dp.roomsize = v3s16(2, 5, 2);
345 dp.notifytype = GENNOTIFY_TEMPLE;
346 } else if (stone_type == SANDSTONE) {
347 dp.c_cobble = c_sandstonebrick;
348 dp.c_moss = c_sandstonebrick;
349 dp.c_stair = c_sandstonebrick;
351 dp.diagonal_dirs = false;
353 dp.holesize = v3s16(2, 2, 2);
354 dp.roomsize = v3s16(2, 0, 2);
355 dp.notifytype = GENNOTIFY_DUNGEON;
358 DungeonGen dgen(this, &dp);
359 dgen.generate(blockseed, full_node_min, full_node_max);
362 // Generate the registered decorations
363 if (flags & MG_DECORATIONS)
364 m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);
366 // Generate the registered ores
367 m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
369 // Sprinkle some dust on top after everything else was generated
372 //TimeTaker tll("liquid_lighting");
374 updateLiquid(&data->transforming_liquid, full_node_min, full_node_max);
376 if (flags & MG_LIGHT)
378 node_min - v3s16(0, 1, 0),
379 node_max + v3s16(0, 1, 0),
383 //mapgen_profiler->avg("liquid_lighting", tll.stop() / 1000.f);
384 //mapgen_profiler->avg("makeChunk", t.stop() / 1000.f);
386 this->generating = false;
390 // Populate the noise tables and do most of the
391 // calculation necessary to determine terrain height.
392 void MapgenValleys::calculateNoise()
394 //TimeTaker t("calculateNoise", NULL, PRECISION_MICRO);
397 int y = node_min.Y - 1;
400 //TimeTaker tcn("actualNoise");
402 noise_filler_depth->perlinMap2D(x, z);
403 noise_heat_blend->perlinMap2D(x, z);
404 noise_heat->perlinMap2D(x, z);
405 noise_humidity_blend->perlinMap2D(x, z);
406 noise_humidity->perlinMap2D(x, z);
407 noise_inter_valley_slope->perlinMap2D(x, z);
408 noise_rivers->perlinMap2D(x, z);
409 noise_terrain_height->perlinMap2D(x, z);
410 noise_valley_depth->perlinMap2D(x, z);
411 noise_valley_profile->perlinMap2D(x, z);
414 // Make this 2D for speed, if requested.
415 noise_inter_valley_fill->perlinMap2D(x, z);
418 noise_cliffs->perlinMap2D(x, z);
420 noise_corr->perlinMap2D(x, z);
422 noise_inter_valley_fill->perlinMap3D(x, y, z);
425 if (flags & MG_CAVES) {
426 noise_simple_caves_1->perlinMap3D(x, y, z);
427 noise_simple_caves_2->perlinMap3D(x, y, z);
430 //mapgen_profiler->avg("noisemaps", tcn.stop() / 1000.f);
432 for (s32 index = 0; index < csize.X * csize.Z; index++) {
433 noise_heat->result[index] += noise_heat_blend->result[index];
434 noise_heat->result[index] += temperature_adjust;
435 noise_humidity->result[index] += noise_humidity_blend->result[index];
441 for (tn.z = node_min.Z; tn.z <= node_max.Z; tn.z++)
442 for (tn.x = node_min.X; tn.x <= node_max.X; tn.x++, index++) {
443 // The parameters that we actually need to generate terrain
444 // are passed by address (and the return value).
445 tn.terrain_height = noise_terrain_height->result[index];
446 // River noise is replaced with base terrain, which
447 // is basically the height of the water table.
448 tn.rivers = &noise_rivers->result[index];
449 // Valley depth noise is replaced with the valley
450 // number that represents the height of terrain
451 // over rivers and is used to determine about
452 // how close a river is for humidity calculation.
453 tn.valley = &noise_valley_depth->result[index];
454 tn.valley_profile = noise_valley_profile->result[index];
455 // Slope noise is replaced by the calculated slope
456 // which is used to get terrain height in the slow
457 // method, to create sharper mountains.
458 tn.slope = &noise_inter_valley_slope->result[index];
459 tn.inter_valley_fill = noise_inter_valley_fill->result[index];
460 tn.cliffs = noise_cliffs->result[index];
461 tn.corr = noise_corr->result[index];
463 // This is the actual terrain height.
464 float mount = terrainLevelFromNoise(&tn);
465 noise_terrain_height->result[index] = mount;
468 // Assign humidity adjusted by water proximity.
469 // I can't think of a reason why a mod would expect base humidity
470 // from noise or at any altitude other than ground level.
471 noise_humidity->result[index] = humidityByTerrain(
472 noise_humidity->result[index],
474 noise_rivers->result[index],
475 noise_valley_depth->result[index]);
477 // Assign heat adjusted by altitude. See humidity, above.
478 if (use_altitude_chill && mount > 0.f)
479 noise_heat->result[index] *= pow(0.5f, (mount - altitude_chill / 3.f) / altitude_chill);
483 heatmap = noise_heat->result;
484 humidmap = noise_humidity->result;
488 // This keeps us from having to maintain two similar sets of
489 // complicated code to determine ground level.
490 float MapgenValleys::terrainLevelFromNoise(TerrainNoise *tn)
492 float inter_valley_slope = *tn->slope;
494 // The square function changes the behaviour of this noise:
495 // very often small, and sometimes very high.
496 float valley_d = pow(*tn->valley, 2);
498 // valley_d is here because terrain is generally higher where valleys
499 // are deep (mountains). base represents the height of the
500 // rivers, most of the surface is above.
501 float base = tn->terrain_height + valley_d;
503 // "river" represents the distance from the river, in arbitrary units.
504 float river = fabs(*tn->rivers) - river_size;
506 // Use the curve of the function 1−exp(−(x/a)²) to model valleys.
507 // Making "a" vary (0 < a ≤ 1) changes the shape of the valleys.
508 // Try it with a geometry software !
509 // (here x = "river" and a = valley_profile).
510 // "valley" represents the height of the terrain, from the rivers.
511 *tn->valley = valley_d * (1.f - exp(- pow(river / tn->valley_profile, 2)));
513 // approximate height of the terrain at this point
514 float mount = base + *tn->valley;
516 *tn->slope *= *tn->valley;
518 // Rivers are placed where "river" is negative, so where the original
519 // noise value is close to zero.
520 // Base ground is returned as rivers since it's basically the water table.
523 // Use the the function −sqrt(1−x²) which models a circle.
524 float depth = (river_depth * sqrt(1.f - pow((river / river_size + 1), 2)));
526 // base - depth : height of the bottom of the river
527 // water_level - 2 : don't make rivers below 2 nodes under the surface
531 mount = fmin(fmax(base - depth, (float) (water_level - min_bottom)), mount);
533 // Slope has no influence on rivers.
538 // The penultimate step builds up the heights, but we reduce it
539 // occasionally to create cliffs.
540 float delta = sin(tn->inter_valley_fill) * *tn->slope;
541 if (cliff_terrain && tn->cliffs >= 0.2f)
542 mount += delta * 0.66f;
546 // Use yet another noise to make the heights look more rugged.
548 && mount > water_level
549 && fabs(inter_valley_slope * tn->inter_valley_fill) < 0.3f)
550 mount += ((delta < 0.f) ? -1.f : 1.f) * pow(fabs(delta), 0.5f) * fabs(sin(tn->corr));
557 // This avoids duplicating the code in terrainLevelFromNoise, adding
558 // only the final step of terrain generation without a noise map.
559 float MapgenValleys::adjustedTerrainLevelFromNoise(TerrainNoise *tn)
561 float mount = terrainLevelFromNoise(tn);
564 for (s16 y = round(mount); y <= round(mount) + 1000; y++) {
565 float fill = NoisePerlin3D(&noise_inter_valley_fill->np, tn->x, y, tn->z, seed);
567 if (fill * *tn->slope <= y - mount) {
568 mount = fmax(y - 1, mount);
578 float MapgenValleys::humidityByTerrain(
584 // Although the original valleys adjusts humidity by distance
585 // from seawater, this causes problems with the default biomes.
586 // Adjust only by freshwater proximity.
587 float humidity = humidity_base + humidity_adjust;
589 if (humid_rivers && mount > water_level) {
590 // Offset to make everything average the same.
591 humidity -= (humidity_break_point - humidity_adjust) / 3.f;
593 // This method is from the original lua.
594 float water_table = pow(0.5f, fmax(rivers / 3.f, 0.f));
595 // This adds humidity next to rivers and lakes.
596 float river_water = pow(0.5f, fmax(valley / 12.f, 0.f));
598 float water = water_table + (1.f - water_table) * river_water;
599 humidity = fmax(humidity, (humidity_break_point * water));
606 inline int MapgenValleys::getGroundLevelAtPoint(v2s16 p)
608 // Base terrain calculation
609 return terrainLevelAtPoint(p.X, p.Y);
613 float MapgenValleys::terrainLevelAtPoint(s16 x, s16 z)
617 float rivers = NoisePerlin2D(&noise_rivers->np, x, z, seed);
618 float valley = NoisePerlin2D(&noise_valley_depth->np, x, z, seed);
619 float inter_valley_slope = NoisePerlin2D(&noise_inter_valley_slope->np, x, z, seed);
623 tn.terrain_height = NoisePerlin2D(&noise_terrain_height->np, x, z, seed);
626 tn.valley_profile = NoisePerlin2D(&noise_valley_profile->np, x, z, seed);
627 tn.slope = &inter_valley_slope;
628 tn.inter_valley_fill = 0.f;
633 tn.inter_valley_fill = NoisePerlin2D(&noise_inter_valley_fill->np, x, z, seed);
636 tn.cliffs = NoisePerlin2D(&noise_cliffs->np, x, z, seed);
638 tn.corr = NoisePerlin2D(&noise_corr->np, x, z, seed);
641 return adjustedTerrainLevelFromNoise(&tn);
645 int MapgenValleys::generateTerrain()
647 MapNode n_air(CONTENT_AIR);
648 MapNode n_river_water(c_river_water_source);
649 MapNode n_sand(c_sand);
650 MapNode n_stone(c_stone);
651 MapNode n_water(c_water_source);
653 v3s16 em = vm->m_area.getExtent();
654 s16 surface_max_y = -MAX_MAP_GENERATION_LIMIT;
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 s16 river_y = round(noise_rivers->result[index_2d]);
660 s16 surface_y = round(noise_terrain_height->result[index_2d]);
661 float slope = noise_inter_valley_slope->result[index_2d];
663 heightmap[index_2d] = surface_y;
665 if (surface_y > surface_max_y)
666 surface_max_y = surface_y;
670 index_3d = (z - node_min.Z) * zstride + (x - node_min.X);
672 u32 index_data = vm->m_area.index(x, node_min.Y - 1, z);
674 // Mapgens concern themselves with stone and water.
675 for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
678 fill = noise_inter_valley_fill->result[index_3d];
680 if (vm->m_data[index_data].getContent() == CONTENT_IGNORE) {
681 bool river = (river_y > surface_y);
683 if (river && y == surface_y) {
685 vm->m_data[index_data] = n_sand;
686 } else if ((fast_terrain || river) && y <= surface_y) {
688 vm->m_data[index_data] = n_stone;
689 } else if (river && y < river_y) {
691 vm->m_data[index_data] = n_river_water;
692 } else if ((!fast_terrain) && (!river) && fill * slope > y - surface_y) {
693 // ground (slow method)
694 vm->m_data[index_data] = n_stone;
695 heightmap[index_2d] = surface_max_y = y;
696 } else if (y <= water_level) {
698 vm->m_data[index_data] = n_water;
700 vm->m_data[index_data] = n_air;
704 vm->m_area.add_y(em, index_data, 1);
710 // Assign the humidity adjusted by water proximity.
711 noise_humidity->result[index_2d] = humidityByTerrain(
712 noise_humidity->result[index_2d],
714 noise_rivers->result[index_2d],
715 noise_valley_depth->result[index_2d]);
717 // Assign the heat adjusted by altitude. See humidity, above.
718 if (use_altitude_chill && surface_max_y > 0)
719 noise_heat->result[index_2d]
720 *= pow(0.5f, (surface_max_y - altitude_chill / 3.f) / altitude_chill);
724 return surface_max_y;
728 MgStoneType MapgenValleys::generateBiomes(float *heat_map, float *humidity_map)
730 v3s16 em = vm->m_area.getExtent();
732 MgStoneType stone_type = STONE;
734 for (s16 z = node_min.Z; z <= node_max.Z; z++)
735 for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
739 u16 depth_water_top = 0;
740 u32 vi = vm->m_area.index(x, node_max.Y, z);
742 // Check node at base of mapchunk above, either a node of a previously
743 // generated mapchunk or if not, a node of overgenerated base terrain.
744 content_t c_above = vm->m_data[vi + em.X].getContent();
745 bool air_above = c_above == CONTENT_AIR;
746 bool water_above = (c_above == c_water_source);
748 // If there is air or water above enable top/filler placement, otherwise force
749 // nplaced to stone level by setting a number exceeding any possible filler depth.
750 u16 nplaced = (air_above || water_above) ? 0 : U16_MAX;
752 for (s16 y = node_max.Y; y >= node_min.Y; y--) {
753 content_t c = vm->m_data[vi].getContent();
755 // Biome is recalculated each time an upper surface is detected while
756 // working down a column. The selected biome then remains in effect for
757 // all nodes below until the next surface and biome recalculation.
758 // Biome is recalculated:
759 // 1. At the surface of stone below air or water.
760 // 2. At the surface of water below air.
761 // 3. When stone or water is detected but biome has not yet been calculated.
762 if ((c == c_stone && (air_above || water_above || !biome))
763 || ((c == c_water_source || c == c_river_water_source)
764 && (air_above || !biome))) {
765 // Both heat and humidity have already been adjusted for altitude.
766 biome = bmgr->getBiome(heat_map[index], humidity_map[index], y);
768 depth_top = biome->depth_top;
769 base_filler = MYMAX(depth_top
770 + biome->depth_filler
771 + noise_filler_depth->result[index], 0.f);
772 depth_water_top = biome->depth_water_top;
774 // Detect stone type for dungeons during every biome calculation.
775 // This is more efficient than detecting per-node and will not
776 // miss any desert stone or sandstone biomes.
777 if (biome->c_stone == c_desert_stone)
778 stone_type = DESERT_STONE;
779 else if (biome->c_stone == c_sandstone)
780 stone_type = SANDSTONE;
784 content_t c_below = vm->m_data[vi - em.X].getContent();
786 // If the node below isn't solid, make this node stone, so that
787 // any top/filler nodes above are structurally supported.
788 // This is done by aborting the cycle of top/filler placement
789 // immediately by forcing nplaced to stone level.
790 if (c_below == CONTENT_AIR
791 || c_below == c_water_source
792 || c_below == c_river_water_source)
795 if (nplaced < depth_top) {
796 vm->m_data[vi] = MapNode(biome->c_top);
798 } else if (nplaced < base_filler) {
799 vm->m_data[vi] = MapNode(biome->c_filler);
802 vm->m_data[vi] = MapNode(biome->c_stone);
807 } else if (c == c_water_source) {
808 vm->m_data[vi] = MapNode((y > (s32)(water_level - depth_water_top))
809 ? biome->c_water_top : biome->c_water);
810 nplaced = 0; // Enable top/filler placement for next surface
813 } else if (c == c_river_water_source) {
814 vm->m_data[vi] = MapNode(biome->c_river_water);
815 nplaced = U16_MAX; // Sand was already placed under rivers.
818 } else if (c == CONTENT_AIR) {
819 nplaced = 0; // Enable top/filler placement for next surface
822 } else { // Possible various nodes overgenerated from neighbouring mapchunks
823 nplaced = U16_MAX; // Disable top/filler placement
828 vm->m_area.add_y(em, vi, -1);
836 void MapgenValleys::dustTopNodes()
838 if (node_max.Y < water_level)
841 v3s16 em = vm->m_area.getExtent();
844 for (s16 z = node_min.Z; z <= node_max.Z; z++)
845 for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
846 Biome *biome = (Biome *)bmgr->getRaw(biomemap[index]);
848 if (biome->c_dust == CONTENT_IGNORE)
851 u32 vi = vm->m_area.index(x, full_node_max.Y, z);
852 content_t c_full_max = vm->m_data[vi].getContent();
855 if (c_full_max == CONTENT_AIR) {
856 y_start = full_node_max.Y - 1;
857 } else if (c_full_max == CONTENT_IGNORE) {
858 vi = vm->m_area.index(x, node_max.Y + 1, z);
859 content_t c_max = vm->m_data[vi].getContent();
861 if (c_max == CONTENT_AIR)
862 y_start = node_max.Y;
869 vi = vm->m_area.index(x, y_start, z);
870 for (s16 y = y_start; y >= node_min.Y - 1; y--) {
871 if (vm->m_data[vi].getContent() != CONTENT_AIR)
874 vm->m_area.add_y(em, vi, -1);
877 content_t c = vm->m_data[vi].getContent();
878 if (!ndef->get(c).buildable_to && c != CONTENT_IGNORE && c != biome->c_dust) {
879 vm->m_area.add_y(em, vi, 1);
880 vm->m_data[vi] = MapNode(biome->c_dust);
886 void MapgenValleys::generateSimpleCaves(s16 max_stone_y)
888 PseudoRandom ps(blockseed + 72202);
890 MapNode n_air(CONTENT_AIR);
891 MapNode n_dirt(c_dirt);
892 MapNode n_lava(c_lava_source);
893 MapNode n_water(c_river_water_source);
895 v3s16 em = vm->m_area.getExtent();
897 s16 base_water_chance = 0;
898 if (water_features < 11)
899 base_water_chance = ceil(MAX_MAP_GENERATION_LIMIT / (water_features * 1000));
901 if (max_stone_y >= node_min.Y) {
904 for (s16 z = node_min.Z; z <= node_max.Z; z++)
905 for (s16 x = node_min.X; x <= node_max.X; x++, index_2d++) {
906 bool air_above = false;
907 //bool underground = false;
908 u32 index_data = vm->m_area.index(x, node_max.Y + 1, z);
910 index_3d = (z - node_min.Z) * zstride + (csize.Y + 1) * ystride + (x - node_min.X);
912 // Dig caves on down loop to check for air above.
913 for (s16 y = node_max.Y + 1;
915 y--, index_3d -= ystride, vm->m_area.add_y(em, index_data, -1)) {
916 float terrain = noise_terrain_height->result[index_2d];
918 // Saves some time and prevents removing above ground nodes.
919 if (y > terrain + 1) {
924 content_t c = vm->m_data[index_data].getContent();
925 bool n1 = (fabs(noise_simple_caves_1->result[index_3d]) < 0.07f);
926 bool n2 = (fabs(noise_simple_caves_2->result[index_3d]) < 0.07f);
928 // River water is (foolishly) not set as ground content
929 // in the default game. This can produce strange results
930 // when a cave undercuts a river. However, that's not for
931 // the mapgen to correct. Fix it in lua.
933 if (c == CONTENT_AIR) {
935 } else if (n1 && n2 && ndef->get(c).is_ground_content) {
936 // When both n's are true, we're in a cave.
937 vm->m_data[index_data] = n_air;
940 && (c == c_stone || c == c_sandstone || c == c_desert_stone)) {
942 s16 sr = ps.next() & 1023;
944 vm->m_area.add_y(em, j, 1);
946 if (sr > (terrain - y) * 25) {
947 // Put dirt in caves near the surface.
948 Biome *biome = (Biome *)bmgr->getRaw(biomemap[index_2d]);
949 vm->m_data[index_data] = MapNode(biome->c_filler);
953 if (y <= lava_max_height && c == c_stone) {
954 // Lava spawns increase with depth.
955 lava_chance = ceil((lava_max_height - y + 1) / 10000);
957 if (sr < lava_chance)
958 vm->m_data[j] = n_lava;
961 if (base_water_chance > 0 && y <= cave_water_max_height) {
962 s16 water_chance = base_water_chance
963 - (abs(y - water_level) / (water_features * 1000));
965 // Waterfalls may get out of control above ground.
967 // If sr < 0 then we should have already placed lava --
968 // don't immediately dump water on it.
969 if (sr >= 0 && sr < water_chance)
970 vm->m_data[j] = n_water;
977 // If we're not in a cave, there's no open space.