Mapgen Carpathian: Add optional rivers (#7977)
[oweals/minetest.git] / src / mapgen / mapgen_carpathian.cpp
1 /*
2 Minetest
3 Copyright (C) 2017-2019 vlapsley, Vaughan Lapsley <vlapsley@gmail.com>
4 Copyright (C) 2017-2019 paramat
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License along
17 with this program; if not, write to the Free Software Foundation, Inc.,
18 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21
22 #include <cmath>
23 #include "mapgen.h"
24 #include "voxel.h"
25 #include "noise.h"
26 #include "mapblock.h"
27 #include "mapnode.h"
28 #include "map.h"
29 #include "content_sao.h"
30 #include "nodedef.h"
31 #include "voxelalgorithms.h"
32 //#include "profiler.h" // For TimeTaker
33 #include "settings.h" // For g_settings
34 #include "emerge.h"
35 #include "dungeongen.h"
36 #include "cavegen.h"
37 #include "mg_biome.h"
38 #include "mg_ore.h"
39 #include "mg_decoration.h"
40 #include "mapgen_carpathian.h"
41
42
43 FlagDesc flagdesc_mapgen_carpathian[] = {
44         {"caverns", MGCARPATHIAN_CAVERNS},
45         {"rivers",  MGCARPATHIAN_RIVERS},
46         {NULL,      0}
47 };
48
49
50 ///////////////////////////////////////////////////////////////////////////////
51
52
53 MapgenCarpathian::MapgenCarpathian(MapgenCarpathianParams *params, EmergeManager *emerge)
54         : MapgenBasic(MAPGEN_CARPATHIAN, params, emerge)
55 {
56         base_level       = params->base_level;
57         river_width      = params->river_width;
58         river_depth      = params->river_depth;
59         valley_width     = params->valley_width;
60
61         spflags          = params->spflags;
62         cave_width       = params->cave_width;
63         large_cave_depth = params->large_cave_depth;
64         lava_depth       = params->lava_depth;
65         cavern_limit     = params->cavern_limit;
66         cavern_taper     = params->cavern_taper;
67         cavern_threshold = params->cavern_threshold;
68         dungeon_ymin     = params->dungeon_ymin;
69         dungeon_ymax     = params->dungeon_ymax;
70
71         grad_wl = 1 - water_level;
72
73         //// 2D Terrain noise
74         noise_filler_depth  = new Noise(&params->np_filler_depth,  seed, csize.X, csize.Z);
75         noise_height1       = new Noise(&params->np_height1,       seed, csize.X, csize.Z);
76         noise_height2       = new Noise(&params->np_height2,       seed, csize.X, csize.Z);
77         noise_height3       = new Noise(&params->np_height3,       seed, csize.X, csize.Z);
78         noise_height4       = new Noise(&params->np_height4,       seed, csize.X, csize.Z);
79         noise_hills_terrain = new Noise(&params->np_hills_terrain, seed, csize.X, csize.Z);
80         noise_ridge_terrain = new Noise(&params->np_ridge_terrain, seed, csize.X, csize.Z);
81         noise_step_terrain  = new Noise(&params->np_step_terrain,  seed, csize.X, csize.Z);
82         noise_hills         = new Noise(&params->np_hills,         seed, csize.X, csize.Z);
83         noise_ridge_mnt     = new Noise(&params->np_ridge_mnt,     seed, csize.X, csize.Z);
84         noise_step_mnt      = new Noise(&params->np_step_mnt,      seed, csize.X, csize.Z);
85         if (spflags & MGCARPATHIAN_RIVERS)
86                 noise_rivers    = new Noise(&params->np_rivers,        seed, csize.X, csize.Z);
87
88         //// 3D terrain noise
89         // 1 up 1 down overgeneration
90         noise_mnt_var = new Noise(&params->np_mnt_var, seed, csize.X, csize.Y + 2, csize.Z);
91
92         //// Cave noise
93         MapgenBasic::np_cave1  = params->np_cave1;
94         MapgenBasic::np_cave2  = params->np_cave2;
95         MapgenBasic::np_cavern = params->np_cavern;
96         MapgenBasic::np_dungeons = params->np_dungeons;
97 }
98
99
100 MapgenCarpathian::~MapgenCarpathian()
101 {
102         delete noise_filler_depth;
103         delete noise_height1;
104         delete noise_height2;
105         delete noise_height3;
106         delete noise_height4;
107         delete noise_hills_terrain;
108         delete noise_ridge_terrain;
109         delete noise_step_terrain;
110         delete noise_hills;
111         delete noise_ridge_mnt;
112         delete noise_step_mnt;
113         if (spflags & MGCARPATHIAN_RIVERS)
114                 delete noise_rivers;
115
116         delete noise_mnt_var;
117 }
118
119
120 MapgenCarpathianParams::MapgenCarpathianParams():
121         np_filler_depth  (0,   1,   v3f(128,  128,  128),  261,   3, 0.7,  2.0),
122         np_height1       (0,   5,   v3f(251,  251,  251),  9613,  5, 0.5,  2.0),
123         np_height2       (0,   5,   v3f(383,  383,  383),  1949,  5, 0.5,  2.0),
124         np_height3       (0,   5,   v3f(509,  509,  509),  3211,  5, 0.5,  2.0),
125         np_height4       (0,   5,   v3f(631,  631,  631),  1583,  5, 0.5,  2.0),
126         np_hills_terrain (1,   1,   v3f(1301, 1301, 1301), 1692,  5, 0.5,  2.0),
127         np_ridge_terrain (1,   1,   v3f(1889, 1889, 1889), 3568,  5, 0.5,  2.0),
128         np_step_terrain  (1,   1,   v3f(1889, 1889, 1889), 4157,  5, 0.5,  2.0),
129         np_hills         (0,   3,   v3f(257,  257,  257),  6604,  6, 0.5,  2.0),
130         np_ridge_mnt     (0,   12,  v3f(743,  743,  743),  5520,  6, 0.7,  2.0),
131         np_step_mnt      (0,   8,   v3f(509,  509,  509),  2590,  6, 0.6,  2.0),
132         np_rivers        (0,   1,   v3f(1000, 1000, 1000), 85039, 5, 0.6,  2.0),
133         np_mnt_var       (0,   1,   v3f(499,  499,  499),  2490,  5, 0.55, 2.0),
134         np_cave1         (0,   12,  v3f(61,   61,   61),   52534, 3, 0.5,  2.0),
135         np_cave2         (0,   12,  v3f(67,   67,   67),   10325, 3, 0.5,  2.0),
136         np_cavern        (0,   1,   v3f(384,  128,  384),  723,   5, 0.63, 2.0),
137         np_dungeons      (0.9, 0.5, v3f(500,  500,  500),  0,     2, 0.8,  2.0)
138 {
139 }
140
141
142 void MapgenCarpathianParams::readParams(const Settings *settings)
143 {
144         settings->getFlagStrNoEx("mgcarpathian_spflags", spflags, flagdesc_mapgen_carpathian);
145
146         settings->getFloatNoEx("mgcarpathian_base_level",   base_level);
147         settings->getFloatNoEx("mgcarpathian_river_width",  river_width);
148         settings->getFloatNoEx("mgcarpathian_river_depth",  river_depth);
149         settings->getFloatNoEx("mgcarpathian_valley_width", valley_width);
150
151         settings->getFloatNoEx("mgcarpathian_cave_width",       cave_width);
152         settings->getS16NoEx("mgcarpathian_large_cave_depth",   large_cave_depth);
153         settings->getS16NoEx("mgcarpathian_lava_depth",         lava_depth);
154         settings->getS16NoEx("mgcarpathian_cavern_limit",       cavern_limit);
155         settings->getS16NoEx("mgcarpathian_cavern_taper",       cavern_taper);
156         settings->getFloatNoEx("mgcarpathian_cavern_threshold", cavern_threshold);
157         settings->getS16NoEx("mgcarpathian_dungeon_ymin",       dungeon_ymin);
158         settings->getS16NoEx("mgcarpathian_dungeon_ymax",       dungeon_ymax);
159
160         settings->getNoiseParams("mgcarpathian_np_filler_depth",  np_filler_depth);
161         settings->getNoiseParams("mgcarpathian_np_height1",       np_height1);
162         settings->getNoiseParams("mgcarpathian_np_height2",       np_height2);
163         settings->getNoiseParams("mgcarpathian_np_height3",       np_height3);
164         settings->getNoiseParams("mgcarpathian_np_height4",       np_height4);
165         settings->getNoiseParams("mgcarpathian_np_hills_terrain", np_hills_terrain);
166         settings->getNoiseParams("mgcarpathian_np_ridge_terrain", np_ridge_terrain);
167         settings->getNoiseParams("mgcarpathian_np_step_terrain",  np_step_terrain);
168         settings->getNoiseParams("mgcarpathian_np_hills",         np_hills);
169         settings->getNoiseParams("mgcarpathian_np_ridge_mnt",     np_ridge_mnt);
170         settings->getNoiseParams("mgcarpathian_np_step_mnt",      np_step_mnt);
171         settings->getNoiseParams("mgcarpathian_np_rivers",        np_rivers);
172         settings->getNoiseParams("mgcarpathian_np_mnt_var",       np_mnt_var);
173         settings->getNoiseParams("mgcarpathian_np_cave1",         np_cave1);
174         settings->getNoiseParams("mgcarpathian_np_cave2",         np_cave2);
175         settings->getNoiseParams("mgcarpathian_np_cavern",        np_cavern);
176         settings->getNoiseParams("mgcarpathian_np_dungeons",      np_dungeons);
177 }
178
179
180 void MapgenCarpathianParams::writeParams(Settings *settings) const
181 {
182         settings->setFlagStr("mgcarpathian_spflags", spflags, flagdesc_mapgen_carpathian, U32_MAX);
183
184         settings->setFloat("mgcarpathian_base_level",   base_level);
185         settings->setFloat("mgcarpathian_river_width",  river_width);
186         settings->setFloat("mgcarpathian_river_depth",  river_depth);
187         settings->setFloat("mgcarpathian_valley_width", valley_width);
188
189         settings->setFloat("mgcarpathian_cave_width",       cave_width);
190         settings->setS16("mgcarpathian_large_cave_depth",   large_cave_depth);
191         settings->setS16("mgcarpathian_lava_depth",         lava_depth);
192         settings->setS16("mgcarpathian_cavern_limit",       cavern_limit);
193         settings->setS16("mgcarpathian_cavern_taper",       cavern_taper);
194         settings->setFloat("mgcarpathian_cavern_threshold", cavern_threshold);
195         settings->setS16("mgcarpathian_dungeon_ymin",       dungeon_ymin);
196         settings->setS16("mgcarpathian_dungeon_ymax",       dungeon_ymax);
197
198         settings->setNoiseParams("mgcarpathian_np_filler_depth",  np_filler_depth);
199         settings->setNoiseParams("mgcarpathian_np_height1",       np_height1);
200         settings->setNoiseParams("mgcarpathian_np_height2",       np_height2);
201         settings->setNoiseParams("mgcarpathian_np_height3",       np_height3);
202         settings->setNoiseParams("mgcarpathian_np_height4",       np_height4);
203         settings->setNoiseParams("mgcarpathian_np_hills_terrain", np_hills_terrain);
204         settings->setNoiseParams("mgcarpathian_np_ridge_terrain", np_ridge_terrain);
205         settings->setNoiseParams("mgcarpathian_np_step_terrain",  np_step_terrain);
206         settings->setNoiseParams("mgcarpathian_np_hills",         np_hills);
207         settings->setNoiseParams("mgcarpathian_np_ridge_mnt",     np_ridge_mnt);
208         settings->setNoiseParams("mgcarpathian_np_step_mnt",      np_step_mnt);
209         settings->setNoiseParams("mgcarpathian_np_rivers",        np_rivers);
210         settings->setNoiseParams("mgcarpathian_np_mnt_var",       np_mnt_var);
211         settings->setNoiseParams("mgcarpathian_np_cave1",         np_cave1);
212         settings->setNoiseParams("mgcarpathian_np_cave2",         np_cave2);
213         settings->setNoiseParams("mgcarpathian_np_cavern",        np_cavern);
214         settings->setNoiseParams("mgcarpathian_np_dungeons",      np_dungeons);
215 }
216
217
218 ////////////////////////////////////////////////////////////////////////////////
219
220
221 // Lerp function
222 inline float MapgenCarpathian::getLerp(float noise1, float noise2, float mod)
223 {
224         return noise1 + mod * (noise2 - noise1);
225 }
226
227 // Steps function
228 float MapgenCarpathian::getSteps(float noise)
229 {
230         float w = 0.5f;
231         float k = std::floor(noise / w);
232         float f = (noise - k * w) / w;
233         float s = std::fmin(2.f * f, 1.f);
234         return (k + s) * w;
235 }
236
237
238 ////////////////////////////////////////////////////////////////////////////////
239
240
241 void MapgenCarpathian::makeChunk(BlockMakeData *data)
242 {
243         // Pre-conditions
244         assert(data->vmanip);
245         assert(data->nodedef);
246         assert(data->blockpos_requested.X >= data->blockpos_min.X &&
247                         data->blockpos_requested.Y >= data->blockpos_min.Y &&
248                         data->blockpos_requested.Z >= data->blockpos_min.Z);
249         assert(data->blockpos_requested.X <= data->blockpos_max.X &&
250                         data->blockpos_requested.Y <= data->blockpos_max.Y &&
251                         data->blockpos_requested.Z <= data->blockpos_max.Z);
252
253         this->generating = true;
254         this->vm = data->vmanip;
255         this->ndef = data->nodedef;
256
257         v3s16 blockpos_min = data->blockpos_min;
258         v3s16 blockpos_max = data->blockpos_max;
259         node_min = blockpos_min * MAP_BLOCKSIZE;
260         node_max = (blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
261         full_node_min = (blockpos_min - 1) * MAP_BLOCKSIZE;
262         full_node_max = (blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
263
264         // Create a block-specific seed
265         blockseed = getBlockSeed2(full_node_min, seed);
266
267         // Generate terrain
268         s16 stone_surface_max_y = generateTerrain();
269
270         // Create heightmap
271         updateHeightmap(node_min, node_max);
272
273         // Init biome generator, place biome-specific nodes, and build biomemap
274         if (flags & MG_BIOMES) {
275                 biomegen->calcBiomeNoise(node_min);
276                 generateBiomes();
277         }
278
279         // Generate tunnels, caverns and large randomwalk caves
280         if (flags & MG_CAVES) {
281                 // Generate tunnels first as caverns confuse them
282                 generateCavesNoiseIntersection(stone_surface_max_y);
283
284                 // Generate caverns
285                 bool near_cavern = false;
286                 if (spflags & MGCARPATHIAN_CAVERNS)
287                         near_cavern = generateCavernsNoise(stone_surface_max_y);
288
289                 // Generate large randomwalk caves
290                 if (near_cavern)
291                         // Disable large randomwalk caves in this mapchunk by setting
292                         // 'large cave depth' to world base. Avoids excessive liquid in
293                         // large caverns and floating blobs of overgenerated liquid.
294                         generateCavesRandomWalk(stone_surface_max_y,
295                                 -MAX_MAP_GENERATION_LIMIT);
296                 else
297                         generateCavesRandomWalk(stone_surface_max_y, large_cave_depth);
298         }
299
300         // Generate the registered ores
301         m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
302
303         // Generate dungeons
304         if ((flags & MG_DUNGEONS) && full_node_min.Y >= dungeon_ymin &&
305                         full_node_max.Y <= dungeon_ymax)
306                 generateDungeons(stone_surface_max_y);
307
308         // Generate the registered decorations
309         if (flags & MG_DECORATIONS)
310                 m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);
311
312         // Sprinkle some dust on top after everything else was generated
313         if (flags & MG_BIOMES)
314                 dustTopNodes();
315
316         // Update liquids
317         updateLiquid(&data->transforming_liquid, full_node_min, full_node_max);
318
319         // Calculate lighting
320         if (flags & MG_LIGHT) {
321                 calcLighting(node_min - v3s16(0, 1, 0), node_max + v3s16(0, 1, 0),
322                                 full_node_min, full_node_max);
323         }
324
325         this->generating = false;
326 }
327
328
329 ////////////////////////////////////////////////////////////////////////////////
330
331
332 int MapgenCarpathian::getSpawnLevelAtPoint(v2s16 p)
333 {
334         // If rivers are enabled, first check if in a river channel
335         if (spflags & MGCARPATHIAN_RIVERS) {
336                 float river = std::fabs(NoisePerlin2D(&noise_rivers->np, p.X, p.Y, seed)) -
337                         river_width;
338                 if (river < 0.0f)
339                         return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
340         }
341
342         float height1 = NoisePerlin2D(&noise_height1->np, p.X, p.Y, seed);
343         float height2 = NoisePerlin2D(&noise_height2->np, p.X, p.Y, seed);
344         float height3 = NoisePerlin2D(&noise_height3->np, p.X, p.Y, seed);
345         float height4 = NoisePerlin2D(&noise_height4->np, p.X, p.Y, seed);
346
347         float hterabs = std::fabs(NoisePerlin2D(&noise_hills_terrain->np, p.X, p.Y, seed));
348         float n_hills = NoisePerlin2D(&noise_hills->np, p.X, p.Y, seed);
349         float hill_mnt = hterabs * hterabs * hterabs * n_hills * n_hills;
350
351         float rterabs = std::fabs(NoisePerlin2D(&noise_ridge_terrain->np, p.X, p.Y, seed));
352         float n_ridge_mnt = NoisePerlin2D(&noise_ridge_mnt->np, p.X, p.Y, seed);
353         float ridge_mnt = rterabs * rterabs * rterabs * (1.0f - std::fabs(n_ridge_mnt));
354
355         float sterabs = std::fabs(NoisePerlin2D(&noise_step_terrain->np, p.X, p.Y, seed));
356         float n_step_mnt = NoisePerlin2D(&noise_step_mnt->np, p.X, p.Y, seed);
357         float step_mnt = sterabs * sterabs * sterabs * getSteps(n_step_mnt);
358
359         float valley = 1.0f;
360         float river = 0.0f;
361
362         if ((spflags & MGCARPATHIAN_RIVERS) && node_max.Y >= water_level - 16) {
363                 river = std::fabs(NoisePerlin2D(&noise_rivers->np, p.X, p.Y, seed)) - river_width;
364                 if (river <= valley_width) {
365                         // Within river valley
366                         if (river < 0.0f) {
367                                 // River channel
368                                 valley = river;
369                         } else {
370                                 // Valley slopes.
371                                 // 0 at river edge, 1 at valley edge.
372                                 float riversc = river / valley_width;
373                                 // Smoothstep
374                                 valley = riversc * riversc * (3.0f - 2.0f * riversc);
375                         }
376                 }
377         }
378
379         bool solid_below = false;
380         u8 cons_non_solid = 0; // consecutive non-solid nodes
381
382         for (s16 y = water_level; y <= water_level + 32; y++) {
383                 float mnt_var = NoisePerlin3D(&noise_mnt_var->np, p.X, y, p.Y, seed);
384                 float hill1 = getLerp(height1, height2, mnt_var);
385                 float hill2 = getLerp(height3, height4, mnt_var);
386                 float hill3 = getLerp(height3, height2, mnt_var);
387                 float hill4 = getLerp(height1, height4, mnt_var);
388
389                 float hilliness = std::fmax(std::fmin(hill1, hill2), std::fmin(hill3, hill4));
390                 float hills = hill_mnt * hilliness;
391                 float ridged_mountains = ridge_mnt * hilliness;
392                 float step_mountains = step_mnt * hilliness;
393
394                 s32 grad = 1 - y;
395
396                 float mountains = hills + ridged_mountains + step_mountains;
397                 float surface_level = base_level + mountains + grad;
398
399                 if ((spflags & MGCARPATHIAN_RIVERS) && river <= valley_width) {
400                         if (valley < 0.0f) {
401                                 // River channel
402                                 surface_level = std::fmin(surface_level,
403                                         water_level - std::sqrt(-valley) * river_depth);
404                         } else if (surface_level > water_level) {
405                                 // Valley slopes
406                                 surface_level = water_level + (surface_level - water_level) * valley;
407                         }
408                 }
409
410                 if (y < surface_level) { //TODO '<=' fix from generateTerrain()
411                         // solid node
412                         solid_below = true;
413                         cons_non_solid = 0;
414                 } else {
415                         // non-solid node
416                         cons_non_solid++;
417                         if (cons_non_solid == 3 && solid_below)
418                                 return y - 1;
419                 }
420         }
421
422         return MAX_MAP_GENERATION_LIMIT; // No suitable spawn point found
423 }
424
425
426 ////////////////////////////////////////////////////////////////////////////////
427
428
429 int MapgenCarpathian::generateTerrain()
430 {
431         MapNode mn_air(CONTENT_AIR);
432         MapNode mn_stone(c_stone);
433         MapNode mn_water(c_water_source);
434
435         // Calculate noise for terrain generation
436         noise_height1->perlinMap2D(node_min.X, node_min.Z);
437         noise_height2->perlinMap2D(node_min.X, node_min.Z);
438         noise_height3->perlinMap2D(node_min.X, node_min.Z);
439         noise_height4->perlinMap2D(node_min.X, node_min.Z);
440         noise_hills_terrain->perlinMap2D(node_min.X, node_min.Z);
441         noise_ridge_terrain->perlinMap2D(node_min.X, node_min.Z);
442         noise_step_terrain->perlinMap2D(node_min.X, node_min.Z);
443         noise_hills->perlinMap2D(node_min.X, node_min.Z);
444         noise_ridge_mnt->perlinMap2D(node_min.X, node_min.Z);
445         noise_step_mnt->perlinMap2D(node_min.X, node_min.Z);
446         noise_mnt_var->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
447
448         if (spflags & MGCARPATHIAN_RIVERS)
449                 noise_rivers->perlinMap2D(node_min.X, node_min.Z);
450
451         //// Place nodes
452         const v3s16 &em = vm->m_area.getExtent();
453         s16 stone_surface_max_y = -MAX_MAP_GENERATION_LIMIT;
454         u32 index2d = 0;
455
456         for (s16 z = node_min.Z; z <= node_max.Z; z++)
457         for (s16 x = node_min.X; x <= node_max.X; x++, index2d++) {
458                 // Hill/Mountain height (hilliness)
459                 float height1 = noise_height1->result[index2d];
460                 float height2 = noise_height2->result[index2d];
461                 float height3 = noise_height3->result[index2d];
462                 float height4 = noise_height4->result[index2d];
463
464                 // Rolling hills
465                 float hterabs = std::fabs(noise_hills_terrain->result[index2d]);
466                 float n_hills = noise_hills->result[index2d];
467                 float hill_mnt = hterabs * hterabs * hterabs * n_hills * n_hills;
468
469                 // Ridged mountains
470                 float rterabs = std::fabs(noise_ridge_terrain->result[index2d]);
471                 float n_ridge_mnt = noise_ridge_mnt->result[index2d];
472                 float ridge_mnt = rterabs * rterabs * rterabs *
473                         (1.0f - std::fabs(n_ridge_mnt));
474
475                 // Step (terraced) mountains
476                 float sterabs = std::fabs(noise_step_terrain->result[index2d]);
477                 float n_step_mnt = noise_step_mnt->result[index2d];
478                 float step_mnt = sterabs * sterabs * sterabs * getSteps(n_step_mnt);
479
480                 // Rivers
481                 float valley = 1.0f;
482                 float river = 0.0f;
483
484                 if ((spflags & MGCARPATHIAN_RIVERS) && node_max.Y >= water_level - 16) {
485                         river = std::fabs(noise_rivers->result[index2d]) - river_width;
486                         if (river <= valley_width) {
487                                 // Within river valley
488                                 if (river < 0.0f) {
489                                         // River channel
490                                         valley = river;
491                                 } else {
492                                         // Valley slopes.
493                                         // 0 at river edge, 1 at valley edge.
494                                         float riversc = river / valley_width;
495                                         // Smoothstep
496                                         valley = riversc * riversc * (3.0f - 2.0f * riversc);
497                                 }
498                         }
499                 }
500
501                 // Initialise 3D noise index and voxelmanip index to column base
502                 u32 index3d = (z - node_min.Z) * zstride_1u1d + (x - node_min.X);
503                 u32 vi = vm->m_area.index(x, node_min.Y - 1, z);
504
505                 for (s16 y = node_min.Y - 1; y <= node_max.Y + 1;
506                                 y++,
507                                 index3d += ystride,
508                                 VoxelArea::add_y(em, vi, 1)) {
509                         if (vm->m_data[vi].getContent() != CONTENT_IGNORE)
510                                 continue;
511
512                         // Combine height noises and apply 3D variation
513                         float mnt_var = noise_mnt_var->result[index3d];
514                         float hill1 = getLerp(height1, height2, mnt_var);
515                         float hill2 = getLerp(height3, height4, mnt_var);
516                         float hill3 = getLerp(height3, height2, mnt_var);
517                         float hill4 = getLerp(height1, height4, mnt_var);
518
519                         // 'hilliness' determines whether hills/mountains are
520                         // small or large
521                         float hilliness =
522                                 std::fmax(std::fmin(hill1, hill2), std::fmin(hill3, hill4));
523                         float hills = hill_mnt * hilliness;
524                         float ridged_mountains = ridge_mnt * hilliness;
525                         float step_mountains = step_mnt * hilliness;
526
527                         // Gradient & shallow seabed
528                         s32 grad = (y < water_level) ? grad_wl + (water_level - y) * 3 :
529                                 1 - y;
530
531                         // Final terrain level
532                         float mountains = hills + ridged_mountains + step_mountains;
533                         float surface_level = base_level + mountains + grad;
534
535                         // Rivers
536                         if ((spflags & MGCARPATHIAN_RIVERS) && node_max.Y >= water_level - 16 &&
537                                         river <= valley_width) {
538                                 if (valley < 0.0f) {
539                                         // River channel
540                                         surface_level = std::fmin(surface_level,
541                                                 water_level - std::sqrt(-valley) * river_depth);
542                                 } else if (surface_level > water_level) {
543                                         // Valley slopes
544                                         surface_level = water_level + (surface_level - water_level) * valley;
545                                 }
546                         }
547
548                         if (y < surface_level) { //TODO '<='
549                                 vm->m_data[vi] = mn_stone; // Stone
550                                 if (y > stone_surface_max_y)
551                                         stone_surface_max_y = y;
552                         } else if (y <= water_level) {
553                                 vm->m_data[vi] = mn_water; // Sea water
554                         } else {
555                                 vm->m_data[vi] = mn_air; // Air
556                         }
557                 }
558         }
559
560         return stone_surface_max_y;
561 }