2
0

mapgen_flat.cpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. /*
  2. Minetest
  3. Copyright (C) 2015-2017 paramat
  4. Copyright (C) 2015-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_flat.h"
  35. FlagDesc flagdesc_mapgen_flat[] = {
  36. {"lakes", MGFLAT_LAKES},
  37. {"hills", MGFLAT_HILLS},
  38. {NULL, 0}
  39. };
  40. ///////////////////////////////////////////////////////////////////////////////////////
  41. MapgenFlat::MapgenFlat(int mapgenid, MapgenFlatParams *params, EmergeManager *emerge)
  42. : MapgenBasic(mapgenid, params, emerge)
  43. {
  44. this->spflags = params->spflags;
  45. this->ground_level = params->ground_level;
  46. this->large_cave_depth = params->large_cave_depth;
  47. this->cave_width = params->cave_width;
  48. this->lake_threshold = params->lake_threshold;
  49. this->lake_steepness = params->lake_steepness;
  50. this->hill_threshold = params->hill_threshold;
  51. this->hill_steepness = params->hill_steepness;
  52. // 2D noise
  53. noise_filler_depth = new Noise(&params->np_filler_depth, seed, csize.X, csize.Z);
  54. if ((spflags & MGFLAT_LAKES) || (spflags & MGFLAT_HILLS))
  55. noise_terrain = new Noise(&params->np_terrain, seed, csize.X, csize.Z);
  56. // 3D noise
  57. MapgenBasic::np_cave1 = params->np_cave1;
  58. MapgenBasic::np_cave2 = params->np_cave2;
  59. }
  60. MapgenFlat::~MapgenFlat()
  61. {
  62. delete noise_filler_depth;
  63. if ((spflags & MGFLAT_LAKES) || (spflags & MGFLAT_HILLS))
  64. delete noise_terrain;
  65. }
  66. MapgenFlatParams::MapgenFlatParams()
  67. {
  68. np_terrain = NoiseParams(0, 1, v3f(600, 600, 600), 7244, 5, 0.6, 2.0);
  69. np_filler_depth = NoiseParams(0, 1.2, v3f(150, 150, 150), 261, 3, 0.7, 2.0);
  70. np_cave1 = NoiseParams(0, 12, v3f(61, 61, 61), 52534, 3, 0.5, 2.0);
  71. np_cave2 = NoiseParams(0, 12, v3f(67, 67, 67), 10325, 3, 0.5, 2.0);
  72. }
  73. void MapgenFlatParams::readParams(const Settings *settings)
  74. {
  75. settings->getFlagStrNoEx("mgflat_spflags", spflags, flagdesc_mapgen_flat);
  76. settings->getS16NoEx("mgflat_ground_level", ground_level);
  77. settings->getS16NoEx("mgflat_large_cave_depth", large_cave_depth);
  78. settings->getFloatNoEx("mgflat_cave_width", cave_width);
  79. settings->getFloatNoEx("mgflat_lake_threshold", lake_threshold);
  80. settings->getFloatNoEx("mgflat_lake_steepness", lake_steepness);
  81. settings->getFloatNoEx("mgflat_hill_threshold", hill_threshold);
  82. settings->getFloatNoEx("mgflat_hill_steepness", hill_steepness);
  83. settings->getNoiseParams("mgflat_np_terrain", np_terrain);
  84. settings->getNoiseParams("mgflat_np_filler_depth", np_filler_depth);
  85. settings->getNoiseParams("mgflat_np_cave1", np_cave1);
  86. settings->getNoiseParams("mgflat_np_cave2", np_cave2);
  87. }
  88. void MapgenFlatParams::writeParams(Settings *settings) const
  89. {
  90. settings->setFlagStr("mgflat_spflags", spflags, flagdesc_mapgen_flat, U32_MAX);
  91. settings->setS16("mgflat_ground_level", ground_level);
  92. settings->setS16("mgflat_large_cave_depth", large_cave_depth);
  93. settings->setFloat("mgflat_cave_width", cave_width);
  94. settings->setFloat("mgflat_lake_threshold", lake_threshold);
  95. settings->setFloat("mgflat_lake_steepness", lake_steepness);
  96. settings->setFloat("mgflat_hill_threshold", hill_threshold);
  97. settings->setFloat("mgflat_hill_steepness", hill_steepness);
  98. settings->setNoiseParams("mgflat_np_terrain", np_terrain);
  99. settings->setNoiseParams("mgflat_np_filler_depth", np_filler_depth);
  100. settings->setNoiseParams("mgflat_np_cave1", np_cave1);
  101. settings->setNoiseParams("mgflat_np_cave2", np_cave2);
  102. }
  103. /////////////////////////////////////////////////////////////////
  104. int MapgenFlat::getSpawnLevelAtPoint(v2s16 p)
  105. {
  106. s16 level_at_point = ground_level;
  107. float n_terrain = 0.0f;
  108. if ((spflags & MGFLAT_LAKES) || (spflags & MGFLAT_HILLS))
  109. n_terrain = NoisePerlin2D(&noise_terrain->np, p.X, p.Y, seed);
  110. if ((spflags & MGFLAT_LAKES) && n_terrain < lake_threshold) {
  111. level_at_point = ground_level -
  112. (lake_threshold - n_terrain) * lake_steepness;
  113. } else if ((spflags & MGFLAT_HILLS) && n_terrain > hill_threshold) {
  114. level_at_point = ground_level +
  115. (n_terrain - hill_threshold) * hill_steepness;
  116. }
  117. if (ground_level < water_level) // Ocean world, allow spawn in water
  118. return MYMAX(level_at_point, water_level);
  119. else if (level_at_point > water_level)
  120. return level_at_point; // Spawn on land
  121. else
  122. return MAX_MAP_GENERATION_LIMIT; // Unsuitable spawn point
  123. }
  124. void MapgenFlat::makeChunk(BlockMakeData *data)
  125. {
  126. // Pre-conditions
  127. assert(data->vmanip);
  128. assert(data->nodedef);
  129. assert(data->blockpos_requested.X >= data->blockpos_min.X &&
  130. data->blockpos_requested.Y >= data->blockpos_min.Y &&
  131. data->blockpos_requested.Z >= data->blockpos_min.Z);
  132. assert(data->blockpos_requested.X <= data->blockpos_max.X &&
  133. data->blockpos_requested.Y <= data->blockpos_max.Y &&
  134. data->blockpos_requested.Z <= data->blockpos_max.Z);
  135. this->generating = true;
  136. this->vm = data->vmanip;
  137. this->ndef = data->nodedef;
  138. //TimeTaker t("makeChunk");
  139. v3s16 blockpos_min = data->blockpos_min;
  140. v3s16 blockpos_max = data->blockpos_max;
  141. node_min = blockpos_min * MAP_BLOCKSIZE;
  142. node_max = (blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
  143. full_node_min = (blockpos_min - 1) * MAP_BLOCKSIZE;
  144. full_node_max = (blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
  145. blockseed = getBlockSeed2(full_node_min, seed);
  146. // Generate base terrain, mountains, and ridges with initial heightmaps
  147. s16 stone_surface_max_y = generateTerrain();
  148. // Create heightmap
  149. updateHeightmap(node_min, node_max);
  150. // Init biome generator, place biome-specific nodes, and build biomemap
  151. biomegen->calcBiomeNoise(node_min);
  152. MgStoneType stone_type = generateBiomes();
  153. if (flags & MG_CAVES)
  154. generateCaves(stone_surface_max_y, large_cave_depth);
  155. if (flags & MG_DUNGEONS)
  156. generateDungeons(stone_surface_max_y, stone_type);
  157. // Generate the registered decorations
  158. if (flags & MG_DECORATIONS)
  159. m_emerge->decomgr->placeAllDecos(this, blockseed, node_min, node_max);
  160. // Generate the registered ores
  161. m_emerge->oremgr->placeAllOres(this, blockseed, node_min, node_max);
  162. // Sprinkle some dust on top after everything else was generated
  163. dustTopNodes();
  164. //printf("makeChunk: %dms\n", t.stop());
  165. updateLiquid(&data->transforming_liquid, full_node_min, full_node_max);
  166. if (flags & MG_LIGHT)
  167. calcLighting(node_min - v3s16(0, 1, 0), node_max + v3s16(0, 1, 0),
  168. full_node_min, full_node_max);
  169. //setLighting(node_min - v3s16(1, 0, 1) * MAP_BLOCKSIZE,
  170. // node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE, 0xFF);
  171. this->generating = false;
  172. }
  173. s16 MapgenFlat::generateTerrain()
  174. {
  175. MapNode n_air(CONTENT_AIR);
  176. MapNode n_stone(c_stone);
  177. MapNode n_water(c_water_source);
  178. v3s16 em = vm->m_area.getExtent();
  179. s16 stone_surface_max_y = -MAX_MAP_GENERATION_LIMIT;
  180. u32 ni2d = 0;
  181. bool use_noise = (spflags & MGFLAT_LAKES) || (spflags & MGFLAT_HILLS);
  182. if (use_noise)
  183. noise_terrain->perlinMap2D(node_min.X, node_min.Z);
  184. for (s16 z = node_min.Z; z <= node_max.Z; z++)
  185. for (s16 x = node_min.X; x <= node_max.X; x++, ni2d++) {
  186. s16 stone_level = ground_level;
  187. float n_terrain = use_noise ? noise_terrain->result[ni2d] : 0.0f;
  188. if ((spflags & MGFLAT_LAKES) && n_terrain < lake_threshold) {
  189. s16 depress = (lake_threshold - n_terrain) * lake_steepness;
  190. stone_level = ground_level - depress;
  191. } else if ((spflags & MGFLAT_HILLS) && n_terrain > hill_threshold) {
  192. s16 rise = (n_terrain - hill_threshold) * hill_steepness;
  193. stone_level = ground_level + rise;
  194. }
  195. u32 vi = vm->m_area.index(x, node_min.Y - 1, z);
  196. for (s16 y = node_min.Y - 1; y <= node_max.Y + 1; y++) {
  197. if (vm->m_data[vi].getContent() == CONTENT_IGNORE) {
  198. if (y <= stone_level) {
  199. vm->m_data[vi] = n_stone;
  200. if (y > stone_surface_max_y)
  201. stone_surface_max_y = y;
  202. } else if (y <= water_level) {
  203. vm->m_data[vi] = n_water;
  204. } else {
  205. vm->m_data[vi] = n_air;
  206. }
  207. }
  208. vm->m_area.add_y(em, vi, 1);
  209. }
  210. }
  211. return stone_surface_max_y;
  212. }