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", MG_VALLEYS_ALT_CHILL},
60 {"humid_rivers", MG_VALLEYS_HUMID_RIVERS},
64 ///////////////////////////////////////////////////////////////////////////////
67 MapgenValleys::MapgenValleys(int mapgenid, MapgenParams *params, EmergeManager *emerge)
68 : Mapgen(mapgenid, params, emerge)
70 this->m_emerge = emerge;
71 this->bmgr = emerge->biomemgr;
73 //// amount of elements to skip for the next index
74 //// for noise/height/biome maps (not vmanip)
75 this->ystride = csize.X;
76 this->zstride = csize.X * (csize.Y + 2);
78 this->biomemap = new u8[csize.X * csize.Z];
79 this->heightmap = new s16[csize.X * csize.Z];
81 this->humidmap = NULL;
83 this->map_gen_limit = MYMIN(MAX_MAP_GENERATION_LIMIT,
84 g_settings->getU16("map_generation_limit"));
86 MapgenValleysParams *sp = (MapgenValleysParams *)params->sparams;
87 this->spflags = sp->spflags;
89 this->humid_rivers = (spflags & MG_VALLEYS_HUMID_RIVERS);
90 this->use_altitude_chill = (spflags & MG_VALLEYS_ALT_CHILL);
92 this->altitude_chill = sp->altitude_chill;
93 this->humidity_adjust = params->np_biome_humidity.offset - 50.f;
94 this->large_cave_depth = sp->large_cave_depth;
95 this->lava_features_lim = rangelim(sp->lava_features, 0, 10);
96 this->massive_cave_depth = sp->massive_cave_depth;
97 this->river_depth_bed = sp->river_depth + 1.f;
98 this->river_size_factor = sp->river_size / 100.f;
99 this->water_features_lim = rangelim(sp->water_features, 0, 10);
101 // a small chance of overflows if the settings are very high
102 this->cave_water_max_height = water_level + MYMAX(0, water_features_lim - 6) * 50;
103 this->lava_max_height = water_level + MYMAX(0, lava_features_lim - 6) * 50;
105 tcave_cache = new float[csize.Y + 2];
107 //// 2D Terrain noise
108 noise_filler_depth = new Noise(&sp->np_filler_depth, seed, csize.X, csize.Z);
109 noise_inter_valley_slope = new Noise(&sp->np_inter_valley_slope, seed, csize.X, csize.Z);
110 noise_rivers = new Noise(&sp->np_rivers, seed, csize.X, csize.Z);
111 noise_terrain_height = new Noise(&sp->np_terrain_height, seed, csize.X, csize.Z);
112 noise_valley_depth = new Noise(&sp->np_valley_depth, seed, csize.X, csize.Z);
113 noise_valley_profile = new Noise(&sp->np_valley_profile, seed, csize.X, csize.Z);
115 //// 3D Terrain noise
116 noise_cave1 = new Noise(&sp->np_cave1, seed, csize.X, csize.Y + 2, csize.Z);
117 noise_cave2 = new Noise(&sp->np_cave2, seed, csize.X, csize.Y + 2, csize.Z);
118 noise_inter_valley_fill = new Noise(&sp->np_inter_valley_fill, seed, csize.X, csize.Y + 2, csize.Z);
119 noise_massive_caves = new Noise(&sp->np_massive_caves, seed, csize.X, csize.Y + 2, csize.Z);
122 noise_heat_blend = new Noise(¶ms->np_biome_heat_blend, seed, csize.X, csize.Z);
123 noise_heat = new Noise(¶ms->np_biome_heat, seed, csize.X, csize.Z);
124 noise_humidity_blend = new Noise(¶ms->np_biome_humidity_blend, seed, csize.X, csize.Z);
125 noise_humidity = new Noise(¶ms->np_biome_humidity, seed, csize.X, csize.Z);
127 //// Resolve nodes to be used
128 INodeDefManager *ndef = emerge->ndef;
130 c_cobble = ndef->getId("mapgen_cobble");
131 c_desert_stone = ndef->getId("mapgen_desert_stone");
132 c_dirt = ndef->getId("mapgen_dirt");
133 c_lava_source = ndef->getId("mapgen_lava_source");
134 c_mossycobble = ndef->getId("mapgen_mossycobble");
135 c_river_water_source = ndef->getId("mapgen_river_water_source");
136 c_sand = ndef->getId("mapgen_sand");
137 c_sandstonebrick = ndef->getId("mapgen_sandstonebrick");
138 c_sandstone = ndef->getId("mapgen_sandstone");
139 c_stair_cobble = ndef->getId("mapgen_stair_cobble");
140 c_stair_sandstonebrick = ndef->getId("mapgen_stair_sandstonebrick");
141 c_stone = ndef->getId("mapgen_stone");
142 c_water_source = ndef->getId("mapgen_water_source");
144 if (c_mossycobble == CONTENT_IGNORE)
145 c_mossycobble = c_cobble;
146 if (c_river_water_source == CONTENT_IGNORE)
147 c_river_water_source = c_water_source;
148 if (c_sand == CONTENT_IGNORE)
150 if (c_sandstonebrick == CONTENT_IGNORE)
151 c_sandstonebrick = c_sandstone;
152 if (c_stair_cobble == CONTENT_IGNORE)
153 c_stair_cobble = c_cobble;
154 if (c_stair_sandstonebrick == CONTENT_IGNORE)
155 c_stair_sandstonebrick = c_sandstone;
159 MapgenValleys::~MapgenValleys()
163 delete noise_filler_depth;
165 delete noise_heat_blend;
166 delete noise_humidity;
167 delete noise_humidity_blend;
168 delete noise_inter_valley_fill;
169 delete noise_inter_valley_slope;
171 delete noise_massive_caves;
172 delete noise_terrain_height;
173 delete noise_valley_depth;
174 delete noise_valley_profile;
178 delete[] tcave_cache;
182 MapgenValleysParams::MapgenValleysParams()
184 spflags = MG_VALLEYS_HUMID_RIVERS | MG_VALLEYS_ALT_CHILL;
186 altitude_chill = 90; // The altitude at which temperature drops by 20C.
187 large_cave_depth = -33;
188 lava_features = 0; // How often water will occur in caves.
189 massive_cave_depth = -256; // highest altitude of massive caves
190 river_depth = 4; // How deep to carve river channels.
191 river_size = 5; // How wide to make rivers.
192 water_features = 0; // How often water will occur in caves.
194 np_cave1 = NoiseParams(0, 12, v3f(96, 96, 96), 52534, 4, 0.5, 2.0);
195 np_cave2 = NoiseParams(0, 12, v3f(96, 96, 96), 10325, 4, 0.5, 2.0);
196 np_filler_depth = NoiseParams(0.f, 1.2f, v3f(256, 256, 256), 1605, 3, 0.5f, 2.f);
197 np_inter_valley_fill = NoiseParams(0.f, 1.f, v3f(256, 512, 256), 1993, 6, 0.8f, 2.f);
198 np_inter_valley_slope = NoiseParams(0.5f, 0.5f, v3f(128, 128, 128), 746, 1, 1.f, 2.f);
199 np_rivers = NoiseParams(0.f, 1.f, v3f(256, 256, 256), -6050, 5, 0.6f, 2.f);
200 np_massive_caves = NoiseParams(0.f, 1.f, v3f(768, 256, 768), 59033, 6, 0.63f, 2.f);
201 np_terrain_height = NoiseParams(-10.f, 50.f, v3f(1024, 1024, 1024), 5202, 6, 0.4f, 2.f);
202 np_valley_depth = NoiseParams(5.f, 4.f, v3f(512, 512, 512), -1914, 1, 1.f, 2.f);
203 np_valley_profile = NoiseParams(0.6f, 0.5f, v3f(512, 512, 512), 777, 1, 1.f, 2.f);
207 void MapgenValleysParams::readParams(const Settings *settings)
209 settings->getFlagStrNoEx("mg_valleys_spflags", spflags, flagdesc_mapgen_valleys);
211 settings->getU16NoEx("mg_valleys_altitude_chill", altitude_chill);
212 settings->getS16NoEx("mg_valleys_large_cave_depth", large_cave_depth);
213 settings->getU16NoEx("mg_valleys_lava_features", lava_features);
214 settings->getS16NoEx("mg_valleys_massive_cave_depth", massive_cave_depth);
215 settings->getU16NoEx("mg_valleys_river_depth", river_depth);
216 settings->getU16NoEx("mg_valleys_river_size", river_size);
217 settings->getU16NoEx("mg_valleys_water_features", water_features);
219 settings->getNoiseParams("mg_valleys_np_cave1", np_cave1);
220 settings->getNoiseParams("mg_valleys_np_cave2", np_cave2);
221 settings->getNoiseParams("mg_valleys_np_filler_depth", np_filler_depth);
222 settings->getNoiseParams("mg_valleys_np_inter_valley_fill", np_inter_valley_fill);
223 settings->getNoiseParams("mg_valleys_np_inter_valley_slope", np_inter_valley_slope);
224 settings->getNoiseParams("mg_valleys_np_rivers", np_rivers);
225 settings->getNoiseParams("mg_valleys_np_massive_caves", np_massive_caves);
226 settings->getNoiseParams("mg_valleys_np_terrain_height", np_terrain_height);
227 settings->getNoiseParams("mg_valleys_np_valley_depth", np_valley_depth);
228 settings->getNoiseParams("mg_valleys_np_valley_profile", np_valley_profile);
232 void MapgenValleysParams::writeParams(Settings *settings) const
234 settings->setFlagStr("mg_valleys_spflags", spflags, flagdesc_mapgen_valleys, U32_MAX);
236 settings->setU16("mg_valleys_altitude_chill", altitude_chill);
237 settings->setS16("mg_valleys_large_cave_depth", large_cave_depth);
238 settings->setU16("mg_valleys_lava_features", lava_features);
239 settings->setS16("mg_valleys_massive_cave_depth", massive_cave_depth);
240 settings->setU16("mg_valleys_river_depth", river_depth);
241 settings->setU16("mg_valleys_river_size", river_size);
242 settings->setU16("mg_valleys_water_features", water_features);
244 settings->setNoiseParams("mg_valleys_np_cave1", np_cave1);
245 settings->setNoiseParams("mg_valleys_np_cave2", np_cave2);
246 settings->setNoiseParams("mg_valleys_np_filler_depth", np_filler_depth);
247 settings->setNoiseParams("mg_valleys_np_inter_valley_fill", np_inter_valley_fill);
248 settings->setNoiseParams("mg_valleys_np_inter_valley_slope", np_inter_valley_slope);
249 settings->setNoiseParams("mg_valleys_np_rivers", np_rivers);
250 settings->setNoiseParams("mg_valleys_np_massive_caves", np_massive_caves);
251 settings->setNoiseParams("mg_valleys_np_terrain_height", np_terrain_height);
252 settings->setNoiseParams("mg_valleys_np_valley_depth", np_valley_depth);
253 settings->setNoiseParams("mg_valleys_np_valley_profile", np_valley_profile);
257 ///////////////////////////////////////
260 void MapgenValleys::makeChunk(BlockMakeData *data)
263 assert(data->vmanip);
264 assert(data->nodedef);
265 assert(data->blockpos_requested.X >= data->blockpos_min.X &&
266 data->blockpos_requested.Y >= data->blockpos_min.Y &&
267 data->blockpos_requested.Z >= data->blockpos_min.Z);
268 assert(data->blockpos_requested.X <= data->blockpos_max.X &&
269 data->blockpos_requested.Y <= data->blockpos_max.Y &&
270 data->blockpos_requested.Z <= data->blockpos_max.Z);
272 this->generating = true;
273 this->vm = data->vmanip;
274 this->ndef = data->nodedef;
276 //TimeTaker t("makeChunk");
278 v3s16 blockpos_min = data->blockpos_min;
279 v3s16 blockpos_max = data->blockpos_max;
280 node_min = blockpos_min * MAP_BLOCKSIZE;
281 node_max = (blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
282 full_node_min = (blockpos_min - 1) * MAP_BLOCKSIZE;
283 full_node_max = (blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
285 blockseed = getBlockSeed2(full_node_min, seed);
287 // Generate noise maps and base terrain height.
290 // Generate base terrain with initial heightmaps
291 s16 stone_surface_max_y = generateTerrain();
293 // Create biomemap at heightmap surface
294 bmgr->calcBiomes(csize.X, csize.Z, heatmap, humidmap, heightmap, biomemap);
296 // Actually place the biome-specific nodes
297 MgStoneType stone_type = generateBiomes(heatmap, humidmap);
300 if (flags & MG_CAVES)
301 generateCaves(stone_surface_max_y);
304 if ((flags & MG_DUNGEONS) && node_max.Y < 50 && (stone_surface_max_y >= node_min.Y)) {
307 dp.np_rarity = nparams_dungeon_rarity;
308 dp.np_density = nparams_dungeon_density;
309 dp.np_wetness = nparams_dungeon_wetness;
310 dp.c_water = c_water_source;
311 if (stone_type == STONE) {
312 dp.c_cobble = c_cobble;
313 dp.c_moss = c_mossycobble;
314 dp.c_stair = c_stair_cobble;
316 dp.diagonal_dirs = false;
318 dp.holesize = v3s16(1, 2, 1);
319 dp.roomsize = v3s16(0, 0, 0);
320 dp.notifytype = GENNOTIFY_DUNGEON;
321 } else if (stone_type == DESERT_STONE) {
322 dp.c_cobble = c_desert_stone;
323 dp.c_moss = c_desert_stone;
324 dp.c_stair = c_desert_stone;
326 dp.diagonal_dirs = true;
328 dp.holesize = v3s16(2, 3, 2);
329 dp.roomsize = v3s16(2, 5, 2);
330 dp.notifytype = GENNOTIFY_TEMPLE;
331 } else if (stone_type == SANDSTONE) {
332 dp.c_cobble = c_sandstonebrick;
333 dp.c_moss = c_sandstonebrick;
334 dp.c_stair = c_sandstonebrick;
336 dp.diagonal_dirs = false;
338 dp.holesize = v3s16(2, 2, 2);
339 dp.roomsize = v3s16(2, 0, 2);
340 dp.notifytype = GENNOTIFY_DUNGEON;
343 DungeonGen dgen(this, &dp);
344 dgen.generate(blockseed, full_node_min, full_node_max);
347 // Generate the registered decorations
348 if (flags & MG_DECORATIONS)
349 m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);
351 // Generate the registered ores
352 m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
354 // Sprinkle some dust on top after everything else was generated
357 //TimeTaker tll("liquid_lighting");
359 updateLiquid(&data->transforming_liquid, full_node_min, full_node_max);
361 if (flags & MG_LIGHT)
363 node_min - v3s16(0, 1, 0),
364 node_max + v3s16(0, 1, 0),
368 //mapgen_profiler->avg("liquid_lighting", tll.stop() / 1000.f);
369 //mapgen_profiler->avg("makeChunk", t.stop() / 1000.f);
371 this->generating = false;
375 // Populate the noise tables and do most of the
376 // calculation necessary to determine terrain height.
377 void MapgenValleys::calculateNoise()
379 //TimeTaker t("calculateNoise", NULL, PRECISION_MICRO);
382 int y = node_min.Y - 1;
385 //TimeTaker tcn("actualNoise");
387 noise_filler_depth->perlinMap2D(x, z);
388 noise_heat_blend->perlinMap2D(x, z);
389 noise_heat->perlinMap2D(x, z);
390 noise_humidity_blend->perlinMap2D(x, z);
391 noise_humidity->perlinMap2D(x, z);
392 noise_inter_valley_slope->perlinMap2D(x, z);
393 noise_rivers->perlinMap2D(x, z);
394 noise_terrain_height->perlinMap2D(x, z);
395 noise_valley_depth->perlinMap2D(x, z);
396 noise_valley_profile->perlinMap2D(x, z);
398 noise_inter_valley_fill->perlinMap3D(x, y, z);
400 //mapgen_profiler->avg("noisemaps", tcn.stop() / 1000.f);
402 for (s32 index = 0; index < csize.X * csize.Z; index++) {
403 noise_heat->result[index] += noise_heat_blend->result[index];
404 noise_humidity->result[index] += noise_humidity_blend->result[index];
410 for (tn.z = node_min.Z; tn.z <= node_max.Z; tn.z++)
411 for (tn.x = node_min.X; tn.x <= node_max.X; tn.x++, index++) {
412 // The parameters that we actually need to generate terrain
413 // are passed by address (and the return value).
414 tn.terrain_height = noise_terrain_height->result[index];
415 // River noise is replaced with base terrain, which
416 // is basically the height of the water table.
417 tn.rivers = &noise_rivers->result[index];
418 // Valley depth noise is replaced with the valley
419 // number that represents the height of terrain
420 // over rivers and is used to determine about
421 // how close a river is for humidity calculation.
422 tn.valley = &noise_valley_depth->result[index];
423 tn.valley_profile = noise_valley_profile->result[index];
424 // Slope noise is replaced by the calculated slope
425 // which is used to get terrain height in the slow
426 // method, to create sharper mountains.
427 tn.slope = &noise_inter_valley_slope->result[index];
428 tn.inter_valley_fill = noise_inter_valley_fill->result[index];
430 // This is the actual terrain height.
431 float mount = terrainLevelFromNoise(&tn);
432 noise_terrain_height->result[index] = mount;
435 heatmap = noise_heat->result;
436 humidmap = noise_humidity->result;
440 // This keeps us from having to maintain two similar sets of
441 // complicated code to determine ground level.
442 float MapgenValleys::terrainLevelFromNoise(TerrainNoise *tn)
444 // The square function changes the behaviour of this noise:
445 // very often small, and sometimes very high.
446 float valley_d = MYSQUARE(*tn->valley);
448 // valley_d is here because terrain is generally higher where valleys
449 // are deep (mountains). base represents the height of the
450 // rivers, most of the surface is above.
451 float base = tn->terrain_height + valley_d;
453 // "river" represents the distance from the river, in arbitrary units.
454 float river = fabs(*tn->rivers) - river_size_factor;
456 // Use the curve of the function 1-exp(-(x/a)^2) to model valleys.
457 // Making "a" vary (0 < a <= 1) changes the shape of the valleys.
458 // Try it with a geometry software !
459 // (here x = "river" and a = valley_profile).
460 // "valley" represents the height of the terrain, from the rivers.
462 float t = river / tn->valley_profile;
463 *tn->valley = valley_d * (1.f - exp(- MYSQUARE(t)));
466 // approximate height of the terrain at this point
467 float mount = base + *tn->valley;
469 *tn->slope *= *tn->valley;
471 // Rivers are placed where "river" is negative, so where the original
472 // noise value is close to zero.
473 // Base ground is returned as rivers since it's basically the water table.
476 // Use the the function -sqrt(1-x^2) which models a circle.
479 float t = river / river_size_factor + 1;
480 depth = (river_depth_bed * sqrt(MYMAX(0, 1.f - MYSQUARE(t))));
483 // base - depth : height of the bottom of the river
484 // water_level - 6 : don't make rivers below 6 nodes under the surface
485 mount = rangelim(base - depth, (float) (water_level - 6), mount);
487 // Slope has no influence on rivers.
495 // This avoids duplicating the code in terrainLevelFromNoise, adding
496 // only the final step of terrain generation without a noise map.
497 float MapgenValleys::adjustedTerrainLevelFromNoise(TerrainNoise *tn)
499 float mount = terrainLevelFromNoise(tn);
500 s16 y_start = myround(mount);
502 for (s16 y = y_start; y <= y_start + 1000; y++) {
503 float fill = NoisePerlin3D(&noise_inter_valley_fill->np, tn->x, y, tn->z, seed);
505 if (fill * *tn->slope <= y - mount) {
506 mount = MYMAX(y - 1, mount);
515 int MapgenValleys::getGroundLevelAtPoint(v2s16 p)
517 // ***********************************
518 // This method (deliberately) does not
519 // return correct terrain values.
520 // ***********************************
522 // Since MT doesn't normally deal with rivers, check
523 // to make sure this isn't a request for a location
525 float rivers = NoisePerlin2D(&noise_rivers->np, p.X, p.Y, seed);
527 // If it's wet, return an unusable number.
528 if (fabs(rivers) < river_size_factor)
529 return MAX_MAP_GENERATION_LIMIT;
531 // Otherwise, return the real result.
532 return terrainLevelAtPoint(p.X, p.Y);
536 float MapgenValleys::terrainLevelAtPoint(s16 x, s16 z)
540 float rivers = NoisePerlin2D(&noise_rivers->np, x, z, seed);
541 float valley = NoisePerlin2D(&noise_valley_depth->np, x, z, seed);
542 float inter_valley_slope = NoisePerlin2D(&noise_inter_valley_slope->np, x, z, seed);
546 tn.terrain_height = NoisePerlin2D(&noise_terrain_height->np, x, z, seed);
549 tn.valley_profile = NoisePerlin2D(&noise_valley_profile->np, x, z, seed);
550 tn.slope = &inter_valley_slope;
551 tn.inter_valley_fill = 0.f;
553 return adjustedTerrainLevelFromNoise(&tn);
557 int MapgenValleys::generateTerrain()
559 MapNode n_air(CONTENT_AIR);
560 MapNode n_river_water(c_river_water_source);
561 MapNode n_sand(c_sand);
562 MapNode n_stone(c_stone);
563 MapNode n_water(c_water_source);
565 v3s16 em = vm->m_area.getExtent();
566 s16 surface_max_y = -MAX_MAP_GENERATION_LIMIT;
569 for (s16 z = node_min.Z; z <= node_max.Z; z++)
570 for (s16 x = node_min.X; x <= node_max.X; x++, index_2d++) {
571 s16 river_y = floor(noise_rivers->result[index_2d]);
572 s16 surface_y = floor(noise_terrain_height->result[index_2d]);
573 float slope = noise_inter_valley_slope->result[index_2d];
575 heightmap[index_2d] = surface_y;
577 if (surface_y > surface_max_y)
578 surface_max_y = surface_y;
580 u32 index_3d = (z - node_min.Z) * zstride + (x - node_min.X);
581 u32 index_data = vm->m_area.index(x, node_min.Y - 1, z);
583 // Mapgens concern themselves with stone and water.
584 for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
586 fill = noise_inter_valley_fill->result[index_3d];
588 if (vm->m_data[index_data].getContent() == CONTENT_IGNORE) {
589 bool river = (river_y > surface_y);
591 if (river && y == surface_y) {
593 vm->m_data[index_data] = n_sand;
594 } else if (river && y <= surface_y) {
596 vm->m_data[index_data] = n_stone;
597 } else if (river && y < river_y) {
599 vm->m_data[index_data] = n_river_water;
600 } else if ((!river) && myround(fill * slope) >= y - surface_y) {
602 vm->m_data[index_data] = n_stone;
603 heightmap[index_2d] = surface_max_y = y;
604 } else if (y <= water_level) {
606 vm->m_data[index_data] = n_water;
608 vm->m_data[index_data] = n_air;
612 vm->m_area.add_y(em, index_data, 1);
616 // Although the original valleys adjusts humidity by distance
617 // from seawater, this causes problems with the default biomes.
618 // Adjust only by freshwater proximity.
619 const float humidity_offset = 0.8f; // derived by testing
621 noise_humidity->result[index_2d] *= (1 + pow(0.5f, MYMAX((surface_max_y
622 - noise_rivers->result[index_2d]) / 3.f, 0.f))) * humidity_offset;
624 // Assign the heat adjusted by altitude.
625 if (use_altitude_chill && surface_max_y > 0)
626 noise_heat->result[index_2d] *=
627 pow(0.5f, (surface_max_y - altitude_chill / 3.f) / altitude_chill);
630 return surface_max_y;
634 MgStoneType MapgenValleys::generateBiomes(float *heat_map, float *humidity_map)
636 v3s16 em = vm->m_area.getExtent();
638 MgStoneType stone_type = STONE;
640 for (s16 z = node_min.Z; z <= node_max.Z; z++)
641 for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
645 u16 depth_water_top = 0;
646 u32 vi = vm->m_area.index(x, node_max.Y, z);
648 // Check node at base of mapchunk above, either a node of a previously
649 // generated mapchunk or if not, a node of overgenerated base terrain.
650 content_t c_above = vm->m_data[vi + em.X].getContent();
651 bool air_above = c_above == CONTENT_AIR;
652 bool water_above = (c_above == c_water_source);
654 // If there is air or water above enable top/filler placement, otherwise force
655 // nplaced to stone level by setting a number exceeding any possible filler depth.
656 u16 nplaced = (air_above || water_above) ? 0 : U16_MAX;
658 for (s16 y = node_max.Y; y >= node_min.Y; y--) {
659 content_t c = vm->m_data[vi].getContent();
661 // Biome is recalculated each time an upper surface is detected while
662 // working down a column. The selected biome then remains in effect for
663 // all nodes below until the next surface and biome recalculation.
664 // Biome is recalculated:
665 // 1. At the surface of stone below air or water.
666 // 2. At the surface of water below air.
667 // 3. When stone or water is detected but biome has not yet been calculated.
668 if ((c == c_stone && (air_above || water_above || !biome))
669 || ((c == c_water_source || c == c_river_water_source)
670 && (air_above || !biome))) {
671 // Both heat and humidity have already been adjusted for altitude.
672 biome = bmgr->getBiome(heat_map[index], humidity_map[index], y);
674 depth_top = biome->depth_top;
675 base_filler = MYMAX(depth_top
676 + biome->depth_filler
677 + noise_filler_depth->result[index], 0.f);
678 depth_water_top = biome->depth_water_top;
680 // Detect stone type for dungeons during every biome calculation.
681 // This is more efficient than detecting per-node and will not
682 // miss any desert stone or sandstone biomes.
683 if (biome->c_stone == c_desert_stone)
684 stone_type = DESERT_STONE;
685 else if (biome->c_stone == c_sandstone)
686 stone_type = SANDSTONE;
690 content_t c_below = vm->m_data[vi - em.X].getContent();
692 // If the node below isn't solid, make this node stone, so that
693 // any top/filler nodes above are structurally supported.
694 // This is done by aborting the cycle of top/filler placement
695 // immediately by forcing nplaced to stone level.
696 if (c_below == CONTENT_AIR
697 || c_below == c_water_source
698 || c_below == c_river_water_source)
701 if (nplaced < depth_top) {
702 vm->m_data[vi] = MapNode(biome->c_top);
704 } else if (nplaced < base_filler) {
705 vm->m_data[vi] = MapNode(biome->c_filler);
708 vm->m_data[vi] = MapNode(biome->c_stone);
713 } else if (c == c_water_source) {
714 vm->m_data[vi] = MapNode((y > (s32)(water_level - depth_water_top))
715 ? biome->c_water_top : biome->c_water);
716 nplaced = 0; // Enable top/filler placement for next surface
719 } else if (c == c_river_water_source) {
720 vm->m_data[vi] = MapNode(biome->c_river_water);
721 nplaced = U16_MAX; // Sand was already placed under rivers.
724 } else if (c == CONTENT_AIR) {
725 nplaced = 0; // Enable top/filler placement for next surface
728 } else { // Possible various nodes overgenerated from neighbouring mapchunks
729 nplaced = U16_MAX; // Disable top/filler placement
734 vm->m_area.add_y(em, vi, -1);
742 void MapgenValleys::dustTopNodes()
744 if (node_max.Y < water_level)
747 v3s16 em = vm->m_area.getExtent();
750 for (s16 z = node_min.Z; z <= node_max.Z; z++)
751 for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
752 Biome *biome = (Biome *)bmgr->getRaw(biomemap[index]);
754 if (biome->c_dust == CONTENT_IGNORE)
757 u32 vi = vm->m_area.index(x, full_node_max.Y, z);
758 content_t c_full_max = vm->m_data[vi].getContent();
761 if (c_full_max == CONTENT_AIR) {
762 y_start = full_node_max.Y - 1;
763 } else if (c_full_max == CONTENT_IGNORE) {
764 vi = vm->m_area.index(x, node_max.Y + 1, z);
765 content_t c_max = vm->m_data[vi].getContent();
767 if (c_max == CONTENT_AIR)
768 y_start = node_max.Y;
775 vi = vm->m_area.index(x, y_start, z);
776 for (s16 y = y_start; y >= node_min.Y - 1; y--) {
777 if (vm->m_data[vi].getContent() != CONTENT_AIR)
780 vm->m_area.add_y(em, vi, -1);
783 content_t c = vm->m_data[vi].getContent();
784 if (!ndef->get(c).buildable_to && c != CONTENT_IGNORE && c != biome->c_dust) {
785 vm->m_area.add_y(em, vi, 1);
786 vm->m_data[vi] = MapNode(biome->c_dust);
792 void MapgenValleys::generateCaves(s16 max_stone_y)
794 if (max_stone_y < node_min.Y)
797 noise_cave1->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
798 noise_cave2->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
800 PseudoRandom ps(blockseed + 72202);
802 MapNode n_air(CONTENT_AIR);
803 MapNode n_lava(c_lava_source);
804 MapNode n_water(c_river_water_source);
806 v3s16 em = vm->m_area.getExtent();
808 // Cave blend distance near YMIN, YMAX
809 const float massive_cave_blend = 128.f;
810 // noise threshold for massive caves
811 const float massive_cave_threshold = 0.6f;
812 // mct: 1 = small rare caves, 0.5 1/3rd ground volume, 0 = 1/2 ground volume.
814 float yblmin = -map_gen_limit + massive_cave_blend * 1.5f;
815 float yblmax = massive_cave_depth - massive_cave_blend * 1.5f;
816 bool made_a_big_one = false;
818 // Cache the tcave values as they only vary by altitude.
819 if (node_max.Y <= massive_cave_depth) {
820 noise_massive_caves->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
822 for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
823 float tcave = massive_cave_threshold;
826 float t = (yblmin - y) / massive_cave_blend;
827 tcave += MYSQUARE(t);
828 } else if (y > yblmax) {
829 float t = (y - yblmax) / massive_cave_blend;
830 tcave += MYSQUARE(t);
833 tcave_cache[y - node_min.Y + 1] = tcave;
837 // lava_depth varies between one and ten as you approach
838 // the bottom of the world.
839 s16 lava_depth = ceil((lava_max_height - node_min.Y + 1) * 10.f / map_gen_limit);
840 // This allows random lava spawns to be less common at the surface.
841 s16 lava_chance = MYCUBE(lava_features_lim) * lava_depth;
842 // water_depth varies between ten and one on the way down.
843 s16 water_depth = ceil((map_gen_limit - abs(node_min.Y) + 1) * 10.f / map_gen_limit);
844 // This allows random water spawns to be more common at the surface.
845 s16 water_chance = MYCUBE(water_features_lim) * water_depth;
847 // Reduce the odds of overflows even further.
848 if (node_max.Y > water_level) {
855 for (s16 z = node_min.Z; z <= node_max.Z; z++)
856 for (s16 x = node_min.X; x <= node_max.X; x++, index_2d++) {
857 Biome *biome = (Biome *)bmgr->getRaw(biomemap[index_2d]);
858 bool air_above = false;
859 bool underground = false;
860 u32 index_data = vm->m_area.index(x, node_max.Y + 1, z);
862 index_3d = (z - node_min.Z) * zstride + (csize.Y + 1) * ystride + (x - node_min.X);
864 // Dig caves on down loop to check for air above.
865 for (s16 y = node_max.Y + 1;
867 y--, index_3d -= ystride, vm->m_area.add_y(em, index_data, -1)) {
868 float terrain = noise_terrain_height->result[index_2d];
871 if (y > terrain + 10) {
874 } else if (y < terrain - 40) {
878 // Dig massive caves.
879 if (node_max.Y <= massive_cave_depth
880 && noise_massive_caves->result[index_3d]
881 > tcave_cache[y - node_min.Y + 1]) {
882 vm->m_data[index_data] = n_air;
883 made_a_big_one = true;
886 content_t c = vm->m_data[index_data].getContent();
887 float d1 = contour(noise_cave1->result[index_3d]);
888 float d2 = contour(noise_cave2->result[index_3d]);
890 // River water is not set as ground content
891 // in the default game. This can produce strange results
892 // when a cave undercuts a river. However, that's not for
893 // the mapgen to correct. Fix it in lua.
895 if (c == CONTENT_AIR) {
897 } else if (d1 * d2 > 0.3f && ndef->get(c).is_ground_content) {
899 vm->m_data[index_data] = n_air;
901 } else if (air_above && (c == biome->c_filler || c == biome->c_stone)) {
903 s16 sr = ps.range(0,39);
905 vm->m_area.add_y(em, j, 1);
907 if (sr > terrain - y) {
908 // Put dirt in caves near the surface.
910 vm->m_data[index_data] = MapNode(biome->c_filler);
912 vm->m_data[index_data] = MapNode(biome->c_top);
913 } else if (sr < 3 && underground) {
915 if (lava_features_lim > 0 && y <= lava_max_height
916 && c == biome->c_stone && sr < lava_chance)
917 vm->m_data[j] = n_lava;
921 // If sr < 0 then we should have already placed lava --
922 // don't immediately dump water on it.
923 if (water_features_lim > 0 && y <= cave_water_max_height
924 && sr >= 0 && sr < water_chance)
925 vm->m_data[j] = n_water;
930 } else if (c == biome->c_filler || c == biome->c_stone) {
939 if (node_max.Y <= large_cave_depth && (!made_a_big_one)) {
940 u32 bruises_count = ps.range(0, 2);
941 for (u32 i = 0; i < bruises_count; i++) {
942 CaveV5 cave(this, &ps);
943 cave.makeCave(node_min, node_max, max_stone_y);