3 Copyright (C) 2010-2016 paramat, Matt Gregory
4 Copyright (C) 2010-2016 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
5 Copyright (C) 2017 vlapsley, Vaughan Lapsley <vlapsley@gmail.com>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License along
18 with this program; if not, write to the Free Software Foundation, Inc.,
19 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include "content_sao.h"
32 #include "voxelalgorithms.h"
33 //#include "profiler.h" // For TimeTaker
34 #include "settings.h" // For g_settings
36 #include "dungeongen.h"
40 #include "mg_decoration.h"
41 #include "mapgen_carpathian.h"
44 FlagDesc flagdesc_mapgen_carpathian[] = {
45 {"caverns", MGCARPATHIAN_CAVERNS},
50 ///////////////////////////////////////////////////////////////////////////////
53 MapgenCarpathian::MapgenCarpathian(
54 int mapgenid, MapgenCarpathianParams *params, EmergeManager *emerge)
55 : MapgenBasic(mapgenid, params, emerge)
57 spflags = params->spflags;
58 cave_width = params->cave_width;
59 large_cave_depth = params->large_cave_depth;
60 lava_depth = params->lava_depth;
61 cavern_limit = params->cavern_limit;
62 cavern_taper = params->cavern_taper;
63 cavern_threshold = params->cavern_threshold;
64 grad_wl = 1 - water_level;
67 noise_base = new Noise(¶ms->np_base, seed, csize.X, csize.Z);
68 noise_filler_depth = new Noise(¶ms->np_filler_depth, seed, csize.X, csize.Z);
69 noise_height1 = new Noise(¶ms->np_height1, seed, csize.X, csize.Z);
70 noise_height2 = new Noise(¶ms->np_height2, seed, csize.X, csize.Z);
71 noise_height3 = new Noise(¶ms->np_height3, seed, csize.X, csize.Z);
72 noise_height4 = new Noise(¶ms->np_height4, seed, csize.X, csize.Z);
73 noise_hills_terrain = new Noise(¶ms->np_hills_terrain, seed, csize.X, csize.Z);
74 noise_ridge_terrain = new Noise(¶ms->np_ridge_terrain, seed, csize.X, csize.Z);
75 noise_step_terrain = new Noise(¶ms->np_step_terrain, seed, csize.X, csize.Z);
76 noise_hills = new Noise(¶ms->np_hills, seed, csize.X, csize.Z);
77 noise_ridge_mnt = new Noise(¶ms->np_ridge_mnt, seed, csize.X, csize.Z);
78 noise_step_mnt = new Noise(¶ms->np_step_mnt, seed, csize.X, csize.Z);
81 // 1 up 1 down overgeneration
82 noise_mnt_var = new Noise(¶ms->np_mnt_var, seed, csize.X, csize.Y + 2, csize.Z);
85 MapgenBasic::np_cave1 = params->np_cave1;
86 MapgenBasic::np_cave2 = params->np_cave2;
87 MapgenBasic::np_cavern = params->np_cavern;
91 MapgenCarpathian::~MapgenCarpathian()
94 delete noise_filler_depth;
99 delete noise_hills_terrain;
100 delete noise_ridge_terrain;
101 delete noise_step_terrain;
103 delete noise_ridge_mnt;
104 delete noise_step_mnt;
105 delete noise_mnt_var;
109 MapgenCarpathianParams::MapgenCarpathianParams()
111 np_base = NoiseParams(12, 1, v3f(2557, 2557, 2557), 6538, 4, 0.8, 0.5);
112 np_filler_depth = NoiseParams(0, 1, v3f(128, 128, 128), 261, 3, 0.7, 2.0);
113 np_height1 = NoiseParams(0, 5, v3f(251, 251, 251), 9613, 5, 0.5, 2.0);
114 np_height2 = NoiseParams(0, 5, v3f(383, 383, 383), 1949, 5, 0.5, 2.0);
115 np_height3 = NoiseParams(0, 5, v3f(509, 509, 509), 3211, 5, 0.5, 2.0);
116 np_height4 = NoiseParams(0, 5, v3f(631, 631, 631), 1583, 5, 0.5, 2.0);
117 np_hills_terrain = NoiseParams(1, 1, v3f(1301, 1301, 1301), 1692, 5, 0.5, 2.0);
118 np_ridge_terrain = NoiseParams(1, 1, v3f(1889, 1889, 1889), 3568, 5, 0.5, 2.0);
119 np_step_terrain = NoiseParams(1, 1, v3f(1889, 1889, 1889), 4157, 5, 0.5, 2.0);
120 np_hills = NoiseParams(0, 3, v3f(257, 257, 257), 6604, 6, 0.5, 2.0);
121 np_ridge_mnt = NoiseParams(0, 12, v3f(743, 743, 743), 5520, 6, 0.7, 2.0);
122 np_step_mnt = NoiseParams(0, 8, v3f(509, 509, 509), 2590, 6, 0.6, 2.0);
123 np_mnt_var = NoiseParams(0, 1, v3f(499, 499, 499), 2490, 5, 0.6, 2.0);
124 np_cave1 = NoiseParams(0, 12, v3f(61, 61, 61), 52534, 3, 0.5, 2.0);
125 np_cave2 = NoiseParams(0, 12, v3f(67, 67, 67), 10325, 3, 0.5, 2.0);
126 np_cavern = NoiseParams(0, 1, v3f(384, 128, 384), 723, 5, 0.63, 2.0);
130 void MapgenCarpathianParams::readParams(const Settings *settings)
132 settings->getFlagStrNoEx("mgcarpathian_spflags", spflags, flagdesc_mapgen_carpathian);
133 settings->getFloatNoEx("mgcarpathian_cave_width", cave_width);
134 settings->getS16NoEx("mgcarpathian_large_cave_depth", large_cave_depth);
135 settings->getS16NoEx("mgcarpathian_lava_depth", lava_depth);
136 settings->getS16NoEx("mgcarpathian_cavern_limit", cavern_limit);
137 settings->getS16NoEx("mgcarpathian_cavern_taper", cavern_taper);
138 settings->getFloatNoEx("mgcarpathian_cavern_threshold", cavern_threshold);
140 settings->getNoiseParams("mgcarpathian_np_base", np_base);
141 settings->getNoiseParams("mgcarpathian_np_filler_depth", np_filler_depth);
142 settings->getNoiseParams("mgcarpathian_np_height1", np_height1);
143 settings->getNoiseParams("mgcarpathian_np_height2", np_height2);
144 settings->getNoiseParams("mgcarpathian_np_height3", np_height3);
145 settings->getNoiseParams("mgcarpathian_np_height4", np_height4);
146 settings->getNoiseParams("mgcarpathian_np_hills_terrain", np_hills_terrain);
147 settings->getNoiseParams("mgcarpathian_np_ridge_terrain", np_ridge_terrain);
148 settings->getNoiseParams("mgcarpathian_np_step_terrain", np_step_terrain);
149 settings->getNoiseParams("mgcarpathian_np_hills", np_hills);
150 settings->getNoiseParams("mgcarpathian_np_ridge_mnt", np_ridge_mnt);
151 settings->getNoiseParams("mgcarpathian_np_step_mnt", np_step_mnt);
152 settings->getNoiseParams("mgcarpathian_np_mnt_var", np_mnt_var);
153 settings->getNoiseParams("mgcarpathian_np_cave1", np_cave1);
154 settings->getNoiseParams("mgcarpathian_np_cave2", np_cave2);
155 settings->getNoiseParams("mgcarpathian_np_cavern", np_cavern);
159 void MapgenCarpathianParams::writeParams(Settings *settings) const
161 settings->setFlagStr("mgcarpathian_spflags", spflags, flagdesc_mapgen_carpathian, U32_MAX);
162 settings->setFloat("mgcarpathian_cave_width", cave_width);
163 settings->setS16("mgcarpathian_large_cave_depth", large_cave_depth);
164 settings->setS16("mgcarpathian_lava_depth", lava_depth);
165 settings->setS16("mgcarpathian_cavern_limit", cavern_limit);
166 settings->setS16("mgcarpathian_cavern_taper", cavern_taper);
167 settings->setFloat("mgcarpathian_cavern_threshold", cavern_threshold);
169 settings->setNoiseParams("mgcarpathian_np_base", np_base);
170 settings->setNoiseParams("mgcarpathian_np_filler_depth", np_filler_depth);
171 settings->setNoiseParams("mgcarpathian_np_height1", np_height1);
172 settings->setNoiseParams("mgcarpathian_np_height2", np_height2);
173 settings->setNoiseParams("mgcarpathian_np_height3", np_height3);
174 settings->setNoiseParams("mgcarpathian_np_height4", np_height4);
175 settings->setNoiseParams("mgcarpathian_np_hills_terrain", np_hills_terrain);
176 settings->setNoiseParams("mgcarpathian_np_ridge_terrain", np_ridge_terrain);
177 settings->setNoiseParams("mgcarpathian_np_step_terrain", np_step_terrain);
178 settings->setNoiseParams("mgcarpathian_np_hills", np_hills);
179 settings->setNoiseParams("mgcarpathian_np_ridge_mnt", np_ridge_mnt);
180 settings->setNoiseParams("mgcarpathian_np_step_mnt", np_step_mnt);
181 settings->setNoiseParams("mgcarpathian_np_mnt_var", np_mnt_var);
182 settings->setNoiseParams("mgcarpathian_np_cave1", np_cave1);
183 settings->setNoiseParams("mgcarpathian_np_cave2", np_cave2);
184 settings->setNoiseParams("mgcarpathian_np_cavern", np_cavern);
188 ///////////////////////////////////////////////////////////////////////////////
192 inline float MapgenCarpathian::getLerp(float noise1, float noise2, float mod)
194 return noise1 + mod * (noise2 - noise1);
198 float MapgenCarpathian::getSteps(float noise1, float noise2)
200 float w = fabs(noise2);
201 float k = floor(noise1 / w);
202 float f = (noise1 - k * w) / w;
203 float s = std::fmin(2.f * f, 1.f);
208 ///////////////////////////////////////////////////////////////////////////////
211 void MapgenCarpathian::makeChunk(BlockMakeData *data)
214 assert(data->vmanip);
215 assert(data->nodedef);
216 assert(data->blockpos_requested.X >= data->blockpos_min.X &&
217 data->blockpos_requested.Y >= data->blockpos_min.Y &&
218 data->blockpos_requested.Z >= data->blockpos_min.Z);
219 assert(data->blockpos_requested.X <= data->blockpos_max.X &&
220 data->blockpos_requested.Y <= data->blockpos_max.Y &&
221 data->blockpos_requested.Z <= data->blockpos_max.Z);
223 this->generating = true;
224 this->vm = data->vmanip;
225 this->ndef = data->nodedef;
227 v3s16 blockpos_min = data->blockpos_min;
228 v3s16 blockpos_max = data->blockpos_max;
229 node_min = blockpos_min * MAP_BLOCKSIZE;
230 node_max = (blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
231 full_node_min = (blockpos_min - 1) * MAP_BLOCKSIZE;
232 full_node_max = (blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
234 // Create a block-specific seed
235 blockseed = getBlockSeed2(full_node_min, seed);
238 s16 stone_surface_max_y = generateTerrain();
241 updateHeightmap(node_min, node_max);
243 // Init biome generator, place biome-specific nodes, and build biomemap
244 biomegen->calcBiomeNoise(node_min);
246 MgStoneType mgstone_type;
247 content_t biome_stone;
248 generateBiomes(&mgstone_type, &biome_stone, water_level - 1);
250 // Generate caverns, tunnels and classic caves
251 if (flags & MG_CAVES) {
252 bool has_cavern = false;
254 if (spflags & MGCARPATHIAN_CAVERNS)
255 has_cavern = generateCaverns(stone_surface_max_y);
256 // Generate tunnels and classic caves
258 // Disable classic caves in this mapchunk by setting
259 // 'large cave depth' to world base. Avoids excessive liquid in
260 // large caverns and floating blobs of overgenerated liquid.
261 generateCaves(stone_surface_max_y, -MAX_MAP_GENERATION_LIMIT);
263 generateCaves(stone_surface_max_y, large_cave_depth);
267 if (flags & MG_DUNGEONS)
268 generateDungeons(stone_surface_max_y, mgstone_type, biome_stone);
270 // Generate the registered decorations
271 if (flags & MG_DECORATIONS)
272 m_emerge->decomgr->placeAllDecos(this, blockseed,
273 node_min, node_max, water_level - 1);
275 // Generate the registered ores
276 m_emerge->oremgr->placeAllOres(this, blockseed,
277 node_min, node_max, water_level - 1);
279 // Sprinkle some dust on top after everything else was generated
283 updateLiquid(&data->transforming_liquid, full_node_min, full_node_max);
285 // Calculate lighting
286 if (flags & MG_LIGHT) {
287 calcLighting(node_min - v3s16(0, 1, 0), node_max + v3s16(0, 1, 0),
288 full_node_min, full_node_max);
291 this->generating = false;
295 ///////////////////////////////////////////////////////////////////////////////
298 int MapgenCarpathian::getSpawnLevelAtPoint(v2s16 p)
300 s16 level_at_point = terrainLevelAtPoint(p.X, p.Y);
301 if (level_at_point <= water_level || level_at_point > water_level + 32)
302 return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
304 return level_at_point;
308 float MapgenCarpathian::terrainLevelAtPoint(s16 x, s16 z)
310 float ground = NoisePerlin2D(&noise_base->np, x, z, seed);
311 float height1 = NoisePerlin2D(&noise_height1->np, x, z, seed);
312 float height2 = NoisePerlin2D(&noise_height2->np, x, z, seed);
313 float height3 = NoisePerlin2D(&noise_height3->np, x, z, seed);
314 float height4 = NoisePerlin2D(&noise_height4->np, x, z, seed);
315 float hter = NoisePerlin2D(&noise_hills_terrain->np, x, z, seed);
316 float rter = NoisePerlin2D(&noise_ridge_terrain->np, x, z, seed);
317 float ster = NoisePerlin2D(&noise_step_terrain->np, x, z, seed);
318 float n_hills = NoisePerlin2D(&noise_hills->np, x, z, seed);
319 float n_ridge_mnt = NoisePerlin2D(&noise_ridge_mnt->np, x, z, seed);
320 float n_step_mnt = NoisePerlin2D(&noise_step_mnt->np, x, z, seed);
322 int height = -MAX_MAP_GENERATION_LIMIT;
324 for (s16 y = 1; y <= 30; y++) {
325 float mnt_var = NoisePerlin3D(&noise_mnt_var->np, x, y, z, seed);
327 // Gradient & shallow seabed
328 s32 grad = (y < water_level) ? grad_wl + (water_level - y) * 3 : 1 - y;
330 // Hill/Mountain height (hilliness)
331 float hill1 = getLerp(height1, height2, mnt_var);
332 float hill2 = getLerp(height3, height4, mnt_var);
333 float hill3 = getLerp(height3, height2, mnt_var);
334 float hill4 = getLerp(height1, height4, mnt_var);
335 float hilliness = std::fmax(std::fmin(hill1, hill2), std::fmin(hill3, hill4));
338 float hill_mnt = hilliness * pow(n_hills, 2.f);
339 float hills = pow(hter, 3.f) * hill_mnt;
342 float ridge_mnt = hilliness * (1.f - fabs(n_ridge_mnt));
343 float ridged_mountains = pow(rter, 3.f) * ridge_mnt;
345 // Step (terraced) mountains
346 float step_mnt = hilliness * getSteps(n_step_mnt, fabs(mnt_var));
347 float step_mountains = pow(ster, 3.f) * step_mnt;
349 // Final terrain level
350 float mountains = hills + ridged_mountains + step_mountains;
351 float surface_level = ground + mountains + grad;
353 if (y > surface_level && height < 0)
361 ///////////////////////////////////////////////////////////////////////////////
364 int MapgenCarpathian::generateTerrain()
366 MapNode mn_air(CONTENT_AIR);
367 MapNode mn_stone(c_stone);
368 MapNode mn_water(c_water_source);
370 s16 stone_surface_max_y = -MAX_MAP_GENERATION_LIMIT;
374 // Calculate noise for terrain generation
375 noise_base->perlinMap2D(node_min.X, node_min.Z);
376 noise_height1->perlinMap2D(node_min.X, node_min.Z);
377 noise_height2->perlinMap2D(node_min.X, node_min.Z);
378 noise_height3->perlinMap2D(node_min.X, node_min.Z);
379 noise_height4->perlinMap2D(node_min.X, node_min.Z);
380 noise_hills_terrain->perlinMap2D(node_min.X, node_min.Z);
381 noise_ridge_terrain->perlinMap2D(node_min.X, node_min.Z);
382 noise_step_terrain->perlinMap2D(node_min.X, node_min.Z);
383 noise_hills->perlinMap2D(node_min.X, node_min.Z);
384 noise_ridge_mnt->perlinMap2D(node_min.X, node_min.Z);
385 noise_step_mnt->perlinMap2D(node_min.X, node_min.Z);
386 noise_mnt_var->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
389 for (s16 z = node_min.Z; z <= node_max.Z; z++) {
390 for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
391 u32 vi = vm->m_area.index(node_min.X, y, z);
392 for (s16 x = node_min.X; x <= node_max.X;
393 x++, vi++, index2d++, index3d++) {
394 if (vm->m_data[vi].getContent() != CONTENT_IGNORE)
398 float ground = noise_base->result[index2d];
400 // Gradient & shallow seabed
401 s32 grad = (y < water_level) ? grad_wl + (water_level - y) * 3 : 1 - y;
403 // Hill/Mountain height (hilliness)
404 float height1 = noise_height1->result[index2d];
405 float height2 = noise_height2->result[index2d];
406 float height3 = noise_height3->result[index2d];
407 float height4 = noise_height4->result[index2d];
408 float mnt_var = noise_mnt_var->result[index3d];
409 // Combine height noises and apply 3D variation
410 float hill1 = getLerp(height1, height2, mnt_var);
411 float hill2 = getLerp(height3, height4, mnt_var);
412 float hill3 = getLerp(height3, height2, mnt_var);
413 float hill4 = getLerp(height1, height4, mnt_var);
414 // 'hilliness' determines whether hills/mountains are
416 float hilliness = std::fmax(std::fmin(hill1, hill2), std::fmin(hill3, hill4));
419 float hter = noise_hills_terrain->result[index2d];
420 float n_hills = noise_hills->result[index2d];
421 float hill_mnt = hilliness * pow(n_hills, 2.f);
422 float hills = pow(fabs(hter), 3.f) * hill_mnt;
425 float rter = noise_ridge_terrain->result[index2d];
426 float n_ridge_mnt = noise_ridge_mnt->result[index2d];
427 float ridge_mnt = hilliness * (1.f - fabs(n_ridge_mnt));
428 float ridged_mountains = pow(fabs(rter), 3.f) * ridge_mnt;
430 // Step (terraced) mountains
431 float ster = noise_step_terrain->result[index2d];
432 float n_step_mnt = noise_step_mnt->result[index2d];
433 float step_mnt = hilliness * getSteps(n_step_mnt, fabs(mnt_var));
434 float step_mountains = pow(fabs(ster), 3.f) * step_mnt;
436 // Final terrain level
437 float mountains = hills + ridged_mountains + step_mountains;
438 float surface_level = ground + mountains + grad;
440 if (y < surface_level) {
441 vm->m_data[vi] = mn_stone; // Stone
442 if (y > stone_surface_max_y)
443 stone_surface_max_y = y;
444 } else if (y <= water_level) {
445 vm->m_data[vi] = mn_water; // Sea water
447 vm->m_data[vi] = mn_air; // Air
455 return stone_surface_max_y;