3 Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published by
7 the Free Software Foundation; either version 2.1 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "mapgen_indev.h"
21 #include "constants.h"
24 #include "util/numeric.h"
27 /////////////////// Mapgen Indev perlin noise (default values - not used, from config or defaultsettings)
29 NoiseIndevParams nparams_indev_def;
32 NoiseIndevParams nparams_indev_def_terrain_base;
33 // (-AVERAGE_MUD_AMOUNT, 20.0, v3f(250.0, 250.0, 250.0), 82341, 5, 0.6, 1);
34 NoiseIndevParams nparams_indev_def_terrain_higher;
35 // (20.0, 16.0, v3f(500.0, 500.0, 500.0), 85039, 5, 0.6, 1);
36 NoiseIndevParams nparams_indev_def_steepness;
37 // (0.85, 0.5, v3f(125.0, 125.0, 125.0), -932, 5, 0.7, 1);
38 NoiseIndevParams nparams_indev_def_mud;
39 // (AVERAGE_MUD_AMOUNT, 2.0, v3f(200.0, 200.0, 200.0), 91013, 3, 0.55, 1);
40 NoiseIndevParams nparams_indev_def_float_islands;
41 // (1, 10.0, v3f(500.0, 500.0, 500.0), 32451, 5, 0.6, 1);
42 NoiseIndevParams nparams_indev_def_biome;
45 ///////////////////////////////////////////////////////////////////////////////
47 void NoiseIndev::init(NoiseIndevParams *np, int seed, int sx, int sy, int sz) {
48 Noise::init((NoiseParams*)np, seed, sx, sy, sz);
52 NoiseIndev::NoiseIndev(NoiseIndevParams *np, int seed, int sx, int sy) : Noise(np, seed, sx, sy) {
53 init(np, seed, sx, sy, 1);
56 NoiseIndev::NoiseIndev(NoiseIndevParams *np, int seed, int sx, int sy, int sz) : Noise(np, seed, sx, sy, sz) {
57 init(np, seed, sx, sy, sz);
60 float farscale(float scale, float z) {
61 return ( 1 + ( 1 - (MAP_GENERATION_LIMIT * 1 - (fabs(z)) ) / (MAP_GENERATION_LIMIT * 1) ) * (scale - 1) );
64 float farscale(float scale, float x, float z) {
65 return ( 1 + ( 1 - (MAP_GENERATION_LIMIT * 2 - (fabs(x) + fabs(z)) ) / (MAP_GENERATION_LIMIT * 2) ) * (scale - 1) );
68 float farscale(float scale, float x, float y, float z) {
69 return ( 1 + ( 1 - (MAP_GENERATION_LIMIT * 3 - (fabs(x) + fabs(y) + fabs(z)) ) / (MAP_GENERATION_LIMIT * 3) ) * (scale - 1) );
72 void NoiseIndev::transformNoiseMapFarScale(float xx, float yy, float zz) {
74 for (int z = 0; z != sz; z++) {
75 for (int y = 0; y != sy; y++) {
76 for (int x = 0; x != sx; x++) {
77 result[i] = result[i] * npindev->scale * farscale(npindev->farscale, xx, yy, zz) + npindev->offset;
84 MapgenIndev::MapgenIndev(int mapgenid, MapgenIndevParams *params, EmergeManager *emerge)
85 : MapgenV6(mapgenid, params, emerge)
87 noiseindev_terrain_base = new NoiseIndev(¶ms->npindev_terrain_base, seed, csize.X, csize.Z);
88 noiseindev_terrain_higher = new NoiseIndev(¶ms->npindev_terrain_higher, seed, csize.X, csize.Z);
89 noiseindev_steepness = new NoiseIndev(¶ms->npindev_steepness, seed, csize.X, csize.Z);
90 noiseindev_mud = new NoiseIndev(¶ms->npindev_mud, seed, csize.X, csize.Z);
91 noiseindev_float_islands1 = new NoiseIndev(¶ms->npindev_float_islands1, seed, csize.X, csize.Y, csize.Z);
92 noiseindev_float_islands2 = new NoiseIndev(¶ms->npindev_float_islands2, seed, csize.X, csize.Y, csize.Z);
93 noiseindev_float_islands3 = new NoiseIndev(¶ms->npindev_float_islands3, seed, csize.X, csize.Z);
94 noiseindev_biome = new NoiseIndev(¶ms->npindev_biome, seed, csize.X, csize.Z);
97 MapgenIndev::~MapgenIndev() {
98 delete noiseindev_terrain_base;
99 delete noiseindev_terrain_higher;
100 delete noiseindev_steepness;
101 //delete noise_height_select;
102 //delete noise_trees;
103 delete noiseindev_mud;
104 //delete noise_beach;
105 delete noiseindev_float_islands1;
106 delete noiseindev_float_islands2;
107 delete noiseindev_float_islands3;
108 delete noiseindev_biome;
111 void MapgenIndev::calculateNoise() {
115 // Need to adjust for the original implementation's +.5 offset...
116 if (!(flags & MG_FLAT)) {
117 noiseindev_terrain_base->perlinMap2D(
118 x + 0.5 * noiseindev_terrain_base->npindev->spread.X * farscale(noiseindev_terrain_base->npindev->farspread, x, z),
119 z + 0.5 * noiseindev_terrain_base->npindev->spread.Z * farscale(noiseindev_terrain_base->npindev->farspread, x, z));
120 noiseindev_terrain_base->transformNoiseMapFarScale(x, y, z);
122 noiseindev_terrain_higher->perlinMap2D(
123 x + 0.5 * noiseindev_terrain_higher->npindev->spread.X * farscale(noiseindev_terrain_higher->npindev->farspread, x, z),
124 z + 0.5 * noiseindev_terrain_higher->npindev->spread.Z * farscale(noiseindev_terrain_higher->npindev->farspread, x, z));
125 noiseindev_terrain_higher->transformNoiseMapFarScale(x, y, z);
127 noiseindev_steepness->perlinMap2D(
128 x + 0.5 * noiseindev_steepness->npindev->spread.X * farscale(noiseindev_steepness->npindev->farspread, x, z),
129 z + 0.5 * noiseindev_steepness->npindev->spread.Z * farscale(noiseindev_steepness->npindev->farspread, x, z));
130 noiseindev_steepness->transformNoiseMapFarScale(x, y, z);
132 noise_height_select->perlinMap2D(
133 x + 0.5 * noise_height_select->np->spread.X,
134 z + 0.5 * noise_height_select->np->spread.Z);
136 noiseindev_float_islands1->perlinMap3D(
137 x + 0.33 * noiseindev_float_islands1->npindev->spread.X * farscale(noiseindev_float_islands1->npindev->farspread, x, y, z),
138 y + 0.33 * noiseindev_float_islands1->npindev->spread.Y * farscale(noiseindev_float_islands1->npindev->farspread, x, y, z),
139 z + 0.33 * noiseindev_float_islands1->npindev->spread.Z * farscale(noiseindev_float_islands1->npindev->farspread, x, y, z)
141 noiseindev_float_islands1->transformNoiseMapFarScale(x, y, z);
143 noiseindev_float_islands2->perlinMap3D(
144 x + 0.33 * noiseindev_float_islands2->npindev->spread.X * farscale(noiseindev_float_islands2->npindev->farspread, x, y, z),
145 y + 0.33 * noiseindev_float_islands2->npindev->spread.Y * farscale(noiseindev_float_islands2->npindev->farspread, x, y, z),
146 z + 0.33 * noiseindev_float_islands2->npindev->spread.Z * farscale(noiseindev_float_islands2->npindev->farspread, x, y, z)
148 noiseindev_float_islands2->transformNoiseMapFarScale(x, y, z);
150 noiseindev_float_islands3->perlinMap2D(
151 x + 0.5 * noiseindev_float_islands3->npindev->spread.X * farscale(noiseindev_float_islands3->npindev->farspread, x, z),
152 z + 0.5 * noiseindev_float_islands3->npindev->spread.Z * farscale(noiseindev_float_islands3->npindev->farspread, x, z));
153 noiseindev_float_islands3->transformNoiseMapFarScale(x, y, z);
155 noiseindev_mud->perlinMap2D(
156 x + 0.5 * noiseindev_mud->npindev->spread.X * farscale(noiseindev_mud->npindev->farspread, x, y, z),
157 z + 0.5 * noiseindev_mud->npindev->spread.Z * farscale(noiseindev_mud->npindev->farspread, x, y, z));
158 noiseindev_mud->transformNoiseMapFarScale(x, y, z);
160 noise_beach->perlinMap2D(
161 x + 0.2 * noise_beach->np->spread.X,
162 z + 0.7 * noise_beach->np->spread.Z);
164 noise_biome->perlinMap2D(
165 x + 0.6 * noiseindev_biome->npindev->spread.X * farscale(noiseindev_biome->npindev->farspread, x, z),
166 z + 0.2 * noiseindev_biome->npindev->spread.Z * farscale(noiseindev_biome->npindev->farspread, x, z));
169 bool MapgenIndevParams::readParams(Settings *settings) {
170 freq_desert = settings->getFloat("mgv6_freq_desert");
171 freq_beach = settings->getFloat("mgv6_freq_beach");
174 settings->getNoiseIndevParams("mgindev_np_terrain_base", npindev_terrain_base) &&
175 settings->getNoiseIndevParams("mgindev_np_terrain_higher", npindev_terrain_higher) &&
176 settings->getNoiseIndevParams("mgindev_np_steepness", npindev_steepness) &&
177 settings->getNoiseParams("mgv6_np_height_select", np_height_select) &&
178 settings->getNoiseParams("mgv6_np_trees", np_trees) &&
179 settings->getNoiseIndevParams("mgindev_np_mud", npindev_mud) &&
180 settings->getNoiseParams("mgv6_np_beach", np_beach) &&
181 settings->getNoiseIndevParams("mgindev_np_biome", npindev_biome) &&
182 settings->getNoiseParams("mgv6_np_cave", np_cave) &&
183 settings->getNoiseIndevParams("mgindev_np_float_islands1", npindev_float_islands1) &&
184 settings->getNoiseIndevParams("mgindev_np_float_islands2", npindev_float_islands2) &&
185 settings->getNoiseIndevParams("mgindev_np_float_islands3", npindev_float_islands3);
189 void MapgenIndevParams::writeParams(Settings *settings) {
190 settings->setFloat("mgv6_freq_desert", freq_desert);
191 settings->setFloat("mgv6_freq_beach", freq_beach);
193 settings->setNoiseIndevParams("mgindev_np_terrain_base", npindev_terrain_base);
194 settings->setNoiseIndevParams("mgindev_np_terrain_higher", npindev_terrain_higher);
195 settings->setNoiseIndevParams("mgindev_np_steepness", npindev_steepness);
196 settings->setNoiseParams("mgv6_np_height_select", np_height_select);
197 settings->setNoiseParams("mgv6_np_trees", np_trees);
198 settings->setNoiseIndevParams("mgindev_np_mud", npindev_mud);
199 settings->setNoiseParams("mgv6_np_beach", np_beach);
200 settings->setNoiseIndevParams("mgindev_np_biome", npindev_biome);
201 settings->setNoiseParams("mgv6_np_cave", np_cave);
202 settings->setNoiseIndevParams("mgindev_np_float_islands1", npindev_float_islands1);
203 settings->setNoiseIndevParams("mgindev_np_float_islands2", npindev_float_islands2);
204 settings->setNoiseIndevParams("mgindev_np_float_islands3", npindev_float_islands3);
208 float MapgenIndev::baseTerrainLevelFromNoise(v2s16 p) {
212 float terrain_base = NoisePerlin2DPosOffset(noiseindev_terrain_base->npindev,
213 p.X, 0.5, p.Y, 0.5, seed);
214 float terrain_higher = NoisePerlin2DPosOffset(noiseindev_terrain_higher->npindev,
215 p.X, 0.5, p.Y, 0.5, seed);
216 float steepness = NoisePerlin2DPosOffset(noiseindev_steepness->npindev,
217 p.X, 0.5, p.Y, 0.5, seed);
218 float height_select = NoisePerlin2DNoTxfmPosOffset(noise_height_select->np,
219 p.X, 0.5, p.Y, 0.5, seed);
221 return baseTerrainLevel(terrain_base, terrain_higher,
222 steepness, height_select);
225 float MapgenIndev::baseTerrainLevelFromMap(int index) {
229 float terrain_base = noiseindev_terrain_base->result[index];
230 float terrain_higher = noiseindev_terrain_higher->result[index];
231 float steepness = noiseindev_steepness->result[index];
232 float height_select = noise_height_select->result[index];
234 return baseTerrainLevel(terrain_base, terrain_higher,
235 steepness, height_select);
238 float MapgenIndev::getMudAmount(int index) {
240 return AVERAGE_MUD_AMOUNT;
242 /*return ((float)AVERAGE_MUD_AMOUNT + 2.0 * noise2d_perlin(
243 0.5+(float)p.X/200, 0.5+(float)p.Y/200,
244 seed+91013, 3, 0.55));*/
246 return noiseindev_mud->result[index];
249 void MapgenIndev::generateCaves(int max_stone_y) {
250 float cave_amount = NoisePerlin2D(np_cave, node_min.X, node_min.Y, seed);
251 int volume_nodes = (node_max.X - node_min.X + 1) *
252 (node_max.Y - node_min.Y + 1) * MAP_BLOCKSIZE;
253 cave_amount = MYMAX(0.0, cave_amount);
254 u32 caves_count = cave_amount * volume_nodes / 50000;
255 u32 bruises_count = 1;
256 PseudoRandom ps(blockseed + 21343);
257 PseudoRandom ps2(blockseed + 1032);
259 if (ps.range(1, 6) == 1)
260 bruises_count = ps.range(0, ps.range(0, 2));
262 if (getBiome(v2s16(node_min.X, node_min.Z)) == BT_DESERT) {
267 for (u32 i = 0; i < caves_count + bruises_count; i++) {
268 bool large_cave = (i >= caves_count);
269 CaveIndev cave(this, &ps, &ps2, node_min, large_cave);
271 cave.makeCave(node_min, node_max, max_stone_y);
275 CaveIndev::CaveIndev(MapgenIndev *mg, PseudoRandom *ps, PseudoRandom *ps2,
276 v3s16 node_min, bool is_large_cave) {
278 this->water_level = mg->water_level;
279 this->large_cave = is_large_cave;
282 this->c_water_source = mg->c_water_source;
283 this->c_lava_source = mg->c_lava_source;
285 min_tunnel_diameter = 2;
286 max_tunnel_diameter = ps->range(2,6);
287 dswitchint = ps->range(1,14);
288 flooded = large_cave && ps->range(0,4);
290 part_max_length_rs = ps->range(2,4);
291 float scale = farscale(0.2, node_min.X, node_min.Y, node_min.Z);
292 if (node_min.Y < -100 && !ps->range(0, scale * 30)) { //huge
293 flooded = !ps->range(0, 3);
294 tunnel_routepoints = ps->range(5, 30);
295 min_tunnel_diameter = 30;
296 max_tunnel_diameter = ps->range(40, ps->range(80, 150));
298 tunnel_routepoints = ps->range(5, ps->range(15,30));
299 min_tunnel_diameter = 5;
300 max_tunnel_diameter = ps->range(7, ps->range(8,24));
303 part_max_length_rs = ps->range(2,9);
304 tunnel_routepoints = ps->range(10, ps->range(15,30));
306 large_cave_is_flat = (ps->range(0,1) == 0);
310 // version with one perlin3d. use with good params like
311 settings->setDefault("mgindev_np_float_islands1", "-9.5, 10, (20, 50, 50 ), 45123, 5, 0.6, 1.5, 5");
312 void MapgenIndev::generateFloatIslands(int min_y) {
313 if (node_min.Y < min_y) return;
314 v3s16 p0(node_min.X, node_min.Y, node_min.Z);
315 MapNode n1(c_stone), n2(c_desert_stone);
316 int xl = node_max.X - node_min.X;
317 int yl = node_max.Y - node_min.Y;
318 int zl = node_max.Z - node_min.Z;
320 for (int x1 = 0; x1 <= xl; x1++)
322 //int x = x1 + node_min.Y;
323 for (int z1 = 0; z1 <= zl; z1++)
325 //int z = z1 + node_min.Z;
326 for (int y1 = 0; y1 <= yl; y1++, index++)
328 //int y = y1 + node_min.Y;
329 float noise = noiseindev_float_islands1->result[index];
330 //dstream << " y1="<<y1<< " x1="<<x1<<" z1="<<z1<< " noise="<<noise << std::endl;
332 v3s16 p = p0 + v3s16(x1, y1, z1);
333 u32 i = vm->m_area.index(p);
334 if (!vm->m_area.contains(i))
337 if (vm->m_data[i].getContent() != CONTENT_AIR)
339 vm->m_data[i] = noise > 1 ? n1 : n2;
347 void MapgenIndev::generateFloatIslands(int min_y) {
348 if (node_min.Y < min_y) return;
349 PseudoRandom pr(blockseed + 985);
350 // originally from http://forum.minetest.net/viewtopic.php?id=4776
351 float RAR = 0.8 * farscale(0.4, node_min.Y); // 0.4; // Island rarity in chunk layer. -0.4 = thick layer with holes, 0 = 50%, 0.4 = desert rarity, 0.7 = very rare.
352 float AMPY = 24; // 24; // Amplitude of island centre y variation.
353 float TGRAD = 24; // 24; // Noise gradient to create top surface. Tallness of island top.
354 float BGRAD = 24; // 24; // Noise gradient to create bottom surface. Tallness of island bottom.
356 v3s16 p0(node_min.X, node_min.Y, node_min.Z);
359 float xl = node_max.X - node_min.X;
360 float yl = node_max.Y - node_min.Y;
361 float zl = node_max.Z - node_min.Z;
362 float midy = node_min.Y + yl * 0.5;
363 u32 index = 0, index2d = 0;
364 for (int x1 = 0; x1 <= xl; ++x1)
366 for (int z1 = 0; z1 <= zl; ++z1, ++index2d)
368 float noise3 = noiseindev_float_islands3->result[index2d];
369 float pmidy = midy + noise3 / 1.5 * AMPY;
370 for (int y1 = 0; y1 <= yl; ++y1, ++index)
372 int y = y1 + node_min.Y;
373 float noise1 = noiseindev_float_islands1->result[index];
374 float offset = y > pmidy ? (y - pmidy) / TGRAD : (pmidy - y) / BGRAD;
375 float noise1off = noise1 - offset - RAR;
376 if (noise1off > 0 && noise1off < 0.7) {
377 float noise2 = noiseindev_float_islands2->result[index];
378 if (noise2 - noise1off > -0.7){
379 v3s16 p = p0 + v3s16(x1, y1, z1);
380 u32 i = vm->m_area.index(p);
381 if (!vm->m_area.contains(i))
384 if (vm->m_data[i].getContent() != CONTENT_AIR)
394 void MapgenIndev::generateExperimental() {
395 int float_islands = g_settings->getS16("mgindev_float_islands");
397 generateFloatIslands(float_islands);