mapgen_v7.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713
  1. /*
  2. Minetest
  3. Copyright (C) 2013-2016 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
  4. Copyright (C) 2014-2017 paramat
  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.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public License along
  14. with this program; if not, write to the Free Software Foundation, Inc.,
  15. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  16. */
  17. #include "mapgen.h"
  18. #include "voxel.h"
  19. #include "noise.h"
  20. #include "mapblock.h"
  21. #include "mapnode.h"
  22. #include "map.h"
  23. #include "content_sao.h"
  24. #include "nodedef.h"
  25. #include "voxelalgorithms.h"
  26. //#include "profiler.h" // For TimeTaker
  27. #include "settings.h" // For g_settings
  28. #include "emerge.h"
  29. #include "dungeongen.h"
  30. #include "cavegen.h"
  31. #include "mg_biome.h"
  32. #include "mg_ore.h"
  33. #include "mg_decoration.h"
  34. #include "mapgen_v7.h"
  35. FlagDesc flagdesc_mapgen_v7[] = {
  36. {"mountains", MGV7_MOUNTAINS},
  37. {"ridges", MGV7_RIDGES},
  38. {"floatlands", MGV7_FLOATLANDS},
  39. {"caverns", MGV7_CAVERNS},
  40. {NULL, 0}
  41. };
  42. ///////////////////////////////////////////////////////////////////////////////
  43. MapgenV7::MapgenV7(int mapgenid, MapgenV7Params *params, EmergeManager *emerge)
  44. : MapgenBasic(mapgenid, params, emerge)
  45. {
  46. this->spflags = params->spflags;
  47. this->cave_width = params->cave_width;
  48. this->float_mount_density = params->float_mount_density;
  49. this->float_mount_height = params->float_mount_height;
  50. this->floatland_level = params->floatland_level;
  51. this->shadow_limit = params->shadow_limit;
  52. this->cavern_limit = params->cavern_limit;
  53. this->cavern_taper = params->cavern_taper;
  54. this->cavern_threshold = params->cavern_threshold;
  55. // 2D noise
  56. noise_terrain_base = new Noise(&params->np_terrain_base, seed, csize.X, csize.Z);
  57. noise_terrain_alt = new Noise(&params->np_terrain_alt, seed, csize.X, csize.Z);
  58. noise_terrain_persist = new Noise(&params->np_terrain_persist, seed, csize.X, csize.Z);
  59. noise_height_select = new Noise(&params->np_height_select, seed, csize.X, csize.Z);
  60. noise_filler_depth = new Noise(&params->np_filler_depth, seed, csize.X, csize.Z);
  61. if (spflags & MGV7_MOUNTAINS)
  62. noise_mount_height = new Noise(&params->np_mount_height, seed, csize.X, csize.Z);
  63. if (spflags & MGV7_FLOATLANDS) {
  64. noise_floatland_base = new Noise(&params->np_floatland_base, seed, csize.X, csize.Z);
  65. noise_float_base_height = new Noise(&params->np_float_base_height, seed, csize.X, csize.Z);
  66. }
  67. if (spflags & MGV7_RIDGES) {
  68. noise_ridge_uwater = new Noise(&params->np_ridge_uwater, seed, csize.X, csize.Z);
  69. // 3D noise, 1-up 1-down overgeneration
  70. noise_ridge = new Noise(&params->np_ridge, seed, csize.X, csize.Y + 2, csize.Z);
  71. }
  72. // 3D noise, 1 up, 1 down overgeneration
  73. if ((spflags & MGV7_MOUNTAINS) || (spflags & MGV7_FLOATLANDS))
  74. noise_mountain = new Noise(&params->np_mountain, seed, csize.X, csize.Y + 2, csize.Z);
  75. // 3D noise, 1 down overgeneration
  76. MapgenBasic::np_cave1 = params->np_cave1;
  77. MapgenBasic::np_cave2 = params->np_cave2;
  78. MapgenBasic::np_cavern = params->np_cavern;
  79. }
  80. MapgenV7::~MapgenV7()
  81. {
  82. delete noise_terrain_base;
  83. delete noise_terrain_alt;
  84. delete noise_terrain_persist;
  85. delete noise_height_select;
  86. delete noise_filler_depth;
  87. if (spflags & MGV7_MOUNTAINS)
  88. delete noise_mount_height;
  89. if (spflags & MGV7_FLOATLANDS) {
  90. delete noise_floatland_base;
  91. delete noise_float_base_height;
  92. }
  93. if (spflags & MGV7_RIDGES) {
  94. delete noise_ridge_uwater;
  95. delete noise_ridge;
  96. }
  97. if ((spflags & MGV7_MOUNTAINS) || (spflags & MGV7_FLOATLANDS))
  98. delete noise_mountain;
  99. }
  100. MapgenV7Params::MapgenV7Params()
  101. {
  102. np_terrain_base = NoiseParams(4, 70, v3f(600, 600, 600), 82341, 5, 0.6, 2.0);
  103. np_terrain_alt = NoiseParams(4, 25, v3f(600, 600, 600), 5934, 5, 0.6, 2.0);
  104. np_terrain_persist = NoiseParams(0.6, 0.1, v3f(2000, 2000, 2000), 539, 3, 0.6, 2.0);
  105. np_height_select = NoiseParams(-8, 16, v3f(500, 500, 500), 4213, 6, 0.7, 2.0);
  106. np_filler_depth = NoiseParams(0, 1.2, v3f(150, 150, 150), 261, 3, 0.7, 2.0);
  107. np_mount_height = NoiseParams(256, 112, v3f(1000, 1000, 1000), 72449, 3, 0.6, 2.0);
  108. np_ridge_uwater = NoiseParams(0, 1, v3f(1000, 1000, 1000), 85039, 5, 0.6, 2.0);
  109. np_floatland_base = NoiseParams(-0.6, 1.5, v3f(600, 600, 600), 114, 5, 0.6, 2.0);
  110. np_float_base_height = NoiseParams(48, 24, v3f(300, 300, 300), 907, 4, 0.7, 2.0);
  111. np_mountain = NoiseParams(-0.6, 1, v3f(250, 350, 250), 5333, 5, 0.63, 2.0);
  112. np_ridge = NoiseParams(0, 1, v3f(100, 100, 100), 6467, 4, 0.75, 2.0);
  113. np_cavern = NoiseParams(0, 1, v3f(384, 128, 384), 723, 5, 0.63, 2.0);
  114. np_cave1 = NoiseParams(0, 12, v3f(61, 61, 61), 52534, 3, 0.5, 2.0);
  115. np_cave2 = NoiseParams(0, 12, v3f(67, 67, 67), 10325, 3, 0.5, 2.0);
  116. }
  117. void MapgenV7Params::readParams(const Settings *settings)
  118. {
  119. settings->getFlagStrNoEx("mgv7_spflags", spflags, flagdesc_mapgen_v7);
  120. settings->getFloatNoEx("mgv7_cave_width", cave_width);
  121. settings->getFloatNoEx("mgv7_float_mount_density", float_mount_density);
  122. settings->getFloatNoEx("mgv7_float_mount_height", float_mount_height);
  123. settings->getS16NoEx("mgv7_floatland_level", floatland_level);
  124. settings->getS16NoEx("mgv7_shadow_limit", shadow_limit);
  125. settings->getS16NoEx("mgv7_cavern_limit", cavern_limit);
  126. settings->getS16NoEx("mgv7_cavern_taper", cavern_taper);
  127. settings->getFloatNoEx("mgv7_cavern_threshold", cavern_threshold);
  128. settings->getNoiseParams("mgv7_np_terrain_base", np_terrain_base);
  129. settings->getNoiseParams("mgv7_np_terrain_alt", np_terrain_alt);
  130. settings->getNoiseParams("mgv7_np_terrain_persist", np_terrain_persist);
  131. settings->getNoiseParams("mgv7_np_height_select", np_height_select);
  132. settings->getNoiseParams("mgv7_np_filler_depth", np_filler_depth);
  133. settings->getNoiseParams("mgv7_np_mount_height", np_mount_height);
  134. settings->getNoiseParams("mgv7_np_ridge_uwater", np_ridge_uwater);
  135. settings->getNoiseParams("mgv7_np_floatland_base", np_floatland_base);
  136. settings->getNoiseParams("mgv7_np_float_base_height", np_float_base_height);
  137. settings->getNoiseParams("mgv7_np_mountain", np_mountain);
  138. settings->getNoiseParams("mgv7_np_ridge", np_ridge);
  139. settings->getNoiseParams("mgv7_np_cavern", np_cavern);
  140. settings->getNoiseParams("mgv7_np_cave1", np_cave1);
  141. settings->getNoiseParams("mgv7_np_cave2", np_cave2);
  142. }
  143. void MapgenV7Params::writeParams(Settings *settings) const
  144. {
  145. settings->setFlagStr("mgv7_spflags", spflags, flagdesc_mapgen_v7, U32_MAX);
  146. settings->setFloat("mgv7_cave_width", cave_width);
  147. settings->setFloat("mgv7_float_mount_density", float_mount_density);
  148. settings->setFloat("mgv7_float_mount_height", float_mount_height);
  149. settings->setS16("mgv7_floatland_level", floatland_level);
  150. settings->setS16("mgv7_shadow_limit", shadow_limit);
  151. settings->setS16("mgv7_cavern_limit", cavern_limit);
  152. settings->setS16("mgv7_cavern_taper", cavern_taper);
  153. settings->setFloat("mgv7_cavern_threshold", cavern_threshold);
  154. settings->setNoiseParams("mgv7_np_terrain_base", np_terrain_base);
  155. settings->setNoiseParams("mgv7_np_terrain_alt", np_terrain_alt);
  156. settings->setNoiseParams("mgv7_np_terrain_persist", np_terrain_persist);
  157. settings->setNoiseParams("mgv7_np_height_select", np_height_select);
  158. settings->setNoiseParams("mgv7_np_filler_depth", np_filler_depth);
  159. settings->setNoiseParams("mgv7_np_mount_height", np_mount_height);
  160. settings->setNoiseParams("mgv7_np_ridge_uwater", np_ridge_uwater);
  161. settings->setNoiseParams("mgv7_np_floatland_base", np_floatland_base);
  162. settings->setNoiseParams("mgv7_np_float_base_height", np_float_base_height);
  163. settings->setNoiseParams("mgv7_np_mountain", np_mountain);
  164. settings->setNoiseParams("mgv7_np_ridge", np_ridge);
  165. settings->setNoiseParams("mgv7_np_cavern", np_cavern);
  166. settings->setNoiseParams("mgv7_np_cave1", np_cave1);
  167. settings->setNoiseParams("mgv7_np_cave2", np_cave2);
  168. }
  169. ///////////////////////////////////////////////////////////////////////////////
  170. int MapgenV7::getSpawnLevelAtPoint(v2s16 p)
  171. {
  172. // Base terrain calculation
  173. s16 y = baseTerrainLevelAtPoint(p.X, p.Y);
  174. // If enabled, check if inside a river
  175. if (spflags & MGV7_RIDGES) {
  176. float width = 0.2;
  177. float uwatern = NoisePerlin2D(&noise_ridge_uwater->np, p.X, p.Y, seed) * 2;
  178. if (fabs(uwatern) <= width)
  179. return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
  180. }
  181. // If mountains are disabled, terrain level is base terrain level
  182. // Avoids spawn on non-existant mountain terrain
  183. if (!(spflags & MGV7_MOUNTAINS)) {
  184. if (y <= water_level || y > water_level + 16)
  185. return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
  186. else
  187. return y;
  188. }
  189. // Mountain terrain calculation
  190. int iters = 128;
  191. while (iters--) {
  192. if (!getMountainTerrainAtPoint(p.X, y + 1, p.Y)) { // If air above
  193. if (y <= water_level || y > water_level + 16)
  194. return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
  195. else
  196. return y;
  197. }
  198. y++;
  199. }
  200. // Unsuitable spawn point, no mountain surface found
  201. return MAX_MAP_GENERATION_LIMIT;
  202. }
  203. void MapgenV7::makeChunk(BlockMakeData *data)
  204. {
  205. // Pre-conditions
  206. assert(data->vmanip);
  207. assert(data->nodedef);
  208. assert(data->blockpos_requested.X >= data->blockpos_min.X &&
  209. data->blockpos_requested.Y >= data->blockpos_min.Y &&
  210. data->blockpos_requested.Z >= data->blockpos_min.Z);
  211. assert(data->blockpos_requested.X <= data->blockpos_max.X &&
  212. data->blockpos_requested.Y <= data->blockpos_max.Y &&
  213. data->blockpos_requested.Z <= data->blockpos_max.Z);
  214. this->generating = true;
  215. this->vm = data->vmanip;
  216. this->ndef = data->nodedef;
  217. //TimeTaker t("makeChunk");
  218. v3s16 blockpos_min = data->blockpos_min;
  219. v3s16 blockpos_max = data->blockpos_max;
  220. node_min = blockpos_min * MAP_BLOCKSIZE;
  221. node_max = (blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
  222. full_node_min = (blockpos_min - 1) * MAP_BLOCKSIZE;
  223. full_node_max = (blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
  224. blockseed = getBlockSeed2(full_node_min, seed);
  225. // Generate base and mountain terrain
  226. // An initial heightmap is no longer created here for use in generateRidgeTerrain()
  227. s16 stone_surface_max_y = generateTerrain();
  228. // Generate rivers
  229. if (spflags & MGV7_RIDGES)
  230. generateRidgeTerrain();
  231. // Create heightmap
  232. updateHeightmap(node_min, node_max);
  233. // Init biome generator, place biome-specific nodes, and build biomemap
  234. biomegen->calcBiomeNoise(node_min);
  235. MgStoneType stone_type = generateBiomes();
  236. // Generate caverns, tunnels and classic caves
  237. if (flags & MG_CAVES) {
  238. bool near_cavern = false;
  239. // Generate caverns
  240. if (spflags & MGV7_CAVERNS)
  241. near_cavern = generateCaverns(stone_surface_max_y);
  242. // Generate tunnels and classic caves
  243. if (near_cavern)
  244. // Disable classic caves in this mapchunk by setting
  245. // 'large cave depth' to world base. Avoids excessive liquid in
  246. // large caverns and floating blobs of overgenerated liquid.
  247. generateCaves(stone_surface_max_y, -MAX_MAP_GENERATION_LIMIT);
  248. else
  249. generateCaves(stone_surface_max_y, water_level);
  250. }
  251. // Generate dungeons
  252. if (flags & MG_DUNGEONS)
  253. generateDungeons(stone_surface_max_y, stone_type);
  254. // Generate the registered decorations
  255. if (flags & MG_DECORATIONS)
  256. m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);
  257. // Generate the registered ores
  258. m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
  259. // Sprinkle some dust on top after everything else was generated
  260. dustTopNodes();
  261. //printf("makeChunk: %dms\n", t.stop());
  262. // Update liquids
  263. updateLiquid(&data->transforming_liquid, full_node_min, full_node_max);
  264. // Calculate lighting
  265. // Limit floatland shadow
  266. bool propagate_shadow = !((spflags & MGV7_FLOATLANDS) &&
  267. node_min.Y <= shadow_limit && node_max.Y >= shadow_limit);
  268. if (flags & MG_LIGHT)
  269. calcLighting(node_min - v3s16(0, 1, 0), node_max + v3s16(0, 1, 0),
  270. full_node_min, full_node_max, propagate_shadow);
  271. //setLighting(node_min - v3s16(1, 0, 1) * MAP_BLOCKSIZE,
  272. // node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE, 0xFF);
  273. this->generating = false;
  274. }
  275. float MapgenV7::baseTerrainLevelAtPoint(s16 x, s16 z)
  276. {
  277. float hselect = NoisePerlin2D(&noise_height_select->np, x, z, seed);
  278. hselect = rangelim(hselect, 0.0, 1.0);
  279. float persist = NoisePerlin2D(&noise_terrain_persist->np, x, z, seed);
  280. noise_terrain_base->np.persist = persist;
  281. float height_base = NoisePerlin2D(&noise_terrain_base->np, x, z, seed);
  282. noise_terrain_alt->np.persist = persist;
  283. float height_alt = NoisePerlin2D(&noise_terrain_alt->np, x, z, seed);
  284. if (height_alt > height_base)
  285. return height_alt;
  286. return (height_base * hselect) + (height_alt * (1.0 - hselect));
  287. }
  288. float MapgenV7::baseTerrainLevelFromMap(int index)
  289. {
  290. float hselect = rangelim(noise_height_select->result[index], 0.0, 1.0);
  291. float height_base = noise_terrain_base->result[index];
  292. float height_alt = noise_terrain_alt->result[index];
  293. if (height_alt > height_base)
  294. return height_alt;
  295. return (height_base * hselect) + (height_alt * (1.0 - hselect));
  296. }
  297. bool MapgenV7::getMountainTerrainAtPoint(s16 x, s16 y, s16 z)
  298. {
  299. float mnt_h_n = NoisePerlin2D(&noise_mount_height->np, x, z, seed);
  300. float density_gradient = -((float)y / mnt_h_n);
  301. float mnt_n = NoisePerlin3D(&noise_mountain->np, x, y, z, seed);
  302. return mnt_n + density_gradient >= 0.0;
  303. }
  304. bool MapgenV7::getMountainTerrainFromMap(int idx_xyz, int idx_xz, s16 y)
  305. {
  306. float mounthn = noise_mount_height->result[idx_xz];
  307. float density_gradient = -((float)y / mounthn);
  308. float mountn = noise_mountain->result[idx_xyz];
  309. return mountn + density_gradient >= 0.0;
  310. }
  311. bool MapgenV7::getFloatlandMountainFromMap(int idx_xyz, int idx_xz, s16 y)
  312. {
  313. // Make rim 2 nodes thick to match floatland base terrain
  314. float density_gradient = (y >= floatland_level) ?
  315. -pow((float)(y - floatland_level) / float_mount_height, 0.75f) :
  316. -pow((float)(floatland_level - 1 - y) / float_mount_height, 0.75f);
  317. float floatn = noise_mountain->result[idx_xyz] + float_mount_density;
  318. return floatn + density_gradient >= 0.0f;
  319. }
  320. void MapgenV7::floatBaseExtentFromMap(s16 *float_base_min, s16 *float_base_max, int idx_xz)
  321. {
  322. // '+1' to avoid a layer of stone at y = MAX_MAP_GENERATION_LIMIT
  323. s16 base_min = MAX_MAP_GENERATION_LIMIT + 1;
  324. s16 base_max = MAX_MAP_GENERATION_LIMIT;
  325. float n_base = noise_floatland_base->result[idx_xz];
  326. if (n_base > 0.0f) {
  327. float n_base_height = noise_float_base_height->result[idx_xz];
  328. float amp = n_base * n_base_height;
  329. float ridge = n_base_height / 3.0f;
  330. base_min = floatland_level - amp / 1.5f;
  331. if (amp > ridge * 2.0f) {
  332. // Lake bed
  333. base_max = floatland_level - (amp - ridge * 2.0f) / 2.0f;
  334. } else {
  335. // Hills and ridges
  336. float diff = fabs(amp - ridge) / ridge;
  337. // Smooth ridges using the 'smoothstep function'
  338. float smooth_diff = diff * diff * (3.0f - 2.0f * diff);
  339. base_max = floatland_level + ridge - smooth_diff * ridge;
  340. }
  341. }
  342. *float_base_min = base_min;
  343. *float_base_max = base_max;
  344. }
  345. int MapgenV7::generateTerrain()
  346. {
  347. MapNode n_air(CONTENT_AIR);
  348. MapNode n_stone(c_stone);
  349. MapNode n_water(c_water_source);
  350. //// Calculate noise for terrain generation
  351. noise_terrain_persist->perlinMap2D(node_min.X, node_min.Z);
  352. float *persistmap = noise_terrain_persist->result;
  353. noise_terrain_base->perlinMap2D(node_min.X, node_min.Z, persistmap);
  354. noise_terrain_alt->perlinMap2D(node_min.X, node_min.Z, persistmap);
  355. noise_height_select->perlinMap2D(node_min.X, node_min.Z);
  356. if ((spflags & MGV7_MOUNTAINS) || (spflags & MGV7_FLOATLANDS)) {
  357. noise_mountain->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
  358. }
  359. if (spflags & MGV7_MOUNTAINS) {
  360. noise_mount_height->perlinMap2D(node_min.X, node_min.Z);
  361. }
  362. if (spflags & MGV7_FLOATLANDS) {
  363. noise_floatland_base->perlinMap2D(node_min.X, node_min.Z);
  364. noise_float_base_height->perlinMap2D(node_min.X, node_min.Z);
  365. }
  366. //// Place nodes
  367. v3s16 em = vm->m_area.getExtent();
  368. s16 stone_surface_max_y = -MAX_MAP_GENERATION_LIMIT;
  369. u32 index2d = 0;
  370. for (s16 z = node_min.Z; z <= node_max.Z; z++)
  371. for (s16 x = node_min.X; x <= node_max.X; x++, index2d++) {
  372. s16 surface_y = baseTerrainLevelFromMap(index2d);
  373. if (surface_y > stone_surface_max_y)
  374. stone_surface_max_y = surface_y;
  375. // Get extent of floatland base terrain
  376. // '+1' to avoid a layer of stone at y = MAX_MAP_GENERATION_LIMIT
  377. s16 float_base_min = MAX_MAP_GENERATION_LIMIT + 1;
  378. s16 float_base_max = MAX_MAP_GENERATION_LIMIT;
  379. if (spflags & MGV7_FLOATLANDS)
  380. floatBaseExtentFromMap(&float_base_min, &float_base_max, index2d);
  381. u32 vi = vm->m_area.index(x, node_min.Y - 1, z);
  382. u32 index3d = (z - node_min.Z) * zstride_1u1d + (x - node_min.X);
  383. for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
  384. if (vm->m_data[vi].getContent() == CONTENT_IGNORE) {
  385. if (y <= surface_y) {
  386. vm->m_data[vi] = n_stone; // Base terrain
  387. } else if ((spflags & MGV7_MOUNTAINS) &&
  388. getMountainTerrainFromMap(index3d, index2d, y)) {
  389. vm->m_data[vi] = n_stone; // Mountain terrain
  390. if (y > stone_surface_max_y)
  391. stone_surface_max_y = y;
  392. } else if ((spflags & MGV7_FLOATLANDS) &&
  393. ((y >= float_base_min && y <= float_base_max) ||
  394. getFloatlandMountainFromMap(index3d, index2d, y))) {
  395. vm->m_data[vi] = n_stone; // Floatland terrain
  396. stone_surface_max_y = node_max.Y;
  397. } else if (y <= water_level) {
  398. vm->m_data[vi] = n_water; // Ground level water
  399. } else if ((spflags & MGV7_FLOATLANDS) &&
  400. (y >= float_base_max && y <= floatland_level)) {
  401. vm->m_data[vi] = n_water; // Floatland water
  402. } else {
  403. vm->m_data[vi] = n_air;
  404. }
  405. }
  406. vm->m_area.add_y(em, vi, 1);
  407. index3d += ystride;
  408. }
  409. }
  410. return stone_surface_max_y;
  411. }
  412. void MapgenV7::generateRidgeTerrain()
  413. {
  414. if ((node_max.Y < water_level - 16) || (node_max.Y > shadow_limit))
  415. return;
  416. noise_ridge->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
  417. noise_ridge_uwater->perlinMap2D(node_min.X, node_min.Z);
  418. MapNode n_water(c_water_source);
  419. MapNode n_air(CONTENT_AIR);
  420. u32 index = 0;
  421. float width = 0.2;
  422. for (s16 z = node_min.Z; z <= node_max.Z; z++)
  423. for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
  424. u32 vi = vm->m_area.index(node_min.X, y, z);
  425. for (s16 x = node_min.X; x <= node_max.X; x++, index++, vi++) {
  426. int j = (z - node_min.Z) * csize.X + (x - node_min.X);
  427. float uwatern = noise_ridge_uwater->result[j] * 2;
  428. if (fabs(uwatern) > width)
  429. continue;
  430. float altitude = y - water_level;
  431. float height_mod = (altitude + 17) / 2.5;
  432. float width_mod = width - fabs(uwatern);
  433. float nridge = noise_ridge->result[index] * MYMAX(altitude, 0) / 7.0;
  434. if (nridge + width_mod * height_mod < 0.6)
  435. continue;
  436. vm->m_data[vi] = (y > water_level) ? n_air : n_water;
  437. }
  438. }
  439. }
  440. ////////////////////////////////////////////////////////////////////////////////
  441. //// Code Boneyard
  442. ////
  443. //// Much of the stuff here has potential to become useful again at some point
  444. //// in the future, but we don't want it to get lost or forgotten in version
  445. //// control.
  446. ////
  447. #if 0
  448. int MapgenV7::generateMountainTerrain(s16 ymax)
  449. {
  450. MapNode n_stone(c_stone);
  451. u32 j = 0;
  452. for (s16 z = node_min.Z; z <= node_max.Z; z++)
  453. for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
  454. u32 vi = vm->m_area.index(node_min.X, y, z);
  455. for (s16 x = node_min.X; x <= node_max.X; x++) {
  456. int index = (z - node_min.Z) * csize.X + (x - node_min.X);
  457. content_t c = vm->m_data[vi].getContent();
  458. if (getMountainTerrainFromMap(j, index, y)
  459. && (c == CONTENT_AIR || c == c_water_source)) {
  460. vm->m_data[vi] = n_stone;
  461. if (y > ymax)
  462. ymax = y;
  463. }
  464. vi++;
  465. j++;
  466. }
  467. }
  468. return ymax;
  469. }
  470. #endif
  471. #if 0
  472. void MapgenV7::carveRivers() {
  473. MapNode n_air(CONTENT_AIR), n_water_source(c_water_source);
  474. MapNode n_stone(c_stone);
  475. u32 index = 0;
  476. int river_depth = 4;
  477. for (s16 z = node_min.Z; z <= node_max.Z; z++)
  478. for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
  479. float terrain_mod = noise_terrain_mod->result[index];
  480. NoiseParams *np = noise_terrain_river->np;
  481. np.persist = noise_terrain_persist->result[index];
  482. float terrain_river = NoisePerlin2DNoTxfm(np, x, z, seed);
  483. float height = terrain_river * (1 - abs(terrain_mod)) *
  484. noise_terrain_river->np.scale;
  485. height = log(height * height); //log(h^3) is pretty interesting for terrain
  486. s16 y = heightmap[index];
  487. if (height < 1.0 && y > river_depth &&
  488. y - river_depth >= node_min.Y && y <= node_max.Y) {
  489. for (s16 ry = y; ry != y - river_depth; ry--) {
  490. u32 vi = vm->m_area.index(x, ry, z);
  491. vm->m_data[vi] = n_air;
  492. }
  493. u32 vi = vm->m_area.index(x, y - river_depth, z);
  494. vm->m_data[vi] = n_water_source;
  495. }
  496. }
  497. }
  498. #endif
  499. #if 0
  500. void MapgenV7::addTopNodes()
  501. {
  502. v3s16 em = vm->m_area.getExtent();
  503. s16 ntopnodes;
  504. u32 index = 0;
  505. for (s16 z = node_min.Z; z <= node_max.Z; z++)
  506. for (s16 x = node_min.X; x <= node_max.X; x++, index++) {
  507. Biome *biome = bmgr->biomes[biomemap[index]];
  508. //////////////////// First, add top nodes below the ridge
  509. s16 y = ridge_heightmap[index];
  510. // This cutoff is good enough, but not perfect.
  511. // It will cut off potentially placed top nodes at chunk boundaries
  512. if (y < node_min.Y)
  513. continue;
  514. if (y > node_max.Y) {
  515. y = node_max.Y; // Let's see if we can still go downward anyway
  516. u32 vi = vm->m_area.index(x, y, z);
  517. content_t c = vm->m_data[vi].getContent();
  518. if (ndef->get(c).walkable)
  519. continue;
  520. }
  521. // N.B. It is necessary to search downward since ridge_heightmap[i]
  522. // might not be the actual height, just the lowest part in the chunk
  523. // where a ridge had been carved
  524. u32 i = vm->m_area.index(x, y, z);
  525. for (; y >= node_min.Y; y--) {
  526. content_t c = vm->m_data[i].getContent();
  527. if (ndef->get(c).walkable)
  528. break;
  529. vm->m_area.add_y(em, i, -1);
  530. }
  531. if (y != node_min.Y - 1 && y >= water_level) {
  532. ridge_heightmap[index] = y; //update ridgeheight
  533. ntopnodes = biome->top_depth;
  534. for (; y <= node_max.Y && ntopnodes; y++) {
  535. ntopnodes--;
  536. vm->m_data[i] = MapNode(biome->c_top);
  537. vm->m_area.add_y(em, i, 1);
  538. }
  539. // If dirt, grow grass on it.
  540. if (y > water_level - 10 &&
  541. vm->m_data[i].getContent() == CONTENT_AIR) {
  542. vm->m_area.add_y(em, i, -1);
  543. if (vm->m_data[i].getContent() == c_dirt)
  544. vm->m_data[i] = MapNode(c_dirt_with_grass);
  545. }
  546. }
  547. //////////////////// Now, add top nodes on top of the ridge
  548. y = heightmap[index];
  549. if (y > node_max.Y) {
  550. y = node_max.Y; // Let's see if we can still go downward anyway
  551. u32 vi = vm->m_area.index(x, y, z);
  552. content_t c = vm->m_data[vi].getContent();
  553. if (ndef->get(c).walkable)
  554. continue;
  555. }
  556. i = vm->m_area.index(x, y, z);
  557. for (; y >= node_min.Y; y--) {
  558. content_t c = vm->m_data[i].getContent();
  559. if (ndef->get(c).walkable)
  560. break;
  561. vm->m_area.add_y(em, i, -1);
  562. }
  563. if (y != node_min.Y - 1) {
  564. ntopnodes = biome->top_depth;
  565. // Let's see if we've already added it...
  566. if (y == ridge_heightmap[index] + ntopnodes - 1)
  567. continue;
  568. for (; y <= node_max.Y && ntopnodes; y++) {
  569. ntopnodes--;
  570. vm->m_data[i] = MapNode(biome->c_top);
  571. vm->m_area.add_y(em, i, 1);
  572. }
  573. // If dirt, grow grass on it.
  574. if (y > water_level - 10 &&
  575. vm->m_data[i].getContent() == CONTENT_AIR) {
  576. vm->m_area.add_y(em, i, -1);
  577. if (vm->m_data[i].getContent() == c_dirt)
  578. vm->m_data[i] = MapNode(c_dirt_with_grass);
  579. }
  580. }
  581. }
  582. }
  583. #endif