2
0

mapgen_v5.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  1. /*
  2. Minetest
  3. Copyright (C) 2014-2017 paramat
  4. Copyright (C) 2014-2016 kwolekr, Ryan Kwolek <kwolekr@minetest.net>
  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_v5.h"
  35. FlagDesc flagdesc_mapgen_v5[] = {
  36. {"caverns", MGV5_CAVERNS},
  37. {NULL, 0}
  38. };
  39. MapgenV5::MapgenV5(int mapgenid, MapgenV5Params *params, EmergeManager *emerge)
  40. : MapgenBasic(mapgenid, params, emerge)
  41. {
  42. this->spflags = params->spflags;
  43. this->cave_width = params->cave_width;
  44. this->cavern_limit = params->cavern_limit;
  45. this->cavern_taper = params->cavern_taper;
  46. this->cavern_threshold = params->cavern_threshold;
  47. // Terrain noise
  48. noise_filler_depth = new Noise(&params->np_filler_depth, seed, csize.X, csize.Z);
  49. noise_factor = new Noise(&params->np_factor, seed, csize.X, csize.Z);
  50. noise_height = new Noise(&params->np_height, seed, csize.X, csize.Z);
  51. // 3D terrain noise
  52. // 1-up 1-down overgeneration
  53. noise_ground = new Noise(&params->np_ground, seed, csize.X, csize.Y + 2, csize.Z);
  54. // 1 down overgeneration
  55. MapgenBasic::np_cave1 = params->np_cave1;
  56. MapgenBasic::np_cave2 = params->np_cave2;
  57. MapgenBasic::np_cavern = params->np_cavern;
  58. }
  59. MapgenV5::~MapgenV5()
  60. {
  61. delete noise_filler_depth;
  62. delete noise_factor;
  63. delete noise_height;
  64. delete noise_ground;
  65. }
  66. MapgenV5Params::MapgenV5Params()
  67. {
  68. np_filler_depth = NoiseParams(0, 1, v3f(150, 150, 150), 261, 4, 0.7, 2.0);
  69. np_factor = NoiseParams(0, 1, v3f(250, 250, 250), 920381, 3, 0.45, 2.0);
  70. np_height = NoiseParams(0, 10, v3f(250, 250, 250), 84174, 4, 0.5, 2.0);
  71. np_ground = NoiseParams(0, 40, v3f(80, 80, 80), 983240, 4, 0.55, 2.0, NOISE_FLAG_EASED);
  72. np_cave1 = NoiseParams(0, 12, v3f(50, 50, 50), 52534, 4, 0.5, 2.0);
  73. np_cave2 = NoiseParams(0, 12, v3f(50, 50, 50), 10325, 4, 0.5, 2.0);
  74. np_cavern = NoiseParams(0, 1, v3f(384, 128, 384), 723, 5, 0.63, 2.0);
  75. }
  76. void MapgenV5Params::readParams(const Settings *settings)
  77. {
  78. settings->getFlagStrNoEx("mgv5_spflags", spflags, flagdesc_mapgen_v5);
  79. settings->getFloatNoEx("mgv5_cave_width", cave_width);
  80. settings->getS16NoEx("mgv5_cavern_limit", cavern_limit);
  81. settings->getS16NoEx("mgv5_cavern_taper", cavern_taper);
  82. settings->getFloatNoEx("mgv5_cavern_threshold", cavern_threshold);
  83. settings->getNoiseParams("mgv5_np_filler_depth", np_filler_depth);
  84. settings->getNoiseParams("mgv5_np_factor", np_factor);
  85. settings->getNoiseParams("mgv5_np_height", np_height);
  86. settings->getNoiseParams("mgv5_np_ground", np_ground);
  87. settings->getNoiseParams("mgv5_np_cave1", np_cave1);
  88. settings->getNoiseParams("mgv5_np_cave2", np_cave2);
  89. settings->getNoiseParams("mgv5_np_cavern", np_cavern);
  90. }
  91. void MapgenV5Params::writeParams(Settings *settings) const
  92. {
  93. settings->setFlagStr("mgv5_spflags", spflags, flagdesc_mapgen_v5, U32_MAX);
  94. settings->setFloat("mgv5_cave_width", cave_width);
  95. settings->setS16("mgv5_cavern_limit", cavern_limit);
  96. settings->setS16("mgv5_cavern_taper", cavern_taper);
  97. settings->setFloat("mgv5_cavern_threshold", cavern_threshold);
  98. settings->setNoiseParams("mgv5_np_filler_depth", np_filler_depth);
  99. settings->setNoiseParams("mgv5_np_factor", np_factor);
  100. settings->setNoiseParams("mgv5_np_height", np_height);
  101. settings->setNoiseParams("mgv5_np_ground", np_ground);
  102. settings->setNoiseParams("mgv5_np_cave1", np_cave1);
  103. settings->setNoiseParams("mgv5_np_cave2", np_cave2);
  104. settings->setNoiseParams("mgv5_np_cavern", np_cavern);
  105. }
  106. int MapgenV5::getSpawnLevelAtPoint(v2s16 p)
  107. {
  108. //TimeTaker t("getGroundLevelAtPoint", NULL, PRECISION_MICRO);
  109. float f = 0.55 + NoisePerlin2D(&noise_factor->np, p.X, p.Y, seed);
  110. if (f < 0.01)
  111. f = 0.01;
  112. else if (f >= 1.0)
  113. f *= 1.6;
  114. float h = NoisePerlin2D(&noise_height->np, p.X, p.Y, seed);
  115. for (s16 y = 128; y >= -128; y--) {
  116. float n_ground = NoisePerlin3D(&noise_ground->np, p.X, y, p.Y, seed);
  117. if (n_ground * f > y - h) { // If solid
  118. // If either top 2 nodes of search are solid this is inside a
  119. // mountain or floatland with possibly no space for the player to spawn.
  120. if (y >= 127) {
  121. return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
  122. } else { // Ground below at least 2 nodes of empty space
  123. if (y <= water_level || y > water_level + 16)
  124. return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
  125. else
  126. return y;
  127. }
  128. }
  129. }
  130. //printf("getGroundLevelAtPoint: %dus\n", t.stop());
  131. return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn position, no ground found
  132. }
  133. void MapgenV5::makeChunk(BlockMakeData *data)
  134. {
  135. // Pre-conditions
  136. assert(data->vmanip);
  137. assert(data->nodedef);
  138. assert(data->blockpos_requested.X >= data->blockpos_min.X &&
  139. data->blockpos_requested.Y >= data->blockpos_min.Y &&
  140. data->blockpos_requested.Z >= data->blockpos_min.Z);
  141. assert(data->blockpos_requested.X <= data->blockpos_max.X &&
  142. data->blockpos_requested.Y <= data->blockpos_max.Y &&
  143. data->blockpos_requested.Z <= data->blockpos_max.Z);
  144. this->generating = true;
  145. this->vm = data->vmanip;
  146. this->ndef = data->nodedef;
  147. //TimeTaker t("makeChunk");
  148. v3s16 blockpos_min = data->blockpos_min;
  149. v3s16 blockpos_max = data->blockpos_max;
  150. node_min = blockpos_min * MAP_BLOCKSIZE;
  151. node_max = (blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
  152. full_node_min = (blockpos_min - 1) * MAP_BLOCKSIZE;
  153. full_node_max = (blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
  154. // Create a block-specific seed
  155. blockseed = getBlockSeed2(full_node_min, seed);
  156. // Generate base terrain
  157. s16 stone_surface_max_y = generateBaseTerrain();
  158. // Create heightmap
  159. updateHeightmap(node_min, node_max);
  160. // Init biome generator, place biome-specific nodes, and build biomemap
  161. biomegen->calcBiomeNoise(node_min);
  162. MgStoneType stone_type = generateBiomes();
  163. // Generate caverns, tunnels and classic caves
  164. if (flags & MG_CAVES) {
  165. bool near_cavern = false;
  166. // Generate caverns
  167. if (spflags & MGV5_CAVERNS)
  168. near_cavern = generateCaverns(stone_surface_max_y);
  169. // Generate tunnels and classic caves
  170. if (near_cavern)
  171. // Disable classic caves in this mapchunk by setting
  172. // 'large cave depth' to world base. Avoids excessive liquid in
  173. // large caverns and floating blobs of overgenerated liquid.
  174. generateCaves(stone_surface_max_y, -MAX_MAP_GENERATION_LIMIT);
  175. else
  176. generateCaves(stone_surface_max_y, MGV5_LARGE_CAVE_DEPTH);
  177. }
  178. // Generate dungeons and desert temples
  179. if (flags & MG_DUNGEONS)
  180. generateDungeons(stone_surface_max_y, stone_type);
  181. // Generate the registered decorations
  182. if (flags & MG_DECORATIONS)
  183. m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);
  184. // Generate the registered ores
  185. m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
  186. // Sprinkle some dust on top after everything else was generated
  187. dustTopNodes();
  188. //printf("makeChunk: %dms\n", t.stop());
  189. // Add top and bottom side of water to transforming_liquid queue
  190. updateLiquid(&data->transforming_liquid, full_node_min, full_node_max);
  191. // Calculate lighting
  192. if (flags & MG_LIGHT) {
  193. calcLighting(node_min - v3s16(0, 1, 0), node_max + v3s16(0, 1, 0),
  194. full_node_min, full_node_max);
  195. }
  196. this->generating = false;
  197. }
  198. int MapgenV5::generateBaseTerrain()
  199. {
  200. u32 index = 0;
  201. u32 index2d = 0;
  202. int stone_surface_max_y = -MAX_MAP_GENERATION_LIMIT;
  203. noise_factor->perlinMap2D(node_min.X, node_min.Z);
  204. noise_height->perlinMap2D(node_min.X, node_min.Z);
  205. noise_ground->perlinMap3D(node_min.X, node_min.Y - 1, node_min.Z);
  206. for (s16 z=node_min.Z; z<=node_max.Z; z++) {
  207. for (s16 y=node_min.Y - 1; y<=node_max.Y + 1; y++) {
  208. u32 vi = vm->m_area.index(node_min.X, y, z);
  209. for (s16 x=node_min.X; x<=node_max.X; x++, vi++, index++, index2d++) {
  210. if (vm->m_data[vi].getContent() != CONTENT_IGNORE)
  211. continue;
  212. float f = 0.55 + noise_factor->result[index2d];
  213. if (f < 0.01)
  214. f = 0.01;
  215. else if (f >= 1.0)
  216. f *= 1.6;
  217. float h = noise_height->result[index2d];
  218. if (noise_ground->result[index] * f < y - h) {
  219. if (y <= water_level)
  220. vm->m_data[vi] = MapNode(c_water_source);
  221. else
  222. vm->m_data[vi] = MapNode(CONTENT_AIR);
  223. } else {
  224. vm->m_data[vi] = MapNode(c_stone);
  225. if (y > stone_surface_max_y)
  226. stone_surface_max_y = y;
  227. }
  228. }
  229. index2d -= ystride;
  230. }
  231. index2d += ystride;
  232. }
  233. return stone_surface_max_y;
  234. }