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);
245 MgStoneType stone_type = generateBiomes(water_level - 1);
247 // Generate caverns, tunnels and classic caves
248 if (flags & MG_CAVES) {
249 bool has_cavern = false;
251 if (spflags & MGCARPATHIAN_CAVERNS)
252 has_cavern = generateCaverns(stone_surface_max_y);
253 // Generate tunnels and classic caves
255 // Disable classic caves in this mapchunk by setting
256 // 'large cave depth' to world base. Avoids excessive liquid in
257 // large caverns and floating blobs of overgenerated liquid.
258 generateCaves(stone_surface_max_y, -MAX_MAP_GENERATION_LIMIT);
260 generateCaves(stone_surface_max_y, large_cave_depth);
264 if (flags & MG_DUNGEONS)
265 generateDungeons(stone_surface_max_y, stone_type);
267 // Generate the registered decorations
268 if (flags & MG_DECORATIONS)
269 m_emerge->decomgr->placeAllDecos(this, blockseed,
270 node_min, node_max, water_level - 1);
272 // Generate the registered ores
273 m_emerge->oremgr->placeAllOres(this, blockseed,
274 node_min, node_max, water_level - 1);
276 // Sprinkle some dust on top after everything else was generated
280 updateLiquid(&data->transforming_liquid, full_node_min, full_node_max);
282 // Calculate lighting
283 if (flags & MG_LIGHT) {
284 calcLighting(node_min - v3s16(0, 1, 0), node_max + v3s16(0, 1, 0),
285 full_node_min, full_node_max);
288 this->generating = false;
292 ///////////////////////////////////////////////////////////////////////////////
295 int MapgenCarpathian::getSpawnLevelAtPoint(v2s16 p)
297 s16 level_at_point = terrainLevelAtPoint(p.X, p.Y);
298 if (level_at_point <= water_level || level_at_point > water_level + 32)
299 return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
301 return level_at_point;
305 float MapgenCarpathian::terrainLevelAtPoint(s16 x, s16 z)
307 float ground = NoisePerlin2D(&noise_base->np, x, z, seed);
308 float height1 = NoisePerlin2D(&noise_height1->np, x, z, seed);
309 float height2 = NoisePerlin2D(&noise_height2->np, x, z, seed);
310 float height3 = NoisePerlin2D(&noise_height3->np, x, z, seed);
311 float height4 = NoisePerlin2D(&noise_height4->np, x, z, seed);
312 float hter = NoisePerlin2D(&noise_hills_terrain->np, x, z, seed);
313 float rter = NoisePerlin2D(&noise_ridge_terrain->np, x, z, seed);
314 float ster = NoisePerlin2D(&noise_step_terrain->np, x, z, seed);
315 float n_hills = NoisePerlin2D(&noise_hills->np, x, z, seed);
316 float n_ridge_mnt = NoisePerlin2D(&noise_ridge_mnt->np, x, z, seed);
317 float n_step_mnt = NoisePerlin2D(&noise_step_mnt->np, x, z, seed);
319 int height = -MAX_MAP_GENERATION_LIMIT;
321 for (s16 y = 1; y <= 30; y++) {
322 float mnt_var = NoisePerlin3D(&noise_mnt_var->np, x, y, z, seed);
324 // Gradient & shallow seabed
325 s32 grad = (y < water_level) ? grad_wl + (water_level - y) * 3 : 1 - y;
327 // Hill/Mountain height (hilliness)
328 float hill1 = getLerp(height1, height2, mnt_var);
329 float hill2 = getLerp(height3, height4, mnt_var);
330 float hill3 = getLerp(height3, height2, mnt_var);
331 float hill4 = getLerp(height1, height4, mnt_var);
332 float hilliness = std::fmax(std::fmin(hill1, hill2), std::fmin(hill3, hill4));
335 float hill_mnt = hilliness * pow(n_hills, 2.f);
336 float hills = pow(hter, 3.f) * hill_mnt;
339 float ridge_mnt = hilliness * (1.f - fabs(n_ridge_mnt));
340 float ridged_mountains = pow(rter, 3.f) * ridge_mnt;
342 // Step (terraced) mountains
343 float step_mnt = hilliness * getSteps(n_step_mnt, fabs(mnt_var));
344 float step_mountains = pow(ster, 3.f) * step_mnt;
346 // Final terrain level
347 float mountains = hills + ridged_mountains + step_mountains;
348 float surface_level = ground + mountains + grad;
350 if (y > surface_level && height < 0)
358 ///////////////////////////////////////////////////////////////////////////////
361 int MapgenCarpathian::generateTerrain()
363 MapNode mn_air(CONTENT_AIR);
364 MapNode mn_stone(c_stone);
365 MapNode mn_water(c_water_source);
367 s16 stone_surface_max_y = -MAX_MAP_GENERATION_LIMIT;
371 // Calculate noise for terrain generation
372 noise_base->perlinMap2D(node_min.X, node_min.Z);
373 noise_height1->perlinMap2D(node_min.X, node_min.Z);
374 noise_height2->perlinMap2D(node_min.X, node_min.Z);
375 noise_height3->perlinMap2D(node_min.X, node_min.Z);
376 noise_height4->perlinMap2D(node_min.X, node_min.Z);
377 noise_hills_terrain->perlinMap2D(node_min.X, node_min.Z);
378 noise_ridge_terrain->perlinMap2D(node_min.X, node_min.Z);
379 noise_step_terrain->perlinMap2D(node_min.X, node_min.Z);
380 noise_hills->perlinMap2D(node_min.X, node_min.Z);
381 noise_ridge_mnt->perlinMap2D(node_min.X, node_min.Z);
382 noise_step_mnt->perlinMap2D(node_min.X, node_min.Z);
383 noise_mnt_var->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
386 for (s16 z = node_min.Z; z <= node_max.Z; z++) {
387 for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
388 u32 vi = vm->m_area.index(node_min.X, y, z);
389 for (s16 x = node_min.X; x <= node_max.X;
390 x++, vi++, index2d++, index3d++) {
391 if (vm->m_data[vi].getContent() != CONTENT_IGNORE)
395 float ground = noise_base->result[index2d];
397 // Gradient & shallow seabed
398 s32 grad = (y < water_level) ? grad_wl + (water_level - y) * 3 : 1 - y;
400 // Hill/Mountain height (hilliness)
401 float height1 = noise_height1->result[index2d];
402 float height2 = noise_height2->result[index2d];
403 float height3 = noise_height3->result[index2d];
404 float height4 = noise_height4->result[index2d];
405 float mnt_var = noise_mnt_var->result[index3d];
406 // Combine height noises and apply 3D variation
407 float hill1 = getLerp(height1, height2, mnt_var);
408 float hill2 = getLerp(height3, height4, mnt_var);
409 float hill3 = getLerp(height3, height2, mnt_var);
410 float hill4 = getLerp(height1, height4, mnt_var);
411 // 'hilliness' determines whether hills/mountains are
413 float hilliness = std::fmax(std::fmin(hill1, hill2), std::fmin(hill3, hill4));
416 float hter = noise_hills_terrain->result[index2d];
417 float n_hills = noise_hills->result[index2d];
418 float hill_mnt = hilliness * pow(n_hills, 2.f);
419 float hills = pow(fabs(hter), 3.f) * hill_mnt;
422 float rter = noise_ridge_terrain->result[index2d];
423 float n_ridge_mnt = noise_ridge_mnt->result[index2d];
424 float ridge_mnt = hilliness * (1.f - fabs(n_ridge_mnt));
425 float ridged_mountains = pow(fabs(rter), 3.f) * ridge_mnt;
427 // Step (terraced) mountains
428 float ster = noise_step_terrain->result[index2d];
429 float n_step_mnt = noise_step_mnt->result[index2d];
430 float step_mnt = hilliness * getSteps(n_step_mnt, fabs(mnt_var));
431 float step_mountains = pow(fabs(ster), 3.f) * step_mnt;
433 // Final terrain level
434 float mountains = hills + ridged_mountains + step_mountains;
435 float surface_level = ground + mountains + grad;
437 if (y < surface_level) {
438 vm->m_data[vi] = mn_stone; // Stone
439 if (y > stone_surface_max_y)
440 stone_surface_max_y = y;
441 } else if (y <= water_level) {
442 vm->m_data[vi] = mn_water; // Sea water
444 vm->m_data[vi] = mn_air; // Air
452 return stone_surface_max_y;